| /* |
| * s6105 platform devices |
| * |
| * Copyright (c) 2009 emlix GmbH |
| */ |
| |
| #include <linux/kernel.h> |
| #include <linux/gpio.h> |
| #include <linux/init.h> |
| #include <linux/irq.h> |
| #include <linux/phy.h> |
| #include <linux/platform_device.h> |
| #include <linux/serial.h> |
| #include <linux/serial_8250.h> |
| |
| #include <variant/hardware.h> |
| #include <variant/dmac.h> |
| |
| #include <platform/gpio.h> |
| |
| #define GPIO3_INTNUM 3 |
| #define UART_INTNUM 4 |
| #define GMAC_INTNUM 5 |
| |
| static const signed char gpio3_irq_mappings[] = { |
| S6_INTC_GPIO(3), |
| -1 |
| }; |
| |
| static const signed char uart_irq_mappings[] = { |
| S6_INTC_UART(0), |
| S6_INTC_UART(1), |
| -1, |
| }; |
| |
| static const signed char gmac_irq_mappings[] = { |
| S6_INTC_GMAC_STAT, |
| S6_INTC_GMAC_ERR, |
| S6_INTC_DMA_HOSTTERMCNT(0), |
| S6_INTC_DMA_HOSTTERMCNT(1), |
| -1 |
| }; |
| |
| const signed char *platform_irq_mappings[NR_IRQS] = { |
| [GPIO3_INTNUM] = gpio3_irq_mappings, |
| [UART_INTNUM] = uart_irq_mappings, |
| [GMAC_INTNUM] = gmac_irq_mappings, |
| }; |
| |
| static struct plat_serial8250_port serial_platform_data[] = { |
| { |
| .membase = (void *)S6_REG_UART + 0x0000, |
| .mapbase = S6_REG_UART + 0x0000, |
| .irq = UART_INTNUM, |
| .uartclk = S6_SCLK, |
| .regshift = 2, |
| .iotype = SERIAL_IO_MEM, |
| .flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST, |
| }, |
| { |
| .membase = (void *)S6_REG_UART + 0x1000, |
| .mapbase = S6_REG_UART + 0x1000, |
| .irq = UART_INTNUM, |
| .uartclk = S6_SCLK, |
| .regshift = 2, |
| .iotype = SERIAL_IO_MEM, |
| .flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST, |
| }, |
| { }, |
| }; |
| |
| static struct resource s6_gmac_resource[] = { |
| { |
| .name = "mem", |
| .start = (resource_size_t)S6_REG_GMAC, |
| .end = (resource_size_t)S6_REG_GMAC + 0x10000 - 1, |
| .flags = IORESOURCE_MEM, |
| }, |
| { |
| .name = "dma", |
| .start = (resource_size_t) |
| DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACTX), |
| .end = (resource_size_t) |
| DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACTX) + 0x100 - 1, |
| .flags = IORESOURCE_DMA, |
| }, |
| { |
| .name = "dma", |
| .start = (resource_size_t) |
| DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACRX), |
| .end = (resource_size_t) |
| DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACRX) + 0x100 - 1, |
| .flags = IORESOURCE_DMA, |
| }, |
| { |
| .name = "io", |
| .start = (resource_size_t)S6_MEM_GMAC, |
| .end = (resource_size_t)S6_MEM_GMAC + 0x2000000 - 1, |
| .flags = IORESOURCE_IO, |
| }, |
| { |
| .name = "irq", |
| .start = (resource_size_t)GMAC_INTNUM, |
| .flags = IORESOURCE_IRQ, |
| }, |
| { |
| .name = "irq", |
| .start = (resource_size_t)PHY_POLL, |
| .flags = IORESOURCE_IRQ, |
| }, |
| }; |
| |
| static int __init prepare_phy_irq(int pin) |
| { |
| int irq; |
| if (gpio_request(pin, "s6gmac_phy") < 0) |
| goto fail; |
| if (gpio_direction_input(pin) < 0) |
| goto free; |
| irq = gpio_to_irq(pin); |
| if (irq < 0) |
| goto free; |
| if (set_irq_type(irq, IRQ_TYPE_LEVEL_LOW) < 0) |
| goto free; |
| return irq; |
| free: |
| gpio_free(pin); |
| fail: |
| return PHY_POLL; |
| } |
| |
| static struct platform_device platform_devices[] = { |
| { |
| .name = "serial8250", |
| .id = PLAT8250_DEV_PLATFORM, |
| .dev = { |
| .platform_data = serial_platform_data, |
| }, |
| }, |
| { |
| .name = "s6gmac", |
| .id = 0, |
| .resource = s6_gmac_resource, |
| .num_resources = ARRAY_SIZE(s6_gmac_resource), |
| }, |
| }; |
| |
| static int __init device_init(void) |
| { |
| int i; |
| |
| s6_gmac_resource[5].start = prepare_phy_irq(GPIO_PHY_IRQ); |
| |
| for (i = 0; i < ARRAY_SIZE(platform_devices); i++) |
| platform_device_register(&platform_devices[i]); |
| return 0; |
| } |
| arch_initcall_sync(device_init); |