diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-11 01:50:38 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-11 01:50:38 +0300 |
commit | e773202e227c8ebbf369b9b924e15cca4d93824b (patch) | |
tree | 623a15fe0593e7ff2e79f0a5918fb4b3e739e2ee /arch/arm | |
parent | abf8792d0e1b203e303ed1c02437e0e10a39dcda (diff) | |
parent | d2a40972ec70bd2060d3c46050a101a9678d2991 (diff) | |
download | linux-e773202e227c8ebbf369b9b924e15cca4d93824b.tar.xz |
Merge branch 'for-torvalds' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson
* 'for-torvalds' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson:
ux500: allow 5500 and 8500 to be built together
ux500: modem_irq is only for 5500
ux500: dynamic SOC detection
ux500: rename MOP board Kconfig
ux500: remove build-time changing macros
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/configs/u8500_defconfig | 4 | ||||
-rw-r--r-- | arch/arm/mach-ux500/Kconfig | 26 | ||||
-rw-r--r-- | arch/arm/mach-ux500/Makefile | 5 | ||||
-rw-r--r-- | arch/arm/mach-ux500/clock.c | 14 | ||||
-rw-r--r-- | arch/arm/mach-ux500/cpu-db5500.c | 18 | ||||
-rw-r--r-- | arch/arm/mach-ux500/cpu-db8500.c | 105 | ||||
-rw-r--r-- | arch/arm/mach-ux500/cpu.c | 78 | ||||
-rw-r--r-- | arch/arm/mach-ux500/id.c | 107 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/debug-macro.S | 19 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/entry-macro.S | 5 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/hardware.h | 108 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/id.h | 80 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/irqs.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/setup.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-ux500/modem-irq-db5500.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-ux500/platsmp.c | 37 |
16 files changed, 354 insertions, 261 deletions
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index be80f037f85a..52d86c4485bf 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -9,6 +9,10 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_LBDAF is not set # CONFIG_BLK_DEV_BSG is not set CONFIG_ARCH_U8500=y +CONFIG_UX500_SOC_DB5500=y +CONFIG_UX500_SOC_DB8500=y +CONFIG_MACH_U8500=y +CONFIG_MACH_U5500=y CONFIG_SMP=y CONFIG_NR_CPUS=2 CONFIG_PREEMPT=y diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 2dd44a0b4615..247caa3400d0 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -7,28 +7,30 @@ config UX500_SOC_COMMON select HAS_MTU select NOMADIK_GPIO -config UX500_SOC_DB8500 - bool +menu "Ux500 SoC" config UX500_SOC_DB5500 - bool + bool "DB5500" + +config UX500_SOC_DB8500 + bool "DB8500" + +endmenu -choice - prompt "Ux500 target platform" - default MACH_U8500_MOP +menu "Ux500 target platform" -config MACH_U8500_MOP +config MACH_U8500 bool "U8500 Development platform" - select UX500_SOC_DB8500 + depends on UX500_SOC_DB8500 help Include support for the mop500 development platform. config MACH_U5500 bool "U5500 Development platform" - select UX500_SOC_DB5500 + depends on UX500_SOC_DB5500 help Include support for the U5500 development platform. -endchoice +endmenu config UX500_DEBUG_UART int "Ux500 UART to use for low-level debug" @@ -39,14 +41,14 @@ config UX500_DEBUG_UART config U5500_MODEM_IRQ bool "Modem IRQ support" - depends on MACH_U5500 + depends on UX500_SOC_DB5500 default y help Add support for handling IRQ:s from modem side config U5500_MBOX bool "Mailbox support" - depends on MACH_U5500 && U5500_MODEM_IRQ + depends on U5500_MODEM_IRQ default y help Add support for U5500 mailbox communication with modem side diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 12052e8e064c..53ebb429e971 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -2,10 +2,11 @@ # Makefile for the linux kernel, U8500 machine. # -obj-y := clock.o cpu.o devices.o devices-common.o +obj-y := clock.o cpu.o devices.o devices-common.o \ + id.o obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o -obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o \ +obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \ board-mop500-keypads.o obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index ccff2dae167f..b2b0a3b9be8f 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -136,8 +136,7 @@ EXPORT_SYMBOL(clk_disable); */ static unsigned long clk_mtu_get_rate(struct clk *clk) { - void __iomem *addr = __io_address(UX500_PRCMU_BASE) - + PRCM_TCR; + void __iomem *addr; u32 tcr; int mtu = (int) clk->data; /* @@ -149,13 +148,20 @@ static unsigned long clk_mtu_get_rate(struct clk *clk) unsigned long mturate; unsigned long retclk; + if (cpu_is_u5500()) + addr = __io_address(U5500_PRCMU_BASE); + else if (cpu_is_u8500()) + addr = __io_address(U8500_PRCMU_BASE); + else + ux500_unknown_soc(); + /* * On a startup, always conifgure the TCR to the doze mode; * bootloaders do it for us. Do this in the kernel too. */ - writel(PRCM_TCR_DOZE_MODE, addr); + writel(PRCM_TCR_DOZE_MODE, addr + PRCM_TCR); - tcr = readl(addr); + tcr = readl(addr + PRCM_TCR); /* Get the rate from the parent as a default */ if (clk->parent_periph) diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index acc841e48de4..af04e0891a78 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c @@ -21,7 +21,20 @@ #include "devices-db5500.h" +static struct map_desc u5500_uart_io_desc[] __initdata = { + __IO_DEV_DESC(U5500_UART0_BASE, SZ_4K), + __IO_DEV_DESC(U5500_UART2_BASE, SZ_4K), +}; + static struct map_desc u5500_io_desc[] __initdata = { + __IO_DEV_DESC(U5500_GIC_CPU_BASE, SZ_4K), + __IO_DEV_DESC(U5500_GIC_DIST_BASE, SZ_4K), + __IO_DEV_DESC(U5500_L2CC_BASE, SZ_4K), + __IO_DEV_DESC(U5500_TWD_BASE, SZ_4K), + __IO_DEV_DESC(U5500_MTU0_BASE, SZ_4K), + __IO_DEV_DESC(U5500_SCU_BASE, SZ_4K), + __IO_DEV_DESC(U5500_BACKUPRAM0_BASE, SZ_8K), + __IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K), __IO_DEV_DESC(U5500_GPIO1_BASE, SZ_4K), __IO_DEV_DESC(U5500_GPIO2_BASE, SZ_4K), @@ -143,6 +156,11 @@ static void __init db5500_add_gpios(void) void __init u5500_map_io(void) { + /* + * Map the UARTs early so that the DEBUG_LL stuff continues to work. + */ + iotable_init(u5500_uart_io_desc, ARRAY_SIZE(u5500_uart_io_desc)); + ux500_map_io(); iotable_init(u5500_io_desc, ARRAY_SIZE(u5500_io_desc)); diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index c0f34a404c53..1748fbc58530 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -29,13 +29,31 @@ static struct platform_device *platform_devs[] __initdata = { }; /* 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_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 u8500_ed_io_desc[] __initdata = { @@ -52,71 +70,13 @@ static struct map_desc u8500_v2_io_desc[] __initdata = { __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, 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; -}; - -/* This isn't going to change at runtime */ -static struct db8500_asic_id db8500_id; - -static void __init get_db8500_asic_id(void) -{ - u32 asicid; - - 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(); - - db8500_id.process = (asicid >> 24); - db8500_id.partnumber = (asicid >> 16) & 0xFFFFU; - db8500_id.revision = asicid & 0xFFU; -} - -bool cpu_is_u8500v10(void) -{ - return (db8500_id.revision == U8500_ASIC_REV_V10); -} - -bool cpu_is_u8500v11(void) -{ - return (db8500_id.revision == U8500_ASIC_REV_V11); -} - -bool cpu_is_u8500v20(void) -{ - return (db8500_id.revision == U8500_ASIC_REV_V20); -} - void __init u8500_map_io(void) { + /* + * 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)); + ux500_map_io(); iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); @@ -127,9 +87,6 @@ void __init u8500_map_io(void) 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)); - - /* Read out the ASIC ID as early as we can */ - get_db8500_asic_id(); } static resource_size_t __initdata db8500_gpio_base[] = { @@ -159,20 +116,6 @@ static void __init db8500_add_gpios(void) */ 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"); - if (cpu_is_u8500ed()) dma40_u8500ed_fixup(); diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index 5730409c0f7d..5a43107c6232 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -23,37 +23,25 @@ #include "clock.h" -static struct map_desc ux500_io_desc[] __initdata = { - __IO_DEV_DESC(UX500_UART0_BASE, SZ_4K), - __IO_DEV_DESC(UX500_UART2_BASE, SZ_4K), - - __IO_DEV_DESC(UX500_GIC_CPU_BASE, SZ_4K), - __IO_DEV_DESC(UX500_GIC_DIST_BASE, SZ_4K), - __IO_DEV_DESC(UX500_L2CC_BASE, SZ_4K), - __IO_DEV_DESC(UX500_TWD_BASE, SZ_4K), - __IO_DEV_DESC(UX500_SCU_BASE, SZ_4K), - - __IO_DEV_DESC(UX500_CLKRST1_BASE, SZ_4K), - __IO_DEV_DESC(UX500_CLKRST2_BASE, SZ_4K), - __IO_DEV_DESC(UX500_CLKRST3_BASE, SZ_4K), - __IO_DEV_DESC(UX500_CLKRST5_BASE, SZ_4K), - __IO_DEV_DESC(UX500_CLKRST6_BASE, SZ_4K), - - __IO_DEV_DESC(UX500_MTU0_BASE, SZ_4K), - __IO_DEV_DESC(UX500_MTU1_BASE, SZ_4K), - - __IO_DEV_DESC(UX500_BACKUPRAM0_BASE, SZ_8K), -}; - -void __init ux500_map_io(void) -{ - iotable_init(ux500_io_desc, ARRAY_SIZE(ux500_io_desc)); -} +#ifdef CONFIG_CACHE_L2X0 +static void __iomem *l2x0_base; +#endif void __init ux500_init_irq(void) { - gic_init(0, 29, __io_address(UX500_GIC_DIST_BASE), - __io_address(UX500_GIC_CPU_BASE)); + void __iomem *dist_base; + void __iomem *cpu_base; + + if (cpu_is_u5500()) { + dist_base = __io_address(U5500_GIC_DIST_BASE); + cpu_base = __io_address(U5500_GIC_CPU_BASE); + } else if (cpu_is_u8500()) { + dist_base = __io_address(U8500_GIC_DIST_BASE); + cpu_base = __io_address(U8500_GIC_CPU_BASE); + } else + ux500_unknown_soc(); + + gic_init(0, 29, dist_base, cpu_base); /* * Init clocks here so that they are available for system timer @@ -74,7 +62,8 @@ static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask) static inline void ux500_cache_sync(void) { - void __iomem *base = __io_address(UX500_L2CC_BASE); + void __iomem *base = l2x0_base; + writel_relaxed(0, base + L2X0_CACHE_SYNC); ux500_cache_wait(base + L2X0_CACHE_SYNC, 1); } @@ -96,20 +85,23 @@ static void ux500_l2x0_disable(void) */ static void ux500_l2x0_inv_all(void) { - void __iomem *l2x0_base = __io_address(UX500_L2CC_BASE); + void __iomem *base = l2x0_base; uint32_t l2x0_way_mask = (1<<16) - 1; /* Bitmask of active ways */ /* invalidate all ways */ - writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); - ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); + writel_relaxed(l2x0_way_mask, base + L2X0_INV_WAY); + ux500_cache_wait(base + L2X0_INV_WAY, l2x0_way_mask); ux500_cache_sync(); } static int ux500_l2x0_init(void) { - void __iomem *l2x0_base; - - l2x0_base = __io_address(UX500_L2CC_BASE); + if (cpu_is_u5500()) + l2x0_base = __io_address(U5500_L2CC_BASE); + else if (cpu_is_u8500()) + l2x0_base = __io_address(U8500_L2CC_BASE); + else + ux500_unknown_soc(); /* 64KB way size, 8 way associativity, force WA */ l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); @@ -127,13 +119,21 @@ static void __init ux500_timer_init(void) { #ifdef CONFIG_LOCAL_TIMERS /* Setup the local timer base */ - twd_base = __io_address(UX500_TWD_BASE); + if (cpu_is_u5500()) + twd_base = __io_address(U5500_TWD_BASE); + else if (cpu_is_u8500()) + twd_base = __io_address(U8500_TWD_BASE); + else + ux500_unknown_soc(); #endif - /* Setup the MTU base */ - if (cpu_is_u8500ed()) + if (cpu_is_u5500()) + mtu_base = __io_address(U5500_MTU0_BASE); + else if (cpu_is_u8500ed()) mtu_base = __io_address(U8500_MTU0_BASE_ED); + else if (cpu_is_u8500()) + mtu_base = __io_address(U8500_MTU0_BASE); else - mtu_base = __io_address(UX500_MTU0_BASE); + ux500_unknown_soc(); nmdk_timer_init(); } diff --git a/arch/arm/mach-ux500/id.c b/arch/arm/mach-ux500/id.c new file mode 100644 index 000000000000..d35122ebc67b --- /dev/null +++ b/arch/arm/mach-ux500/id.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> + +#include <asm/cputype.h> +#include <asm/tlbflush.h> +#include <asm/cacheflush.h> +#include <asm/mach/map.h> + +#include <mach/hardware.h> +#include <mach/setup.h> + +struct dbx500_asic_id dbx500_id; + +static unsigned int ux500_read_asicid(phys_addr_t addr) +{ + phys_addr_t base = addr & ~0xfff; + struct map_desc desc = { + .virtual = IO_ADDRESS(base), + .pfn = __phys_to_pfn(base), + .length = SZ_16K, + .type = MT_DEVICE, + }; + + iotable_init(&desc, 1); + + /* As in devicemaps_init() */ + local_flush_tlb_all(); + flush_cache_all(); + + return readl(__io_address(addr)); +} + +static void ux500_print_soc_info(unsigned int asicid) +{ + unsigned int rev = dbx500_revision(); + + pr_info("DB%4x ", dbx500_partnumber()); + + if (rev == 0x01) + pr_cont("Early Drop"); + else if (rev >= 0xA0) + pr_cont("v%d.%d" , (rev >> 4) - 0xA + 1, rev & 0xf); + else + pr_cont("Unknown"); + + pr_cont(" [%#010x]\n", asicid); +} + +static unsigned int partnumber(unsigned int asicid) +{ + return (asicid >> 8) & 0xffff; +} + +/* + * SOC MIDR ASICID ADDRESS ASICID VALUE + * DB8500ed 0x410fc090 0x9001FFF4 0x00850001 + * DB8500v1 0x411fc091 0x9001FFF4 0x008500A0 + * DB8500v1.1 0x411fc091 0x9001FFF4 0x008500A1 + * DB8500v2 0x412fc091 0x9001DBF4 0x008500B0 + * DB5500v1 0x412fc091 0x9001FFF4 0x005500A0 + */ + +void __init ux500_map_io(void) +{ + unsigned int cpuid = read_cpuid_id(); + unsigned int asicid = 0; + phys_addr_t addr = 0; + + switch (cpuid) { + case 0x410fc090: /* DB8500ed */ + case 0x411fc091: /* DB8500v1 */ + addr = 0x9001FFF4; + break; + + case 0x412fc091: /* DB8500v2 / DB5500v1 */ + asicid = ux500_read_asicid(0x9001DBF4); + if (partnumber(asicid) == 0x8500) + /* DB8500v2 */ + break; + + /* DB5500v1 */ + addr = 0x9001FFF4; + break; + } + + if (addr) + asicid = ux500_read_asicid(addr); + + if (!asicid) { + pr_err("Unable to identify SoC\n"); + ux500_unknown_soc(); + } + + dbx500_id.process = asicid >> 24; + dbx500_id.partnumber = partnumber(asicid); + dbx500_id.revision = asicid & 0xff; + + ux500_print_soc_info(asicid); +} diff --git a/arch/arm/mach-ux500/include/mach/debug-macro.S b/arch/arm/mach-ux500/include/mach/debug-macro.S index be7c0f14e310..700fb05ee815 100644 --- a/arch/arm/mach-ux500/include/mach/debug-macro.S +++ b/arch/arm/mach-ux500/include/mach/debug-macro.S @@ -14,7 +14,24 @@ #error Invalid Ux500 debug UART #endif -#define __UX500_UART(n) UX500_UART##n##_BASE +/* + * DEBUG_LL only works if only one SOC is built in. We don't use #else below + * in order to get "__UX500_UART redefined" warnings if more than one SOC is + * built, so that there's some hint during the build that something is wrong. + */ + +#ifdef CONFIG_UX500_SOC_DB5500 +#define __UX500_UART(n) U5500_UART##n##_BASE +#endif + +#ifdef CONFIG_UX500_SOC_DB8500 +#define __UX500_UART(n) U8500_UART##n##_BASE +#endif + +#ifndef __UX500_UART +#error Unknown SOC +#endif + #define UX500_UART(n) __UX500_UART(n) #define UART_BASE UX500_UART(CONFIG_UX500_DEBUG_UART) diff --git a/arch/arm/mach-ux500/include/mach/entry-macro.S b/arch/arm/mach-ux500/include/mach/entry-macro.S index a37f585a3ecb..071bba94f727 100644 --- a/arch/arm/mach-ux500/include/mach/entry-macro.S +++ b/arch/arm/mach-ux500/include/mach/entry-macro.S @@ -11,15 +11,10 @@ * warranty of any kind, whether express or implied. */ #include <mach/hardware.h> -#define HAVE_GET_IRQNR_PREAMBLE #include <asm/hardware/entry-macro-gic.S> .macro disable_fiq .endm - .macro get_irqnr_preamble, base, tmp - ldr \base, =IO_ADDRESS(UX500_GIC_CPU_BASE) - .endm - .macro arch_ret_to_user, tmp1, tmp2 .endm diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h index 6295cc581355..bf63f2631ba0 100644 --- a/arch/arm/mach-ux500/include/mach/hardware.h +++ b/arch/arm/mach-ux500/include/mach/hardware.h @@ -29,118 +29,12 @@ #include <mach/db8500-regs.h> #include <mach/db5500-regs.h> -#ifdef CONFIG_UX500_SOC_DB8500 -#define UX500(periph) U8500_##periph##_BASE -#elif defined(CONFIG_UX500_SOC_DB5500) -#define UX500(periph) U5500_##periph##_BASE -#endif - -#define UX500_BACKUPRAM0_BASE UX500(BACKUPRAM0) -#define UX500_BACKUPRAM1_BASE UX500(BACKUPRAM1) -#define UX500_B2R2_BASE UX500(B2R2) - -#define UX500_CLKRST1_BASE UX500(CLKRST1) -#define UX500_CLKRST2_BASE UX500(CLKRST2) -#define UX500_CLKRST3_BASE UX500(CLKRST3) -#define UX500_CLKRST5_BASE UX500(CLKRST5) -#define UX500_CLKRST6_BASE UX500(CLKRST6) - -#define UX500_DMA_BASE UX500(DMA) -#define UX500_FSMC_BASE UX500(FSMC) - -#define UX500_GIC_CPU_BASE UX500(GIC_CPU) -#define UX500_GIC_DIST_BASE UX500(GIC_DIST) - -#define UX500_I2C1_BASE UX500(I2C1) -#define UX500_I2C2_BASE UX500(I2C2) -#define UX500_I2C3_BASE UX500(I2C3) - -#define UX500_L2CC_BASE UX500(L2CC) -#define UX500_MCDE_BASE UX500(MCDE) -#define UX500_MTU0_BASE UX500(MTU0) -#define UX500_MTU1_BASE UX500(MTU1) -#define UX500_PRCMU_BASE UX500(PRCMU) - -#define UX500_RNG_BASE UX500(RNG) -#define UX500_RTC_BASE UX500(RTC) - -#define UX500_SCU_BASE UX500(SCU) - -#define UX500_SDI0_BASE UX500(SDI0) -#define UX500_SDI1_BASE UX500(SDI1) -#define UX500_SDI2_BASE UX500(SDI2) -#define UX500_SDI3_BASE UX500(SDI3) -#define UX500_SDI4_BASE UX500(SDI4) - -#define UX500_SPI0_BASE UX500(SPI0) -#define UX500_SPI1_BASE UX500(SPI1) -#define UX500_SPI2_BASE UX500(SPI2) -#define UX500_SPI3_BASE UX500(SPI3) - -#define UX500_SIA_BASE UX500(SIA) -#define UX500_SVA_BASE UX500(SVA) - -#define UX500_TWD_BASE UX500(TWD) - -#define UX500_UART0_BASE UX500(UART0) -#define UX500_UART1_BASE UX500(UART1) -#define UX500_UART2_BASE UX500(UART2) - -#define UX500_USBOTG_BASE UX500(USBOTG) - /* ST-Ericsson modified pl022 id */ #define SSP_PER_ID 0x01080022 #ifndef __ASSEMBLY__ -#include <asm/cputype.h> - -static inline bool cpu_is_u8500(void) -{ -#ifdef CONFIG_UX500_SOC_DB8500 - return 1; -#else - return 0; -#endif -} - -#define CPUID_DB8500ED 0x410fc090 -#define CPUID_DB8500V1 0x411fc091 -#define CPUID_DB8500V2 0x412fc091 - -static inline bool cpu_is_u8500ed(void) -{ - return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500ED); -} - -static inline bool cpu_is_u8500v1(void) -{ - return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V1); -} - -static inline bool cpu_is_u8500v2(void) -{ - return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V2); -} - -#ifdef CONFIG_UX500_SOC_DB8500 -bool cpu_is_u8500v10(void); -bool cpu_is_u8500v11(void); -bool cpu_is_u8500v20(void); -#else -static inline bool cpu_is_u8500v10(void) { return false; } -static inline bool cpu_is_u8500v11(void) { return false; } -static inline bool cpu_is_u8500v20(void) { return false; } -#endif - -static inline bool cpu_is_u5500(void) -{ -#ifdef CONFIG_UX500_SOC_DB5500 - return 1; -#else - return 0; -#endif -} +#include <mach/id.h> #define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) diff --git a/arch/arm/mach-ux500/include/mach/id.h b/arch/arm/mach-ux500/include/mach/id.h new file mode 100644 index 000000000000..f1288d10b6ab --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/id.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef __MACH_UX500_ID +#define __MACH_UX500_ID + +/** + * struct dbx500_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 + */ +struct dbx500_asic_id { + u16 partnumber; + u8 revision; + u8 process; +}; + +extern struct dbx500_asic_id dbx500_id; + +static inline unsigned int __attribute_const__ dbx500_partnumber(void) +{ + return dbx500_id.partnumber; +} + +static inline unsigned int __attribute_const__ dbx500_revision(void) +{ + return dbx500_id.revision; +} + +/* + * SOCs + */ + +static inline bool __attribute_const__ cpu_is_u8500(void) +{ + return dbx500_partnumber() == 0x8500; +} + +static inline bool __attribute_const__ cpu_is_u5500(void) +{ + return dbx500_partnumber() == 0x5500; +} + +/* + * 8500 revisions + */ + +static inline bool __attribute_const__ cpu_is_u8500ed(void) +{ + return cpu_is_u8500() && dbx500_revision() == 0x00; +} + +static inline bool __attribute_const__ cpu_is_u8500v1(void) +{ + return cpu_is_u8500() && (dbx500_revision() & 0xf0) == 0xA0; +} + +static inline bool __attribute_const__ cpu_is_u8500v10(void) +{ + return cpu_is_u8500() && dbx500_revision() == 0xA0; +} + +static inline bool __attribute_const__ cpu_is_u8500v11(void) +{ + return cpu_is_u8500() && dbx500_revision() == 0xA1; +} + +static inline bool __attribute_const__ cpu_is_u8500v2(void) +{ + return cpu_is_u8500() && ((dbx500_revision() & 0xf0) == 0xB0); +} + +#define ux500_unknown_soc() BUG() + +#endif diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h index 880ae45bc235..ba1294c13c4d 100644 --- a/arch/arm/mach-ux500/include/mach/irqs.h +++ b/arch/arm/mach-ux500/include/mach/irqs.h @@ -36,7 +36,7 @@ /* This will be overridden by board-specific irq headers */ #define IRQ_BOARD_END IRQ_BOARD_START -#ifdef CONFIG_MACH_U8500_MOP +#ifdef CONFIG_MACH_U8500 #include <mach/irqs-board-mop500.h> #endif diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index 469877e0de90..a7d363fdb4cd 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -14,7 +14,7 @@ #include <asm/mach/time.h> #include <linux/init.h> -extern void __init ux500_map_io(void); +void __init ux500_map_io(void); extern void __init u5500_map_io(void); extern void __init u8500_map_io(void); diff --git a/arch/arm/mach-ux500/modem-irq-db5500.c b/arch/arm/mach-ux500/modem-irq-db5500.c index 3187f8871169..e1296a7447c8 100644 --- a/arch/arm/mach-ux500/modem-irq-db5500.c +++ b/arch/arm/mach-ux500/modem-irq-db5500.c @@ -12,6 +12,8 @@ #include <linux/io.h> #include <linux/slab.h> +#include <mach/id.h> + #define MODEM_INTCON_BASE_ADDR 0xBFFD3000 #define MODEM_INTCON_SIZE 0xFFF @@ -101,6 +103,9 @@ static int modem_irq_init(void) static struct irq_chip modem_irq_chip; struct modem_irq *mi; + if (!cpu_is_u5500()) + return -ENODEV; + pr_info("modem_irq: Set up IRQ handler for incoming modem IRQ %d\n", IRQ_DB5500_MODEM); diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index d77e76cb7edd..4fff4d408417 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -20,6 +20,7 @@ #include <asm/cacheflush.h> #include <asm/smp_scu.h> #include <mach/hardware.h> +#include <mach/setup.h> /* * control for which core is the next to come out of the secondary @@ -40,6 +41,18 @@ static void write_pen_release(int val) outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); } +static void __iomem *scu_base_addr(void) +{ + if (cpu_is_u5500()) + return __io_address(U5500_SCU_BASE); + else if (cpu_is_u8500()) + return __io_address(U8500_SCU_BASE); + else + ux500_unknown_soc(); + + return NULL; +} + static DEFINE_SPINLOCK(boot_lock); void __cpuinit platform_secondary_init(unsigned int cpu) @@ -100,21 +113,28 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) static void __init wakeup_secondary(void) { + void __iomem *backupram; + + if (cpu_is_u5500()) + backupram = __io_address(U5500_BACKUPRAM0_BASE); + else if (cpu_is_u8500()) + backupram = __io_address(U8500_BACKUPRAM0_BASE); + else + ux500_unknown_soc(); + /* * write the address of secondary startup into the backup ram register * at offset 0x1FF4, then write the magic number 0xA1FEED01 to the * backup ram register at offset 0x1FF0, which is what boot rom code * is waiting for. This would wake up the secondary core from WFE */ -#define U8500_CPU1_JUMPADDR_OFFSET 0x1FF4 +#define UX500_CPU1_JUMPADDR_OFFSET 0x1FF4 __raw_writel(virt_to_phys(u8500_secondary_startup), - __io_address(UX500_BACKUPRAM0_BASE) + - U8500_CPU1_JUMPADDR_OFFSET); + backupram + UX500_CPU1_JUMPADDR_OFFSET); -#define U8500_CPU1_WAKEMAGIC_OFFSET 0x1FF0 +#define UX500_CPU1_WAKEMAGIC_OFFSET 0x1FF0 __raw_writel(0xA1FEED01, - __io_address(UX500_BACKUPRAM0_BASE) + - U8500_CPU1_WAKEMAGIC_OFFSET); + backupram + UX500_CPU1_WAKEMAGIC_OFFSET); /* make sure write buffer is drained */ mb(); @@ -126,9 +146,10 @@ static void __init wakeup_secondary(void) */ void __init smp_init_cpus(void) { + void __iomem *scu_base = scu_base_addr(); unsigned int i, ncores; - ncores = scu_get_core_count(__io_address(UX500_SCU_BASE)); + ncores = scu_base ? scu_get_core_count(scu_base) : 1; /* sanity check */ if (ncores > NR_CPUS) { @@ -154,6 +175,6 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus) for (i = 0; i < max_cpus; i++) set_cpu_present(i, true); - scu_enable(__io_address(UX500_SCU_BASE)); + scu_enable(scu_base_addr()); wakeup_secondary(); } |