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