18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Platform device support for Au1x00 SoCs. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright 2004, Matt Porter <mporter@kernel.crashing.org> 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * (C) Copyright Embedded Alley Solutions, Inc 2005 78c2ecf20Sopenharmony_ci * Author: Pantelis Antoniou <pantelis@embeddedalley.com> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This file is licensed under the terms of the GNU General Public 108c2ecf20Sopenharmony_ci * License version 2. This program is licensed "as is" without any 118c2ecf20Sopenharmony_ci * warranty of any kind, whether express or implied. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/clk.h> 158c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 168c2ecf20Sopenharmony_ci#include <linux/etherdevice.h> 178c2ecf20Sopenharmony_ci#include <linux/init.h> 188c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 198c2ecf20Sopenharmony_ci#include <linux/serial_8250.h> 208c2ecf20Sopenharmony_ci#include <linux/slab.h> 218c2ecf20Sopenharmony_ci#include <linux/usb/ehci_pdriver.h> 228c2ecf20Sopenharmony_ci#include <linux/usb/ohci_pdriver.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include <asm/mach-au1x00/au1000.h> 258c2ecf20Sopenharmony_ci#include <asm/mach-au1x00/au1xxx_dbdma.h> 268c2ecf20Sopenharmony_ci#include <asm/mach-au1x00/au1100_mmc.h> 278c2ecf20Sopenharmony_ci#include <asm/mach-au1x00/au1xxx_eth.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <prom.h> 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic void alchemy_8250_pm(struct uart_port *port, unsigned int state, 328c2ecf20Sopenharmony_ci unsigned int old_state) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci#ifdef CONFIG_SERIAL_8250 358c2ecf20Sopenharmony_ci switch (state) { 368c2ecf20Sopenharmony_ci case 0: 378c2ecf20Sopenharmony_ci alchemy_uart_enable(CPHYSADDR(port->membase)); 388c2ecf20Sopenharmony_ci serial8250_do_pm(port, state, old_state); 398c2ecf20Sopenharmony_ci break; 408c2ecf20Sopenharmony_ci case 3: /* power off */ 418c2ecf20Sopenharmony_ci serial8250_do_pm(port, state, old_state); 428c2ecf20Sopenharmony_ci alchemy_uart_disable(CPHYSADDR(port->membase)); 438c2ecf20Sopenharmony_ci break; 448c2ecf20Sopenharmony_ci default: 458c2ecf20Sopenharmony_ci serial8250_do_pm(port, state, old_state); 468c2ecf20Sopenharmony_ci break; 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci#endif 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#define PORT(_base, _irq) \ 528c2ecf20Sopenharmony_ci { \ 538c2ecf20Sopenharmony_ci .mapbase = _base, \ 548c2ecf20Sopenharmony_ci .irq = _irq, \ 558c2ecf20Sopenharmony_ci .regshift = 2, \ 568c2ecf20Sopenharmony_ci .iotype = UPIO_AU, \ 578c2ecf20Sopenharmony_ci .flags = UPF_SKIP_TEST | UPF_IOREMAP | \ 588c2ecf20Sopenharmony_ci UPF_FIXED_TYPE, \ 598c2ecf20Sopenharmony_ci .type = PORT_16550A, \ 608c2ecf20Sopenharmony_ci .pm = alchemy_8250_pm, \ 618c2ecf20Sopenharmony_ci } 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic struct plat_serial8250_port au1x00_uart_data[][4] __initdata = { 648c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1000] = { 658c2ecf20Sopenharmony_ci PORT(AU1000_UART0_PHYS_ADDR, AU1000_UART0_INT), 668c2ecf20Sopenharmony_ci PORT(AU1000_UART1_PHYS_ADDR, AU1000_UART1_INT), 678c2ecf20Sopenharmony_ci PORT(AU1000_UART2_PHYS_ADDR, AU1000_UART2_INT), 688c2ecf20Sopenharmony_ci PORT(AU1000_UART3_PHYS_ADDR, AU1000_UART3_INT), 698c2ecf20Sopenharmony_ci }, 708c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1500] = { 718c2ecf20Sopenharmony_ci PORT(AU1000_UART0_PHYS_ADDR, AU1500_UART0_INT), 728c2ecf20Sopenharmony_ci PORT(AU1000_UART3_PHYS_ADDR, AU1500_UART3_INT), 738c2ecf20Sopenharmony_ci }, 748c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1100] = { 758c2ecf20Sopenharmony_ci PORT(AU1000_UART0_PHYS_ADDR, AU1100_UART0_INT), 768c2ecf20Sopenharmony_ci PORT(AU1000_UART1_PHYS_ADDR, AU1100_UART1_INT), 778c2ecf20Sopenharmony_ci PORT(AU1000_UART3_PHYS_ADDR, AU1100_UART3_INT), 788c2ecf20Sopenharmony_ci }, 798c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1550] = { 808c2ecf20Sopenharmony_ci PORT(AU1000_UART0_PHYS_ADDR, AU1550_UART0_INT), 818c2ecf20Sopenharmony_ci PORT(AU1000_UART1_PHYS_ADDR, AU1550_UART1_INT), 828c2ecf20Sopenharmony_ci PORT(AU1000_UART3_PHYS_ADDR, AU1550_UART3_INT), 838c2ecf20Sopenharmony_ci }, 848c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1200] = { 858c2ecf20Sopenharmony_ci PORT(AU1000_UART0_PHYS_ADDR, AU1200_UART0_INT), 868c2ecf20Sopenharmony_ci PORT(AU1000_UART1_PHYS_ADDR, AU1200_UART1_INT), 878c2ecf20Sopenharmony_ci }, 888c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1300] = { 898c2ecf20Sopenharmony_ci PORT(AU1300_UART0_PHYS_ADDR, AU1300_UART0_INT), 908c2ecf20Sopenharmony_ci PORT(AU1300_UART1_PHYS_ADDR, AU1300_UART1_INT), 918c2ecf20Sopenharmony_ci PORT(AU1300_UART2_PHYS_ADDR, AU1300_UART2_INT), 928c2ecf20Sopenharmony_ci PORT(AU1300_UART3_PHYS_ADDR, AU1300_UART3_INT), 938c2ecf20Sopenharmony_ci }, 948c2ecf20Sopenharmony_ci}; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic struct platform_device au1xx0_uart_device = { 978c2ecf20Sopenharmony_ci .name = "serial8250", 988c2ecf20Sopenharmony_ci .id = PLAT8250_DEV_AU1X00, 998c2ecf20Sopenharmony_ci}; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistatic void __init alchemy_setup_uarts(int ctype) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci long uartclk; 1048c2ecf20Sopenharmony_ci int s = sizeof(struct plat_serial8250_port); 1058c2ecf20Sopenharmony_ci int c = alchemy_get_uarts(ctype); 1068c2ecf20Sopenharmony_ci struct plat_serial8250_port *ports; 1078c2ecf20Sopenharmony_ci struct clk *clk = clk_get(NULL, ALCHEMY_PERIPH_CLK); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci if (IS_ERR(clk)) 1108c2ecf20Sopenharmony_ci return; 1118c2ecf20Sopenharmony_ci if (clk_prepare_enable(clk)) { 1128c2ecf20Sopenharmony_ci clk_put(clk); 1138c2ecf20Sopenharmony_ci return; 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci uartclk = clk_get_rate(clk); 1168c2ecf20Sopenharmony_ci clk_put(clk); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci ports = kcalloc(s, (c + 1), GFP_KERNEL); 1198c2ecf20Sopenharmony_ci if (!ports) { 1208c2ecf20Sopenharmony_ci printk(KERN_INFO "Alchemy: no memory for UART data\n"); 1218c2ecf20Sopenharmony_ci return; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci memcpy(ports, au1x00_uart_data[ctype], s * c); 1248c2ecf20Sopenharmony_ci au1xx0_uart_device.dev.platform_data = ports; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* Fill up uartclk. */ 1278c2ecf20Sopenharmony_ci for (s = 0; s < c; s++) 1288c2ecf20Sopenharmony_ci ports[s].uartclk = uartclk; 1298c2ecf20Sopenharmony_ci if (platform_device_register(&au1xx0_uart_device)) 1308c2ecf20Sopenharmony_ci printk(KERN_INFO "Alchemy: failed to register UARTs\n"); 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic u64 alchemy_all_dmamask = DMA_BIT_MASK(32); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci/* Power on callback for the ehci platform driver */ 1378c2ecf20Sopenharmony_cistatic int alchemy_ehci_power_on(struct platform_device *pdev) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci return alchemy_usb_control(ALCHEMY_USB_EHCI0, 1); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci/* Power off/suspend callback for the ehci platform driver */ 1438c2ecf20Sopenharmony_cistatic void alchemy_ehci_power_off(struct platform_device *pdev) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); 1468c2ecf20Sopenharmony_ci} 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistatic struct usb_ehci_pdata alchemy_ehci_pdata = { 1498c2ecf20Sopenharmony_ci .no_io_watchdog = 1, 1508c2ecf20Sopenharmony_ci .power_on = alchemy_ehci_power_on, 1518c2ecf20Sopenharmony_ci .power_off = alchemy_ehci_power_off, 1528c2ecf20Sopenharmony_ci .power_suspend = alchemy_ehci_power_off, 1538c2ecf20Sopenharmony_ci}; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci/* Power on callback for the ohci platform driver */ 1568c2ecf20Sopenharmony_cistatic int alchemy_ohci_power_on(struct platform_device *pdev) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci int unit; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci unit = (pdev->id == 1) ? 1618c2ecf20Sopenharmony_ci ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci return alchemy_usb_control(unit, 1); 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci/* Power off/suspend callback for the ohci platform driver */ 1678c2ecf20Sopenharmony_cistatic void alchemy_ohci_power_off(struct platform_device *pdev) 1688c2ecf20Sopenharmony_ci{ 1698c2ecf20Sopenharmony_ci int unit; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci unit = (pdev->id == 1) ? 1728c2ecf20Sopenharmony_ci ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci alchemy_usb_control(unit, 0); 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistatic struct usb_ohci_pdata alchemy_ohci_pdata = { 1788c2ecf20Sopenharmony_ci .power_on = alchemy_ohci_power_on, 1798c2ecf20Sopenharmony_ci .power_off = alchemy_ohci_power_off, 1808c2ecf20Sopenharmony_ci .power_suspend = alchemy_ohci_power_off, 1818c2ecf20Sopenharmony_ci}; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic unsigned long alchemy_ohci_data[][2] __initdata = { 1848c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1000] = { AU1000_USB_OHCI_PHYS_ADDR, AU1000_USB_HOST_INT }, 1858c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1500] = { AU1000_USB_OHCI_PHYS_ADDR, AU1500_USB_HOST_INT }, 1868c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1100] = { AU1000_USB_OHCI_PHYS_ADDR, AU1100_USB_HOST_INT }, 1878c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1550] = { AU1550_USB_OHCI_PHYS_ADDR, AU1550_USB_HOST_INT }, 1888c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1200] = { AU1200_USB_OHCI_PHYS_ADDR, AU1200_USB_INT }, 1898c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1300] = { AU1300_USB_OHCI0_PHYS_ADDR, AU1300_USB_INT }, 1908c2ecf20Sopenharmony_ci}; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_cistatic unsigned long alchemy_ehci_data[][2] __initdata = { 1938c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1200] = { AU1200_USB_EHCI_PHYS_ADDR, AU1200_USB_INT }, 1948c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1300] = { AU1300_USB_EHCI_PHYS_ADDR, AU1300_USB_INT }, 1958c2ecf20Sopenharmony_ci}; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic int __init _new_usbres(struct resource **r, struct platform_device **d) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci *r = kcalloc(2, sizeof(struct resource), GFP_KERNEL); 2008c2ecf20Sopenharmony_ci if (!*r) 2018c2ecf20Sopenharmony_ci return -ENOMEM; 2028c2ecf20Sopenharmony_ci *d = kzalloc(sizeof(struct platform_device), GFP_KERNEL); 2038c2ecf20Sopenharmony_ci if (!*d) { 2048c2ecf20Sopenharmony_ci kfree(*r); 2058c2ecf20Sopenharmony_ci return -ENOMEM; 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci (*d)->dev.coherent_dma_mask = DMA_BIT_MASK(32); 2098c2ecf20Sopenharmony_ci (*d)->num_resources = 2; 2108c2ecf20Sopenharmony_ci (*d)->resource = *r; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci return 0; 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic void __init alchemy_setup_usb(int ctype) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci struct resource *res; 2188c2ecf20Sopenharmony_ci struct platform_device *pdev; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci /* setup OHCI0. Every variant has one */ 2218c2ecf20Sopenharmony_ci if (_new_usbres(&res, &pdev)) 2228c2ecf20Sopenharmony_ci return; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci res[0].start = alchemy_ohci_data[ctype][0]; 2258c2ecf20Sopenharmony_ci res[0].end = res[0].start + 0x100 - 1; 2268c2ecf20Sopenharmony_ci res[0].flags = IORESOURCE_MEM; 2278c2ecf20Sopenharmony_ci res[1].start = alchemy_ohci_data[ctype][1]; 2288c2ecf20Sopenharmony_ci res[1].end = res[1].start; 2298c2ecf20Sopenharmony_ci res[1].flags = IORESOURCE_IRQ; 2308c2ecf20Sopenharmony_ci pdev->name = "ohci-platform"; 2318c2ecf20Sopenharmony_ci pdev->id = 0; 2328c2ecf20Sopenharmony_ci pdev->dev.dma_mask = &alchemy_all_dmamask; 2338c2ecf20Sopenharmony_ci pdev->dev.platform_data = &alchemy_ohci_pdata; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci if (platform_device_register(pdev)) 2368c2ecf20Sopenharmony_ci printk(KERN_INFO "Alchemy USB: cannot add OHCI0\n"); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci /* setup EHCI0: Au1200/Au1300 */ 2408c2ecf20Sopenharmony_ci if ((ctype == ALCHEMY_CPU_AU1200) || (ctype == ALCHEMY_CPU_AU1300)) { 2418c2ecf20Sopenharmony_ci if (_new_usbres(&res, &pdev)) 2428c2ecf20Sopenharmony_ci return; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci res[0].start = alchemy_ehci_data[ctype][0]; 2458c2ecf20Sopenharmony_ci res[0].end = res[0].start + 0x100 - 1; 2468c2ecf20Sopenharmony_ci res[0].flags = IORESOURCE_MEM; 2478c2ecf20Sopenharmony_ci res[1].start = alchemy_ehci_data[ctype][1]; 2488c2ecf20Sopenharmony_ci res[1].end = res[1].start; 2498c2ecf20Sopenharmony_ci res[1].flags = IORESOURCE_IRQ; 2508c2ecf20Sopenharmony_ci pdev->name = "ehci-platform"; 2518c2ecf20Sopenharmony_ci pdev->id = 0; 2528c2ecf20Sopenharmony_ci pdev->dev.dma_mask = &alchemy_all_dmamask; 2538c2ecf20Sopenharmony_ci pdev->dev.platform_data = &alchemy_ehci_pdata; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci if (platform_device_register(pdev)) 2568c2ecf20Sopenharmony_ci printk(KERN_INFO "Alchemy USB: cannot add EHCI0\n"); 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci /* Au1300: OHCI1 */ 2608c2ecf20Sopenharmony_ci if (ctype == ALCHEMY_CPU_AU1300) { 2618c2ecf20Sopenharmony_ci if (_new_usbres(&res, &pdev)) 2628c2ecf20Sopenharmony_ci return; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci res[0].start = AU1300_USB_OHCI1_PHYS_ADDR; 2658c2ecf20Sopenharmony_ci res[0].end = res[0].start + 0x100 - 1; 2668c2ecf20Sopenharmony_ci res[0].flags = IORESOURCE_MEM; 2678c2ecf20Sopenharmony_ci res[1].start = AU1300_USB_INT; 2688c2ecf20Sopenharmony_ci res[1].end = res[1].start; 2698c2ecf20Sopenharmony_ci res[1].flags = IORESOURCE_IRQ; 2708c2ecf20Sopenharmony_ci pdev->name = "ohci-platform"; 2718c2ecf20Sopenharmony_ci pdev->id = 1; 2728c2ecf20Sopenharmony_ci pdev->dev.dma_mask = &alchemy_all_dmamask; 2738c2ecf20Sopenharmony_ci pdev->dev.platform_data = &alchemy_ohci_pdata; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci if (platform_device_register(pdev)) 2768c2ecf20Sopenharmony_ci printk(KERN_INFO "Alchemy USB: cannot add OHCI1\n"); 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci} 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci/* Macro to help defining the Ethernet MAC resources */ 2818c2ecf20Sopenharmony_ci#define MAC_RES_COUNT 4 /* MAC regs, MAC en, MAC INT, MACDMA regs */ 2828c2ecf20Sopenharmony_ci#define MAC_RES(_base, _enable, _irq, _macdma) \ 2838c2ecf20Sopenharmony_ci { \ 2848c2ecf20Sopenharmony_ci .start = _base, \ 2858c2ecf20Sopenharmony_ci .end = _base + 0xffff, \ 2868c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM, \ 2878c2ecf20Sopenharmony_ci }, \ 2888c2ecf20Sopenharmony_ci { \ 2898c2ecf20Sopenharmony_ci .start = _enable, \ 2908c2ecf20Sopenharmony_ci .end = _enable + 0x3, \ 2918c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM, \ 2928c2ecf20Sopenharmony_ci }, \ 2938c2ecf20Sopenharmony_ci { \ 2948c2ecf20Sopenharmony_ci .start = _irq, \ 2958c2ecf20Sopenharmony_ci .end = _irq, \ 2968c2ecf20Sopenharmony_ci .flags = IORESOURCE_IRQ \ 2978c2ecf20Sopenharmony_ci }, \ 2988c2ecf20Sopenharmony_ci { \ 2998c2ecf20Sopenharmony_ci .start = _macdma, \ 3008c2ecf20Sopenharmony_ci .end = _macdma + 0x1ff, \ 3018c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM, \ 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic struct resource au1xxx_eth0_resources[][MAC_RES_COUNT] __initdata = { 3058c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1000] = { 3068c2ecf20Sopenharmony_ci MAC_RES(AU1000_MAC0_PHYS_ADDR, 3078c2ecf20Sopenharmony_ci AU1000_MACEN_PHYS_ADDR, 3088c2ecf20Sopenharmony_ci AU1000_MAC0_DMA_INT, 3098c2ecf20Sopenharmony_ci AU1000_MACDMA0_PHYS_ADDR) 3108c2ecf20Sopenharmony_ci }, 3118c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1500] = { 3128c2ecf20Sopenharmony_ci MAC_RES(AU1500_MAC0_PHYS_ADDR, 3138c2ecf20Sopenharmony_ci AU1500_MACEN_PHYS_ADDR, 3148c2ecf20Sopenharmony_ci AU1500_MAC0_DMA_INT, 3158c2ecf20Sopenharmony_ci AU1000_MACDMA0_PHYS_ADDR) 3168c2ecf20Sopenharmony_ci }, 3178c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1100] = { 3188c2ecf20Sopenharmony_ci MAC_RES(AU1000_MAC0_PHYS_ADDR, 3198c2ecf20Sopenharmony_ci AU1000_MACEN_PHYS_ADDR, 3208c2ecf20Sopenharmony_ci AU1100_MAC0_DMA_INT, 3218c2ecf20Sopenharmony_ci AU1000_MACDMA0_PHYS_ADDR) 3228c2ecf20Sopenharmony_ci }, 3238c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1550] = { 3248c2ecf20Sopenharmony_ci MAC_RES(AU1000_MAC0_PHYS_ADDR, 3258c2ecf20Sopenharmony_ci AU1000_MACEN_PHYS_ADDR, 3268c2ecf20Sopenharmony_ci AU1550_MAC0_DMA_INT, 3278c2ecf20Sopenharmony_ci AU1000_MACDMA0_PHYS_ADDR) 3288c2ecf20Sopenharmony_ci }, 3298c2ecf20Sopenharmony_ci}; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_cistatic struct au1000_eth_platform_data au1xxx_eth0_platform_data = { 3328c2ecf20Sopenharmony_ci .phy1_search_mac0 = 1, 3338c2ecf20Sopenharmony_ci}; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic struct platform_device au1xxx_eth0_device = { 3368c2ecf20Sopenharmony_ci .name = "au1000-eth", 3378c2ecf20Sopenharmony_ci .id = 0, 3388c2ecf20Sopenharmony_ci .num_resources = MAC_RES_COUNT, 3398c2ecf20Sopenharmony_ci .dev = { 3408c2ecf20Sopenharmony_ci .dma_mask = &alchemy_all_dmamask, 3418c2ecf20Sopenharmony_ci .coherent_dma_mask = DMA_BIT_MASK(32), 3428c2ecf20Sopenharmony_ci .platform_data = &au1xxx_eth0_platform_data, 3438c2ecf20Sopenharmony_ci }, 3448c2ecf20Sopenharmony_ci}; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_cistatic struct resource au1xxx_eth1_resources[][MAC_RES_COUNT] __initdata = { 3478c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1000] = { 3488c2ecf20Sopenharmony_ci MAC_RES(AU1000_MAC1_PHYS_ADDR, 3498c2ecf20Sopenharmony_ci AU1000_MACEN_PHYS_ADDR + 4, 3508c2ecf20Sopenharmony_ci AU1000_MAC1_DMA_INT, 3518c2ecf20Sopenharmony_ci AU1000_MACDMA1_PHYS_ADDR) 3528c2ecf20Sopenharmony_ci }, 3538c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1500] = { 3548c2ecf20Sopenharmony_ci MAC_RES(AU1500_MAC1_PHYS_ADDR, 3558c2ecf20Sopenharmony_ci AU1500_MACEN_PHYS_ADDR + 4, 3568c2ecf20Sopenharmony_ci AU1500_MAC1_DMA_INT, 3578c2ecf20Sopenharmony_ci AU1000_MACDMA1_PHYS_ADDR) 3588c2ecf20Sopenharmony_ci }, 3598c2ecf20Sopenharmony_ci [ALCHEMY_CPU_AU1550] = { 3608c2ecf20Sopenharmony_ci MAC_RES(AU1000_MAC1_PHYS_ADDR, 3618c2ecf20Sopenharmony_ci AU1000_MACEN_PHYS_ADDR + 4, 3628c2ecf20Sopenharmony_ci AU1550_MAC1_DMA_INT, 3638c2ecf20Sopenharmony_ci AU1000_MACDMA1_PHYS_ADDR) 3648c2ecf20Sopenharmony_ci }, 3658c2ecf20Sopenharmony_ci}; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_cistatic struct au1000_eth_platform_data au1xxx_eth1_platform_data = { 3688c2ecf20Sopenharmony_ci .phy1_search_mac0 = 1, 3698c2ecf20Sopenharmony_ci}; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_cistatic struct platform_device au1xxx_eth1_device = { 3728c2ecf20Sopenharmony_ci .name = "au1000-eth", 3738c2ecf20Sopenharmony_ci .id = 1, 3748c2ecf20Sopenharmony_ci .num_resources = MAC_RES_COUNT, 3758c2ecf20Sopenharmony_ci .dev = { 3768c2ecf20Sopenharmony_ci .dma_mask = &alchemy_all_dmamask, 3778c2ecf20Sopenharmony_ci .coherent_dma_mask = DMA_BIT_MASK(32), 3788c2ecf20Sopenharmony_ci .platform_data = &au1xxx_eth1_platform_data, 3798c2ecf20Sopenharmony_ci }, 3808c2ecf20Sopenharmony_ci}; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_civoid __init au1xxx_override_eth_cfg(unsigned int port, 3838c2ecf20Sopenharmony_ci struct au1000_eth_platform_data *eth_data) 3848c2ecf20Sopenharmony_ci{ 3858c2ecf20Sopenharmony_ci if (!eth_data || port > 1) 3868c2ecf20Sopenharmony_ci return; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci if (port == 0) 3898c2ecf20Sopenharmony_ci memcpy(&au1xxx_eth0_platform_data, eth_data, 3908c2ecf20Sopenharmony_ci sizeof(struct au1000_eth_platform_data)); 3918c2ecf20Sopenharmony_ci else 3928c2ecf20Sopenharmony_ci memcpy(&au1xxx_eth1_platform_data, eth_data, 3938c2ecf20Sopenharmony_ci sizeof(struct au1000_eth_platform_data)); 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_cistatic void __init alchemy_setup_macs(int ctype) 3978c2ecf20Sopenharmony_ci{ 3988c2ecf20Sopenharmony_ci int ret, i; 3998c2ecf20Sopenharmony_ci unsigned char ethaddr[6]; 4008c2ecf20Sopenharmony_ci struct resource *macres; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci /* Handle 1st MAC */ 4038c2ecf20Sopenharmony_ci if (alchemy_get_macs(ctype) < 1) 4048c2ecf20Sopenharmony_ci return; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci macres = kmemdup(au1xxx_eth0_resources[ctype], 4078c2ecf20Sopenharmony_ci sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL); 4088c2ecf20Sopenharmony_ci if (!macres) { 4098c2ecf20Sopenharmony_ci printk(KERN_INFO "Alchemy: no memory for MAC0 resources\n"); 4108c2ecf20Sopenharmony_ci return; 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci au1xxx_eth0_device.resource = macres; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci i = prom_get_ethernet_addr(ethaddr); 4158c2ecf20Sopenharmony_ci if (!i && !is_valid_ether_addr(au1xxx_eth0_platform_data.mac)) 4168c2ecf20Sopenharmony_ci memcpy(au1xxx_eth0_platform_data.mac, ethaddr, 6); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci ret = platform_device_register(&au1xxx_eth0_device); 4198c2ecf20Sopenharmony_ci if (ret) 4208c2ecf20Sopenharmony_ci printk(KERN_INFO "Alchemy: failed to register MAC0\n"); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci /* Handle 2nd MAC */ 4248c2ecf20Sopenharmony_ci if (alchemy_get_macs(ctype) < 2) 4258c2ecf20Sopenharmony_ci return; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci macres = kmemdup(au1xxx_eth1_resources[ctype], 4288c2ecf20Sopenharmony_ci sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL); 4298c2ecf20Sopenharmony_ci if (!macres) { 4308c2ecf20Sopenharmony_ci printk(KERN_INFO "Alchemy: no memory for MAC1 resources\n"); 4318c2ecf20Sopenharmony_ci return; 4328c2ecf20Sopenharmony_ci } 4338c2ecf20Sopenharmony_ci au1xxx_eth1_device.resource = macres; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci ethaddr[5] += 1; /* next addr for 2nd MAC */ 4368c2ecf20Sopenharmony_ci if (!i && !is_valid_ether_addr(au1xxx_eth1_platform_data.mac)) 4378c2ecf20Sopenharmony_ci memcpy(au1xxx_eth1_platform_data.mac, ethaddr, 6); 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci /* Register second MAC if enabled in pinfunc */ 4408c2ecf20Sopenharmony_ci if (!(alchemy_rdsys(AU1000_SYS_PINFUNC) & SYS_PF_NI2)) { 4418c2ecf20Sopenharmony_ci ret = platform_device_register(&au1xxx_eth1_device); 4428c2ecf20Sopenharmony_ci if (ret) 4438c2ecf20Sopenharmony_ci printk(KERN_INFO "Alchemy: failed to register MAC1\n"); 4448c2ecf20Sopenharmony_ci } 4458c2ecf20Sopenharmony_ci} 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_cistatic int __init au1xxx_platform_init(void) 4488c2ecf20Sopenharmony_ci{ 4498c2ecf20Sopenharmony_ci int ctype = alchemy_get_cputype(); 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci alchemy_setup_uarts(ctype); 4528c2ecf20Sopenharmony_ci alchemy_setup_macs(ctype); 4538c2ecf20Sopenharmony_ci alchemy_setup_usb(ctype); 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci return 0; 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ciarch_initcall(au1xxx_platform_init); 459