Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Platform device support for Au1x00 SoCs.
0003  *
0004  * Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
0005  *
0006  * (C) Copyright Embedded Alley Solutions, Inc 2005
0007  * Author: Pantelis Antoniou <pantelis@embeddedalley.com>
0008  *
0009  * This file is licensed under the terms of the GNU General Public
0010  * License version 2.  This program is licensed "as is" without any
0011  * warranty of any kind, whether express or implied.
0012  */
0013 
0014 #include <linux/clk.h>
0015 #include <linux/dma-mapping.h>
0016 #include <linux/etherdevice.h>
0017 #include <linux/init.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/serial_8250.h>
0020 #include <linux/slab.h>
0021 #include <linux/usb/ehci_pdriver.h>
0022 #include <linux/usb/ohci_pdriver.h>
0023 
0024 #include <asm/mach-au1x00/au1000.h>
0025 #include <asm/mach-au1x00/au1xxx_dbdma.h>
0026 #include <asm/mach-au1x00/au1100_mmc.h>
0027 #include <asm/mach-au1x00/au1xxx_eth.h>
0028 
0029 #include <prom.h>
0030 
0031 static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
0032                 unsigned int old_state)
0033 {
0034 #ifdef CONFIG_SERIAL_8250
0035     switch (state) {
0036     case 0:
0037         alchemy_uart_enable(CPHYSADDR(port->membase));
0038         serial8250_do_pm(port, state, old_state);
0039         break;
0040     case 3:     /* power off */
0041         serial8250_do_pm(port, state, old_state);
0042         alchemy_uart_disable(CPHYSADDR(port->membase));
0043         break;
0044     default:
0045         serial8250_do_pm(port, state, old_state);
0046         break;
0047     }
0048 #endif
0049 }
0050 
0051 #define PORT(_base, _irq)                   \
0052     {                           \
0053         .mapbase    = _base,            \
0054         .irq        = _irq,             \
0055         .regshift   = 2,                \
0056         .iotype     = UPIO_AU,          \
0057         .flags      = UPF_SKIP_TEST | UPF_IOREMAP | \
0058                   UPF_FIXED_TYPE,       \
0059         .type       = PORT_16550A,          \
0060         .pm     = alchemy_8250_pm,      \
0061     }
0062 
0063 static struct plat_serial8250_port au1x00_uart_data[][4] __initdata = {
0064     [ALCHEMY_CPU_AU1000] = {
0065         PORT(AU1000_UART0_PHYS_ADDR, AU1000_UART0_INT),
0066         PORT(AU1000_UART1_PHYS_ADDR, AU1000_UART1_INT),
0067         PORT(AU1000_UART2_PHYS_ADDR, AU1000_UART2_INT),
0068         PORT(AU1000_UART3_PHYS_ADDR, AU1000_UART3_INT),
0069     },
0070     [ALCHEMY_CPU_AU1500] = {
0071         PORT(AU1000_UART0_PHYS_ADDR, AU1500_UART0_INT),
0072         PORT(AU1000_UART3_PHYS_ADDR, AU1500_UART3_INT),
0073     },
0074     [ALCHEMY_CPU_AU1100] = {
0075         PORT(AU1000_UART0_PHYS_ADDR, AU1100_UART0_INT),
0076         PORT(AU1000_UART1_PHYS_ADDR, AU1100_UART1_INT),
0077         PORT(AU1000_UART3_PHYS_ADDR, AU1100_UART3_INT),
0078     },
0079     [ALCHEMY_CPU_AU1550] = {
0080         PORT(AU1000_UART0_PHYS_ADDR, AU1550_UART0_INT),
0081         PORT(AU1000_UART1_PHYS_ADDR, AU1550_UART1_INT),
0082         PORT(AU1000_UART3_PHYS_ADDR, AU1550_UART3_INT),
0083     },
0084     [ALCHEMY_CPU_AU1200] = {
0085         PORT(AU1000_UART0_PHYS_ADDR, AU1200_UART0_INT),
0086         PORT(AU1000_UART1_PHYS_ADDR, AU1200_UART1_INT),
0087     },
0088     [ALCHEMY_CPU_AU1300] = {
0089         PORT(AU1300_UART0_PHYS_ADDR, AU1300_UART0_INT),
0090         PORT(AU1300_UART1_PHYS_ADDR, AU1300_UART1_INT),
0091         PORT(AU1300_UART2_PHYS_ADDR, AU1300_UART2_INT),
0092         PORT(AU1300_UART3_PHYS_ADDR, AU1300_UART3_INT),
0093     },
0094 };
0095 
0096 static struct platform_device au1xx0_uart_device = {
0097     .name           = "serial8250",
0098     .id         = PLAT8250_DEV_AU1X00,
0099 };
0100 
0101 static void __init alchemy_setup_uarts(int ctype)
0102 {
0103     long uartclk;
0104     int s = sizeof(struct plat_serial8250_port);
0105     int c = alchemy_get_uarts(ctype);
0106     struct plat_serial8250_port *ports;
0107     struct clk *clk = clk_get(NULL, ALCHEMY_PERIPH_CLK);
0108 
0109     if (IS_ERR(clk))
0110         return;
0111     if (clk_prepare_enable(clk)) {
0112         clk_put(clk);
0113         return;
0114     }
0115     uartclk = clk_get_rate(clk);
0116     clk_put(clk);
0117 
0118     ports = kcalloc(s, (c + 1), GFP_KERNEL);
0119     if (!ports) {
0120         printk(KERN_INFO "Alchemy: no memory for UART data\n");
0121         return;
0122     }
0123     memcpy(ports, au1x00_uart_data[ctype], s * c);
0124     au1xx0_uart_device.dev.platform_data = ports;
0125 
0126     /* Fill up uartclk. */
0127     for (s = 0; s < c; s++)
0128         ports[s].uartclk = uartclk;
0129     if (platform_device_register(&au1xx0_uart_device))
0130         printk(KERN_INFO "Alchemy: failed to register UARTs\n");
0131 }
0132 
0133 
0134 static u64 alchemy_all_dmamask = DMA_BIT_MASK(32);
0135 
0136 /* Power on callback for the ehci platform driver */
0137 static int alchemy_ehci_power_on(struct platform_device *pdev)
0138 {
0139     return alchemy_usb_control(ALCHEMY_USB_EHCI0, 1);
0140 }
0141 
0142 /* Power off/suspend callback for the ehci platform driver */
0143 static void alchemy_ehci_power_off(struct platform_device *pdev)
0144 {
0145     alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
0146 }
0147 
0148 static struct usb_ehci_pdata alchemy_ehci_pdata = {
0149     .no_io_watchdog = 1,
0150     .power_on   = alchemy_ehci_power_on,
0151     .power_off  = alchemy_ehci_power_off,
0152     .power_suspend  = alchemy_ehci_power_off,
0153 };
0154 
0155 /* Power on callback for the ohci platform driver */
0156 static int alchemy_ohci_power_on(struct platform_device *pdev)
0157 {
0158     int unit;
0159 
0160     unit = (pdev->id == 1) ?
0161         ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
0162 
0163     return alchemy_usb_control(unit, 1);
0164 }
0165 
0166 /* Power off/suspend callback for the ohci platform driver */
0167 static void alchemy_ohci_power_off(struct platform_device *pdev)
0168 {
0169     int unit;
0170 
0171     unit = (pdev->id == 1) ?
0172         ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
0173 
0174     alchemy_usb_control(unit, 0);
0175 }
0176 
0177 static struct usb_ohci_pdata alchemy_ohci_pdata = {
0178     .power_on       = alchemy_ohci_power_on,
0179     .power_off      = alchemy_ohci_power_off,
0180     .power_suspend      = alchemy_ohci_power_off,
0181 };
0182 
0183 static unsigned long alchemy_ohci_data[][2] __initdata = {
0184     [ALCHEMY_CPU_AU1000] = { AU1000_USB_OHCI_PHYS_ADDR, AU1000_USB_HOST_INT },
0185     [ALCHEMY_CPU_AU1500] = { AU1000_USB_OHCI_PHYS_ADDR, AU1500_USB_HOST_INT },
0186     [ALCHEMY_CPU_AU1100] = { AU1000_USB_OHCI_PHYS_ADDR, AU1100_USB_HOST_INT },
0187     [ALCHEMY_CPU_AU1550] = { AU1550_USB_OHCI_PHYS_ADDR, AU1550_USB_HOST_INT },
0188     [ALCHEMY_CPU_AU1200] = { AU1200_USB_OHCI_PHYS_ADDR, AU1200_USB_INT },
0189     [ALCHEMY_CPU_AU1300] = { AU1300_USB_OHCI0_PHYS_ADDR, AU1300_USB_INT },
0190 };
0191 
0192 static unsigned long alchemy_ehci_data[][2] __initdata = {
0193     [ALCHEMY_CPU_AU1200] = { AU1200_USB_EHCI_PHYS_ADDR, AU1200_USB_INT },
0194     [ALCHEMY_CPU_AU1300] = { AU1300_USB_EHCI_PHYS_ADDR, AU1300_USB_INT },
0195 };
0196 
0197 static int __init _new_usbres(struct resource **r, struct platform_device **d)
0198 {
0199     *r = kcalloc(2, sizeof(struct resource), GFP_KERNEL);
0200     if (!*r)
0201         return -ENOMEM;
0202     *d = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
0203     if (!*d) {
0204         kfree(*r);
0205         return -ENOMEM;
0206     }
0207 
0208     (*d)->dev.coherent_dma_mask = DMA_BIT_MASK(32);
0209     (*d)->num_resources = 2;
0210     (*d)->resource = *r;
0211 
0212     return 0;
0213 }
0214 
0215 static void __init alchemy_setup_usb(int ctype)
0216 {
0217     struct resource *res;
0218     struct platform_device *pdev;
0219 
0220     /* setup OHCI0.  Every variant has one */
0221     if (_new_usbres(&res, &pdev))
0222         return;
0223 
0224     res[0].start = alchemy_ohci_data[ctype][0];
0225     res[0].end = res[0].start + 0x100 - 1;
0226     res[0].flags = IORESOURCE_MEM;
0227     res[1].start = alchemy_ohci_data[ctype][1];
0228     res[1].end = res[1].start;
0229     res[1].flags = IORESOURCE_IRQ;
0230     pdev->name = "ohci-platform";
0231     pdev->id = 0;
0232     pdev->dev.dma_mask = &alchemy_all_dmamask;
0233     pdev->dev.platform_data = &alchemy_ohci_pdata;
0234 
0235     if (platform_device_register(pdev))
0236         printk(KERN_INFO "Alchemy USB: cannot add OHCI0\n");
0237 
0238 
0239     /* setup EHCI0: Au1200/Au1300 */
0240     if ((ctype == ALCHEMY_CPU_AU1200) || (ctype == ALCHEMY_CPU_AU1300)) {
0241         if (_new_usbres(&res, &pdev))
0242             return;
0243 
0244         res[0].start = alchemy_ehci_data[ctype][0];
0245         res[0].end = res[0].start + 0x100 - 1;
0246         res[0].flags = IORESOURCE_MEM;
0247         res[1].start = alchemy_ehci_data[ctype][1];
0248         res[1].end = res[1].start;
0249         res[1].flags = IORESOURCE_IRQ;
0250         pdev->name = "ehci-platform";
0251         pdev->id = 0;
0252         pdev->dev.dma_mask = &alchemy_all_dmamask;
0253         pdev->dev.platform_data = &alchemy_ehci_pdata;
0254 
0255         if (platform_device_register(pdev))
0256             printk(KERN_INFO "Alchemy USB: cannot add EHCI0\n");
0257     }
0258 
0259     /* Au1300: OHCI1 */
0260     if (ctype == ALCHEMY_CPU_AU1300) {
0261         if (_new_usbres(&res, &pdev))
0262             return;
0263 
0264         res[0].start = AU1300_USB_OHCI1_PHYS_ADDR;
0265         res[0].end = res[0].start + 0x100 - 1;
0266         res[0].flags = IORESOURCE_MEM;
0267         res[1].start = AU1300_USB_INT;
0268         res[1].end = res[1].start;
0269         res[1].flags = IORESOURCE_IRQ;
0270         pdev->name = "ohci-platform";
0271         pdev->id = 1;
0272         pdev->dev.dma_mask = &alchemy_all_dmamask;
0273         pdev->dev.platform_data = &alchemy_ohci_pdata;
0274 
0275         if (platform_device_register(pdev))
0276             printk(KERN_INFO "Alchemy USB: cannot add OHCI1\n");
0277     }
0278 }
0279 
0280 /* Macro to help defining the Ethernet MAC resources */
0281 #define MAC_RES_COUNT   4   /* MAC regs, MAC en, MAC INT, MACDMA regs */
0282 #define MAC_RES(_base, _enable, _irq, _macdma)      \
0283     {                       \
0284         .start  = _base,            \
0285         .end    = _base + 0xffff,       \
0286         .flags  = IORESOURCE_MEM,       \
0287     },                      \
0288     {                       \
0289         .start  = _enable,          \
0290         .end    = _enable + 0x3,        \
0291         .flags  = IORESOURCE_MEM,       \
0292     },                      \
0293     {                       \
0294         .start  = _irq,             \
0295         .end    = _irq,             \
0296         .flags  = IORESOURCE_IRQ        \
0297     },                      \
0298     {                       \
0299         .start  = _macdma,          \
0300         .end    = _macdma + 0x1ff,      \
0301         .flags  = IORESOURCE_MEM,       \
0302     }
0303 
0304 static struct resource au1xxx_eth0_resources[][MAC_RES_COUNT] __initdata = {
0305     [ALCHEMY_CPU_AU1000] = {
0306         MAC_RES(AU1000_MAC0_PHYS_ADDR,
0307             AU1000_MACEN_PHYS_ADDR,
0308             AU1000_MAC0_DMA_INT,
0309             AU1000_MACDMA0_PHYS_ADDR)
0310     },
0311     [ALCHEMY_CPU_AU1500] = {
0312         MAC_RES(AU1500_MAC0_PHYS_ADDR,
0313             AU1500_MACEN_PHYS_ADDR,
0314             AU1500_MAC0_DMA_INT,
0315             AU1000_MACDMA0_PHYS_ADDR)
0316     },
0317     [ALCHEMY_CPU_AU1100] = {
0318         MAC_RES(AU1000_MAC0_PHYS_ADDR,
0319             AU1000_MACEN_PHYS_ADDR,
0320             AU1100_MAC0_DMA_INT,
0321             AU1000_MACDMA0_PHYS_ADDR)
0322     },
0323     [ALCHEMY_CPU_AU1550] = {
0324         MAC_RES(AU1000_MAC0_PHYS_ADDR,
0325             AU1000_MACEN_PHYS_ADDR,
0326             AU1550_MAC0_DMA_INT,
0327             AU1000_MACDMA0_PHYS_ADDR)
0328     },
0329 };
0330 
0331 static struct au1000_eth_platform_data au1xxx_eth0_platform_data = {
0332     .phy1_search_mac0 = 1,
0333 };
0334 
0335 static struct platform_device au1xxx_eth0_device = {
0336     .name       = "au1000-eth",
0337     .id     = 0,
0338     .num_resources  = MAC_RES_COUNT,
0339     .dev = {
0340         .dma_mask               = &alchemy_all_dmamask,
0341         .coherent_dma_mask      = DMA_BIT_MASK(32),
0342         .platform_data          = &au1xxx_eth0_platform_data,
0343     },
0344 };
0345 
0346 static struct resource au1xxx_eth1_resources[][MAC_RES_COUNT] __initdata = {
0347     [ALCHEMY_CPU_AU1000] = {
0348         MAC_RES(AU1000_MAC1_PHYS_ADDR,
0349             AU1000_MACEN_PHYS_ADDR + 4,
0350             AU1000_MAC1_DMA_INT,
0351             AU1000_MACDMA1_PHYS_ADDR)
0352     },
0353     [ALCHEMY_CPU_AU1500] = {
0354         MAC_RES(AU1500_MAC1_PHYS_ADDR,
0355             AU1500_MACEN_PHYS_ADDR + 4,
0356             AU1500_MAC1_DMA_INT,
0357             AU1000_MACDMA1_PHYS_ADDR)
0358     },
0359     [ALCHEMY_CPU_AU1550] = {
0360         MAC_RES(AU1000_MAC1_PHYS_ADDR,
0361             AU1000_MACEN_PHYS_ADDR + 4,
0362             AU1550_MAC1_DMA_INT,
0363             AU1000_MACDMA1_PHYS_ADDR)
0364     },
0365 };
0366 
0367 static struct au1000_eth_platform_data au1xxx_eth1_platform_data = {
0368     .phy1_search_mac0 = 1,
0369 };
0370 
0371 static struct platform_device au1xxx_eth1_device = {
0372     .name       = "au1000-eth",
0373     .id     = 1,
0374     .num_resources  = MAC_RES_COUNT,
0375     .dev = {
0376         .dma_mask               = &alchemy_all_dmamask,
0377         .coherent_dma_mask      = DMA_BIT_MASK(32),
0378         .platform_data          = &au1xxx_eth1_platform_data,
0379     },
0380 };
0381 
0382 void __init au1xxx_override_eth_cfg(unsigned int port,
0383             struct au1000_eth_platform_data *eth_data)
0384 {
0385     if (!eth_data || port > 1)
0386         return;
0387 
0388     if (port == 0)
0389         memcpy(&au1xxx_eth0_platform_data, eth_data,
0390             sizeof(struct au1000_eth_platform_data));
0391     else
0392         memcpy(&au1xxx_eth1_platform_data, eth_data,
0393             sizeof(struct au1000_eth_platform_data));
0394 }
0395 
0396 static void __init alchemy_setup_macs(int ctype)
0397 {
0398     int ret, i;
0399     unsigned char ethaddr[6];
0400     struct resource *macres;
0401 
0402     /* Handle 1st MAC */
0403     if (alchemy_get_macs(ctype) < 1)
0404         return;
0405 
0406     macres = kmemdup(au1xxx_eth0_resources[ctype],
0407              sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL);
0408     if (!macres) {
0409         printk(KERN_INFO "Alchemy: no memory for MAC0 resources\n");
0410         return;
0411     }
0412     au1xxx_eth0_device.resource = macres;
0413 
0414     i = prom_get_ethernet_addr(ethaddr);
0415     if (!i && !is_valid_ether_addr(au1xxx_eth0_platform_data.mac))
0416         memcpy(au1xxx_eth0_platform_data.mac, ethaddr, 6);
0417 
0418     ret = platform_device_register(&au1xxx_eth0_device);
0419     if (ret)
0420         printk(KERN_INFO "Alchemy: failed to register MAC0\n");
0421 
0422 
0423     /* Handle 2nd MAC */
0424     if (alchemy_get_macs(ctype) < 2)
0425         return;
0426 
0427     macres = kmemdup(au1xxx_eth1_resources[ctype],
0428              sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL);
0429     if (!macres) {
0430         printk(KERN_INFO "Alchemy: no memory for MAC1 resources\n");
0431         return;
0432     }
0433     au1xxx_eth1_device.resource = macres;
0434 
0435     ethaddr[5] += 1;    /* next addr for 2nd MAC */
0436     if (!i && !is_valid_ether_addr(au1xxx_eth1_platform_data.mac))
0437         memcpy(au1xxx_eth1_platform_data.mac, ethaddr, 6);
0438 
0439     /* Register second MAC if enabled in pinfunc */
0440     if (!(alchemy_rdsys(AU1000_SYS_PINFUNC) & SYS_PF_NI2)) {
0441         ret = platform_device_register(&au1xxx_eth1_device);
0442         if (ret)
0443             printk(KERN_INFO "Alchemy: failed to register MAC1\n");
0444     }
0445 }
0446 
0447 static int __init au1xxx_platform_init(void)
0448 {
0449     int ctype = alchemy_get_cputype();
0450 
0451     alchemy_setup_uarts(ctype);
0452     alchemy_setup_macs(ctype);
0453     alchemy_setup_usb(ctype);
0454 
0455     return 0;
0456 }
0457 
0458 arch_initcall(au1xxx_platform_init);