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 */
26static 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
86static 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"
96static 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 */
110static 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
133static 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
142static 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
165static 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 */
180static 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
193static 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
246fail3:
247	gpio_free(MCFQSPI_CS2);
248fail2:
249	gpio_free(MCFQSPI_CS1);
250fail1:
251	gpio_free(MCFQSPI_CS0);
252fail0:
253	return status;
254}
255
256static 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
266static 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
287static 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
308static 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
315static struct mcfqspi_platform_data mcf_qspi_data = {
316	.bus_num		= 0,
317	.num_chipselect		= 4,
318	.cs_control		= &mcf_cs_control,
319};
320
321static 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
330static 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 */
346static 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
361static 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
368arch_initcall(mcf_init_devices);
369
370