diff options
Diffstat (limited to 'arch/arm/mach-ux500/cpu-db8500.c')
-rw-r--r-- | arch/arm/mach-ux500/cpu-db8500.c | 221 |
1 files changed, 127 insertions, 94 deletions
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 4acab7544b3c..516126cb357d 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -12,152 +12,185 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/amba/bus.h> +#include <linux/interrupt.h> #include <linux/irq.h> #include <linux/gpio.h> #include <linux/platform_device.h> #include <linux/io.h> #include <asm/mach/map.h> +#include <asm/pmu.h> #include <mach/hardware.h> #include <mach/setup.h> #include <mach/devices.h> +#include <mach/usb.h> -static struct platform_device *platform_devs[] __initdata = { - &u8500_gpio_devs[0], - &u8500_gpio_devs[1], - &u8500_gpio_devs[2], - &u8500_gpio_devs[3], - &u8500_gpio_devs[4], - &u8500_gpio_devs[5], - &u8500_gpio_devs[6], - &u8500_gpio_devs[7], - &u8500_gpio_devs[8], - &u8500_dma40_device, -}; +#include "devices-db8500.h" +#include "ste-dma40-db8500.h" /* minimum static i/o mapping required to boot U8500 platforms */ +static struct map_desc u8500_uart_io_desc[] __initdata = { + __IO_DEV_DESC(U8500_UART0_BASE, SZ_4K), + __IO_DEV_DESC(U8500_UART2_BASE, SZ_4K), +}; + static struct map_desc u8500_io_desc[] __initdata = { + __IO_DEV_DESC(U8500_GIC_CPU_BASE, SZ_4K), + __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K), + __IO_DEV_DESC(U8500_L2CC_BASE, SZ_4K), + __IO_DEV_DESC(U8500_TWD_BASE, SZ_4K), + __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), + __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K), + __IO_DEV_DESC(U8500_BACKUPRAM0_BASE, SZ_8K), + + __IO_DEV_DESC(U8500_CLKRST1_BASE, SZ_4K), + __IO_DEV_DESC(U8500_CLKRST2_BASE, SZ_4K), + __IO_DEV_DESC(U8500_CLKRST3_BASE, SZ_4K), + __IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K), + __IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K), + __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), - __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K), - __MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M), }; -static struct map_desc u8500ed_io_desc[] __initdata = { +static struct map_desc u8500_ed_io_desc[] __initdata = { __IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K), __IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_8K), }; -static struct map_desc u8500v1_io_desc[] __initdata = { +static struct map_desc u8500_v1_io_desc[] __initdata = { __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), + __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE_V1, SZ_4K), }; -/* - * Functions to differentiate between later ASICs - * We look into the end of the ROM to locate the hardcoded ASIC ID. - * This is only needed to differentiate between minor revisions and - * process variants of an ASIC, the major revisions are encoded in - * the cpuid. - */ -#define U8500_ASIC_ID_LOC_ED_V1 (U8500_BOOT_ROM_BASE + 0x1FFF4) -#define U8500_ASIC_ID_LOC_V2 (U8500_BOOT_ROM_BASE + 0x1DBF4) -#define U8500_ASIC_REV_ED 0x01 -#define U8500_ASIC_REV_V10 0xA0 -#define U8500_ASIC_REV_V11 0xA1 -#define U8500_ASIC_REV_V20 0xB0 - -/** - * struct db8500_asic_id - fields of the ASIC ID - * @process: the manufacturing process, 0x40 is 40 nm - * 0x00 is "standard" - * @partnumber: hithereto 0x8500 for DB8500 - * @revision: version code in the series - * This field definion is not formally defined but makes - * sense. - */ -struct db8500_asic_id { - u8 process; - u16 partnumber; - u8 revision; +static struct map_desc u8500_v2_io_desc[] __initdata = { + __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K), }; -/* This isn't going to change at runtime */ -static struct db8500_asic_id db8500_id; - -static void __init get_db8500_asic_id(void) +void __init u8500_map_io(void) { - u32 asicid; + /* + * Map the UARTs early so that the DEBUG_LL stuff continues to work. + */ + iotable_init(u8500_uart_io_desc, ARRAY_SIZE(u8500_uart_io_desc)); - if (cpu_is_u8500v1() || cpu_is_u8500ed()) - asicid = readl(__io_address(U8500_ASIC_ID_LOC_ED_V1)); - else if (cpu_is_u8500v2()) - asicid = readl(__io_address(U8500_ASIC_ID_LOC_V2)); - else - BUG(); + ux500_map_io(); - db8500_id.process = (asicid >> 24); - db8500_id.partnumber = (asicid >> 16) & 0xFFFFU; - db8500_id.revision = asicid & 0xFFU; -} + iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); -bool cpu_is_u8500v10(void) -{ - return (db8500_id.revision == U8500_ASIC_REV_V10); + if (cpu_is_u8500ed()) + iotable_init(u8500_ed_io_desc, ARRAY_SIZE(u8500_ed_io_desc)); + else if (cpu_is_u8500v1()) + iotable_init(u8500_v1_io_desc, ARRAY_SIZE(u8500_v1_io_desc)); + else if (cpu_is_u8500v2()) + iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc)); } -bool cpu_is_u8500v11(void) -{ - return (db8500_id.revision == U8500_ASIC_REV_V11); -} +static struct resource db8500_pmu_resources[] = { + [0] = { + .start = IRQ_DB8500_PMU, + .end = IRQ_DB8500_PMU, + .flags = IORESOURCE_IRQ, + }, +}; -bool cpu_is_u8500v20(void) +/* + * The PMU IRQ lines of two cores are wired together into a single interrupt. + * Bounce the interrupt to the other core if it's not ours. + */ +static irqreturn_t db8500_pmu_handler(int irq, void *dev, irq_handler_t handler) { - return (db8500_id.revision == U8500_ASIC_REV_V20); + irqreturn_t ret = handler(irq, dev); + int other = !smp_processor_id(); + + if (ret == IRQ_NONE && cpu_online(other)) + irq_set_affinity(irq, cpumask_of(other)); + + /* + * We should be able to get away with the amount of IRQ_NONEs we give, + * while still having the spurious IRQ detection code kick in if the + * interrupt really starts hitting spuriously. + */ + return ret; } -void __init u8500_map_io(void) -{ - ux500_map_io(); +static struct arm_pmu_platdata db8500_pmu_platdata = { + .handle_irq = db8500_pmu_handler, +}; - iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); +static struct platform_device db8500_pmu_device = { + .name = "arm-pmu", + .id = ARM_PMU_DEVICE_CPU, + .num_resources = ARRAY_SIZE(db8500_pmu_resources), + .resource = db8500_pmu_resources, + .dev.platform_data = &db8500_pmu_platdata, +}; - if (cpu_is_u8500ed()) - iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc)); - else - iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc)); +static struct platform_device *platform_devs[] __initdata = { + &u8500_dma40_device, + &db8500_pmu_device, +}; + +static resource_size_t __initdata db8500_gpio_base[] = { + U8500_GPIOBANK0_BASE, + U8500_GPIOBANK1_BASE, + U8500_GPIOBANK2_BASE, + U8500_GPIOBANK3_BASE, + U8500_GPIOBANK4_BASE, + U8500_GPIOBANK5_BASE, + U8500_GPIOBANK6_BASE, + U8500_GPIOBANK7_BASE, + U8500_GPIOBANK8_BASE, +}; - /* Read out the ASIC ID as early as we can */ - get_db8500_asic_id(); +static void __init db8500_add_gpios(void) +{ + struct nmk_gpio_platform_data pdata = { + /* No custom data yet */ + }; + + dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base), + IRQ_DB8500_GPIO0, &pdata); } +static int usb_db8500_rx_dma_cfg[] = { + DB8500_DMA_DEV38_USB_OTG_IEP_1_9, + DB8500_DMA_DEV37_USB_OTG_IEP_2_10, + DB8500_DMA_DEV36_USB_OTG_IEP_3_11, + DB8500_DMA_DEV19_USB_OTG_IEP_4_12, + DB8500_DMA_DEV18_USB_OTG_IEP_5_13, + DB8500_DMA_DEV17_USB_OTG_IEP_6_14, + DB8500_DMA_DEV16_USB_OTG_IEP_7_15, + DB8500_DMA_DEV39_USB_OTG_IEP_8 +}; + +static int usb_db8500_tx_dma_cfg[] = { + DB8500_DMA_DEV38_USB_OTG_OEP_1_9, + DB8500_DMA_DEV37_USB_OTG_OEP_2_10, + DB8500_DMA_DEV36_USB_OTG_OEP_3_11, + DB8500_DMA_DEV19_USB_OTG_OEP_4_12, + DB8500_DMA_DEV18_USB_OTG_OEP_5_13, + DB8500_DMA_DEV17_USB_OTG_OEP_6_14, + DB8500_DMA_DEV16_USB_OTG_OEP_7_15, + DB8500_DMA_DEV39_USB_OTG_OEP_8 +}; + /* * This function is called from the board init */ void __init u8500_init_devices(void) { - /* Display some ASIC boilerplate */ - pr_info("DB8500: process: %02x, revision ID: 0x%02x\n", - db8500_id.process, db8500_id.revision); - if (cpu_is_u8500ed()) - pr_info("DB8500: Early Drop (ED)\n"); - else if (cpu_is_u8500v10()) - pr_info("DB8500: version 1.0\n"); - else if (cpu_is_u8500v11()) - pr_info("DB8500: version 1.1\n"); - else if (cpu_is_u8500v20()) - pr_info("DB8500: version 2.0\n"); - else - pr_warning("ASIC: UNKNOWN SILICON VERSION!\n"); - - ux500_init_devices(); - if (cpu_is_u8500ed()) dma40_u8500ed_fixup(); - /* Register the platform devices */ + db8500_add_rtc(); + db8500_add_gpios(); + db8500_add_usb(usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); + + platform_device_register_simple("cpufreq-u8500", -1, NULL, 0); platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); return ; |