xref: /linux/arch/m68k/coldfire/device.c (revision ca55b2fef3a9373fcfc30f82fd26bc7fccbda732)
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, 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, 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 
370