| /* |
| * arch/arm/plat-orion/common.c |
| * |
| * Marvell Orion SoC common setup code used by multiple mach-/common.c |
| * |
| * This file is licensed under the terms of the GNU General Public |
| * License version 2. This program is licensed "as is" without any |
| * warranty of any kind, whether express or implied. |
| */ |
| |
| #include <linux/kernel.h> |
| #include <linux/init.h> |
| #include <linux/platform_device.h> |
| #include <linux/dma-mapping.h> |
| #include <linux/serial_8250.h> |
| #include <linux/mbus.h> |
| #include <linux/mv643xx_eth.h> |
| #include <linux/mv643xx_i2c.h> |
| #include <net/dsa.h> |
| #include <linux/spi/orion_spi.h> |
| #include <plat/orion_wdt.h> |
| |
| /* Fill in the resources structure and link it into the platform |
| device structure. There is always a memory region, and nearly |
| always an interrupt.*/ |
| static void fill_resources(struct platform_device *device, |
| struct resource *resources, |
| resource_size_t mapbase, |
| resource_size_t size, |
| unsigned int irq) |
| { |
| device->resource = resources; |
| device->num_resources = 1; |
| resources[0].flags = IORESOURCE_MEM; |
| resources[0].start = mapbase; |
| resources[0].end = mapbase + size; |
| |
| if (irq != NO_IRQ) { |
| device->num_resources++; |
| resources[1].flags = IORESOURCE_IRQ; |
| resources[1].start = irq; |
| resources[1].end = irq; |
| } |
| } |
| |
| /***************************************************************************** |
| * UART |
| ****************************************************************************/ |
| static void __init uart_complete( |
| struct platform_device *orion_uart, |
| struct plat_serial8250_port *data, |
| struct resource *resources, |
| unsigned int membase, |
| resource_size_t mapbase, |
| unsigned int irq, |
| unsigned int uartclk) |
| { |
| data->mapbase = mapbase; |
| data->membase = (void __iomem *)membase; |
| data->irq = irq; |
| data->uartclk = uartclk; |
| orion_uart->dev.platform_data = data; |
| |
| fill_resources(orion_uart, resources, mapbase, 0xff, irq); |
| platform_device_register(orion_uart); |
| } |
| |
| /***************************************************************************** |
| * UART0 |
| ****************************************************************************/ |
| static struct plat_serial8250_port orion_uart0_data[] = { |
| { |
| .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, |
| .iotype = UPIO_MEM, |
| .regshift = 2, |
| }, { |
| }, |
| }; |
| |
| static struct resource orion_uart0_resources[2]; |
| |
| static struct platform_device orion_uart0 = { |
| .name = "serial8250", |
| .id = PLAT8250_DEV_PLATFORM, |
| }; |
| |
| void __init orion_uart0_init(unsigned int membase, |
| resource_size_t mapbase, |
| unsigned int irq, |
| unsigned int uartclk) |
| { |
| uart_complete(&orion_uart0, orion_uart0_data, orion_uart0_resources, |
| membase, mapbase, irq, uartclk); |
| } |
| |
| /***************************************************************************** |
| * UART1 |
| ****************************************************************************/ |
| static struct plat_serial8250_port orion_uart1_data[] = { |
| { |
| .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, |
| .iotype = UPIO_MEM, |
| .regshift = 2, |
| }, { |
| }, |
| }; |
| |
| static struct resource orion_uart1_resources[2]; |
| |
| static struct platform_device orion_uart1 = { |
| .name = "serial8250", |
| .id = PLAT8250_DEV_PLATFORM1, |
| }; |
| |
| void __init orion_uart1_init(unsigned int membase, |
| resource_size_t mapbase, |
| unsigned int irq, |
| unsigned int uartclk) |
| { |
| uart_complete(&orion_uart1, orion_uart1_data, orion_uart1_resources, |
| membase, mapbase, irq, uartclk); |
| } |
| |
| /***************************************************************************** |
| * UART2 |
| ****************************************************************************/ |
| static struct plat_serial8250_port orion_uart2_data[] = { |
| { |
| .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, |
| .iotype = UPIO_MEM, |
| .regshift = 2, |
| }, { |
| }, |
| }; |
| |
| static struct resource orion_uart2_resources[2]; |
| |
| static struct platform_device orion_uart2 = { |
| .name = "serial8250", |
| .id = PLAT8250_DEV_PLATFORM2, |
| }; |
| |
| void __init orion_uart2_init(unsigned int membase, |
| resource_size_t mapbase, |
| unsigned int irq, |
| unsigned int uartclk) |
| { |
| uart_complete(&orion_uart2, orion_uart2_data, orion_uart2_resources, |
| membase, mapbase, irq, uartclk); |
| } |
| |
| /***************************************************************************** |
| * UART3 |
| ****************************************************************************/ |
| static struct plat_serial8250_port orion_uart3_data[] = { |
| { |
| .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, |
| .iotype = UPIO_MEM, |
| .regshift = 2, |
| }, { |
| }, |
| }; |
| |
| static struct resource orion_uart3_resources[2]; |
| |
| static struct platform_device orion_uart3 = { |
| .name = "serial8250", |
| .id = 3, |
| }; |
| |
| void __init orion_uart3_init(unsigned int membase, |
| resource_size_t mapbase, |
| unsigned int irq, |
| unsigned int uartclk) |
| { |
| uart_complete(&orion_uart3, orion_uart3_data, orion_uart3_resources, |
| membase, mapbase, irq, uartclk); |
| } |
| |
| /***************************************************************************** |
| * SoC RTC |
| ****************************************************************************/ |
| static struct resource orion_rtc_resource[2]; |
| |
| void __init orion_rtc_init(unsigned long mapbase, |
| unsigned long irq) |
| { |
| orion_rtc_resource[0].start = mapbase; |
| orion_rtc_resource[0].end = mapbase + SZ_32 - 1; |
| orion_rtc_resource[0].flags = IORESOURCE_MEM; |
| orion_rtc_resource[1].start = irq; |
| orion_rtc_resource[1].end = irq; |
| orion_rtc_resource[1].flags = IORESOURCE_IRQ; |
| |
| platform_device_register_simple("rtc-mv", -1, orion_rtc_resource, 2); |
| } |
| |
| /***************************************************************************** |
| * GE |
| ****************************************************************************/ |
| static __init void ge_complete( |
| struct mv643xx_eth_shared_platform_data *orion_ge_shared_data, |
| struct mbus_dram_target_info *mbus_dram_info, int tclk, |
| struct resource *orion_ge_resource, unsigned long irq, |
| struct platform_device *orion_ge_shared, |
| struct mv643xx_eth_platform_data *eth_data, |
| struct platform_device *orion_ge) |
| { |
| orion_ge_shared_data->dram = mbus_dram_info; |
| orion_ge_shared_data->t_clk = tclk; |
| orion_ge_resource->start = irq; |
| orion_ge_resource->end = irq; |
| eth_data->shared = orion_ge_shared; |
| orion_ge->dev.platform_data = eth_data; |
| |
| platform_device_register(orion_ge_shared); |
| platform_device_register(orion_ge); |
| } |
| |
| /***************************************************************************** |
| * GE00 |
| ****************************************************************************/ |
| struct mv643xx_eth_shared_platform_data orion_ge00_shared_data; |
| |
| static struct resource orion_ge00_shared_resources[] = { |
| { |
| .name = "ge00 base", |
| }, { |
| .name = "ge00 err irq", |
| }, |
| }; |
| |
| static struct platform_device orion_ge00_shared = { |
| .name = MV643XX_ETH_SHARED_NAME, |
| .id = 0, |
| .dev = { |
| .platform_data = &orion_ge00_shared_data, |
| }, |
| }; |
| |
| static struct resource orion_ge00_resources[] = { |
| { |
| .name = "ge00 irq", |
| .flags = IORESOURCE_IRQ, |
| }, |
| }; |
| |
| static struct platform_device orion_ge00 = { |
| .name = MV643XX_ETH_NAME, |
| .id = 0, |
| .num_resources = 1, |
| .resource = orion_ge00_resources, |
| .dev = { |
| .coherent_dma_mask = DMA_BIT_MASK(32), |
| }, |
| }; |
| |
| void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data, |
| struct mbus_dram_target_info *mbus_dram_info, |
| unsigned long mapbase, |
| unsigned long irq, |
| unsigned long irq_err, |
| int tclk) |
| { |
| fill_resources(&orion_ge00_shared, orion_ge00_shared_resources, |
| mapbase + 0x2000, SZ_16K - 1, irq_err); |
| ge_complete(&orion_ge00_shared_data, mbus_dram_info, tclk, |
| orion_ge00_resources, irq, &orion_ge00_shared, |
| eth_data, &orion_ge00); |
| } |
| |
| /***************************************************************************** |
| * GE01 |
| ****************************************************************************/ |
| struct mv643xx_eth_shared_platform_data orion_ge01_shared_data = { |
| .shared_smi = &orion_ge00_shared, |
| }; |
| |
| static struct resource orion_ge01_shared_resources[] = { |
| { |
| .name = "ge01 base", |
| }, { |
| .name = "ge01 err irq", |
| }, |
| }; |
| |
| static struct platform_device orion_ge01_shared = { |
| .name = MV643XX_ETH_SHARED_NAME, |
| .id = 1, |
| .dev = { |
| .platform_data = &orion_ge01_shared_data, |
| }, |
| }; |
| |
| static struct resource orion_ge01_resources[] = { |
| { |
| .name = "ge01 irq", |
| .flags = IORESOURCE_IRQ, |
| }, |
| }; |
| |
| static struct platform_device orion_ge01 = { |
| .name = MV643XX_ETH_NAME, |
| .id = 1, |
| .num_resources = 1, |
| .resource = orion_ge01_resources, |
| .dev = { |
| .coherent_dma_mask = DMA_BIT_MASK(32), |
| }, |
| }; |
| |
| void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data, |
| struct mbus_dram_target_info *mbus_dram_info, |
| unsigned long mapbase, |
| unsigned long irq, |
| unsigned long irq_err, |
| int tclk) |
| { |
| fill_resources(&orion_ge01_shared, orion_ge01_shared_resources, |
| mapbase + 0x2000, SZ_16K - 1, irq_err); |
| ge_complete(&orion_ge01_shared_data, mbus_dram_info, tclk, |
| orion_ge01_resources, irq, &orion_ge01_shared, |
| eth_data, &orion_ge01); |
| } |
| |
| /***************************************************************************** |
| * GE10 |
| ****************************************************************************/ |
| struct mv643xx_eth_shared_platform_data orion_ge10_shared_data = { |
| .shared_smi = &orion_ge00_shared, |
| }; |
| |
| static struct resource orion_ge10_shared_resources[] = { |
| { |
| .name = "ge10 base", |
| }, { |
| .name = "ge10 err irq", |
| }, |
| }; |
| |
| static struct platform_device orion_ge10_shared = { |
| .name = MV643XX_ETH_SHARED_NAME, |
| .id = 1, |
| .dev = { |
| .platform_data = &orion_ge10_shared_data, |
| }, |
| }; |
| |
| static struct resource orion_ge10_resources[] = { |
| { |
| .name = "ge10 irq", |
| .flags = IORESOURCE_IRQ, |
| }, |
| }; |
| |
| static struct platform_device orion_ge10 = { |
| .name = MV643XX_ETH_NAME, |
| .id = 1, |
| .num_resources = 2, |
| .resource = orion_ge10_resources, |
| .dev = { |
| .coherent_dma_mask = DMA_BIT_MASK(32), |
| }, |
| }; |
| |
| void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data, |
| struct mbus_dram_target_info *mbus_dram_info, |
| unsigned long mapbase, |
| unsigned long irq, |
| unsigned long irq_err, |
| int tclk) |
| { |
| fill_resources(&orion_ge10_shared, orion_ge10_shared_resources, |
| mapbase + 0x2000, SZ_16K - 1, irq_err); |
| ge_complete(&orion_ge10_shared_data, mbus_dram_info, tclk, |
| orion_ge10_resources, irq, &orion_ge10_shared, |
| eth_data, &orion_ge10); |
| } |
| |
| /***************************************************************************** |
| * GE11 |
| ****************************************************************************/ |
| struct mv643xx_eth_shared_platform_data orion_ge11_shared_data = { |
| .shared_smi = &orion_ge00_shared, |
| }; |
| |
| static struct resource orion_ge11_shared_resources[] = { |
| { |
| .name = "ge11 base", |
| }, { |
| .name = "ge11 err irq", |
| }, |
| }; |
| |
| static struct platform_device orion_ge11_shared = { |
| .name = MV643XX_ETH_SHARED_NAME, |
| .id = 1, |
| .dev = { |
| .platform_data = &orion_ge11_shared_data, |
| }, |
| }; |
| |
| static struct resource orion_ge11_resources[] = { |
| { |
| .name = "ge11 irq", |
| .flags = IORESOURCE_IRQ, |
| }, |
| }; |
| |
| static struct platform_device orion_ge11 = { |
| .name = MV643XX_ETH_NAME, |
| .id = 1, |
| .num_resources = 2, |
| .resource = orion_ge11_resources, |
| .dev = { |
| .coherent_dma_mask = DMA_BIT_MASK(32), |
| }, |
| }; |
| |
| void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data, |
| struct mbus_dram_target_info *mbus_dram_info, |
| unsigned long mapbase, |
| unsigned long irq, |
| unsigned long irq_err, |
| int tclk) |
| { |
| fill_resources(&orion_ge11_shared, orion_ge11_shared_resources, |
| mapbase + 0x2000, SZ_16K - 1, irq_err); |
| ge_complete(&orion_ge11_shared_data, mbus_dram_info, tclk, |
| orion_ge11_resources, irq, &orion_ge11_shared, |
| eth_data, &orion_ge11); |
| } |
| |
| /***************************************************************************** |
| * Ethernet switch |
| ****************************************************************************/ |
| static struct resource orion_switch_resources[] = { |
| { |
| .start = 0, |
| .end = 0, |
| .flags = IORESOURCE_IRQ, |
| }, |
| }; |
| |
| static struct platform_device orion_switch_device = { |
| .name = "dsa", |
| .id = 0, |
| .num_resources = 0, |
| .resource = orion_switch_resources, |
| }; |
| |
| void __init orion_ge00_switch_init(struct dsa_platform_data *d, int irq) |
| { |
| int i; |
| |
| if (irq != NO_IRQ) { |
| orion_switch_resources[0].start = irq; |
| orion_switch_resources[0].end = irq; |
| orion_switch_device.num_resources = 1; |
| } |
| |
| d->netdev = &orion_ge00.dev; |
| for (i = 0; i < d->nr_chips; i++) |
| d->chip[i].mii_bus = &orion_ge00_shared.dev; |
| orion_switch_device.dev.platform_data = d; |
| |
| platform_device_register(&orion_switch_device); |
| } |
| |
| /***************************************************************************** |
| * I2C |
| ****************************************************************************/ |
| static struct mv64xxx_i2c_pdata orion_i2c_pdata = { |
| .freq_n = 3, |
| .timeout = 1000, /* Default timeout of 1 second */ |
| }; |
| |
| static struct resource orion_i2c_resources[2]; |
| |
| static struct platform_device orion_i2c = { |
| .name = MV64XXX_I2C_CTLR_NAME, |
| .id = 0, |
| .dev = { |
| .platform_data = &orion_i2c_pdata, |
| }, |
| }; |
| |
| static struct mv64xxx_i2c_pdata orion_i2c_1_pdata = { |
| .freq_n = 3, |
| .timeout = 1000, /* Default timeout of 1 second */ |
| }; |
| |
| static struct resource orion_i2c_1_resources[2]; |
| |
| static struct platform_device orion_i2c_1 = { |
| .name = MV64XXX_I2C_CTLR_NAME, |
| .id = 1, |
| .dev = { |
| .platform_data = &orion_i2c_1_pdata, |
| }, |
| }; |
| |
| void __init orion_i2c_init(unsigned long mapbase, |
| unsigned long irq, |
| unsigned long freq_m) |
| { |
| orion_i2c_pdata.freq_m = freq_m; |
| fill_resources(&orion_i2c, orion_i2c_resources, mapbase, |
| SZ_32 - 1, irq); |
| platform_device_register(&orion_i2c); |
| } |
| |
| void __init orion_i2c_1_init(unsigned long mapbase, |
| unsigned long irq, |
| unsigned long freq_m) |
| { |
| orion_i2c_1_pdata.freq_m = freq_m; |
| fill_resources(&orion_i2c_1, orion_i2c_1_resources, mapbase, |
| SZ_32 - 1, irq); |
| platform_device_register(&orion_i2c_1); |
| } |
| |
| /***************************************************************************** |
| * SPI |
| ****************************************************************************/ |
| static struct orion_spi_info orion_spi_plat_data; |
| static struct resource orion_spi_resources; |
| |
| static struct platform_device orion_spi = { |
| .name = "orion_spi", |
| .id = 0, |
| .dev = { |
| .platform_data = &orion_spi_plat_data, |
| }, |
| }; |
| |
| static struct orion_spi_info orion_spi_1_plat_data; |
| static struct resource orion_spi_1_resources; |
| |
| static struct platform_device orion_spi_1 = { |
| .name = "orion_spi", |
| .id = 1, |
| .dev = { |
| .platform_data = &orion_spi_1_plat_data, |
| }, |
| }; |
| |
| /* Note: The SPI silicon core does have interrupts. However the |
| * current Linux software driver does not use interrupts. */ |
| |
| void __init orion_spi_init(unsigned long mapbase, |
| unsigned long tclk) |
| { |
| orion_spi_plat_data.tclk = tclk; |
| fill_resources(&orion_spi, &orion_spi_resources, |
| mapbase, SZ_512 - 1, NO_IRQ); |
| platform_device_register(&orion_spi); |
| } |
| |
| void __init orion_spi_1_init(unsigned long mapbase, |
| unsigned long tclk) |
| { |
| orion_spi_1_plat_data.tclk = tclk; |
| fill_resources(&orion_spi_1, &orion_spi_1_resources, |
| mapbase, SZ_512 - 1, NO_IRQ); |
| platform_device_register(&orion_spi_1); |
| } |
| |
| /***************************************************************************** |
| * Watchdog |
| ****************************************************************************/ |
| static struct orion_wdt_platform_data orion_wdt_data; |
| |
| static struct platform_device orion_wdt_device = { |
| .name = "orion_wdt", |
| .id = -1, |
| .dev = { |
| .platform_data = &orion_wdt_data, |
| }, |
| .num_resources = 0, |
| }; |
| |
| void __init orion_wdt_init(unsigned long tclk) |
| { |
| orion_wdt_data.tclk = tclk; |
| platform_device_register(&orion_wdt_device); |
| } |