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