From patchwork Thu Apr 12 17:23:54 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 7768 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id A3EB923E4C for ; Thu, 12 Apr 2012 17:24:17 +0000 (UTC) Received: from mail-yx0-f180.google.com (mail-yx0-f180.google.com [209.85.213.180]) by fiordland.canonical.com (Postfix) with ESMTP id 47F8DA180D1 for ; Thu, 12 Apr 2012 17:24:17 +0000 (UTC) Received: by yenl4 with SMTP id l4so1547553yen.11 for ; Thu, 12 Apr 2012 10:24:16 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to:cc :subject:date:message-id:x-mailer:mime-version:content-type :x-gm-message-state; bh=GSKDxpndZ/VnDZN5y72XjvMZxfgItxaQxxGy9HPr9cI=; b=eLzfQ2uUjrRZu2V2qktJJmAJ7yboJm7EgQ6mmezJjwwhlae+k1BZAeaYFOfcPuHEFB 1DjI5gpflhvaQb1hN+f2D1eTlpB5cxyUWlu4WZXwZAU1cf4rZIpjgWQsIlFRRvEc7OaH z8aamXDkWtJrZ8BxoGhYM9qw6yNGhI2hElswbVt0lQpE6uYPPmrNAJdK+LOWNG4MM28r ZhiQnuvmXzkmI22RftPaK7IFW+FfEZjIQig5SP6SzJXRWmEA+yVLS1/6nrv6a1CvJRll j04OXlFBFCTL1UGxG3l+vEMNYF7+5qg/D5Y1CTJGWIwL3/jcgZQI3YJ+yhHKdCcFLF+k YKOg== Received: by 10.50.188.199 with SMTP id gc7mr3610687igc.40.1334251456116; Thu, 12 Apr 2012 10:24:16 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.70.69 with SMTP id c5csp277318ibj; Thu, 12 Apr 2012 10:24:15 -0700 (PDT) Received: by 10.213.108.147 with SMTP id f19mr272274ebp.162.1334251454530; Thu, 12 Apr 2012 10:24:14 -0700 (PDT) Received: from eu1sys200aog103.obsmtp.com (eu1sys200aog103.obsmtp.com. [207.126.144.115]) by mx.google.com with SMTP id m44si1875797eeh.59.2012.04.12.10.24.10 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 12 Apr 2012 10:24:14 -0700 (PDT) Received-SPF: neutral (google.com: 207.126.144.115 is neither permitted nor denied by best guess record for domain of linus.walleij@stericsson.com) client-ip=207.126.144.115; Authentication-Results: mx.google.com; spf=neutral (google.com: 207.126.144.115 is neither permitted nor denied by best guess record for domain of linus.walleij@stericsson.com) smtp.mail=linus.walleij@stericsson.com Received: from beta.dmz-us.st.com ([167.4.1.35]) (using TLSv1) by eu1sys200aob103.postini.com ([207.126.147.11]) with SMTP ID DSNKT4cPubB6TwJfCzEjIkckM1Ct1dCZ3u4I@postini.com; Thu, 12 Apr 2012 17:24:14 UTC Received: from zeta.dmz-us.st.com (ns4.st.com [167.4.16.71]) by beta.dmz-us.st.com (STMicroelectronics) with ESMTP id 212F54D; Thu, 12 Apr 2012 17:23:44 +0000 (GMT) Received: from relay1.stm.gmessaging.net (unknown [10.230.100.17]) by zeta.dmz-us.st.com (STMicroelectronics) with ESMTP id 17B794E; Thu, 12 Apr 2012 15:22:54 +0000 (GMT) Received: from exdcvycastm004.EQ1STM.local (alteon-source-exch [10.230.100.61]) (using TLSv1 with cipher RC4-MD5 (128/128 bits)) (Client CN "exdcvycastm004", Issuer "exdcvycastm004" (not verified)) by relay1.stm.gmessaging.net (Postfix) with ESMTPS id 6FB2924C075; Thu, 12 Apr 2012 19:23:49 +0200 (CEST) Received: from steludxu4075.lud.stericsson.com (10.230.100.153) by smtp.stericsson.com (10.230.100.2) with Microsoft SMTP Server (TLS) id 8.3.83.0; Thu, 12 Apr 2012 19:23:58 +0200 From: Linus Walleij To: Cc: Linus Walleij , Arnd Bergmann , Sebastien Pasdeloup , Michel Jaouen Subject: [PATCH v3] ARM: ux500: core U9540 support Date: Thu, 12 Apr 2012 19:23:54 +0200 Message-ID: <1334251434-15154-1-git-send-email-linus.walleij@stericsson.com> X-Mailer: git-send-email 1.7.9.2 MIME-Version: 1.0 X-Gm-Message-State: ALoCoQmzQKuP7+MB/CeXYwc145TeGh1BLYh+8Ne3iw+2pT1lcMpR2RuRWxbMZGIUov8yNBfqVm7o From: Linus Walleij This adds support for the U9540 variant of the U8500 series. This is an application processor without internal modem. This is the most basic part with ASIC ID, CPU-related fixes, IRQ list, register ranges, timer, UART, and L2 cache setup. This is based on a patch by Michel Jaouen which was rewritten to fit with the latest 3.3 kernel. ChangeLog v1->v2: deleted the irqs-db9540.h file since we expect to migrate to using Device Tree for getting the IRQs to devices. ChangeLog v2->v3: introduced a fixed virtual offset for the ROM as suggested by Arnd Bergmann. Cc: Arnd Bergmann Signed-off-by: Sebastien Pasdeloup Signed-off-by: Michel Jaouen Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500-uib.c | 2 +- arch/arm/mach-ux500/cache-l2x0.c | 16 +++++++++++++--- arch/arm/mach-ux500/clock.c | 2 +- arch/arm/mach-ux500/cpu-db8500.c | 6 +++--- arch/arm/mach-ux500/cpu.c | 4 ++-- arch/arm/mach-ux500/id.c | 9 +++++++-- arch/arm/mach-ux500/include/mach/db8500-regs.h | 6 ++++++ arch/arm/mach-ux500/include/mach/hardware.h | 3 +++ arch/arm/mach-ux500/include/mach/id.h | 17 ++++++++++++++++- arch/arm/mach-ux500/include/mach/irqs.h | 2 +- arch/arm/mach-ux500/include/mach/setup.h | 7 +++++++ arch/arm/mach-ux500/platsmp.c | 4 ++-- arch/arm/mach-ux500/timer.c | 2 +- drivers/cpufreq/db8500-cpufreq.c | 2 +- 14 files changed, 64 insertions(+), 18 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c index 5af36aa..b29a788 100644 --- a/arch/arm/mach-ux500/board-mop500-uib.c +++ b/arch/arm/mach-ux500/board-mop500-uib.c @@ -102,7 +102,7 @@ static int __init mop500_uib_init(void) struct i2c_adapter *i2c0; int ret; - if (!cpu_is_u8500()) + if (!cpu_is_u8500_family()) return -ENODEV; if (uib) { diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c index 77a75ed..677bb76 100644 --- a/arch/arm/mach-ux500/cache-l2x0.c +++ b/arch/arm/mach-ux500/cache-l2x0.c @@ -36,9 +36,11 @@ static int __init ux500_l2x0_unlock(void) static int __init ux500_l2x0_init(void) { + u32 aux_val = 0x3e000000; + if (cpu_is_u5500()) l2x0_base = __io_address(U5500_L2CC_BASE); - else if (cpu_is_u8500()) + else if (cpu_is_u8500_family()) l2x0_base = __io_address(U8500_L2CC_BASE); else ux500_unknown_soc(); @@ -46,11 +48,19 @@ static int __init ux500_l2x0_init(void) /* Unlock before init */ ux500_l2x0_unlock(); + /* DB9540's L2 has 128KB way size */ + if (cpu_is_u9540()) + /* 128KB way size */ + aux_val |= (0x4 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT); + else + /* 64KB way size */ + aux_val |= (0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT); + /* 64KB way size, 8 way associativity, force WA */ if (of_have_populated_dt()) - l2x0_of_init(0x3e060000, 0xc0000fff); + l2x0_of_init(aux_val, 0xc0000fff); else - l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); + l2x0_init(l2x0_base, aux_val, 0xc0000fff); /* * We can't disable l2 as we are in non secure mode, currently diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index ec35f0a..cc87f77 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -151,7 +151,7 @@ static unsigned long clk_mtu_get_rate(struct clk *clk) if (cpu_is_u5500()) addr = __io_address(U5500_PRCMU_BASE); - else if (cpu_is_u8500()) + else if (cpu_is_u8500_family()) addr = __io_address(U8500_PRCMU_BASE); else ux500_unknown_soc(); diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 9bd8163..0bdcdd9 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -34,8 +34,8 @@ 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 = { +/* U8500 and U9540 common io_desc */ +static struct map_desc u8500_common_io_desc[] __initdata = { /* SCU base also covers GIC CPU BASE and TWD with its 4K page */ __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K), __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K), @@ -66,7 +66,7 @@ void __init u8500_map_io(void) ux500_map_io(); - iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); + iotable_init(u8500_common_io_desc, ARRAY_SIZE(u8500_common_io_desc)); _PRCMU_BASE = __io_address(U8500_PRCMU_BASE); } diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index d11f389..857e481 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -43,7 +43,7 @@ void __init ux500_init_irq(void) 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()) { + } else if (cpu_is_u8500_family()) { dist_base = __io_address(U8500_GIC_DIST_BASE); cpu_base = __io_address(U8500_GIC_CPU_BASE); } else @@ -62,7 +62,7 @@ void __init ux500_init_irq(void) */ if (cpu_is_u5500()) db5500_prcmu_early_init(); - if (cpu_is_u8500()) + if (cpu_is_u8500_family()) db8500_prcmu_early_init(); clk_init(); } diff --git a/arch/arm/mach-ux500/id.c b/arch/arm/mach-ux500/id.c index 15a0f63..d157992 100644 --- a/arch/arm/mach-ux500/id.c +++ b/arch/arm/mach-ux500/id.c @@ -23,7 +23,7 @@ static unsigned int ux500_read_asicid(phys_addr_t addr) { phys_addr_t base = addr & ~0xfff; struct map_desc desc = { - .virtual = IO_ADDRESS(base), + .virtual = UX500_VIRT_ROM, .pfn = __phys_to_pfn(base), .length = SZ_16K, .type = MT_DEVICE, @@ -35,7 +35,7 @@ static unsigned int ux500_read_asicid(phys_addr_t addr) local_flush_tlb_all(); flush_cache_all(); - return readl(__io_address(addr)); + return readl(IOMEM(UX500_VIRT_ROM + (addr & 0xfff))); } static void ux500_print_soc_info(unsigned int asicid) @@ -67,6 +67,7 @@ static unsigned int partnumber(unsigned int asicid) * DB8500v2 0x412fc091 0x9001DBF4 0x008500B0 * DB8520v2.2 0x412fc091 0x9001DBF4 0x008500B2 * DB5500v1 0x412fc091 0x9001FFF4 0x005500A0 + * DB9540 0x413fc090 0xFFFFDBF4 0x009540xx */ void __init ux500_map_io(void) @@ -91,6 +92,10 @@ void __init ux500_map_io(void) /* DB5500v1 */ addr = 0x9001FFF4; break; + + case 0x413fc090: /* DB9540 */ + addr = 0xFFFFDBF4; + break; } if (addr) diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h index 9ec20b9..1530d49 100644 --- a/arch/arm/mach-ux500/include/mach/db8500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h @@ -41,6 +41,10 @@ /* ASIC ID is at 0xbf4 offset within this region */ #define U8500_ASIC_ID_BASE 0x9001D000 +#define U9540_BOOT_ROM_BASE 0xFFFE0000 +/* ASIC ID is at 0xbf4 offset within this region */ +#define U9540_ASIC_ID_BASE 0xFFFFD000 + #define U8500_PER6_BASE 0xa03c0000 #define U8500_PER7_BASE 0xa03d0000 #define U8500_PER5_BASE 0xa03e0000 @@ -96,7 +100,9 @@ #define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000) #define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000) #define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000) +#define U9540_DMC1_BASE (U8500_PER4_BASE + 0x0A000) #define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000) +#define U9540_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x6A000) #define U8500_PRCMU_TCPM_BASE (U8500_PER4_BASE + 0x60000) #define U8500_PRCMU_TIMER_3_BASE (U8500_PER4_BASE + 0x07338) #define U8500_PRCMU_TIMER_4_BASE (U8500_PER4_BASE + 0x07450) diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h index f846989..8361657 100644 --- a/arch/arm/mach-ux500/include/mach/hardware.h +++ b/arch/arm/mach-ux500/include/mach/hardware.h @@ -17,6 +17,8 @@ */ #define U8500_IO_VIRTUAL 0xf0000000 #define U8500_IO_PHYSICAL 0xa0000000 +/* This is where we map in the ROM to check ASIC IDs */ +#define UX500_VIRT_ROM 0xf0000000 /* This macro is used in assembly, so no cast */ #define IO_ADDRESS(x) \ @@ -24,6 +26,7 @@ /* typesafe io address */ #define __io_address(n) IOMEM(IO_ADDRESS(n)) + /* Used by some plat-nomadik code */ #define io_p2v(n) __io_address(n) diff --git a/arch/arm/mach-ux500/include/mach/id.h b/arch/arm/mach-ux500/include/mach/id.h index 833d6a6..c6e2db9 100644 --- a/arch/arm/mach-ux500/include/mach/id.h +++ b/arch/arm/mach-ux500/include/mach/id.h @@ -41,6 +41,16 @@ static inline bool __attribute_const__ cpu_is_u8500(void) return dbx500_partnumber() == 0x8500; } +static inline bool __attribute_const__ cpu_is_u9540(void) +{ + return dbx500_partnumber() == 0x9540; +} + +static inline bool cpu_is_u8500_family(void) +{ + return cpu_is_u8500() || cpu_is_u9540(); +} + static inline bool __attribute_const__ cpu_is_u5500(void) { return dbx500_partnumber() == 0x5500; @@ -111,7 +121,12 @@ static inline bool cpu_is_u8500v21(void) static inline bool cpu_is_u8500v20_or_later(void) { - return cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11(); + /* + * U9540 has so much in common with U8500 that is is considered a + * U8500 variant. + */ + return cpu_is_u9540() || + (cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11()); } static inline bool ux500_is_svp(void) diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h index c23a6b5..7da9ec5 100644 --- a/arch/arm/mach-ux500/include/mach/irqs.h +++ b/arch/arm/mach-ux500/include/mach/irqs.h @@ -24,7 +24,7 @@ */ #define IRQ_MTU0 (IRQ_SHPI_START + 4) -#define DBX500_NR_INTERNAL_IRQS 160 +#define DBX500_NR_INTERNAL_IRQS 166 /* After chip-specific IRQ numbers we have the GPIO ones */ #define NOMADIK_NR_GPIO 288 diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index 3dc00ff..48e007d 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -49,4 +49,11 @@ extern struct sys_timer ux500_timer; .type = MT_MEMORY, \ } +#define __MEM_DEV_DESC_DB9540_ROM(x, sz) { \ + .virtual = IO_ADDRESS_DB9540_ROM(x), \ + .pfn = __phys_to_pfn(x), \ + .length = sz, \ + .type = MT_MEMORY, \ +} + #endif /* __ASM_ARCH_SETUP_H */ diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index eff5842..f499a07 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -50,7 +50,7 @@ static void __iomem *scu_base_addr(void) { if (cpu_is_u5500()) return __io_address(U5500_SCU_BASE); - else if (cpu_is_u8500()) + else if (cpu_is_u8500_family()) return __io_address(U8500_SCU_BASE); else ux500_unknown_soc(); @@ -122,7 +122,7 @@ static void __init wakeup_secondary(void) if (cpu_is_u5500()) backupram = __io_address(U5500_BACKUPRAM0_BASE); - else if (cpu_is_u8500()) + else if (cpu_is_u8500_family()) backupram = __io_address(U8500_BACKUPRAM0_BASE); else ux500_unknown_soc(); diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c index d37df98..3bfbfdf 100644 --- a/arch/arm/mach-ux500/timer.c +++ b/arch/arm/mach-ux500/timer.c @@ -51,7 +51,7 @@ static void __init ux500_timer_init(void) if (cpu_is_u5500()) { mtu_timer_base = __io_address(U5500_MTU0_BASE); prcmu_timer_base = __io_address(U5500_PRCMU_TIMER_3_BASE); - } else if (cpu_is_u8500()) { + } else if (cpu_is_u8500_family()) { mtu_timer_base = __io_address(U8500_MTU0_BASE); prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE); } else { diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c index 0bf1b89..74b830b 100644 --- a/drivers/cpufreq/db8500-cpufreq.c +++ b/drivers/cpufreq/db8500-cpufreq.c @@ -161,7 +161,7 @@ static struct cpufreq_driver db8500_cpufreq_driver = { static int __init db8500_cpufreq_register(void) { - if (!cpu_is_u8500v20_or_later()) + if (!cpu_is_u8500_family()) return -ENODEV; pr_info("cpufreq for DB8500 started\n");