xref: /OK3568_Linux_fs/kernel/arch/mips/alchemy/common/platform.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Platform device support for Au1x00 SoCs.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * (C) Copyright Embedded Alley Solutions, Inc 2005
7*4882a593Smuzhiyun  * Author: Pantelis Antoniou <pantelis@embeddedalley.com>
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * This file is licensed under the terms of the GNU General Public
10*4882a593Smuzhiyun  * License version 2.  This program is licensed "as is" without any
11*4882a593Smuzhiyun  * warranty of any kind, whether express or implied.
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <linux/clk.h>
15*4882a593Smuzhiyun #include <linux/dma-mapping.h>
16*4882a593Smuzhiyun #include <linux/etherdevice.h>
17*4882a593Smuzhiyun #include <linux/init.h>
18*4882a593Smuzhiyun #include <linux/platform_device.h>
19*4882a593Smuzhiyun #include <linux/serial_8250.h>
20*4882a593Smuzhiyun #include <linux/slab.h>
21*4882a593Smuzhiyun #include <linux/usb/ehci_pdriver.h>
22*4882a593Smuzhiyun #include <linux/usb/ohci_pdriver.h>
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #include <asm/mach-au1x00/au1000.h>
25*4882a593Smuzhiyun #include <asm/mach-au1x00/au1xxx_dbdma.h>
26*4882a593Smuzhiyun #include <asm/mach-au1x00/au1100_mmc.h>
27*4882a593Smuzhiyun #include <asm/mach-au1x00/au1xxx_eth.h>
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #include <prom.h>
30*4882a593Smuzhiyun 
alchemy_8250_pm(struct uart_port * port,unsigned int state,unsigned int old_state)31*4882a593Smuzhiyun static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
32*4882a593Smuzhiyun 			    unsigned int old_state)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun #ifdef CONFIG_SERIAL_8250
35*4882a593Smuzhiyun 	switch (state) {
36*4882a593Smuzhiyun 	case 0:
37*4882a593Smuzhiyun 		alchemy_uart_enable(CPHYSADDR(port->membase));
38*4882a593Smuzhiyun 		serial8250_do_pm(port, state, old_state);
39*4882a593Smuzhiyun 		break;
40*4882a593Smuzhiyun 	case 3:		/* power off */
41*4882a593Smuzhiyun 		serial8250_do_pm(port, state, old_state);
42*4882a593Smuzhiyun 		alchemy_uart_disable(CPHYSADDR(port->membase));
43*4882a593Smuzhiyun 		break;
44*4882a593Smuzhiyun 	default:
45*4882a593Smuzhiyun 		serial8250_do_pm(port, state, old_state);
46*4882a593Smuzhiyun 		break;
47*4882a593Smuzhiyun 	}
48*4882a593Smuzhiyun #endif
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #define PORT(_base, _irq)					\
52*4882a593Smuzhiyun 	{							\
53*4882a593Smuzhiyun 		.mapbase	= _base,			\
54*4882a593Smuzhiyun 		.irq		= _irq,				\
55*4882a593Smuzhiyun 		.regshift	= 2,				\
56*4882a593Smuzhiyun 		.iotype		= UPIO_AU,			\
57*4882a593Smuzhiyun 		.flags		= UPF_SKIP_TEST | UPF_IOREMAP | \
58*4882a593Smuzhiyun 				  UPF_FIXED_TYPE,		\
59*4882a593Smuzhiyun 		.type		= PORT_16550A,			\
60*4882a593Smuzhiyun 		.pm		= alchemy_8250_pm,		\
61*4882a593Smuzhiyun 	}
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun static struct plat_serial8250_port au1x00_uart_data[][4] __initdata = {
64*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1000] = {
65*4882a593Smuzhiyun 		PORT(AU1000_UART0_PHYS_ADDR, AU1000_UART0_INT),
66*4882a593Smuzhiyun 		PORT(AU1000_UART1_PHYS_ADDR, AU1000_UART1_INT),
67*4882a593Smuzhiyun 		PORT(AU1000_UART2_PHYS_ADDR, AU1000_UART2_INT),
68*4882a593Smuzhiyun 		PORT(AU1000_UART3_PHYS_ADDR, AU1000_UART3_INT),
69*4882a593Smuzhiyun 	},
70*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1500] = {
71*4882a593Smuzhiyun 		PORT(AU1000_UART0_PHYS_ADDR, AU1500_UART0_INT),
72*4882a593Smuzhiyun 		PORT(AU1000_UART3_PHYS_ADDR, AU1500_UART3_INT),
73*4882a593Smuzhiyun 	},
74*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1100] = {
75*4882a593Smuzhiyun 		PORT(AU1000_UART0_PHYS_ADDR, AU1100_UART0_INT),
76*4882a593Smuzhiyun 		PORT(AU1000_UART1_PHYS_ADDR, AU1100_UART1_INT),
77*4882a593Smuzhiyun 		PORT(AU1000_UART3_PHYS_ADDR, AU1100_UART3_INT),
78*4882a593Smuzhiyun 	},
79*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1550] = {
80*4882a593Smuzhiyun 		PORT(AU1000_UART0_PHYS_ADDR, AU1550_UART0_INT),
81*4882a593Smuzhiyun 		PORT(AU1000_UART1_PHYS_ADDR, AU1550_UART1_INT),
82*4882a593Smuzhiyun 		PORT(AU1000_UART3_PHYS_ADDR, AU1550_UART3_INT),
83*4882a593Smuzhiyun 	},
84*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1200] = {
85*4882a593Smuzhiyun 		PORT(AU1000_UART0_PHYS_ADDR, AU1200_UART0_INT),
86*4882a593Smuzhiyun 		PORT(AU1000_UART1_PHYS_ADDR, AU1200_UART1_INT),
87*4882a593Smuzhiyun 	},
88*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1300] = {
89*4882a593Smuzhiyun 		PORT(AU1300_UART0_PHYS_ADDR, AU1300_UART0_INT),
90*4882a593Smuzhiyun 		PORT(AU1300_UART1_PHYS_ADDR, AU1300_UART1_INT),
91*4882a593Smuzhiyun 		PORT(AU1300_UART2_PHYS_ADDR, AU1300_UART2_INT),
92*4882a593Smuzhiyun 		PORT(AU1300_UART3_PHYS_ADDR, AU1300_UART3_INT),
93*4882a593Smuzhiyun 	},
94*4882a593Smuzhiyun };
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun static struct platform_device au1xx0_uart_device = {
97*4882a593Smuzhiyun 	.name			= "serial8250",
98*4882a593Smuzhiyun 	.id			= PLAT8250_DEV_AU1X00,
99*4882a593Smuzhiyun };
100*4882a593Smuzhiyun 
alchemy_setup_uarts(int ctype)101*4882a593Smuzhiyun static void __init alchemy_setup_uarts(int ctype)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	long uartclk;
104*4882a593Smuzhiyun 	int s = sizeof(struct plat_serial8250_port);
105*4882a593Smuzhiyun 	int c = alchemy_get_uarts(ctype);
106*4882a593Smuzhiyun 	struct plat_serial8250_port *ports;
107*4882a593Smuzhiyun 	struct clk *clk = clk_get(NULL, ALCHEMY_PERIPH_CLK);
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	if (IS_ERR(clk))
110*4882a593Smuzhiyun 		return;
111*4882a593Smuzhiyun 	if (clk_prepare_enable(clk)) {
112*4882a593Smuzhiyun 		clk_put(clk);
113*4882a593Smuzhiyun 		return;
114*4882a593Smuzhiyun 	}
115*4882a593Smuzhiyun 	uartclk = clk_get_rate(clk);
116*4882a593Smuzhiyun 	clk_put(clk);
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	ports = kcalloc(s, (c + 1), GFP_KERNEL);
119*4882a593Smuzhiyun 	if (!ports) {
120*4882a593Smuzhiyun 		printk(KERN_INFO "Alchemy: no memory for UART data\n");
121*4882a593Smuzhiyun 		return;
122*4882a593Smuzhiyun 	}
123*4882a593Smuzhiyun 	memcpy(ports, au1x00_uart_data[ctype], s * c);
124*4882a593Smuzhiyun 	au1xx0_uart_device.dev.platform_data = ports;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	/* Fill up uartclk. */
127*4882a593Smuzhiyun 	for (s = 0; s < c; s++)
128*4882a593Smuzhiyun 		ports[s].uartclk = uartclk;
129*4882a593Smuzhiyun 	if (platform_device_register(&au1xx0_uart_device))
130*4882a593Smuzhiyun 		printk(KERN_INFO "Alchemy: failed to register UARTs\n");
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun static u64 alchemy_all_dmamask = DMA_BIT_MASK(32);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun /* Power on callback for the ehci platform driver */
alchemy_ehci_power_on(struct platform_device * pdev)137*4882a593Smuzhiyun static int alchemy_ehci_power_on(struct platform_device *pdev)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun 	return alchemy_usb_control(ALCHEMY_USB_EHCI0, 1);
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun /* Power off/suspend callback for the ehci platform driver */
alchemy_ehci_power_off(struct platform_device * pdev)143*4882a593Smuzhiyun static void alchemy_ehci_power_off(struct platform_device *pdev)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun 	alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun static struct usb_ehci_pdata alchemy_ehci_pdata = {
149*4882a593Smuzhiyun 	.no_io_watchdog = 1,
150*4882a593Smuzhiyun 	.power_on	= alchemy_ehci_power_on,
151*4882a593Smuzhiyun 	.power_off	= alchemy_ehci_power_off,
152*4882a593Smuzhiyun 	.power_suspend	= alchemy_ehci_power_off,
153*4882a593Smuzhiyun };
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun /* Power on callback for the ohci platform driver */
alchemy_ohci_power_on(struct platform_device * pdev)156*4882a593Smuzhiyun static int alchemy_ohci_power_on(struct platform_device *pdev)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	int unit;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	unit = (pdev->id == 1) ?
161*4882a593Smuzhiyun 		ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	return alchemy_usb_control(unit, 1);
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun /* Power off/suspend callback for the ohci platform driver */
alchemy_ohci_power_off(struct platform_device * pdev)167*4882a593Smuzhiyun static void alchemy_ohci_power_off(struct platform_device *pdev)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun 	int unit;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	unit = (pdev->id == 1) ?
172*4882a593Smuzhiyun 		ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	alchemy_usb_control(unit, 0);
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun static struct usb_ohci_pdata alchemy_ohci_pdata = {
178*4882a593Smuzhiyun 	.power_on		= alchemy_ohci_power_on,
179*4882a593Smuzhiyun 	.power_off		= alchemy_ohci_power_off,
180*4882a593Smuzhiyun 	.power_suspend		= alchemy_ohci_power_off,
181*4882a593Smuzhiyun };
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun static unsigned long alchemy_ohci_data[][2] __initdata = {
184*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1000] = { AU1000_USB_OHCI_PHYS_ADDR, AU1000_USB_HOST_INT },
185*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1500] = { AU1000_USB_OHCI_PHYS_ADDR, AU1500_USB_HOST_INT },
186*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1100] = { AU1000_USB_OHCI_PHYS_ADDR, AU1100_USB_HOST_INT },
187*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1550] = { AU1550_USB_OHCI_PHYS_ADDR, AU1550_USB_HOST_INT },
188*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1200] = { AU1200_USB_OHCI_PHYS_ADDR, AU1200_USB_INT },
189*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1300] = { AU1300_USB_OHCI0_PHYS_ADDR, AU1300_USB_INT },
190*4882a593Smuzhiyun };
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun static unsigned long alchemy_ehci_data[][2] __initdata = {
193*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1200] = { AU1200_USB_EHCI_PHYS_ADDR, AU1200_USB_INT },
194*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1300] = { AU1300_USB_EHCI_PHYS_ADDR, AU1300_USB_INT },
195*4882a593Smuzhiyun };
196*4882a593Smuzhiyun 
_new_usbres(struct resource ** r,struct platform_device ** d)197*4882a593Smuzhiyun static int __init _new_usbres(struct resource **r, struct platform_device **d)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun 	*r = kcalloc(2, sizeof(struct resource), GFP_KERNEL);
200*4882a593Smuzhiyun 	if (!*r)
201*4882a593Smuzhiyun 		return -ENOMEM;
202*4882a593Smuzhiyun 	*d = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
203*4882a593Smuzhiyun 	if (!*d) {
204*4882a593Smuzhiyun 		kfree(*r);
205*4882a593Smuzhiyun 		return -ENOMEM;
206*4882a593Smuzhiyun 	}
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	(*d)->dev.coherent_dma_mask = DMA_BIT_MASK(32);
209*4882a593Smuzhiyun 	(*d)->num_resources = 2;
210*4882a593Smuzhiyun 	(*d)->resource = *r;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	return 0;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun 
alchemy_setup_usb(int ctype)215*4882a593Smuzhiyun static void __init alchemy_setup_usb(int ctype)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun 	struct resource *res;
218*4882a593Smuzhiyun 	struct platform_device *pdev;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	/* setup OHCI0.  Every variant has one */
221*4882a593Smuzhiyun 	if (_new_usbres(&res, &pdev))
222*4882a593Smuzhiyun 		return;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	res[0].start = alchemy_ohci_data[ctype][0];
225*4882a593Smuzhiyun 	res[0].end = res[0].start + 0x100 - 1;
226*4882a593Smuzhiyun 	res[0].flags = IORESOURCE_MEM;
227*4882a593Smuzhiyun 	res[1].start = alchemy_ohci_data[ctype][1];
228*4882a593Smuzhiyun 	res[1].end = res[1].start;
229*4882a593Smuzhiyun 	res[1].flags = IORESOURCE_IRQ;
230*4882a593Smuzhiyun 	pdev->name = "ohci-platform";
231*4882a593Smuzhiyun 	pdev->id = 0;
232*4882a593Smuzhiyun 	pdev->dev.dma_mask = &alchemy_all_dmamask;
233*4882a593Smuzhiyun 	pdev->dev.platform_data = &alchemy_ohci_pdata;
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	if (platform_device_register(pdev))
236*4882a593Smuzhiyun 		printk(KERN_INFO "Alchemy USB: cannot add OHCI0\n");
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	/* setup EHCI0: Au1200/Au1300 */
240*4882a593Smuzhiyun 	if ((ctype == ALCHEMY_CPU_AU1200) || (ctype == ALCHEMY_CPU_AU1300)) {
241*4882a593Smuzhiyun 		if (_new_usbres(&res, &pdev))
242*4882a593Smuzhiyun 			return;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 		res[0].start = alchemy_ehci_data[ctype][0];
245*4882a593Smuzhiyun 		res[0].end = res[0].start + 0x100 - 1;
246*4882a593Smuzhiyun 		res[0].flags = IORESOURCE_MEM;
247*4882a593Smuzhiyun 		res[1].start = alchemy_ehci_data[ctype][1];
248*4882a593Smuzhiyun 		res[1].end = res[1].start;
249*4882a593Smuzhiyun 		res[1].flags = IORESOURCE_IRQ;
250*4882a593Smuzhiyun 		pdev->name = "ehci-platform";
251*4882a593Smuzhiyun 		pdev->id = 0;
252*4882a593Smuzhiyun 		pdev->dev.dma_mask = &alchemy_all_dmamask;
253*4882a593Smuzhiyun 		pdev->dev.platform_data = &alchemy_ehci_pdata;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 		if (platform_device_register(pdev))
256*4882a593Smuzhiyun 			printk(KERN_INFO "Alchemy USB: cannot add EHCI0\n");
257*4882a593Smuzhiyun 	}
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	/* Au1300: OHCI1 */
260*4882a593Smuzhiyun 	if (ctype == ALCHEMY_CPU_AU1300) {
261*4882a593Smuzhiyun 		if (_new_usbres(&res, &pdev))
262*4882a593Smuzhiyun 			return;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 		res[0].start = AU1300_USB_OHCI1_PHYS_ADDR;
265*4882a593Smuzhiyun 		res[0].end = res[0].start + 0x100 - 1;
266*4882a593Smuzhiyun 		res[0].flags = IORESOURCE_MEM;
267*4882a593Smuzhiyun 		res[1].start = AU1300_USB_INT;
268*4882a593Smuzhiyun 		res[1].end = res[1].start;
269*4882a593Smuzhiyun 		res[1].flags = IORESOURCE_IRQ;
270*4882a593Smuzhiyun 		pdev->name = "ohci-platform";
271*4882a593Smuzhiyun 		pdev->id = 1;
272*4882a593Smuzhiyun 		pdev->dev.dma_mask = &alchemy_all_dmamask;
273*4882a593Smuzhiyun 		pdev->dev.platform_data = &alchemy_ohci_pdata;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 		if (platform_device_register(pdev))
276*4882a593Smuzhiyun 			printk(KERN_INFO "Alchemy USB: cannot add OHCI1\n");
277*4882a593Smuzhiyun 	}
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun /* Macro to help defining the Ethernet MAC resources */
281*4882a593Smuzhiyun #define MAC_RES_COUNT	4	/* MAC regs, MAC en, MAC INT, MACDMA regs */
282*4882a593Smuzhiyun #define MAC_RES(_base, _enable, _irq, _macdma)		\
283*4882a593Smuzhiyun 	{						\
284*4882a593Smuzhiyun 		.start	= _base,			\
285*4882a593Smuzhiyun 		.end	= _base + 0xffff,		\
286*4882a593Smuzhiyun 		.flags	= IORESOURCE_MEM,		\
287*4882a593Smuzhiyun 	},						\
288*4882a593Smuzhiyun 	{						\
289*4882a593Smuzhiyun 		.start	= _enable,			\
290*4882a593Smuzhiyun 		.end	= _enable + 0x3,		\
291*4882a593Smuzhiyun 		.flags	= IORESOURCE_MEM,		\
292*4882a593Smuzhiyun 	},						\
293*4882a593Smuzhiyun 	{						\
294*4882a593Smuzhiyun 		.start	= _irq,				\
295*4882a593Smuzhiyun 		.end	= _irq,				\
296*4882a593Smuzhiyun 		.flags	= IORESOURCE_IRQ		\
297*4882a593Smuzhiyun 	},						\
298*4882a593Smuzhiyun 	{						\
299*4882a593Smuzhiyun 		.start	= _macdma,			\
300*4882a593Smuzhiyun 		.end	= _macdma + 0x1ff,		\
301*4882a593Smuzhiyun 		.flags	= IORESOURCE_MEM,		\
302*4882a593Smuzhiyun 	}
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun static struct resource au1xxx_eth0_resources[][MAC_RES_COUNT] __initdata = {
305*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1000] = {
306*4882a593Smuzhiyun 		MAC_RES(AU1000_MAC0_PHYS_ADDR,
307*4882a593Smuzhiyun 			AU1000_MACEN_PHYS_ADDR,
308*4882a593Smuzhiyun 			AU1000_MAC0_DMA_INT,
309*4882a593Smuzhiyun 			AU1000_MACDMA0_PHYS_ADDR)
310*4882a593Smuzhiyun 	},
311*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1500] = {
312*4882a593Smuzhiyun 		MAC_RES(AU1500_MAC0_PHYS_ADDR,
313*4882a593Smuzhiyun 			AU1500_MACEN_PHYS_ADDR,
314*4882a593Smuzhiyun 			AU1500_MAC0_DMA_INT,
315*4882a593Smuzhiyun 			AU1000_MACDMA0_PHYS_ADDR)
316*4882a593Smuzhiyun 	},
317*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1100] = {
318*4882a593Smuzhiyun 		MAC_RES(AU1000_MAC0_PHYS_ADDR,
319*4882a593Smuzhiyun 			AU1000_MACEN_PHYS_ADDR,
320*4882a593Smuzhiyun 			AU1100_MAC0_DMA_INT,
321*4882a593Smuzhiyun 			AU1000_MACDMA0_PHYS_ADDR)
322*4882a593Smuzhiyun 	},
323*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1550] = {
324*4882a593Smuzhiyun 		MAC_RES(AU1000_MAC0_PHYS_ADDR,
325*4882a593Smuzhiyun 			AU1000_MACEN_PHYS_ADDR,
326*4882a593Smuzhiyun 			AU1550_MAC0_DMA_INT,
327*4882a593Smuzhiyun 			AU1000_MACDMA0_PHYS_ADDR)
328*4882a593Smuzhiyun 	},
329*4882a593Smuzhiyun };
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun static struct au1000_eth_platform_data au1xxx_eth0_platform_data = {
332*4882a593Smuzhiyun 	.phy1_search_mac0 = 1,
333*4882a593Smuzhiyun };
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun static struct platform_device au1xxx_eth0_device = {
336*4882a593Smuzhiyun 	.name		= "au1000-eth",
337*4882a593Smuzhiyun 	.id		= 0,
338*4882a593Smuzhiyun 	.num_resources	= MAC_RES_COUNT,
339*4882a593Smuzhiyun 	.dev = {
340*4882a593Smuzhiyun 		.dma_mask               = &alchemy_all_dmamask,
341*4882a593Smuzhiyun 		.coherent_dma_mask      = DMA_BIT_MASK(32),
342*4882a593Smuzhiyun 		.platform_data          = &au1xxx_eth0_platform_data,
343*4882a593Smuzhiyun 	},
344*4882a593Smuzhiyun };
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun static struct resource au1xxx_eth1_resources[][MAC_RES_COUNT] __initdata = {
347*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1000] = {
348*4882a593Smuzhiyun 		MAC_RES(AU1000_MAC1_PHYS_ADDR,
349*4882a593Smuzhiyun 			AU1000_MACEN_PHYS_ADDR + 4,
350*4882a593Smuzhiyun 			AU1000_MAC1_DMA_INT,
351*4882a593Smuzhiyun 			AU1000_MACDMA1_PHYS_ADDR)
352*4882a593Smuzhiyun 	},
353*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1500] = {
354*4882a593Smuzhiyun 		MAC_RES(AU1500_MAC1_PHYS_ADDR,
355*4882a593Smuzhiyun 			AU1500_MACEN_PHYS_ADDR + 4,
356*4882a593Smuzhiyun 			AU1500_MAC1_DMA_INT,
357*4882a593Smuzhiyun 			AU1000_MACDMA1_PHYS_ADDR)
358*4882a593Smuzhiyun 	},
359*4882a593Smuzhiyun 	[ALCHEMY_CPU_AU1550] = {
360*4882a593Smuzhiyun 		MAC_RES(AU1000_MAC1_PHYS_ADDR,
361*4882a593Smuzhiyun 			AU1000_MACEN_PHYS_ADDR + 4,
362*4882a593Smuzhiyun 			AU1550_MAC1_DMA_INT,
363*4882a593Smuzhiyun 			AU1000_MACDMA1_PHYS_ADDR)
364*4882a593Smuzhiyun 	},
365*4882a593Smuzhiyun };
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun static struct au1000_eth_platform_data au1xxx_eth1_platform_data = {
368*4882a593Smuzhiyun 	.phy1_search_mac0 = 1,
369*4882a593Smuzhiyun };
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun static struct platform_device au1xxx_eth1_device = {
372*4882a593Smuzhiyun 	.name		= "au1000-eth",
373*4882a593Smuzhiyun 	.id		= 1,
374*4882a593Smuzhiyun 	.num_resources	= MAC_RES_COUNT,
375*4882a593Smuzhiyun 	.dev = {
376*4882a593Smuzhiyun 		.dma_mask               = &alchemy_all_dmamask,
377*4882a593Smuzhiyun 		.coherent_dma_mask      = DMA_BIT_MASK(32),
378*4882a593Smuzhiyun 		.platform_data          = &au1xxx_eth1_platform_data,
379*4882a593Smuzhiyun 	},
380*4882a593Smuzhiyun };
381*4882a593Smuzhiyun 
au1xxx_override_eth_cfg(unsigned int port,struct au1000_eth_platform_data * eth_data)382*4882a593Smuzhiyun void __init au1xxx_override_eth_cfg(unsigned int port,
383*4882a593Smuzhiyun 			struct au1000_eth_platform_data *eth_data)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun 	if (!eth_data || port > 1)
386*4882a593Smuzhiyun 		return;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	if (port == 0)
389*4882a593Smuzhiyun 		memcpy(&au1xxx_eth0_platform_data, eth_data,
390*4882a593Smuzhiyun 			sizeof(struct au1000_eth_platform_data));
391*4882a593Smuzhiyun 	else
392*4882a593Smuzhiyun 		memcpy(&au1xxx_eth1_platform_data, eth_data,
393*4882a593Smuzhiyun 			sizeof(struct au1000_eth_platform_data));
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun 
alchemy_setup_macs(int ctype)396*4882a593Smuzhiyun static void __init alchemy_setup_macs(int ctype)
397*4882a593Smuzhiyun {
398*4882a593Smuzhiyun 	int ret, i;
399*4882a593Smuzhiyun 	unsigned char ethaddr[6];
400*4882a593Smuzhiyun 	struct resource *macres;
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	/* Handle 1st MAC */
403*4882a593Smuzhiyun 	if (alchemy_get_macs(ctype) < 1)
404*4882a593Smuzhiyun 		return;
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 	macres = kmemdup(au1xxx_eth0_resources[ctype],
407*4882a593Smuzhiyun 			 sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL);
408*4882a593Smuzhiyun 	if (!macres) {
409*4882a593Smuzhiyun 		printk(KERN_INFO "Alchemy: no memory for MAC0 resources\n");
410*4882a593Smuzhiyun 		return;
411*4882a593Smuzhiyun 	}
412*4882a593Smuzhiyun 	au1xxx_eth0_device.resource = macres;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	i = prom_get_ethernet_addr(ethaddr);
415*4882a593Smuzhiyun 	if (!i && !is_valid_ether_addr(au1xxx_eth0_platform_data.mac))
416*4882a593Smuzhiyun 		memcpy(au1xxx_eth0_platform_data.mac, ethaddr, 6);
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	ret = platform_device_register(&au1xxx_eth0_device);
419*4882a593Smuzhiyun 	if (ret)
420*4882a593Smuzhiyun 		printk(KERN_INFO "Alchemy: failed to register MAC0\n");
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	/* Handle 2nd MAC */
424*4882a593Smuzhiyun 	if (alchemy_get_macs(ctype) < 2)
425*4882a593Smuzhiyun 		return;
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	macres = kmemdup(au1xxx_eth1_resources[ctype],
428*4882a593Smuzhiyun 			 sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL);
429*4882a593Smuzhiyun 	if (!macres) {
430*4882a593Smuzhiyun 		printk(KERN_INFO "Alchemy: no memory for MAC1 resources\n");
431*4882a593Smuzhiyun 		return;
432*4882a593Smuzhiyun 	}
433*4882a593Smuzhiyun 	au1xxx_eth1_device.resource = macres;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	ethaddr[5] += 1;	/* next addr for 2nd MAC */
436*4882a593Smuzhiyun 	if (!i && !is_valid_ether_addr(au1xxx_eth1_platform_data.mac))
437*4882a593Smuzhiyun 		memcpy(au1xxx_eth1_platform_data.mac, ethaddr, 6);
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	/* Register second MAC if enabled in pinfunc */
440*4882a593Smuzhiyun 	if (!(alchemy_rdsys(AU1000_SYS_PINFUNC) & SYS_PF_NI2)) {
441*4882a593Smuzhiyun 		ret = platform_device_register(&au1xxx_eth1_device);
442*4882a593Smuzhiyun 		if (ret)
443*4882a593Smuzhiyun 			printk(KERN_INFO "Alchemy: failed to register MAC1\n");
444*4882a593Smuzhiyun 	}
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun 
au1xxx_platform_init(void)447*4882a593Smuzhiyun static int __init au1xxx_platform_init(void)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun 	int ctype = alchemy_get_cputype();
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	alchemy_setup_uarts(ctype);
452*4882a593Smuzhiyun 	alchemy_setup_macs(ctype);
453*4882a593Smuzhiyun 	alchemy_setup_usb(ctype);
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	return 0;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun arch_initcall(au1xxx_platform_init);
459