17f627f03SMagnus Damm /* 27f627f03SMagnus Damm * Emma Mobile EV2 processor support 37f627f03SMagnus Damm * 47f627f03SMagnus Damm * Copyright (C) 2012 Magnus Damm 57f627f03SMagnus Damm * 67f627f03SMagnus Damm * This program is free software; you can redistribute it and/or modify 77f627f03SMagnus Damm * it under the terms of the GNU General Public License as published by 87f627f03SMagnus Damm * the Free Software Foundation; version 2 of the License. 97f627f03SMagnus Damm * 107f627f03SMagnus Damm * This program is distributed in the hope that it will be useful, 117f627f03SMagnus Damm * but WITHOUT ANY WARRANTY; without even the implied warranty of 127f627f03SMagnus Damm * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 137f627f03SMagnus Damm * GNU General Public License for more details. 147f627f03SMagnus Damm * 157f627f03SMagnus Damm * You should have received a copy of the GNU General Public License 167f627f03SMagnus Damm * along with this program; if not, write to the Free Software 177f627f03SMagnus Damm * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 187f627f03SMagnus Damm */ 197f627f03SMagnus Damm #include <linux/kernel.h> 207f627f03SMagnus Damm #include <linux/init.h> 217f627f03SMagnus Damm #include <linux/interrupt.h> 227f627f03SMagnus Damm #include <linux/irq.h> 237f627f03SMagnus Damm #include <linux/platform_device.h> 24088efd92SMagnus Damm #include <linux/platform_data/gpio-em.h> 257f627f03SMagnus Damm #include <linux/delay.h> 267f627f03SMagnus Damm #include <linux/input.h> 277f627f03SMagnus Damm #include <linux/io.h> 287f627f03SMagnus Damm #include <mach/hardware.h> 297f627f03SMagnus Damm #include <mach/common.h> 307f627f03SMagnus Damm #include <mach/emev2.h> 317f627f03SMagnus Damm #include <mach/irqs.h> 327f627f03SMagnus Damm #include <asm/mach-types.h> 337f627f03SMagnus Damm #include <asm/mach/arch.h> 347f627f03SMagnus Damm #include <asm/mach/map.h> 357f627f03SMagnus Damm #include <asm/mach/time.h> 367f627f03SMagnus Damm #include <asm/hardware/gic.h> 377f627f03SMagnus Damm 38bd5a875dSMagnus Damm static struct map_desc emev2_io_desc[] __initdata = { 39bd5a875dSMagnus Damm #ifdef CONFIG_SMP 40bd5a875dSMagnus Damm /* 128K entity map for 0xe0100000 (SMU) */ 41bd5a875dSMagnus Damm { 42bd5a875dSMagnus Damm .virtual = 0xe0100000, 43bd5a875dSMagnus Damm .pfn = __phys_to_pfn(0xe0100000), 44bd5a875dSMagnus Damm .length = SZ_128K, 45bd5a875dSMagnus Damm .type = MT_DEVICE 46bd5a875dSMagnus Damm }, 47bd5a875dSMagnus Damm /* 2M mapping for SCU + L2 controller */ 48bd5a875dSMagnus Damm { 49bd5a875dSMagnus Damm .virtual = 0xf0000000, 50bd5a875dSMagnus Damm .pfn = __phys_to_pfn(0x1e000000), 51bd5a875dSMagnus Damm .length = SZ_2M, 52bd5a875dSMagnus Damm .type = MT_DEVICE 53bd5a875dSMagnus Damm }, 54bd5a875dSMagnus Damm #endif 55bd5a875dSMagnus Damm }; 56bd5a875dSMagnus Damm 57bd5a875dSMagnus Damm void __init emev2_map_io(void) 58bd5a875dSMagnus Damm { 59bd5a875dSMagnus Damm iotable_init(emev2_io_desc, ARRAY_SIZE(emev2_io_desc)); 60bd5a875dSMagnus Damm } 61bd5a875dSMagnus Damm 627f627f03SMagnus Damm /* UART */ 637f627f03SMagnus Damm static struct resource uart0_resources[] = { 647f627f03SMagnus Damm [0] = { 657f627f03SMagnus Damm .start = 0xe1020000, 667f627f03SMagnus Damm .end = 0xe1020037, 677f627f03SMagnus Damm .flags = IORESOURCE_MEM, 687f627f03SMagnus Damm }, 697f627f03SMagnus Damm [1] = { 707f627f03SMagnus Damm .start = 40, 717f627f03SMagnus Damm .flags = IORESOURCE_IRQ, 727f627f03SMagnus Damm } 737f627f03SMagnus Damm }; 747f627f03SMagnus Damm 757f627f03SMagnus Damm static struct platform_device uart0_device = { 767f627f03SMagnus Damm .name = "serial8250-em", 777f627f03SMagnus Damm .id = 0, 787f627f03SMagnus Damm .num_resources = ARRAY_SIZE(uart0_resources), 797f627f03SMagnus Damm .resource = uart0_resources, 807f627f03SMagnus Damm }; 817f627f03SMagnus Damm 827f627f03SMagnus Damm static struct resource uart1_resources[] = { 837f627f03SMagnus Damm [0] = { 847f627f03SMagnus Damm .start = 0xe1030000, 857f627f03SMagnus Damm .end = 0xe1030037, 867f627f03SMagnus Damm .flags = IORESOURCE_MEM, 877f627f03SMagnus Damm }, 887f627f03SMagnus Damm [1] = { 897f627f03SMagnus Damm .start = 41, 907f627f03SMagnus Damm .flags = IORESOURCE_IRQ, 917f627f03SMagnus Damm } 927f627f03SMagnus Damm }; 937f627f03SMagnus Damm 947f627f03SMagnus Damm static struct platform_device uart1_device = { 957f627f03SMagnus Damm .name = "serial8250-em", 967f627f03SMagnus Damm .id = 1, 977f627f03SMagnus Damm .num_resources = ARRAY_SIZE(uart1_resources), 987f627f03SMagnus Damm .resource = uart1_resources, 997f627f03SMagnus Damm }; 1007f627f03SMagnus Damm 1017f627f03SMagnus Damm static struct resource uart2_resources[] = { 1027f627f03SMagnus Damm [0] = { 1037f627f03SMagnus Damm .start = 0xe1040000, 1047f627f03SMagnus Damm .end = 0xe1040037, 1057f627f03SMagnus Damm .flags = IORESOURCE_MEM, 1067f627f03SMagnus Damm }, 1077f627f03SMagnus Damm [1] = { 1087f627f03SMagnus Damm .start = 42, 1097f627f03SMagnus Damm .flags = IORESOURCE_IRQ, 1107f627f03SMagnus Damm } 1117f627f03SMagnus Damm }; 1127f627f03SMagnus Damm 1137f627f03SMagnus Damm static struct platform_device uart2_device = { 1147f627f03SMagnus Damm .name = "serial8250-em", 1157f627f03SMagnus Damm .id = 2, 1167f627f03SMagnus Damm .num_resources = ARRAY_SIZE(uart2_resources), 1177f627f03SMagnus Damm .resource = uart2_resources, 1187f627f03SMagnus Damm }; 1197f627f03SMagnus Damm 1207f627f03SMagnus Damm static struct resource uart3_resources[] = { 1217f627f03SMagnus Damm [0] = { 1227f627f03SMagnus Damm .start = 0xe1050000, 1237f627f03SMagnus Damm .end = 0xe1050037, 1247f627f03SMagnus Damm .flags = IORESOURCE_MEM, 1257f627f03SMagnus Damm }, 1267f627f03SMagnus Damm [1] = { 1277f627f03SMagnus Damm .start = 43, 1287f627f03SMagnus Damm .flags = IORESOURCE_IRQ, 1297f627f03SMagnus Damm } 1307f627f03SMagnus Damm }; 1317f627f03SMagnus Damm 1327f627f03SMagnus Damm static struct platform_device uart3_device = { 1337f627f03SMagnus Damm .name = "serial8250-em", 1347f627f03SMagnus Damm .id = 3, 1357f627f03SMagnus Damm .num_resources = ARRAY_SIZE(uart3_resources), 1367f627f03SMagnus Damm .resource = uart3_resources, 1377f627f03SMagnus Damm }; 1387f627f03SMagnus Damm 1397f627f03SMagnus Damm /* STI */ 1407f627f03SMagnus Damm static struct resource sti_resources[] = { 1417f627f03SMagnus Damm [0] = { 1427f627f03SMagnus Damm .name = "STI", 1437f627f03SMagnus Damm .start = 0xe0180000, 1447f627f03SMagnus Damm .end = 0xe0180053, 1457f627f03SMagnus Damm .flags = IORESOURCE_MEM, 1467f627f03SMagnus Damm }, 1477f627f03SMagnus Damm [1] = { 1487f627f03SMagnus Damm .start = 157, 1497f627f03SMagnus Damm .flags = IORESOURCE_IRQ, 1507f627f03SMagnus Damm }, 1517f627f03SMagnus Damm }; 1527f627f03SMagnus Damm 1537f627f03SMagnus Damm static struct platform_device sti_device = { 1547f627f03SMagnus Damm .name = "em_sti", 1557f627f03SMagnus Damm .id = 0, 1567f627f03SMagnus Damm .resource = sti_resources, 1577f627f03SMagnus Damm .num_resources = ARRAY_SIZE(sti_resources), 1587f627f03SMagnus Damm }; 1597f627f03SMagnus Damm 160088efd92SMagnus Damm 161088efd92SMagnus Damm /* GIO */ 162088efd92SMagnus Damm static struct gpio_em_config gio0_config = { 163088efd92SMagnus Damm .gpio_base = 0, 164088efd92SMagnus Damm .irq_base = EMEV2_GPIO_IRQ(0), 165088efd92SMagnus Damm .number_of_pins = 32, 166088efd92SMagnus Damm }; 167088efd92SMagnus Damm 168088efd92SMagnus Damm static struct resource gio0_resources[] = { 169088efd92SMagnus Damm [0] = { 170088efd92SMagnus Damm .name = "GIO_000", 171088efd92SMagnus Damm .start = 0xe0050000, 172088efd92SMagnus Damm .end = 0xe005002b, 173088efd92SMagnus Damm .flags = IORESOURCE_MEM, 174088efd92SMagnus Damm }, 175088efd92SMagnus Damm [1] = { 176088efd92SMagnus Damm .name = "GIO_000", 177088efd92SMagnus Damm .start = 0xe0050040, 178088efd92SMagnus Damm .end = 0xe005005f, 179088efd92SMagnus Damm .flags = IORESOURCE_MEM, 180088efd92SMagnus Damm }, 181088efd92SMagnus Damm [2] = { 182088efd92SMagnus Damm .start = 99, 183088efd92SMagnus Damm .flags = IORESOURCE_IRQ, 184088efd92SMagnus Damm }, 185088efd92SMagnus Damm [3] = { 186088efd92SMagnus Damm .start = 100, 187088efd92SMagnus Damm .flags = IORESOURCE_IRQ, 188088efd92SMagnus Damm }, 189088efd92SMagnus Damm }; 190088efd92SMagnus Damm 191088efd92SMagnus Damm static struct platform_device gio0_device = { 192088efd92SMagnus Damm .name = "em_gio", 193088efd92SMagnus Damm .id = 0, 194088efd92SMagnus Damm .resource = gio0_resources, 195088efd92SMagnus Damm .num_resources = ARRAY_SIZE(gio0_resources), 196088efd92SMagnus Damm .dev = { 197088efd92SMagnus Damm .platform_data = &gio0_config, 198088efd92SMagnus Damm }, 199088efd92SMagnus Damm }; 200088efd92SMagnus Damm 201088efd92SMagnus Damm static struct gpio_em_config gio1_config = { 202088efd92SMagnus Damm .gpio_base = 32, 203088efd92SMagnus Damm .irq_base = EMEV2_GPIO_IRQ(32), 204088efd92SMagnus Damm .number_of_pins = 32, 205088efd92SMagnus Damm }; 206088efd92SMagnus Damm 207088efd92SMagnus Damm static struct resource gio1_resources[] = { 208088efd92SMagnus Damm [0] = { 209088efd92SMagnus Damm .name = "GIO_032", 210088efd92SMagnus Damm .start = 0xe0050080, 211088efd92SMagnus Damm .end = 0xe00500ab, 212088efd92SMagnus Damm .flags = IORESOURCE_MEM, 213088efd92SMagnus Damm }, 214088efd92SMagnus Damm [1] = { 215088efd92SMagnus Damm .name = "GIO_032", 216088efd92SMagnus Damm .start = 0xe00500c0, 217088efd92SMagnus Damm .end = 0xe00500df, 218088efd92SMagnus Damm .flags = IORESOURCE_MEM, 219088efd92SMagnus Damm }, 220088efd92SMagnus Damm [2] = { 221088efd92SMagnus Damm .start = 101, 222088efd92SMagnus Damm .flags = IORESOURCE_IRQ, 223088efd92SMagnus Damm }, 224088efd92SMagnus Damm [3] = { 225088efd92SMagnus Damm .start = 102, 226088efd92SMagnus Damm .flags = IORESOURCE_IRQ, 227088efd92SMagnus Damm }, 228088efd92SMagnus Damm }; 229088efd92SMagnus Damm 230088efd92SMagnus Damm static struct platform_device gio1_device = { 231088efd92SMagnus Damm .name = "em_gio", 232088efd92SMagnus Damm .id = 1, 233088efd92SMagnus Damm .resource = gio1_resources, 234088efd92SMagnus Damm .num_resources = ARRAY_SIZE(gio1_resources), 235088efd92SMagnus Damm .dev = { 236088efd92SMagnus Damm .platform_data = &gio1_config, 237088efd92SMagnus Damm }, 238088efd92SMagnus Damm }; 239088efd92SMagnus Damm 240088efd92SMagnus Damm static struct gpio_em_config gio2_config = { 241088efd92SMagnus Damm .gpio_base = 64, 242088efd92SMagnus Damm .irq_base = EMEV2_GPIO_IRQ(64), 243088efd92SMagnus Damm .number_of_pins = 32, 244088efd92SMagnus Damm }; 245088efd92SMagnus Damm 246088efd92SMagnus Damm static struct resource gio2_resources[] = { 247088efd92SMagnus Damm [0] = { 248088efd92SMagnus Damm .name = "GIO_064", 249088efd92SMagnus Damm .start = 0xe0050100, 250088efd92SMagnus Damm .end = 0xe005012b, 251088efd92SMagnus Damm .flags = IORESOURCE_MEM, 252088efd92SMagnus Damm }, 253088efd92SMagnus Damm [1] = { 254088efd92SMagnus Damm .name = "GIO_064", 255088efd92SMagnus Damm .start = 0xe0050140, 256088efd92SMagnus Damm .end = 0xe005015f, 257088efd92SMagnus Damm .flags = IORESOURCE_MEM, 258088efd92SMagnus Damm }, 259088efd92SMagnus Damm [2] = { 260088efd92SMagnus Damm .start = 103, 261088efd92SMagnus Damm .flags = IORESOURCE_IRQ, 262088efd92SMagnus Damm }, 263088efd92SMagnus Damm [3] = { 264088efd92SMagnus Damm .start = 104, 265088efd92SMagnus Damm .flags = IORESOURCE_IRQ, 266088efd92SMagnus Damm }, 267088efd92SMagnus Damm }; 268088efd92SMagnus Damm 269088efd92SMagnus Damm static struct platform_device gio2_device = { 270088efd92SMagnus Damm .name = "em_gio", 271088efd92SMagnus Damm .id = 2, 272088efd92SMagnus Damm .resource = gio2_resources, 273088efd92SMagnus Damm .num_resources = ARRAY_SIZE(gio2_resources), 274088efd92SMagnus Damm .dev = { 275088efd92SMagnus Damm .platform_data = &gio2_config, 276088efd92SMagnus Damm }, 277088efd92SMagnus Damm }; 278088efd92SMagnus Damm 279088efd92SMagnus Damm static struct gpio_em_config gio3_config = { 280088efd92SMagnus Damm .gpio_base = 96, 281088efd92SMagnus Damm .irq_base = EMEV2_GPIO_IRQ(96), 282088efd92SMagnus Damm .number_of_pins = 32, 283088efd92SMagnus Damm }; 284088efd92SMagnus Damm 285088efd92SMagnus Damm static struct resource gio3_resources[] = { 286088efd92SMagnus Damm [0] = { 287088efd92SMagnus Damm .name = "GIO_096", 288088efd92SMagnus Damm .start = 0xe0050100, 289088efd92SMagnus Damm .end = 0xe005012b, 290088efd92SMagnus Damm .flags = IORESOURCE_MEM, 291088efd92SMagnus Damm }, 292088efd92SMagnus Damm [1] = { 293088efd92SMagnus Damm .name = "GIO_096", 294088efd92SMagnus Damm .start = 0xe0050140, 295088efd92SMagnus Damm .end = 0xe005015f, 296088efd92SMagnus Damm .flags = IORESOURCE_MEM, 297088efd92SMagnus Damm }, 298088efd92SMagnus Damm [2] = { 299088efd92SMagnus Damm .start = 105, 300088efd92SMagnus Damm .flags = IORESOURCE_IRQ, 301088efd92SMagnus Damm }, 302088efd92SMagnus Damm [3] = { 303088efd92SMagnus Damm .start = 106, 304088efd92SMagnus Damm .flags = IORESOURCE_IRQ, 305088efd92SMagnus Damm }, 306088efd92SMagnus Damm }; 307088efd92SMagnus Damm 308088efd92SMagnus Damm static struct platform_device gio3_device = { 309088efd92SMagnus Damm .name = "em_gio", 310088efd92SMagnus Damm .id = 3, 311088efd92SMagnus Damm .resource = gio3_resources, 312088efd92SMagnus Damm .num_resources = ARRAY_SIZE(gio3_resources), 313088efd92SMagnus Damm .dev = { 314088efd92SMagnus Damm .platform_data = &gio3_config, 315088efd92SMagnus Damm }, 316088efd92SMagnus Damm }; 317088efd92SMagnus Damm 318088efd92SMagnus Damm static struct gpio_em_config gio4_config = { 319088efd92SMagnus Damm .gpio_base = 128, 320088efd92SMagnus Damm .irq_base = EMEV2_GPIO_IRQ(128), 321088efd92SMagnus Damm .number_of_pins = 31, 322088efd92SMagnus Damm }; 323088efd92SMagnus Damm 324088efd92SMagnus Damm static struct resource gio4_resources[] = { 325088efd92SMagnus Damm [0] = { 326088efd92SMagnus Damm .name = "GIO_128", 327088efd92SMagnus Damm .start = 0xe0050200, 328088efd92SMagnus Damm .end = 0xe005022b, 329088efd92SMagnus Damm .flags = IORESOURCE_MEM, 330088efd92SMagnus Damm }, 331088efd92SMagnus Damm [1] = { 332088efd92SMagnus Damm .name = "GIO_128", 333088efd92SMagnus Damm .start = 0xe0050240, 334088efd92SMagnus Damm .end = 0xe005025f, 335088efd92SMagnus Damm .flags = IORESOURCE_MEM, 336088efd92SMagnus Damm }, 337088efd92SMagnus Damm [2] = { 338088efd92SMagnus Damm .start = 107, 339088efd92SMagnus Damm .flags = IORESOURCE_IRQ, 340088efd92SMagnus Damm }, 341088efd92SMagnus Damm [3] = { 342088efd92SMagnus Damm .start = 108, 343088efd92SMagnus Damm .flags = IORESOURCE_IRQ, 344088efd92SMagnus Damm }, 345088efd92SMagnus Damm }; 346088efd92SMagnus Damm 347088efd92SMagnus Damm static struct platform_device gio4_device = { 348088efd92SMagnus Damm .name = "em_gio", 349088efd92SMagnus Damm .id = 4, 350088efd92SMagnus Damm .resource = gio4_resources, 351088efd92SMagnus Damm .num_resources = ARRAY_SIZE(gio4_resources), 352088efd92SMagnus Damm .dev = { 353088efd92SMagnus Damm .platform_data = &gio4_config, 354088efd92SMagnus Damm }, 355088efd92SMagnus Damm }; 356088efd92SMagnus Damm 3577f627f03SMagnus Damm static struct platform_device *emev2_early_devices[] __initdata = { 3587f627f03SMagnus Damm &uart0_device, 3597f627f03SMagnus Damm &uart1_device, 3607f627f03SMagnus Damm &uart2_device, 3617f627f03SMagnus Damm &uart3_device, 3627f627f03SMagnus Damm }; 3637f627f03SMagnus Damm 3647f627f03SMagnus Damm static struct platform_device *emev2_late_devices[] __initdata = { 3657f627f03SMagnus Damm &sti_device, 366088efd92SMagnus Damm &gio0_device, 367088efd92SMagnus Damm &gio1_device, 368088efd92SMagnus Damm &gio2_device, 369088efd92SMagnus Damm &gio3_device, 370088efd92SMagnus Damm &gio4_device, 3717f627f03SMagnus Damm }; 3727f627f03SMagnus Damm 3737f627f03SMagnus Damm void __init emev2_add_standard_devices(void) 3747f627f03SMagnus Damm { 3757f627f03SMagnus Damm emev2_clock_init(); 3767f627f03SMagnus Damm 3777f627f03SMagnus Damm platform_add_devices(emev2_early_devices, 3787f627f03SMagnus Damm ARRAY_SIZE(emev2_early_devices)); 3797f627f03SMagnus Damm 3807f627f03SMagnus Damm platform_add_devices(emev2_late_devices, 3817f627f03SMagnus Damm ARRAY_SIZE(emev2_late_devices)); 3827f627f03SMagnus Damm } 3837f627f03SMagnus Damm 3847f627f03SMagnus Damm void __init emev2_add_early_devices(void) 3857f627f03SMagnus Damm { 3867f627f03SMagnus Damm shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */ 3877f627f03SMagnus Damm 3887f627f03SMagnus Damm early_platform_add_devices(emev2_early_devices, 3897f627f03SMagnus Damm ARRAY_SIZE(emev2_early_devices)); 3907f627f03SMagnus Damm 3917f627f03SMagnus Damm /* setup early console here as well */ 3927f627f03SMagnus Damm shmobile_setup_console(); 3937f627f03SMagnus Damm } 3947f627f03SMagnus Damm 3957f627f03SMagnus Damm void __init emev2_init_irq(void) 3967f627f03SMagnus Damm { 3977f627f03SMagnus Damm void __iomem *gic_dist_base; 3987f627f03SMagnus Damm void __iomem *gic_cpu_base; 3997f627f03SMagnus Damm 4007f627f03SMagnus Damm /* Static mappings, never released */ 4017f627f03SMagnus Damm gic_dist_base = ioremap(0xe0028000, PAGE_SIZE); 4027f627f03SMagnus Damm gic_cpu_base = ioremap(0xe0020000, PAGE_SIZE); 4037f627f03SMagnus Damm BUG_ON(!gic_dist_base || !gic_cpu_base); 4047f627f03SMagnus Damm 4057f627f03SMagnus Damm /* Use GIC to handle interrupts */ 4067f627f03SMagnus Damm gic_init(0, 29, gic_dist_base, gic_cpu_base); 4077f627f03SMagnus Damm } 408