blob: 82af5d883603135161f621ed649cdaed90702243 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/***************************************************************************/
2
3/*
4 * linux/arch/m68knommu/platform/528x/config.c
5 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -03006 * Sub-architcture dependent initialization code for the Freescale
Greg Ungerer980f9232009-04-28 14:24:25 +10007 * 5280, 5281 and 5282 CPUs.
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 *
9 * Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com)
10 * Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
11 */
12
13/***************************************************************************/
14
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include <linux/param.h>
17#include <linux/init.h>
Greg Ungerereb49e902008-02-01 17:34:50 +100018#include <linux/platform_device.h>
Greg Ungerereb49e902008-02-01 17:34:50 +100019#include <linux/io.h>
Steven King91d60412010-01-22 12:43:03 -080020#include <linux/spi/spi.h>
21#include <linux/gpio.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <asm/machdep.h>
23#include <asm/coldfire.h>
24#include <asm/mcfsim.h>
Greg Ungerereb49e902008-02-01 17:34:50 +100025#include <asm/mcfuart.h>
Steven King91d60412010-01-22 12:43:03 -080026#include <asm/mcfqspi.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027
28/***************************************************************************/
29
Greg Ungerereb49e902008-02-01 17:34:50 +100030static struct mcf_platform_uart m528x_uart_platform[] = {
31 {
Greg Ungererf8bb5322011-12-24 00:39:04 +100032 .mapbase = MCFUART_BASE0,
33 .irq = MCF_IRQ_UART0,
34 },
35 {
36 .mapbase = MCFUART_BASE1,
37 .irq = MCF_IRQ_UART1,
Greg Ungerereb49e902008-02-01 17:34:50 +100038 },
39 {
Greg Ungerera0ba4332011-03-06 00:20:01 +100040 .mapbase = MCFUART_BASE2,
Greg Ungererf8bb5322011-12-24 00:39:04 +100041 .irq = MCF_IRQ_UART2,
Greg Ungerereb49e902008-02-01 17:34:50 +100042 },
43 { },
Linus Torvalds1da177e2005-04-16 15:20:36 -070044};
45
Greg Ungerereb49e902008-02-01 17:34:50 +100046static struct platform_device m528x_uart = {
47 .name = "mcfuart",
48 .id = 0,
49 .dev.platform_data = m528x_uart_platform,
50};
51
Greg Ungererffba3f42009-02-26 22:40:38 -080052static struct resource m528x_fec_resources[] = {
53 {
Greg Ungerera0ba4332011-03-06 00:20:01 +100054 .start = MCFFEC_BASE,
55 .end = MCFFEC_BASE + MCFFEC_SIZE - 1,
Greg Ungererffba3f42009-02-26 22:40:38 -080056 .flags = IORESOURCE_MEM,
57 },
58 {
59 .start = 64 + 23,
60 .end = 64 + 23,
61 .flags = IORESOURCE_IRQ,
62 },
63 {
64 .start = 64 + 27,
65 .end = 64 + 27,
66 .flags = IORESOURCE_IRQ,
67 },
68 {
69 .start = 64 + 29,
70 .end = 64 + 29,
71 .flags = IORESOURCE_IRQ,
72 },
73};
74
75static struct platform_device m528x_fec = {
76 .name = "fec",
77 .id = 0,
78 .num_resources = ARRAY_SIZE(m528x_fec_resources),
79 .resource = m528x_fec_resources,
80};
81
Steven King91d60412010-01-22 12:43:03 -080082#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
83static struct resource m528x_qspi_resources[] = {
84 {
85 .start = MCFQSPI_IOBASE,
86 .end = MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
87 .flags = IORESOURCE_MEM,
88 },
89 {
90 .start = MCFINT_VECBASE + MCFINT_QSPI,
91 .end = MCFINT_VECBASE + MCFINT_QSPI,
92 .flags = IORESOURCE_IRQ,
93 },
94};
95
96#define MCFQSPI_CS0 147
97#define MCFQSPI_CS1 148
98#define MCFQSPI_CS2 149
99#define MCFQSPI_CS3 150
100
101static int m528x_cs_setup(struct mcfqspi_cs_control *cs_control)
102{
103 int status;
104
105 status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
106 if (status) {
107 pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
108 goto fail0;
109 }
110 status = gpio_direction_output(MCFQSPI_CS0, 1);
111 if (status) {
112 pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
113 goto fail1;
114 }
115
116 status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
117 if (status) {
118 pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
119 goto fail1;
120 }
121 status = gpio_direction_output(MCFQSPI_CS1, 1);
122 if (status) {
123 pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
124 goto fail2;
125 }
126
127 status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
128 if (status) {
129 pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
130 goto fail2;
131 }
132 status = gpio_direction_output(MCFQSPI_CS2, 1);
133 if (status) {
134 pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
135 goto fail3;
136 }
137
138 status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3");
139 if (status) {
140 pr_debug("gpio_request for MCFQSPI_CS3 failed\n");
141 goto fail3;
142 }
143 status = gpio_direction_output(MCFQSPI_CS3, 1);
144 if (status) {
145 pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n");
146 goto fail4;
147 }
148
149 return 0;
150
151fail4:
152 gpio_free(MCFQSPI_CS3);
153fail3:
154 gpio_free(MCFQSPI_CS2);
155fail2:
156 gpio_free(MCFQSPI_CS1);
157fail1:
158 gpio_free(MCFQSPI_CS0);
159fail0:
160 return status;
161}
162
163static void m528x_cs_teardown(struct mcfqspi_cs_control *cs_control)
164{
165 gpio_free(MCFQSPI_CS3);
166 gpio_free(MCFQSPI_CS2);
167 gpio_free(MCFQSPI_CS1);
168 gpio_free(MCFQSPI_CS0);
169}
170
171static void m528x_cs_select(struct mcfqspi_cs_control *cs_control,
172 u8 chip_select, bool cs_high)
173{
174 gpio_set_value(MCFQSPI_CS0 + chip_select, cs_high);
175}
176
177static void m528x_cs_deselect(struct mcfqspi_cs_control *cs_control,
178 u8 chip_select, bool cs_high)
179{
180 gpio_set_value(MCFQSPI_CS0 + chip_select, !cs_high);
181}
182
183static struct mcfqspi_cs_control m528x_cs_control = {
184 .setup = m528x_cs_setup,
185 .teardown = m528x_cs_teardown,
186 .select = m528x_cs_select,
187 .deselect = m528x_cs_deselect,
188};
189
190static struct mcfqspi_platform_data m528x_qspi_data = {
191 .bus_num = 0,
192 .num_chipselect = 4,
193 .cs_control = &m528x_cs_control,
194};
195
196static struct platform_device m528x_qspi = {
197 .name = "mcfqspi",
198 .id = 0,
199 .num_resources = ARRAY_SIZE(m528x_qspi_resources),
200 .resource = m528x_qspi_resources,
201 .dev.platform_data = &m528x_qspi_data,
202};
203
204static void __init m528x_qspi_init(void)
205{
206 /* setup Port QS for QSPI with gpio CS control */
207 __raw_writeb(0x07, MCFGPIO_PQSPAR);
208}
209#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
Greg Ungererffba3f42009-02-26 22:40:38 -0800210
Greg Ungerereb49e902008-02-01 17:34:50 +1000211static struct platform_device *m528x_devices[] __initdata = {
212 &m528x_uart,
Greg Ungererffba3f42009-02-26 22:40:38 -0800213 &m528x_fec,
Steven King91d60412010-01-22 12:43:03 -0800214#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
215 &m528x_qspi,
216#endif
Greg Ungerereb49e902008-02-01 17:34:50 +1000217};
218
219/***************************************************************************/
220
Greg Ungerercae82a82011-12-24 01:00:48 +1000221static void __init m528x_uarts_init(void)
Greg Ungerereb49e902008-02-01 17:34:50 +1000222{
223 u8 port;
Greg Ungerereb49e902008-02-01 17:34:50 +1000224
Greg Ungerereb49e902008-02-01 17:34:50 +1000225 /* make sure PUAPAR is set for UART0 and UART1 */
Greg Ungerercae82a82011-12-24 01:00:48 +1000226 port = readb(MCF5282_GPIO_PUAPAR);
227 port |= 0x03 | (0x03 << 2);
228 writeb(port, MCF5282_GPIO_PUAPAR);
Greg Ungerereb49e902008-02-01 17:34:50 +1000229}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230
231/***************************************************************************/
232
Greg Ungererffba3f42009-02-26 22:40:38 -0800233static void __init m528x_fec_init(void)
234{
Greg Ungererffba3f42009-02-26 22:40:38 -0800235 u16 v16;
236
Greg Ungererffba3f42009-02-26 22:40:38 -0800237 /* Set multi-function pins to ethernet mode for fec0 */
238 v16 = readw(MCF_IPSBAR + 0x100056);
239 writew(v16 | 0xf00, MCF_IPSBAR + 0x100056);
240 writeb(0xc0, MCF_IPSBAR + 0x100058);
241}
242
243/***************************************************************************/
244
Greg Ungererdd65b1d2009-04-30 23:15:56 +1000245static void m528x_cpu_reset(void)
246{
247 local_irq_disable();
248 __raw_writeb(MCF_RCR_SWRESET, MCF_IPSBAR + MCF_RCR);
249}
250
251/***************************************************************************/
252
Steve Bennett188a9a42008-05-01 12:17:08 +1000253#ifdef CONFIG_WILDFIRE
254void wildfire_halt(void)
255{
256 writeb(0, 0x30000007);
257 writeb(0x2, 0x30000007);
258}
259#endif
260
261#ifdef CONFIG_WILDFIREMOD
262void wildfiremod_halt(void)
263{
264 printk(KERN_INFO "WildFireMod hibernating...\n");
265
266 /* Set portE.5 to Digital IO */
267 MCF5282_GPIO_PEPAR &= ~(1 << (5 * 2));
268
269 /* Make portE.5 an output */
270 MCF5282_GPIO_DDRE |= (1 << 5);
271
272 /* Now toggle portE.5 from low to high */
273 MCF5282_GPIO_PORTE &= ~(1 << 5);
274 MCF5282_GPIO_PORTE |= (1 << 5);
275
276 printk(KERN_EMERG "Failed to hibernate. Halting!\n");
277}
278#endif
279
Greg Ungerereb49e902008-02-01 17:34:50 +1000280void __init config_BSP(char *commandp, int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281{
Steve Bennett188a9a42008-05-01 12:17:08 +1000282#ifdef CONFIG_WILDFIRE
283 mach_halt = wildfire_halt;
284#endif
285#ifdef CONFIG_WILDFIREMOD
286 mach_halt = wildfiremod_halt;
287#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288}
289
290/***************************************************************************/
Greg Ungerereb49e902008-02-01 17:34:50 +1000291
292static int __init init_BSP(void)
293{
Greg Ungererdd65b1d2009-04-30 23:15:56 +1000294 mach_reset = m528x_cpu_reset;
Greg Ungerer35aefb22012-01-23 15:34:58 +1000295 mach_sched_init = hw_timer_init;
Greg Ungerereb49e902008-02-01 17:34:50 +1000296 m528x_uarts_init();
Greg Ungererffba3f42009-02-26 22:40:38 -0800297 m528x_fec_init();
Steven King91d60412010-01-22 12:43:03 -0800298#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
299 m528x_qspi_init();
300#endif
Greg Ungerereb49e902008-02-01 17:34:50 +1000301 platform_add_devices(m528x_devices, ARRAY_SIZE(m528x_devices));
302 return 0;
303}
304
305arch_initcall(init_BSP);
306
307/***************************************************************************/