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