diff options
Diffstat (limited to 'arch/arm/mach-iop13xx/setup.c')
-rw-r--r-- | arch/arm/mach-iop13xx/setup.c | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/arch/arm/mach-iop13xx/setup.c b/arch/arm/mach-iop13xx/setup.c new file mode 100644 index 0000000..3756d2c --- /dev/null +++ b/arch/arm/mach-iop13xx/setup.c @@ -0,0 +1,406 @@ +/* + * iop13xx platform Initialization + * Copyright (c) 2005-2006, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + */ + +#include <linux/serial_8250.h> +#ifdef CONFIG_MTD_PHYSMAP +#include <linux/mtd/physmap.h> +#endif +#include <asm/mach/map.h> +#include <asm/hardware.h> +#include <asm/irq.h> + +#define IOP13XX_UART_XTAL 33334000 +#define IOP13XX_SETUP_DEBUG 0 +#define PRINTK(x...) ((void)(IOP13XX_SETUP_DEBUG && printk(x))) + +/* Standard IO mapping for all IOP13XX based systems + */ +static struct map_desc iop13xx_std_desc[] __initdata = { + { /* mem mapped registers */ + .virtual = IOP13XX_PMMR_VIRT_MEM_BASE, + .pfn = __phys_to_pfn(IOP13XX_PMMR_PHYS_MEM_BASE), + .length = IOP13XX_PMMR_SIZE, + .type = MT_DEVICE, + }, { /* PCIE IO space */ + .virtual = IOP13XX_PCIE_LOWER_IO_VA, + .pfn = __phys_to_pfn(IOP13XX_PCIE_LOWER_IO_PA), + .length = IOP13XX_PCIX_IO_WINDOW_SIZE, + .type = MT_DEVICE, + }, { /* PCIX IO space */ + .virtual = IOP13XX_PCIX_LOWER_IO_VA, + .pfn = __phys_to_pfn(IOP13XX_PCIX_LOWER_IO_PA), + .length = IOP13XX_PCIX_IO_WINDOW_SIZE, + .type = MT_DEVICE, + }, +}; + +static struct resource iop13xx_uart0_resources[] = { + [0] = { + .start = IOP13XX_UART0_PHYS, + .end = IOP13XX_UART0_PHYS + 0x3f, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IOP13XX_UART0, + .end = IRQ_IOP13XX_UART0, + .flags = IORESOURCE_IRQ + } +}; + +static struct resource iop13xx_uart1_resources[] = { + [0] = { + .start = IOP13XX_UART1_PHYS, + .end = IOP13XX_UART1_PHYS + 0x3f, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IOP13XX_UART1, + .end = IRQ_IOP13XX_UART1, + .flags = IORESOURCE_IRQ + } +}; + +static struct plat_serial8250_port iop13xx_uart0_data[] = { + { + .membase = (char*)(IOP13XX_UART0_VIRT), + .mapbase = (IOP13XX_UART0_PHYS), + .irq = IRQ_IOP13XX_UART0, + .uartclk = IOP13XX_UART_XTAL, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_SKIP_TEST, + }, + { }, +}; + +static struct plat_serial8250_port iop13xx_uart1_data[] = { + { + .membase = (char*)(IOP13XX_UART1_VIRT), + .mapbase = (IOP13XX_UART1_PHYS), + .irq = IRQ_IOP13XX_UART1, + .uartclk = IOP13XX_UART_XTAL, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_SKIP_TEST, + }, + { }, +}; + +/* The ids are fixed up later in iop13xx_platform_init */ +static struct platform_device iop13xx_uart0 = { + .name = "serial8250", + .id = 0, + .dev.platform_data = iop13xx_uart0_data, + .num_resources = 2, + .resource = iop13xx_uart0_resources, +}; + +static struct platform_device iop13xx_uart1 = { + .name = "serial8250", + .id = 0, + .dev.platform_data = iop13xx_uart1_data, + .num_resources = 2, + .resource = iop13xx_uart1_resources +}; + +static struct resource iop13xx_i2c_0_resources[] = { + [0] = { + .start = IOP13XX_I2C0_PHYS, + .end = IOP13XX_I2C0_PHYS + 0x18, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IOP13XX_I2C_0, + .end = IRQ_IOP13XX_I2C_0, + .flags = IORESOURCE_IRQ + } +}; + +static struct resource iop13xx_i2c_1_resources[] = { + [0] = { + .start = IOP13XX_I2C1_PHYS, + .end = IOP13XX_I2C1_PHYS + 0x18, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IOP13XX_I2C_1, + .end = IRQ_IOP13XX_I2C_1, + .flags = IORESOURCE_IRQ + } +}; + +static struct resource iop13xx_i2c_2_resources[] = { + [0] = { + .start = IOP13XX_I2C2_PHYS, + .end = IOP13XX_I2C2_PHYS + 0x18, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IOP13XX_I2C_2, + .end = IRQ_IOP13XX_I2C_2, + .flags = IORESOURCE_IRQ + } +}; + +/* I2C controllers. The IOP13XX uses the same block as the IOP3xx, so + * we just use the same device name. + */ + +/* The ids are fixed up later in iop13xx_platform_init */ +static struct platform_device iop13xx_i2c_0_controller = { + .name = "IOP3xx-I2C", + .id = 0, + .num_resources = 2, + .resource = iop13xx_i2c_0_resources +}; + +static struct platform_device iop13xx_i2c_1_controller = { + .name = "IOP3xx-I2C", + .id = 0, + .num_resources = 2, + .resource = iop13xx_i2c_1_resources +}; + +static struct platform_device iop13xx_i2c_2_controller = { + .name = "IOP3xx-I2C", + .id = 0, + .num_resources = 2, + .resource = iop13xx_i2c_2_resources +}; + +#ifdef CONFIG_MTD_PHYSMAP +/* PBI Flash Device + */ +static struct physmap_flash_data iq8134x_flash_data = { + .width = 2, +}; + +static struct resource iq8134x_flash_resource = { + .start = IQ81340_FLASHBASE, + .end = 0, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device iq8134x_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { .platform_data = &iq8134x_flash_data, }, + .num_resources = 1, + .resource = &iq8134x_flash_resource, +}; + +static unsigned long iq8134x_probe_flash_size(void) +{ + uint8_t __iomem *flash_addr = ioremap(IQ81340_FLASHBASE, PAGE_SIZE); + int i; + char query[3]; + unsigned long size = 0; + int width = iq8134x_flash_data.width; + + if (flash_addr) { + /* send CFI 'query' command */ + writew(0x98, flash_addr); + + /* check for CFI compliance */ + for (i = 0; i < 3 * width; i += width) + query[i / width] = readb(flash_addr + (0x10 * width) + i); + + /* read the size */ + if (memcmp(query, "QRY", 3) == 0) + size = 1 << readb(flash_addr + (0x27 * width)); + + /* send CFI 'read array' command */ + writew(0xff, flash_addr); + + iounmap(flash_addr); + } + + return size; +} +#endif + +void __init iop13xx_map_io(void) +{ + /* Initialize the Static Page Table maps */ + iotable_init(iop13xx_std_desc, ARRAY_SIZE(iop13xx_std_desc)); +} + +static int init_uart = 0; +static int init_i2c = 0; + +void __init iop13xx_platform_init(void) +{ + int i; + u32 uart_idx, i2c_idx, plat_idx; + struct platform_device *iop13xx_devices[IQ81340_MAX_PLAT_DEVICES]; + + /* set the bases so we can read the device id */ + iop13xx_set_atu_mmr_bases(); + + memset(iop13xx_devices, 0, sizeof(iop13xx_devices)); + + if (init_uart == IOP13XX_INIT_UART_DEFAULT) { + switch (iop13xx_dev_id()) { + /* enable both uarts on iop341 and iop342 */ + case 0x3380: + case 0x3384: + case 0x3388: + case 0x338c: + case 0x3382: + case 0x3386: + case 0x338a: + case 0x338e: + init_uart |= IOP13XX_INIT_UART_0; + init_uart |= IOP13XX_INIT_UART_1; + break; + /* only enable uart 1 */ + default: + init_uart |= IOP13XX_INIT_UART_1; + } + } + + if (init_i2c == IOP13XX_INIT_I2C_DEFAULT) { + switch (iop13xx_dev_id()) { + /* enable all i2c units on iop341 and iop342 */ + case 0x3380: + case 0x3384: + case 0x3388: + case 0x338c: + case 0x3382: + case 0x3386: + case 0x338a: + case 0x338e: + init_i2c |= IOP13XX_INIT_I2C_0; + init_i2c |= IOP13XX_INIT_I2C_1; + init_i2c |= IOP13XX_INIT_I2C_2; + break; + /* only enable i2c 1 and 2 */ + default: + init_i2c |= IOP13XX_INIT_I2C_1; + init_i2c |= IOP13XX_INIT_I2C_2; + } + } + + plat_idx = 0; + uart_idx = 0; + i2c_idx = 0; + + /* uart 1 (if enabled) is ttyS0 */ + if (init_uart & IOP13XX_INIT_UART_1) { + PRINTK("Adding uart1 to platform device list\n"); + iop13xx_uart1.id = uart_idx++; + iop13xx_devices[plat_idx++] = &iop13xx_uart1; + } + if (init_uart & IOP13XX_INIT_UART_0) { + PRINTK("Adding uart0 to platform device list\n"); + iop13xx_uart0.id = uart_idx++; + iop13xx_devices[plat_idx++] = &iop13xx_uart0; + } + + for(i = 0; i < IQ81340_NUM_I2C; i++) { + if ((init_i2c & (1 << i)) && IOP13XX_SETUP_DEBUG) + printk("Adding i2c%d to platform device list\n", i); + switch(init_i2c & (1 << i)) { + case IOP13XX_INIT_I2C_0: + iop13xx_i2c_0_controller.id = i2c_idx++; + iop13xx_devices[plat_idx++] = + &iop13xx_i2c_0_controller; + break; + case IOP13XX_INIT_I2C_1: + iop13xx_i2c_1_controller.id = i2c_idx++; + iop13xx_devices[plat_idx++] = + &iop13xx_i2c_1_controller; + break; + case IOP13XX_INIT_I2C_2: + iop13xx_i2c_2_controller.id = i2c_idx++; + iop13xx_devices[plat_idx++] = + &iop13xx_i2c_2_controller; + break; + } + } + +#ifdef CONFIG_MTD_PHYSMAP + iq8134x_flash_resource.end = iq8134x_flash_resource.start + + iq8134x_probe_flash_size(); + if (iq8134x_flash_resource.end > iq8134x_flash_resource.start) + iop13xx_devices[plat_idx++] = &iq8134x_flash; + else + printk(KERN_ERR "%s: Failed to probe flash size\n", __FUNCTION__); +#endif + + platform_add_devices(iop13xx_devices, plat_idx); +} + +static int __init iop13xx_init_uart_setup(char *str) +{ + if (str) { + while (*str != '\0') { + switch(*str) { + case '0': + init_uart |= IOP13XX_INIT_UART_0; + break; + case '1': + init_uart |= IOP13XX_INIT_UART_1; + break; + case ',': + case '=': + break; + default: + PRINTK("\"iop13xx_init_uart\" malformed" + " at character: \'%c\'", *str); + *(str + 1) = '\0'; + init_uart = IOP13XX_INIT_UART_DEFAULT; + } + str++; + } + } + return 1; +} + +static int __init iop13xx_init_i2c_setup(char *str) +{ + if (str) { + while (*str != '\0') { + switch(*str) { + case '0': + init_i2c |= IOP13XX_INIT_I2C_0; + break; + case '1': + init_i2c |= IOP13XX_INIT_I2C_1; + break; + case '2': + init_i2c |= IOP13XX_INIT_I2C_2; + break; + case ',': + case '=': + break; + default: + PRINTK("\"iop13xx_init_i2c\" malformed" + " at character: \'%c\'", *str); + *(str + 1) = '\0'; + init_i2c = IOP13XX_INIT_I2C_DEFAULT; + } + str++; + } + } + return 1; +} + +__setup("iop13xx_init_uart", iop13xx_init_uart_setup); +__setup("iop13xx_init_i2c", iop13xx_init_i2c_setup); |