m68knommu: Add support for the Coldfire m5441x.
[muen/linux.git] / arch / m68k / platform / coldfire / device.c
1 /*
2  * device.c  -- common ColdFire SoC device support
3  *
4  * (C) Copyright 2011, Greg Ungerer <gerg@uclinux.org>
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License.  See the file COPYING in the main directory of this archive
8  * for more details.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/io.h>
14 #include <linux/spi/spi.h>
15 #include <linux/gpio.h>
16 #include <linux/fec.h>
17 #include <asm/traps.h>
18 #include <asm/coldfire.h>
19 #include <asm/mcfsim.h>
20 #include <asm/mcfuart.h>
21 #include <asm/mcfqspi.h>
22
23 /*
24  *      All current ColdFire parts contain from 2, 3, 4 or 10 UARTS.
25  */
26 static struct mcf_platform_uart mcf_uart_platform_data[] = {
27         {
28                 .mapbase        = MCFUART_BASE0,
29                 .irq            = MCF_IRQ_UART0,
30         },
31         {
32                 .mapbase        = MCFUART_BASE1,
33                 .irq            = MCF_IRQ_UART1,
34         },
35 #ifdef MCFUART_BASE2
36         {
37                 .mapbase        = MCFUART_BASE2,
38                 .irq            = MCF_IRQ_UART2,
39         },
40 #endif
41 #ifdef MCFUART_BASE3
42         {
43                 .mapbase        = MCFUART_BASE3,
44                 .irq            = MCF_IRQ_UART3,
45         },
46 #endif
47 #ifdef MCFUART_BASE4
48         {
49                 .mapbase        = MCFUART_BASE4,
50                 .irq            = MCF_IRQ_UART4,
51         },
52 #endif
53 #ifdef MCFUART_BASE5
54         {
55                 .mapbase        = MCFUART_BASE5,
56                 .irq            = MCF_IRQ_UART5,
57         },
58 #endif
59 #ifdef MCFUART_BASE6
60         {
61                 .mapbase        = MCFUART_BASE6,
62                 .irq            = MCF_IRQ_UART6,
63         },
64 #endif
65 #ifdef MCFUART_BASE7
66         {
67                 .mapbase        = MCFUART_BASE7,
68                 .irq            = MCF_IRQ_UART7,
69         },
70 #endif
71 #ifdef MCFUART_BASE8
72         {
73                 .mapbase        = MCFUART_BASE8,
74                 .irq            = MCF_IRQ_UART8,
75         },
76 #endif
77 #ifdef MCFUART_BASE9
78         {
79                 .mapbase        = MCFUART_BASE9,
80                 .irq            = MCF_IRQ_UART9,
81         },
82 #endif
83         { },
84 };
85
86 static struct platform_device mcf_uart = {
87         .name                   = "mcfuart",
88         .id                     = 0,
89         .dev.platform_data      = mcf_uart_platform_data,
90 };
91
92 #ifdef CONFIG_FEC
93
94 #ifdef CONFIG_M5441x
95 #define FEC_NAME        "enet-fec"
96 static struct fec_platform_data fec_pdata = {
97         .phy            = PHY_INTERFACE_MODE_RMII,
98 };
99 #define FEC_PDATA       (&fec_pdata)
100 #else
101 #define FEC_NAME        "fec"
102 #define FEC_PDATA       NULL
103 #endif
104
105 /*
106  *      Some ColdFire cores contain the Fast Ethernet Controller (FEC)
107  *      block. It is Freescale's own hardware block. Some ColdFires
108  *      have 2 of these.
109  */
110 static struct resource mcf_fec0_resources[] = {
111         {
112                 .start          = MCFFEC_BASE0,
113                 .end            = MCFFEC_BASE0 + MCFFEC_SIZE0 - 1,
114                 .flags          = IORESOURCE_MEM,
115         },
116         {
117                 .start          = MCF_IRQ_FECRX0,
118                 .end            = MCF_IRQ_FECRX0,
119                 .flags          = IORESOURCE_IRQ,
120         },
121         {
122                 .start          = MCF_IRQ_FECTX0,
123                 .end            = MCF_IRQ_FECTX0,
124                 .flags          = IORESOURCE_IRQ,
125         },
126         {
127                 .start          = MCF_IRQ_FECENTC0,
128                 .end            = MCF_IRQ_FECENTC0,
129                 .flags          = IORESOURCE_IRQ,
130         },
131 };
132
133 static struct platform_device mcf_fec0 = {
134         .name                   = FEC_NAME,
135         .id                     = 0,
136         .num_resources          = ARRAY_SIZE(mcf_fec0_resources),
137         .resource               = mcf_fec0_resources,
138         .dev.platform_data      = FEC_PDATA,
139 };
140
141 #ifdef MCFFEC_BASE1
142 static struct resource mcf_fec1_resources[] = {
143         {
144                 .start          = MCFFEC_BASE1,
145                 .end            = MCFFEC_BASE1 + MCFFEC_SIZE1 - 1,
146                 .flags          = IORESOURCE_MEM,
147         },
148         {
149                 .start          = MCF_IRQ_FECRX1,
150                 .end            = MCF_IRQ_FECRX1,
151                 .flags          = IORESOURCE_IRQ,
152         },
153         {
154                 .start          = MCF_IRQ_FECTX1,
155                 .end            = MCF_IRQ_FECTX1,
156                 .flags          = IORESOURCE_IRQ,
157         },
158         {
159                 .start          = MCF_IRQ_FECENTC1,
160                 .end            = MCF_IRQ_FECENTC1,
161                 .flags          = IORESOURCE_IRQ,
162         },
163 };
164
165 static struct platform_device mcf_fec1 = {
166         .name                   = FEC_NAME,
167         .id                     = 1,
168         .num_resources          = ARRAY_SIZE(mcf_fec1_resources),
169         .resource               = mcf_fec1_resources,
170         .dev.platform_data      = FEC_PDATA,
171 };
172 #endif /* MCFFEC_BASE1 */
173 #endif /* CONFIG_FEC */
174
175 #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
176 /*
177  *      The ColdFire QSPI module is an SPI protocol hardware block used
178  *      on a number of different ColdFire CPUs.
179  */
180 static struct resource mcf_qspi_resources[] = {
181         {
182                 .start          = MCFQSPI_BASE,
183                 .end            = MCFQSPI_BASE + MCFQSPI_SIZE - 1,
184                 .flags          = IORESOURCE_MEM,
185         },
186         {
187                 .start          = MCF_IRQ_QSPI,
188                 .end            = MCF_IRQ_QSPI,
189                 .flags          = IORESOURCE_IRQ,
190         },
191 };
192
193 static int mcf_cs_setup(struct mcfqspi_cs_control *cs_control)
194 {
195         int status;
196
197         status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
198         if (status) {
199                 pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
200                 goto fail0;
201         }
202         status = gpio_direction_output(MCFQSPI_CS0, 1);
203         if (status) {
204                 pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
205                 goto fail1;
206         }
207
208         status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
209         if (status) {
210                 pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
211                 goto fail1;
212         }
213         status = gpio_direction_output(MCFQSPI_CS1, 1);
214         if (status) {
215                 pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
216                 goto fail2;
217         }
218
219         status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
220         if (status) {
221                 pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
222                 goto fail2;
223         }
224         status = gpio_direction_output(MCFQSPI_CS2, 1);
225         if (status) {
226                 pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
227                 goto fail3;
228         }
229
230 #ifdef MCFQSPI_CS3
231         status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3");
232         if (status) {
233                 pr_debug("gpio_request for MCFQSPI_CS3 failed\n");
234                 goto fail3;
235         }
236         status = gpio_direction_output(MCFQSPI_CS3, 1);
237         if (status) {
238                 pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n");
239                 gpio_free(MCFQSPI_CS3);
240                 goto fail3;
241         }
242 #endif
243
244         return 0;
245
246 fail3:
247         gpio_free(MCFQSPI_CS2);
248 fail2:
249         gpio_free(MCFQSPI_CS1);
250 fail1:
251         gpio_free(MCFQSPI_CS0);
252 fail0:
253         return status;
254 }
255
256 static void mcf_cs_teardown(struct mcfqspi_cs_control *cs_control)
257 {
258 #ifdef MCFQSPI_CS3
259         gpio_free(MCFQSPI_CS3);
260 #endif
261         gpio_free(MCFQSPI_CS2);
262         gpio_free(MCFQSPI_CS1);
263         gpio_free(MCFQSPI_CS0);
264 }
265
266 static void mcf_cs_select(struct mcfqspi_cs_control *cs_control,
267                           u8 chip_select, bool cs_high)
268 {
269         switch (chip_select) {
270         case 0:
271                 gpio_set_value(MCFQSPI_CS0, cs_high);
272                 break;
273         case 1:
274                 gpio_set_value(MCFQSPI_CS1, cs_high);
275                 break;
276         case 2:
277                 gpio_set_value(MCFQSPI_CS2, cs_high);
278                 break;
279 #ifdef MCFQSPI_CS3
280         case 3:
281                 gpio_set_value(MCFQSPI_CS3, cs_high);
282                 break;
283 #endif
284         }
285 }
286
287 static void mcf_cs_deselect(struct mcfqspi_cs_control *cs_control,
288                             u8 chip_select, bool cs_high)
289 {
290         switch (chip_select) {
291         case 0:
292                 gpio_set_value(MCFQSPI_CS0, !cs_high);
293                 break;
294         case 1:
295                 gpio_set_value(MCFQSPI_CS1, !cs_high);
296                 break;
297         case 2:
298                 gpio_set_value(MCFQSPI_CS2, !cs_high);
299                 break;
300 #ifdef MCFQSPI_CS3
301         case 3:
302                 gpio_set_value(MCFQSPI_CS3, !cs_high);
303                 break;
304 #endif
305         }
306 }
307
308 static struct mcfqspi_cs_control mcf_cs_control = {
309         .setup                  = mcf_cs_setup,
310         .teardown               = mcf_cs_teardown,
311         .select                 = mcf_cs_select,
312         .deselect               = mcf_cs_deselect,
313 };
314
315 static struct mcfqspi_platform_data mcf_qspi_data = {
316         .bus_num                = 0,
317         .num_chipselect         = 4,
318         .cs_control             = &mcf_cs_control,
319 };
320
321 static struct platform_device mcf_qspi = {
322         .name                   = "mcfqspi",
323         .id                     = 0,
324         .num_resources          = ARRAY_SIZE(mcf_qspi_resources),
325         .resource               = mcf_qspi_resources,
326         .dev.platform_data      = &mcf_qspi_data,
327 };
328 #endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */
329
330 static struct platform_device *mcf_devices[] __initdata = {
331         &mcf_uart,
332 #ifdef CONFIG_FEC
333         &mcf_fec0,
334 #ifdef MCFFEC_BASE1
335         &mcf_fec1,
336 #endif
337 #endif
338 #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
339         &mcf_qspi,
340 #endif
341 };
342
343 /*
344  *      Some ColdFire UARTs let you set the IRQ line to use.
345  */
346 static void __init mcf_uart_set_irq(void)
347 {
348 #ifdef MCFUART_UIVR
349         /* UART0 interrupt setup */
350         writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
351         writeb(MCF_IRQ_UART0, MCFUART_BASE0 + MCFUART_UIVR);
352         mcf_mapirq2imr(MCF_IRQ_UART0, MCFINTC_UART0);
353
354         /* UART1 interrupt setup */
355         writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
356         writeb(MCF_IRQ_UART1, MCFUART_BASE1 + MCFUART_UIVR);
357         mcf_mapirq2imr(MCF_IRQ_UART1, MCFINTC_UART1);
358 #endif
359 }
360
361 static int __init mcf_init_devices(void)
362 {
363         mcf_uart_set_irq();
364         platform_add_devices(mcf_devices, ARRAY_SIZE(mcf_devices));
365         return 0;
366 }
367
368 arch_initcall(mcf_init_devices);
369