m68knommu: simplify the 528x UART setup code
[~shefty/rdma-dev.git] / arch / m68k / platform / 528x / config.c
1 /***************************************************************************/
2
3 /*
4  *      linux/arch/m68knommu/platform/528x/config.c
5  *
6  *      Sub-architcture dependent initialization code for the Freescale
7  *      5280, 5281 and 5282 CPUs.
8  *
9  *      Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com)
10  *      Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
11  */
12
13 /***************************************************************************/
14
15 #include <linux/kernel.h>
16 #include <linux/param.h>
17 #include <linux/init.h>
18 #include <linux/platform_device.h>
19 #include <linux/io.h>
20 #include <linux/spi/spi.h>
21 #include <linux/gpio.h>
22 #include <asm/machdep.h>
23 #include <asm/coldfire.h>
24 #include <asm/mcfsim.h>
25 #include <asm/mcfuart.h>
26 #include <asm/mcfqspi.h>
27
28 /***************************************************************************/
29
30 static struct mcf_platform_uart m528x_uart_platform[] = {
31         {
32                 .mapbase        = MCFUART_BASE0,
33                 .irq            = MCF_IRQ_UART0,
34         },
35         {
36                 .mapbase        = MCFUART_BASE1,
37                 .irq            = MCF_IRQ_UART1,
38         },
39         {
40                 .mapbase        = MCFUART_BASE2,
41                 .irq            = MCF_IRQ_UART2,
42         },
43         { },
44 };
45
46 static struct platform_device m528x_uart = {
47         .name                   = "mcfuart",
48         .id                     = 0,
49         .dev.platform_data      = m528x_uart_platform,
50 };
51
52 static struct resource m528x_fec_resources[] = {
53         {
54                 .start          = MCFFEC_BASE,
55                 .end            = MCFFEC_BASE + MCFFEC_SIZE - 1,
56                 .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
75 static 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
82 #if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
83 static 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
101 static 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
151 fail4:
152         gpio_free(MCFQSPI_CS3);
153 fail3:
154         gpio_free(MCFQSPI_CS2);
155 fail2:
156         gpio_free(MCFQSPI_CS1);
157 fail1:
158         gpio_free(MCFQSPI_CS0);
159 fail0:
160         return status;
161 }
162
163 static 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
171 static 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
177 static 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
183 static 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
190 static struct mcfqspi_platform_data m528x_qspi_data = {
191         .bus_num                = 0,
192         .num_chipselect         = 4,
193         .cs_control             = &m528x_cs_control,
194 };
195
196 static 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
204 static 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) */
210
211 static struct platform_device *m528x_devices[] __initdata = {
212         &m528x_uart,
213         &m528x_fec,
214 #if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
215         &m528x_qspi,
216 #endif
217 };
218
219 /***************************************************************************/
220
221 static void __init m528x_uarts_init(void)
222 {
223         u8 port;
224
225         /* make sure PUAPAR is set for UART0 and UART1 */
226         port = readb(MCF5282_GPIO_PUAPAR);
227         port |= 0x03 | (0x03 << 2);
228         writeb(port, MCF5282_GPIO_PUAPAR);
229 }
230
231 /***************************************************************************/
232
233 static void __init m528x_fec_init(void)
234 {
235         u16 v16;
236
237         /* 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
245 static void m528x_cpu_reset(void)
246 {
247         local_irq_disable();
248         __raw_writeb(MCF_RCR_SWRESET, MCF_IPSBAR + MCF_RCR);
249 }
250
251 /***************************************************************************/
252
253 #ifdef CONFIG_WILDFIRE
254 void wildfire_halt(void)
255 {
256         writeb(0, 0x30000007);
257         writeb(0x2, 0x30000007);
258 }
259 #endif
260
261 #ifdef CONFIG_WILDFIREMOD
262 void 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
280 void __init config_BSP(char *commandp, int size)
281 {
282 #ifdef CONFIG_WILDFIRE
283         mach_halt = wildfire_halt;
284 #endif
285 #ifdef CONFIG_WILDFIREMOD
286         mach_halt = wildfiremod_halt;
287 #endif
288 }
289
290 /***************************************************************************/
291
292 static int __init init_BSP(void)
293 {
294         mach_reset = m528x_cpu_reset;
295         mach_sched_init = hw_timer_init;
296         m528x_uarts_init();
297         m528x_fec_init();
298 #if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
299         m528x_qspi_init();
300 #endif
301         platform_add_devices(m528x_devices, ARRAY_SIZE(m528x_devices));
302         return 0;
303 }
304
305 arch_initcall(init_BSP);
306
307 /***************************************************************************/