diff options
Diffstat (limited to 'arch/arm/plat-orion')
-rw-r--r-- | arch/arm/plat-orion/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/plat-orion/common.c | 957 | ||||
-rw-r--r-- | arch/arm/plat-orion/gpio.c | 112 | ||||
-rw-r--r-- | arch/arm/plat-orion/include/plat/common.h | 117 | ||||
-rw-r--r-- | arch/arm/plat-orion/include/plat/gpio.h | 1 | ||||
-rw-r--r-- | arch/arm/plat-orion/include/plat/mpp.h | 34 | ||||
-rw-r--r-- | arch/arm/plat-orion/irq.c | 49 | ||||
-rw-r--r-- | arch/arm/plat-orion/mpp.c | 78 |
8 files changed, 1232 insertions, 118 deletions
diff --git a/arch/arm/plat-orion/Makefile b/arch/arm/plat-orion/Makefile index 56021a72e10c..95a5fc53b6db 100644 --- a/arch/arm/plat-orion/Makefile +++ b/arch/arm/plat-orion/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -obj-y := irq.o pcie.o time.o +obj-y := irq.o pcie.o time.o common.o mpp.o obj-m := obj-n := obj- := diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c new file mode 100644 index 000000000000..9e5451b3c8e3 --- /dev/null +++ b/arch/arm/plat-orion/common.c @@ -0,0 +1,957 @@ +/* + * 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/ata_platform.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> +#include <plat/mv_xor.h> +#include <plat/ehci-orion.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); +} + +/***************************************************************************** + * XOR + ****************************************************************************/ +static struct mv_xor_platform_shared_data orion_xor_shared_data; + +static u64 orion_xor_dmamask = DMA_BIT_MASK(32); + +void __init orion_xor_init_channels( + struct mv_xor_platform_data *orion_xor0_data, + struct platform_device *orion_xor0_channel, + struct mv_xor_platform_data *orion_xor1_data, + struct platform_device *orion_xor1_channel) +{ + /* + * two engines can't do memset simultaneously, this limitation + * satisfied by removing memset support from one of the engines. + */ + dma_cap_set(DMA_MEMCPY, orion_xor0_data->cap_mask); + dma_cap_set(DMA_XOR, orion_xor0_data->cap_mask); + platform_device_register(orion_xor0_channel); + + dma_cap_set(DMA_MEMCPY, orion_xor1_data->cap_mask); + dma_cap_set(DMA_MEMSET, orion_xor1_data->cap_mask); + dma_cap_set(DMA_XOR, orion_xor1_data->cap_mask); + platform_device_register(orion_xor1_channel); +} + +/***************************************************************************** + * XOR0 + ****************************************************************************/ +static struct resource orion_xor0_shared_resources[] = { + { + .name = "xor 0 low", + .flags = IORESOURCE_MEM, + }, { + .name = "xor 0 high", + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device orion_xor0_shared = { + .name = MV_XOR_SHARED_NAME, + .id = 0, + .dev = { + .platform_data = &orion_xor_shared_data, + }, + .num_resources = ARRAY_SIZE(orion_xor0_shared_resources), + .resource = orion_xor0_shared_resources, +}; + +static struct resource orion_xor00_resources[] = { + [0] = { + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mv_xor_platform_data orion_xor00_data = { + .shared = &orion_xor0_shared, + .hw_id = 0, + .pool_size = PAGE_SIZE, +}; + +static struct platform_device orion_xor00_channel = { + .name = MV_XOR_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(orion_xor00_resources), + .resource = orion_xor00_resources, + .dev = { + .dma_mask = &orion_xor_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(64), + .platform_data = &orion_xor00_data, + }, +}; + +static struct resource orion_xor01_resources[] = { + [0] = { + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mv_xor_platform_data orion_xor01_data = { + .shared = &orion_xor0_shared, + .hw_id = 1, + .pool_size = PAGE_SIZE, +}; + +static struct platform_device orion_xor01_channel = { + .name = MV_XOR_NAME, + .id = 1, + .num_resources = ARRAY_SIZE(orion_xor01_resources), + .resource = orion_xor01_resources, + .dev = { + .dma_mask = &orion_xor_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(64), + .platform_data = &orion_xor01_data, + }, +}; + +void __init orion_xor0_init(struct mbus_dram_target_info *mbus_dram_info, + unsigned long mapbase_low, + unsigned long mapbase_high, + unsigned long irq_0, + unsigned long irq_1) +{ + orion_xor_shared_data.dram = mbus_dram_info; + + orion_xor0_shared_resources[0].start = mapbase_low; + orion_xor0_shared_resources[0].end = mapbase_low + 0xff; + orion_xor0_shared_resources[1].start = mapbase_high; + orion_xor0_shared_resources[1].end = mapbase_high + 0xff; + + orion_xor00_resources[0].start = irq_0; + orion_xor00_resources[0].end = irq_0; + orion_xor01_resources[0].start = irq_1; + orion_xor01_resources[0].end = irq_1; + + platform_device_register(&orion_xor0_shared); + + orion_xor_init_channels(&orion_xor00_data, &orion_xor00_channel, + &orion_xor01_data, &orion_xor01_channel); +} + +/***************************************************************************** + * XOR1 + ****************************************************************************/ +static struct resource orion_xor1_shared_resources[] = { + { + .name = "xor 1 low", + .flags = IORESOURCE_MEM, + }, { + .name = "xor 1 high", + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device orion_xor1_shared = { + .name = MV_XOR_SHARED_NAME, + .id = 1, + .dev = { + .platform_data = &orion_xor_shared_data, + }, + .num_resources = ARRAY_SIZE(orion_xor1_shared_resources), + .resource = orion_xor1_shared_resources, +}; + +static struct resource orion_xor10_resources[] = { + [0] = { + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mv_xor_platform_data orion_xor10_data = { + .shared = &orion_xor1_shared, + .hw_id = 0, + .pool_size = PAGE_SIZE, +}; + +static struct platform_device orion_xor10_channel = { + .name = MV_XOR_NAME, + .id = 2, + .num_resources = ARRAY_SIZE(orion_xor10_resources), + .resource = orion_xor10_resources, + .dev = { + .dma_mask = &orion_xor_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(64), + .platform_data = &orion_xor10_data, + }, +}; + +static struct resource orion_xor11_resources[] = { + [0] = { + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mv_xor_platform_data orion_xor11_data = { + .shared = &orion_xor1_shared, + .hw_id = 1, + .pool_size = PAGE_SIZE, +}; + +static struct platform_device orion_xor11_channel = { + .name = MV_XOR_NAME, + .id = 3, + .num_resources = ARRAY_SIZE(orion_xor11_resources), + .resource = orion_xor11_resources, + .dev = { + .dma_mask = &orion_xor_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(64), + .platform_data = &orion_xor11_data, + }, +}; + +void __init orion_xor1_init(unsigned long mapbase_low, + unsigned long mapbase_high, + unsigned long irq_0, + unsigned long irq_1) +{ + orion_xor1_shared_resources[0].start = mapbase_low; + orion_xor1_shared_resources[0].end = mapbase_low + 0xff; + orion_xor1_shared_resources[1].start = mapbase_high; + orion_xor1_shared_resources[1].end = mapbase_high + 0xff; + + orion_xor10_resources[0].start = irq_0; + orion_xor10_resources[0].end = irq_0; + orion_xor11_resources[0].start = irq_1; + orion_xor11_resources[0].end = irq_1; + + platform_device_register(&orion_xor1_shared); + + orion_xor_init_channels(&orion_xor10_data, &orion_xor10_channel, + &orion_xor11_data, &orion_xor11_channel); +} + +/***************************************************************************** + * EHCI + ****************************************************************************/ +static struct orion_ehci_data orion_ehci_data = { + .phy_version = EHCI_PHY_NA, +}; + +static u64 ehci_dmamask = DMA_BIT_MASK(32); + + +/***************************************************************************** + * EHCI0 + ****************************************************************************/ +static struct resource orion_ehci_resources[2]; + +static struct platform_device orion_ehci = { + .name = "orion-ehci", + .id = 0, + .dev = { + .dma_mask = &ehci_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &orion_ehci_data, + }, +}; + +void __init orion_ehci_init(struct mbus_dram_target_info *mbus_dram_info, + unsigned long mapbase, + unsigned long irq) +{ + orion_ehci_data.dram = mbus_dram_info; + fill_resources(&orion_ehci, orion_ehci_resources, mapbase, SZ_4K - 1, + irq); + + platform_device_register(&orion_ehci); +} + +/***************************************************************************** + * EHCI1 + ****************************************************************************/ +static struct resource orion_ehci_1_resources[2]; + +static struct platform_device orion_ehci_1 = { + .name = "orion-ehci", + .id = 1, + .dev = { + .dma_mask = &ehci_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &orion_ehci_data, + }, +}; + +void __init orion_ehci_1_init(struct mbus_dram_target_info *mbus_dram_info, + unsigned long mapbase, + unsigned long irq) +{ + orion_ehci_data.dram = mbus_dram_info; + fill_resources(&orion_ehci_1, orion_ehci_1_resources, + mapbase, SZ_4K - 1, irq); + + platform_device_register(&orion_ehci_1); +} + +/***************************************************************************** + * EHCI2 + ****************************************************************************/ +static struct resource orion_ehci_2_resources[2]; + +static struct platform_device orion_ehci_2 = { + .name = "orion-ehci", + .id = 2, + .dev = { + .dma_mask = &ehci_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &orion_ehci_data, + }, +}; + +void __init orion_ehci_2_init(struct mbus_dram_target_info *mbus_dram_info, + unsigned long mapbase, + unsigned long irq) +{ + orion_ehci_data.dram = mbus_dram_info; + fill_resources(&orion_ehci_2, orion_ehci_2_resources, + mapbase, SZ_4K - 1, irq); + + platform_device_register(&orion_ehci_2); +} + +/***************************************************************************** + * SATA + ****************************************************************************/ +static struct resource orion_sata_resources[2] = { + { + .name = "sata base", + }, { + .name = "sata irq", + }, +}; + +static struct platform_device orion_sata = { + .name = "sata_mv", + .id = 0, + .dev = { + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +void __init orion_sata_init(struct mv_sata_platform_data *sata_data, + struct mbus_dram_target_info *mbus_dram_info, + unsigned long mapbase, + unsigned long irq) +{ + sata_data->dram = mbus_dram_info; + orion_sata.dev.platform_data = sata_data; + fill_resources(&orion_sata, orion_sata_resources, + mapbase, 0x5000 - 1, irq); + + platform_device_register(&orion_sata); +} + +/***************************************************************************** + * Cryptographic Engines and Security Accelerator (CESA) + ****************************************************************************/ +static struct resource orion_crypto_resources[] = { + { + .name = "regs", + }, { + .name = "crypto interrupt", + }, { + .name = "sram", + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device orion_crypto = { + .name = "mv_crypto", + .id = -1, +}; + +void __init orion_crypto_init(unsigned long mapbase, + unsigned long srambase, + unsigned long sram_size, + unsigned long irq) +{ + fill_resources(&orion_crypto, orion_crypto_resources, + mapbase, 0xffff, irq); + orion_crypto.num_resources = 3; + orion_crypto_resources[2].start = srambase; + orion_crypto_resources[2].end = srambase + sram_size - 1; + + platform_device_register(&orion_crypto); +} diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c index a431a138f402..5b4fffab1eb4 100644 --- a/arch/arm/plat-orion/gpio.c +++ b/arch/arm/plat-orion/gpio.c @@ -321,59 +321,16 @@ EXPORT_SYMBOL(orion_gpio_set_blink); * polarity LEVEL mask * ****************************************************************************/ -static void gpio_irq_ack(struct irq_data *d) -{ - struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d); - int type = irqd_get_trigger_type(d); - - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { - int pin = d->irq - ochip->secondary_irq_base; - - writel(~(1 << pin), GPIO_EDGE_CAUSE(ochip)); - } -} - -static void gpio_irq_mask(struct irq_data *d) -{ - struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d); - int type = irqd_get_trigger_type(d); - void __iomem *reg; - int pin; - - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) - reg = GPIO_EDGE_MASK(ochip); - else - reg = GPIO_LEVEL_MASK(ochip); - - pin = d->irq - ochip->secondary_irq_base; - - writel(readl(reg) & ~(1 << pin), reg); -} - -static void gpio_irq_unmask(struct irq_data *d) -{ - struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d); - int type = irqd_get_trigger_type(d); - void __iomem *reg; - int pin; - - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) - reg = GPIO_EDGE_MASK(ochip); - else - reg = GPIO_LEVEL_MASK(ochip); - - pin = d->irq - ochip->secondary_irq_base; - - writel(readl(reg) | (1 << pin), reg); -} static int gpio_irq_set_type(struct irq_data *d, u32 type) { - struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d); + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct irq_chip_type *ct = irq_data_get_chip_type(d); + struct orion_gpio_chip *ochip = gc->private; int pin; u32 u; - pin = d->irq - ochip->secondary_irq_base; + pin = d->irq - gc->irq_base; u = readl(GPIO_IO_CONF(ochip)) & (1 << pin); if (!u) { @@ -382,18 +339,14 @@ static int gpio_irq_set_type(struct irq_data *d, u32 type) return -EINVAL; } - /* - * Set edge/level type. - */ - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { - __irq_set_handler_locked(d->irq, handle_edge_irq); - } else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { - __irq_set_handler_locked(d->irq, handle_level_irq); - } else { - printk(KERN_ERR "failed to set irq=%d (type=%d)\n", - d->irq, type); + type &= IRQ_TYPE_SENSE_MASK; + if (type == IRQ_TYPE_NONE) return -EINVAL; - } + + /* Check if we need to change chip and handler */ + if (!(ct->type & type)) + if (irq_setup_alt_chip(d, type)) + return -EINVAL; /* * Configure interrupt polarity. @@ -425,19 +378,12 @@ static int gpio_irq_set_type(struct irq_data *d, u32 type) return 0; } -struct irq_chip orion_gpio_irq_chip = { - .name = "orion_gpio_irq", - .irq_ack = gpio_irq_ack, - .irq_mask = gpio_irq_mask, - .irq_unmask = gpio_irq_unmask, - .irq_set_type = gpio_irq_set_type, -}; - void __init orion_gpio_init(int gpio_base, int ngpio, u32 base, int mask_offset, int secondary_irq_base) { struct orion_gpio_chip *ochip; - int i; + struct irq_chip_generic *gc; + struct irq_chip_type *ct; if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips)) return; @@ -471,15 +417,29 @@ void __init orion_gpio_init(int gpio_base, int ngpio, writel(0, GPIO_EDGE_MASK(ochip)); writel(0, GPIO_LEVEL_MASK(ochip)); - for (i = 0; i < ngpio; i++) { - unsigned int irq = secondary_irq_base + i; - - irq_set_chip_and_handler(irq, &orion_gpio_irq_chip, - handle_level_irq); - irq_set_chip_data(irq, ochip); - irq_set_status_flags(irq, IRQ_LEVEL); - set_irq_flags(irq, IRQF_VALID); - } + gc = irq_alloc_generic_chip("orion_gpio_irq", 2, secondary_irq_base, + ochip->base, handle_level_irq); + gc->private = ochip; + + ct = gc->chip_types; + ct->regs.mask = ochip->mask_offset + GPIO_LEVEL_MASK_OFF; + ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW; + ct->chip.irq_mask = irq_gc_mask_clr_bit; + ct->chip.irq_unmask = irq_gc_mask_set_bit; + ct->chip.irq_set_type = gpio_irq_set_type; + + ct++; + ct->regs.mask = ochip->mask_offset + GPIO_EDGE_MASK_OFF; + ct->regs.ack = GPIO_EDGE_CAUSE_OFF; + ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; + ct->chip.irq_ack = irq_gc_ack; + ct->chip.irq_mask = irq_gc_mask_clr_bit; + ct->chip.irq_unmask = irq_gc_mask_set_bit; + ct->chip.irq_set_type = gpio_irq_set_type; + ct->handler = handle_edge_irq; + + irq_setup_generic_chip(gc, IRQ_MSK(ngpio), IRQ_GC_INIT_MASK_CACHE, + IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); } void orion_gpio_irq_handler(int pinoff) diff --git a/arch/arm/plat-orion/include/plat/common.h b/arch/arm/plat-orion/include/plat/common.h new file mode 100644 index 000000000000..a63c357e2ab1 --- /dev/null +++ b/arch/arm/plat-orion/include/plat/common.h @@ -0,0 +1,117 @@ +/* + * arch/arm/plat-orion/include/plat/common.h + * + * Marvell Orion SoC common setup code used by different 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. + */ + +#ifndef __PLAT_COMMON_H +#include <linux/mv643xx_eth.h> + +struct dsa_platform_data; + +void __init orion_uart0_init(unsigned int membase, + resource_size_t mapbase, + unsigned int irq, + unsigned int uartclk); + +void __init orion_uart1_init(unsigned int membase, + resource_size_t mapbase, + unsigned int irq, + unsigned int uartclk); + +void __init orion_uart2_init(unsigned int membase, + resource_size_t mapbase, + unsigned int irq, + unsigned int uartclk); + +void __init orion_uart3_init(unsigned int membase, + resource_size_t mapbase, + unsigned int irq, + unsigned int uartclk); + +void __init orion_rtc_init(unsigned long mapbase, + unsigned long irq); + +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); + +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); + +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); + +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); + +void __init orion_ge00_switch_init(struct dsa_platform_data *d, + int irq); +void __init orion_i2c_init(unsigned long mapbase, + unsigned long irq, + unsigned long freq_m); + +void __init orion_i2c_1_init(unsigned long mapbase, + unsigned long irq, + unsigned long freq_m); + +void __init orion_spi_init(unsigned long mapbase, + unsigned long tclk); + +void __init orion_spi_1_init(unsigned long mapbase, + unsigned long tclk); + +void __init orion_wdt_init(unsigned long tclk); + +void __init orion_xor0_init(struct mbus_dram_target_info *mbus_dram_info, + unsigned long mapbase_low, + unsigned long mapbase_high, + unsigned long irq_0, + unsigned long irq_1); + +void __init orion_xor1_init(unsigned long mapbase_low, + unsigned long mapbase_high, + unsigned long irq_0, + unsigned long irq_1); + +void __init orion_ehci_init(struct mbus_dram_target_info *mbus_dram_info, + unsigned long mapbase, + unsigned long irq); + +void __init orion_ehci_1_init(struct mbus_dram_target_info *mbus_dram_info, + unsigned long mapbase, + unsigned long irq); + +void __init orion_ehci_2_init(struct mbus_dram_target_info *mbus_dram_info, + unsigned long mapbase, + unsigned long irq); + +void __init orion_sata_init(struct mv_sata_platform_data *sata_data, + struct mbus_dram_target_info *mbus_dram_info, + unsigned long mapbase, + unsigned long irq); + +void __init orion_crypto_init(unsigned long mapbase, + unsigned long srambase, + unsigned long sram_size, + unsigned long irq); +#endif diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h index 5578b9803fc6..3075b9fdde83 100644 --- a/arch/arm/plat-orion/include/plat/gpio.h +++ b/arch/arm/plat-orion/include/plat/gpio.h @@ -39,7 +39,6 @@ void __init orion_gpio_init(int gpio_base, int ngpio, /* * GPIO interrupt handling. */ -extern struct irq_chip orion_gpio_irq_chip; void orion_gpio_irq_handler(int irqoff); diff --git a/arch/arm/plat-orion/include/plat/mpp.h b/arch/arm/plat-orion/include/plat/mpp.h new file mode 100644 index 000000000000..723adce99f41 --- /dev/null +++ b/arch/arm/plat-orion/include/plat/mpp.h @@ -0,0 +1,34 @@ +/* + * arch/arm/plat-orion/include/plat/mpp.h + * + * Marvell Orion SoC MPP handling. + * + * 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. + */ + +#ifndef __PLAT_MPP_H +#define __PLAT_MPP_H + +#define MPP_NUM(x) ((x) & 0xff) +#define MPP_SEL(x) (((x) >> 8) & 0xf) + +/* This is the generic MPP macro, without any variant information. + Each machine architecture is expected to extend this with further + bit fields indicating which MPP configurations are valid for a + specific variant. */ + +#define GENERIC_MPP(_num, _sel, _in, _out) ( \ + /* MPP number */ ((_num) & 0xff) | \ + /* MPP select value */ (((_sel) & 0xf) << 8) | \ + /* may be input signal */ ((!!(_in)) << 12) | \ + /* may be output signal */ ((!!(_out)) << 13)) + +#define MPP_INPUT_MASK GENERIC_MPP(0, 0x0, 1, 0) +#define MPP_OUTPUT_MASK GENERIC_MPP(0, 0x0, 0, 1) + +void __init orion_mpp_conf(unsigned int *mpp_list, unsigned int variant_mask, + unsigned int mpp_max, unsigned int dev_bus); + +#endif diff --git a/arch/arm/plat-orion/irq.c b/arch/arm/plat-orion/irq.c index d8d638e09f8f..2d5b9c1ef389 100644 --- a/arch/arm/plat-orion/irq.c +++ b/arch/arm/plat-orion/irq.c @@ -14,52 +14,21 @@ #include <linux/io.h> #include <plat/irq.h> -static void orion_irq_mask(struct irq_data *d) -{ - void __iomem *maskaddr = irq_data_get_irq_chip_data(d); - u32 mask; - - mask = readl(maskaddr); - mask &= ~(1 << (d->irq & 31)); - writel(mask, maskaddr); -} - -static void orion_irq_unmask(struct irq_data *d) -{ - void __iomem *maskaddr = irq_data_get_irq_chip_data(d); - u32 mask; - - mask = readl(maskaddr); - mask |= 1 << (d->irq & 31); - writel(mask, maskaddr); -} - -static struct irq_chip orion_irq_chip = { - .name = "orion_irq", - .irq_mask = orion_irq_mask, - .irq_mask_ack = orion_irq_mask, - .irq_unmask = orion_irq_unmask, -}; - void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr) { - unsigned int i; + struct irq_chip_generic *gc; + struct irq_chip_type *ct; /* * Mask all interrupts initially. */ writel(0, maskaddr); - /* - * Register IRQ sources. - */ - for (i = 0; i < 32; i++) { - unsigned int irq = irq_start + i; - - irq_set_chip_and_handler(irq, &orion_irq_chip, - handle_level_irq); - irq_set_chip_data(irq, maskaddr); - irq_set_status_flags(irq, IRQ_LEVEL); - set_irq_flags(irq, IRQF_VALID); - } + gc = irq_alloc_generic_chip("orion_irq", 1, irq_start, maskaddr, + handle_level_irq); + ct = gc->chip_types; + ct->chip.irq_mask = irq_gc_mask_clr_bit; + ct->chip.irq_unmask = irq_gc_mask_set_bit; + irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_MASK_CACHE, + IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); } diff --git a/arch/arm/plat-orion/mpp.c b/arch/arm/plat-orion/mpp.c new file mode 100644 index 000000000000..91553432711d --- /dev/null +++ b/arch/arm/plat-orion/mpp.c @@ -0,0 +1,78 @@ +/* + * arch/arm/plat-orion/mpp.c + * + * MPP functions for Marvell orion SoCs + * + * 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/mbus.h> +#include <linux/io.h> +#include <linux/gpio.h> +#include <mach/hardware.h> +#include <plat/mpp.h> + +/* Address of the ith MPP control register */ +static __init unsigned long mpp_ctrl_addr(unsigned int i, + unsigned long dev_bus) +{ + return dev_bus + (i) * 4; +} + + +void __init orion_mpp_conf(unsigned int *mpp_list, unsigned int variant_mask, + unsigned int mpp_max, unsigned int dev_bus) +{ + unsigned int mpp_nr_regs = (1 + mpp_max/8); + u32 mpp_ctrl[mpp_nr_regs]; + int i; + + printk(KERN_DEBUG "initial MPP regs:"); + for (i = 0; i < mpp_nr_regs; i++) { + mpp_ctrl[i] = readl(mpp_ctrl_addr(i, dev_bus)); + printk(" %08x", mpp_ctrl[i]); + } + printk("\n"); + + for ( ; *mpp_list; mpp_list++) { + unsigned int num = MPP_NUM(*mpp_list); + unsigned int sel = MPP_SEL(*mpp_list); + int shift, gpio_mode; + + if (num > mpp_max) { + printk(KERN_ERR "orion_mpp_conf: invalid MPP " + "number (%u)\n", num); + continue; + } + if (variant_mask & !(*mpp_list & variant_mask)) { + printk(KERN_WARNING + "orion_mpp_conf: requested MPP%u config " + "unavailable on this hardware\n", num); + continue; + } + + shift = (num & 7) << 2; + mpp_ctrl[num / 8] &= ~(0xf << shift); + mpp_ctrl[num / 8] |= sel << shift; + + gpio_mode = 0; + if (*mpp_list & MPP_INPUT_MASK) + gpio_mode |= GPIO_INPUT_OK; + if (*mpp_list & MPP_OUTPUT_MASK) + gpio_mode |= GPIO_OUTPUT_OK; + if (sel != 0) + gpio_mode = 0; + orion_gpio_set_valid(num, gpio_mode); + } + + printk(KERN_DEBUG " final MPP regs:"); + for (i = 0; i < mpp_nr_regs; i++) { + writel(mpp_ctrl[i], mpp_ctrl_addr(i, dev_bus)); + printk(" %08x", mpp_ctrl[i]); + } + printk("\n"); +} |