From fd0053c9eb7e01b1d300f4c28c9eec7ca4cda690 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 25 Nov 2015 17:32:14 +0100 Subject: [PATCH 01/11] ARM: realview: remove sparsemem hack The realview-pbx platform has an elaborate way of avoiding the use of highmem by redefining its phys_to_virt function. In practice this doesn't help all that much, and it gets in the way of doing multiplatform builds for realview. This removes the feature and kills off the mach/memory.h file for realview. We also lose the ability to do sparsemem with this patch, but that should be put back into place for generic multiplatform configurations, to save a little memory on PBX. Signed-off-by: Arnd Bergmann Signed-off-by: Linus Walleij --- arch/arm/Kconfig | 2 - arch/arm/mach-realview/Kconfig | 5 +- arch/arm/mach-realview/include/mach/memory.h | 64 -------------------- 3 files changed, 2 insertions(+), 69 deletions(-) delete mode 100644 arch/arm/mach-realview/include/mach/memory.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0365cbbc9179..29915c7af9eb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -239,7 +239,6 @@ config ARM_PATCH_PHYS_VIRT bool "Patch physical to virtual translations at runtime" if EMBEDDED default y depends on !XIP_KERNEL && MMU - depends on !ARCH_REALVIEW || !SPARSEMEM help Patch phys-to-virt and virt-to-phys translation functions at boot and module load time according to the position of the @@ -354,7 +353,6 @@ config ARCH_REALVIEW select GENERIC_CLOCKEVENTS select GPIO_PL061 if GPIOLIB select ICST - select NEED_MACH_MEMORY_H select PLAT_VERSATILE select PLAT_VERSATILE_SCHED_CLOCK help diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index 565925f37dc5..0fe63b543f5b 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -102,14 +102,13 @@ config MACH_REALVIEW_PBA8 config MACH_REALVIEW_PBX bool "Support RealView(R) Platform Baseboard Explore" - select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET select ARM_GIC select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP select HAVE_PATA_PLATFORM select HAVE_SMP select MIGHT_HAVE_CACHE_L2X0 - select ZONE_DMA if SPARSEMEM + select ZONE_DMA help Include support for the ARM(R) RealView(R) Platform Baseboard Explore. @@ -124,6 +123,6 @@ config REALVIEW_HIGH_PHYS_OFFSET the board supports 512MB of RAM, this option allows the memory to be accessed contiguously at the high physical offset. On the PBX board, disabling this option allows 1GB of - RAM to be used with SPARSEMEM. + RAM to be used with HIGHMEM. endmenu diff --git a/arch/arm/mach-realview/include/mach/memory.h b/arch/arm/mach-realview/include/mach/memory.h deleted file mode 100644 index 23e7a313f75d..000000000000 --- a/arch/arm/mach-realview/include/mach/memory.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * arch/arm/mach-realview/include/mach/memory.h - * - * Copyright (C) 2003 ARM Limited - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that 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 - */ -#ifndef __ASM_ARCH_MEMORY_H -#define __ASM_ARCH_MEMORY_H - -#ifdef CONFIG_SPARSEMEM - -/* - * Sparsemem definitions for RealView PBX. - * - * The RealView PBX board has another block of 512MB of RAM at 0x20000000, - * however only the block at 0x70000000 (or the 256MB mirror at 0x00000000) - * may be used for DMA. - * - * The macros below define a section size of 256MB and a non-linear virtual to - * physical mapping: - * - * 256MB @ 0x00000000 -> PAGE_OFFSET - * 512MB @ 0x20000000 -> PAGE_OFFSET + 0x10000000 - * 256MB @ 0x80000000 -> PAGE_OFFSET + 0x30000000 - */ -#ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET -#error "SPARSEMEM not available with REALVIEW_HIGH_PHYS_OFFSET" -#endif - -#define MAX_PHYSMEM_BITS 32 -#define SECTION_SIZE_BITS 28 - -/* bank page offsets */ -#define PAGE_OFFSET1 (PAGE_OFFSET + 0x10000000) -#define PAGE_OFFSET2 (PAGE_OFFSET + 0x30000000) - -#define PHYS_OFFSET PLAT_PHYS_OFFSET - -#define __phys_to_virt(phys) \ - ((phys) >= 0x80000000 ? (phys) - 0x80000000 + PAGE_OFFSET2 : \ - (phys) >= 0x20000000 ? (phys) - 0x20000000 + PAGE_OFFSET1 : \ - (phys) + PAGE_OFFSET) - -#define __virt_to_phys(virt) \ - ((virt) >= PAGE_OFFSET2 ? (virt) - PAGE_OFFSET2 + 0x80000000 : \ - (virt) >= PAGE_OFFSET1 ? (virt) - PAGE_OFFSET1 + 0x20000000 : \ - (virt) - PAGE_OFFSET) - -#endif /* CONFIG_SPARSEMEM */ - -#endif From 930748a0335573ff360744e068dd841b63a29bf0 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 25 Nov 2015 17:32:15 +0100 Subject: [PATCH 02/11] ARM: realview: don't map undefined PCI registers PCI support for realview was never merged, and trying to build realview with CONFIG_PCI enabled fails because the constants for the mapping windows are not defined anywhere. This removes them from the static I/O window mapping table as a preparation for multiplatform support. Signed-off-by: Arnd Bergmann Signed-off-by: Linus Walleij --- arch/arm/mach-realview/realview_pba8.c | 8 -------- arch/arm/mach-realview/realview_pbx.c | 8 -------- 2 files changed, 16 deletions(-) diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index 4c64662f5437..b3549a637ff0 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -77,14 +77,6 @@ static struct map_desc realview_pba8_io_desc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE, }, -#ifdef CONFIG_PCI - { - .virtual = PCIX_UNIT_BASE, - .pfn = __phys_to_pfn(REALVIEW_PBA8_PCI_BASE), - .length = REALVIEW_PBA8_PCI_BASE_SIZE, - .type = MT_DEVICE - }, -#endif #ifdef CONFIG_DEBUG_LL { .virtual = IO_ADDRESS(REALVIEW_PBA8_UART0_BASE), diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index 9a22b864219f..f26e1e09f29e 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -79,14 +79,6 @@ static struct map_desc realview_pbx_io_desc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE, }, -#ifdef CONFIG_PCI - { - .virtual = PCIX_UNIT_BASE, - .pfn = __phys_to_pfn(REALVIEW_PBX_PCI_BASE), - .length = REALVIEW_PBX_PCI_BASE_SIZE, - .type = MT_DEVICE, - }, -#endif #ifdef CONFIG_DEBUG_LL { .virtual = IO_ADDRESS(REALVIEW_PBX_UART0_BASE), From 3c30a4a357bd1011322782d6a60fa284d8bd8286 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 25 Nov 2015 17:32:16 +0100 Subject: [PATCH 03/11] clk/realview: stop using machine headers In order to move realview into multiplatform, we have to prevent device drivers from accessing the machine header files. In case of the clk driver, this is very simple, we just copy the small set of register definitions into the driver that needs them. Signed-off-by: Arnd Bergmann Signed-off-by: Linus Walleij --- drivers/clk/versatile/clk-realview.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/clk/versatile/clk-realview.c b/drivers/clk/versatile/clk-realview.c index 86f70997d59d..bd4dd2463e23 100644 --- a/drivers/clk/versatile/clk-realview.c +++ b/drivers/clk/versatile/clk-realview.c @@ -11,11 +11,15 @@ #include #include -#include -#include - #include "clk-icst.h" +#define REALVIEW_SYS_OSC0_OFFSET 0x0C +#define REALVIEW_SYS_OSC1_OFFSET 0x10 +#define REALVIEW_SYS_OSC2_OFFSET 0x14 +#define REALVIEW_SYS_OSC3_OFFSET 0x18 +#define REALVIEW_SYS_OSC4_OFFSET 0x1C /* OSC1 for RealView/AB */ +#define REALVIEW_SYS_LOCK_OFFSET 0x20 + /* * Implementation of the ARM RealView clock trees. */ From 38541bf48588d5350e45167510766f8bb6ba6582 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 25 Nov 2015 17:32:17 +0100 Subject: [PATCH 04/11] ARM: no longer force unbuffered DMA for realview Commit 42c4dafe803dca ("ARM: 6202/1: Do not ARM_DMA_MEM_BUFFERABLE on RealView boards with L210/L220") changed the generic setting for ARM_DMA_MEM_BUFFERABLE to be disabled on any Realview kernel that includes support for any of the ARM11 variations. Doing this was required to allow doing DMA without a lockup in the l2x0 cache controller on the Realview platform. Unfortunately, in a kernel that also contains support for any ARMv7 based machine, the same change makes it impossible to do DMA on ARMv7, which gets in the way of enabling multiplatform support on Realview. As confirmed by Catalin Marinas and Linus Walleij, the current code for Realview that we have in the kernel does not actually perform any DMA, and this is unlikely to change in the future. Therefore we can revert 42c4dafe803dca without introducing regressions, but we must never start using DMA on this platform in the future. Signed-off-by: Arnd Bergmann Cc: Russell King Signed-off-by: Linus Walleij --- arch/arm/mm/Kconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 41218867a9a6..76f65f2d59b1 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -1005,8 +1005,6 @@ config ARM_L1_CACHE_SHIFT config ARM_DMA_MEM_BUFFERABLE bool "Use non-cacheable memory for DMA" if (CPU_V6 || CPU_V6K) && !CPU_V7 - depends on !(MACH_REALVIEW_PB1176 || REALVIEW_EB_ARM11MP || \ - MACH_REALVIEW_PB11MP) default y if CPU_V6 || CPU_V6K || CPU_V7 help Historically, the kernel has used strongly ordered mappings to From 2b749cb3a5153fc4c312e405ecca8a925e6632c8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 25 Nov 2015 17:32:18 +0100 Subject: [PATCH 05/11] ARM: realview: remove private barrier implementation The realview barrier implementation tries to avoid calling outer_sync in order to not lock up as a result of a bug in the l220 cache controller. This gets in the way of the multiplatform support, but we can still remove it if we make sure that the outer_sync function never gets called, by replacing the function pointer with NULL, right after initialization. Signed-off-by: Arnd Bergmann [Fixed up header inclusions] Signed-off-by: Linus Walleij --- arch/arm/mach-realview/Kconfig | 2 -- arch/arm/mach-realview/include/mach/barriers.h | 8 -------- arch/arm/mach-realview/realview_eb.c | 7 +++++++ arch/arm/mach-realview/realview_pb11mp.c | 6 ++++++ 4 files changed, 13 insertions(+), 10 deletions(-) delete mode 100644 arch/arm/mach-realview/include/mach/barriers.h diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index 0fe63b543f5b..055e7355ec14 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -36,7 +36,6 @@ config REALVIEW_EB_A9MP config REALVIEW_EB_ARM11MP bool "Support ARM11MPCore Tile" depends on MACH_REALVIEW_EB - select ARCH_HAS_BARRIERS if SMP select CPU_V6K select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP @@ -57,7 +56,6 @@ config REALVIEW_EB_ARM11MP_REVB config MACH_REALVIEW_PB11MP bool "Support RealView(R) Platform Baseboard for ARM11MPCore" - select ARCH_HAS_BARRIERS if SMP select ARM_GIC select CPU_V6K select HAVE_ARM_SCU if SMP diff --git a/arch/arm/mach-realview/include/mach/barriers.h b/arch/arm/mach-realview/include/mach/barriers.h deleted file mode 100644 index 9a732195aa1c..000000000000 --- a/arch/arm/mach-realview/include/mach/barriers.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Barriers redefined for RealView ARM11MPCore platforms with L220 cache - * controller to work around hardware errata causing the outer_sync() - * operation to deadlock the system. - */ -#define mb() dsb() -#define rmb() dsb() -#define wmb() mb() diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index b3869cbbcc68..1a2a89708fb7 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -450,6 +451,12 @@ static void __init realview_eb_init(void) * Bits: .... ...0 0111 1001 0000 .... .... .... */ l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff); + + /* + * due to a bug in the l220 cache controller, we must not call + * the sync function. stub it out here instead! + */ + outer_cache.sync = NULL; #endif pmu_device.name = core_tile_a9mp() ? "armv7-pmu" : "armv6-pmu"; platform_device_register(&pmu_device); diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index 15c45e25095f..5bb460300b6a 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -345,6 +346,11 @@ static void __init realview_pb11mp_init(void) * Bits: .... ...0 0111 1001 0000 .... .... .... */ l2x0_init(__io_address(REALVIEW_TC11MP_L220_BASE), 0x00790000, 0xfe000fff); + /* + * due to a bug in the l220 cache controller, we must not call + * the sync function. stub it out here instead! + */ + outer_cache.sync = NULL; #endif realview_flash_register(realview_pb11mp_flash_resource, From 179c8fb3c2a6cc86cc746e6d071be00f611328de Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 12 Oct 2015 15:52:50 +0200 Subject: [PATCH 06/11] clk: versatile-icst: convert to use regmap Instead of passing around register bases, pass around a regmap in this driver. This refactoring make things so much easier when we later want to manage an ICST that is part of a syscon. Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Signed-off-by: Linus Walleij --- drivers/clk/versatile/Kconfig | 1 + drivers/clk/versatile/clk-icst.c | 86 ++++++++++++++++++++++---------- 2 files changed, 60 insertions(+), 27 deletions(-) diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig index fc50b6264bed..e733385bca9f 100644 --- a/drivers/clk/versatile/Kconfig +++ b/drivers/clk/versatile/Kconfig @@ -1,6 +1,7 @@ config COMMON_CLK_VERSATILE bool "Clock driver for ARM Reference designs" depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS || ARM64 || COMPILE_TEST + select REGMAP_MMIO ---help--- Supports clocking on ARM Reference designs: - Integrator/AP and Integrator/CP diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index 08c5ee976879..80e955ac6ef5 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c @@ -19,9 +19,13 @@ #include #include #include +#include #include "clk-icst.h" +/* Magic unlocking token used on all Versatile boards */ +#define VERSATILE_LOCK_VAL 0xA05F + /** * struct clk_icst - ICST VCO clock wrapper * @hw: corresponding clock hardware entry @@ -32,8 +36,9 @@ */ struct clk_icst { struct clk_hw hw; - void __iomem *vcoreg; - void __iomem *lockreg; + struct regmap *map; + u32 vcoreg_off; + u32 lockreg_off; struct icst_params *params; unsigned long rate; }; @@ -41,53 +46,67 @@ struct clk_icst { #define to_icst(_hw) container_of(_hw, struct clk_icst, hw) /** - * vco_get() - get ICST VCO settings from a certain register - * @vcoreg: register containing the VCO settings + * vco_get() - get ICST VCO settings from a certain ICST + * @icst: the ICST clock to get + * @vco: the VCO struct to return the value in */ -static struct icst_vco vco_get(void __iomem *vcoreg) +static int vco_get(struct clk_icst *icst, struct icst_vco *vco) { u32 val; - struct icst_vco vco; + int ret; - val = readl(vcoreg); - vco.v = val & 0x1ff; - vco.r = (val >> 9) & 0x7f; - vco.s = (val >> 16) & 03; - return vco; + ret = regmap_read(icst->map, icst->vcoreg_off, &val); + if (ret) + return ret; + vco->v = val & 0x1ff; + vco->r = (val >> 9) & 0x7f; + vco->s = (val >> 16) & 03; + return 0; } /** * vco_set() - commit changes to an ICST VCO - * @locreg: register to poke to unlock the VCO for writing - * @vcoreg: register containing the VCO settings - * @vco: ICST VCO parameters to commit + * @icst: the ICST clock to set + * @vco: the VCO struct to set the changes from */ -static void vco_set(void __iomem *lockreg, - void __iomem *vcoreg, - struct icst_vco vco) +static int vco_set(struct clk_icst *icst, struct icst_vco vco) { u32 val; + int ret; - val = readl(vcoreg) & ~0x7ffff; + ret = regmap_read(icst->map, icst->vcoreg_off, &val); + if (ret) + return ret; val |= vco.v | (vco.r << 9) | (vco.s << 16); /* This magic unlocks the VCO so it can be controlled */ - writel(0xa05f, lockreg); - writel(val, vcoreg); + ret = regmap_write(icst->map, icst->lockreg_off, VERSATILE_LOCK_VAL); + if (ret) + return ret; + ret = regmap_write(icst->map, icst->vcoreg_off, val); + if (ret) + return ret; /* This locks the VCO again */ - writel(0, lockreg); + ret = regmap_write(icst->map, icst->lockreg_off, 0); + if (ret) + return ret; + return 0; } - static unsigned long icst_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_icst *icst = to_icst(hw); struct icst_vco vco; + int ret; if (parent_rate) icst->params->ref = parent_rate; - vco = vco_get(icst->vcoreg); + ret = vco_get(icst, &vco); + if (ret) { + pr_err("ICST: could not get VCO setting\n"); + return 0; + } icst->rate = icst_hz(icst->params, vco); return icst->rate; } @@ -112,8 +131,7 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate, icst->params->ref = parent_rate; vco = icst_hz_to_vco(icst->params, rate); icst->rate = icst_hz(icst->params, vco); - vco_set(icst->lockreg, icst->vcoreg, vco); - return 0; + return vco_set(icst, vco); } static const struct clk_ops icst_ops = { @@ -132,6 +150,11 @@ struct clk *icst_clk_register(struct device *dev, struct clk_icst *icst; struct clk_init_data init; struct icst_params *pclone; + struct regmap_config icst_regmap_conf = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + }; icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL); if (!icst) { @@ -151,10 +174,19 @@ struct clk *icst_clk_register(struct device *dev, init.flags = CLK_IS_ROOT; init.parent_names = (parent_name ? &parent_name : NULL); init.num_parents = (parent_name ? 1 : 0); + icst->map = regmap_init_mmio(dev, base, &icst_regmap_conf); + if (IS_ERR(icst->map)) { + int ret; + + pr_err("could not initialize ICST regmap\n"); + ret = PTR_ERR(icst->map); + kfree(icst); + return ERR_PTR(ret); + } icst->hw.init = &init; icst->params = pclone; - icst->vcoreg = base + desc->vco_offset; - icst->lockreg = base + desc->lock_offset; + icst->vcoreg_off = desc->vco_offset; + icst->lockreg_off = desc->lock_offset; clk = clk_register(dev, &icst->hw); if (IS_ERR(clk)) { From 384d977d74f434ea089e9419fa9233fcfa18602b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 12 Oct 2015 16:14:28 +0200 Subject: [PATCH 07/11] clk: versatile-icst: refactor to allocate regmap separately Break out the registration function so it creates a regmap and pass to the setup function, so the latter can be shared with a device tree probe function that already has a regmap. Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Signed-off-by: Linus Walleij --- drivers/clk/versatile/clk-icst.c | 47 +++++++++++++++++++------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index 80e955ac6ef5..87bd4667b126 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "clk-icst.h" @@ -140,21 +141,16 @@ static const struct clk_ops icst_ops = { .set_rate = icst_set_rate, }; -struct clk *icst_clk_register(struct device *dev, - const struct clk_icst_desc *desc, - const char *name, - const char *parent_name, - void __iomem *base) +static struct clk *icst_clk_setup(struct device *dev, + const struct clk_icst_desc *desc, + const char *name, + const char *parent_name, + struct regmap *map) { struct clk *clk; struct clk_icst *icst; struct clk_init_data init; struct icst_params *pclone; - struct regmap_config icst_regmap_conf = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - }; icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL); if (!icst) { @@ -174,15 +170,7 @@ struct clk *icst_clk_register(struct device *dev, init.flags = CLK_IS_ROOT; init.parent_names = (parent_name ? &parent_name : NULL); init.num_parents = (parent_name ? 1 : 0); - icst->map = regmap_init_mmio(dev, base, &icst_regmap_conf); - if (IS_ERR(icst->map)) { - int ret; - - pr_err("could not initialize ICST regmap\n"); - ret = PTR_ERR(icst->map); - kfree(icst); - return ERR_PTR(ret); - } + icst->map = map; icst->hw.init = &init; icst->params = pclone; icst->vcoreg_off = desc->vco_offset; @@ -196,4 +184,25 @@ struct clk *icst_clk_register(struct device *dev, return clk; } + +struct clk *icst_clk_register(struct device *dev, + const struct clk_icst_desc *desc, + const char *name, + const char *parent_name, + void __iomem *base) +{ + struct regmap_config icst_regmap_conf = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + }; + struct regmap *map; + + map = regmap_init_mmio(dev, base, &icst_regmap_conf); + if (IS_ERR(map)) { + pr_err("could not initialize ICST regmap\n"); + return ERR_CAST(map); + } + return icst_clk_setup(dev, desc, name, parent_name, map); +} EXPORT_SYMBOL_GPL(icst_clk_register); From d430819d69a51dc4798bb98d841afa9af2f5c83a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 13 Oct 2015 14:29:54 +0200 Subject: [PATCH 08/11] clk: versatile-icst: add device tree support This adds support for the ARM syscon ICST clocks to initialized directly from the device tree syscon node on ARM Integrator, Versatile and RealView reference designs. Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Signed-off-by: Linus Walleij --- drivers/clk/versatile/clk-icst.c | 89 +++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index 87bd4667b126..e62f8cb2c9b5 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c @@ -3,7 +3,7 @@ * We wrap the custom interface from into the generic * clock framework. * - * Copyright (C) 2012 Linus Walleij + * Copyright (C) 2012-2015 Linus Walleij * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -206,3 +206,90 @@ struct clk *icst_clk_register(struct device *dev, return icst_clk_setup(dev, desc, name, parent_name, map); } EXPORT_SYMBOL_GPL(icst_clk_register); + +#ifdef CONFIG_OF +/* + * In a device tree, an memory-mapped ICST clock appear as a child + * of a syscon node. Assume this and probe it only as a child of a + * syscon. + */ + +static const struct icst_params icst525_params = { + .vco_max = ICST525_VCO_MAX_5V, + .vco_min = ICST525_VCO_MIN, + .vd_min = 8, + .vd_max = 263, + .rd_min = 3, + .rd_max = 65, + .s2div = icst525_s2div, + .idx2s = icst525_idx2s, +}; + +static const struct icst_params icst307_params = { + .vco_max = ICST307_VCO_MAX, + .vco_min = ICST307_VCO_MIN, + .vd_min = 4 + 8, + .vd_max = 511 + 8, + .rd_min = 1 + 2, + .rd_max = 127 + 2, + .s2div = icst307_s2div, + .idx2s = icst307_idx2s, +}; + +static void __init of_syscon_icst_setup(struct device_node *np) +{ + struct device_node *parent; + struct regmap *map; + struct clk_icst_desc icst_desc; + const char *name = np->name; + const char *parent_name; + struct clk *regclk; + + /* We do not release this reference, we are using it perpetually */ + parent = of_get_parent(np); + if (!parent) { + pr_err("no parent node for syscon ICST clock\n"); + return; + } + map = syscon_node_to_regmap(parent); + if (IS_ERR(map)) { + pr_err("no regmap for syscon ICST clock parent\n"); + return; + } + + if (of_property_read_u32(np, "vco-offset", &icst_desc.vco_offset)) { + pr_err("no VCO register offset for ICST clock\n"); + return; + } + if (of_property_read_u32(np, "lock-offset", &icst_desc.lock_offset)) { + pr_err("no lock register offset for ICST clock\n"); + return; + } + + if (of_device_is_compatible(np, "arm,syscon-icst525")) + icst_desc.params = &icst525_params; + else if (of_device_is_compatible(np, "arm,syscon-icst307")) + icst_desc.params = &icst307_params; + else { + pr_err("unknown ICST clock %s\n", name); + return; + } + + /* Parent clock name is not the same as node parent */ + parent_name = of_clk_get_parent_name(np, 0); + + regclk = icst_clk_setup(NULL, &icst_desc, name, parent_name, map); + if (IS_ERR(regclk)) { + pr_err("error setting up syscon ICST clock %s\n", name); + return; + } + of_clk_add_provider(np, of_clk_src_simple_get, regclk); + pr_debug("registered syscon ICST clock %s\n", name); +} + +CLK_OF_DECLARE(arm_syscon_icst525_clk, + "arm,syscon-icst525", of_syscon_icst_setup); +CLK_OF_DECLARE(arm_syscon_icst307_clk, + "arm,syscon-icst307", of_syscon_icst_setup); + +#endif From 5d87f7a314b94a8852a07d7e2260ee6db66cb29f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Oct 2015 11:08:31 +0200 Subject: [PATCH 09/11] soc: versatile: add support for the PB11MPCore The SoC driver needs a minor update to display the correct sysfs information for the PB11MPCore. Signed-off-by: Linus Walleij --- drivers/soc/versatile/soc-realview.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/soc/versatile/soc-realview.c b/drivers/soc/versatile/soc-realview.c index e642c4540dda..c337764de867 100644 --- a/drivers/soc/versatile/soc-realview.c +++ b/drivers/soc/versatile/soc-realview.c @@ -36,6 +36,8 @@ static const char *realview_board_str(u32 id) switch ((id >> 16) & 0xfff) { case 0x0147: return "HBI-0147"; + case 0x0159: + return "HBI-0159"; default: return "Unknown"; } @@ -44,6 +46,8 @@ static const char *realview_board_str(u32 id) static const char *realview_arch_str(u32 id) { switch ((id >> 8) & 0xf) { + case 0x04: + return "AHB"; case 0x05: return "Multi-layer AXI"; default: From ca5b21fa6ec61cdf8906265141a9f15169d2808b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Oct 2015 11:09:31 +0200 Subject: [PATCH 10/11] ARM: realview: select SP810 and ICST for the DT variant The device tree boot for RealView need the SP810 system controller (same as found on the Versatile Express) to set up the timers on the board so the machine can tick. It further utilize the ICST307 through its system controller for 6 other oscillators. We have to select these from Kconfig or the machine does not boot. Signed-off-by: Linus Walleij --- arch/arm/mach-realview/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index 055e7355ec14..edbc925e42c2 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -4,6 +4,8 @@ menu "RealView platform type" config REALVIEW_DT bool "Support RealView(R) Device Tree based boot" select ARM_GIC + select CLK_SP810 + select ICST select MFD_SYSCON select POWER_RESET select POWER_RESET_VERSATILE From 5420b4b156179ec634d9e42279b6898b85852960 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 9 Oct 2015 13:38:57 +0200 Subject: [PATCH 11/11] ARM: realview: add an DT SMP boot method This adds an SMP boot method for the ARM RealView reference designs. We also select HAVE_SMP by default and make it use SMP_ON_UP so we only need to support one single kernel across the RealView reference designs when using DT. The RealViews need to have the SCU (Snoop Control Unit) activated on boot, and this is now done by looking up its address from the device tree and initializing it and counting the available cores. The RealViews boot by using a magic address register in the system controller (SYS_FLAGS) to store the boot address, the ROM will then read this register to the PC when the CPUs are taken out of WFI. This code uses a handle to the syscon regmap to access this register. Signed-off-by: Linus Walleij --- .../devicetree/bindings/arm/cpus.txt | 1 + arch/arm/mach-realview/Kconfig | 2 + arch/arm/mach-realview/Makefile | 2 +- arch/arm/mach-realview/platsmp-dt.c | 91 +++++++++++++++++++ 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-realview/platsmp-dt.c diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt index 3a07a87fef20..19af9157f094 100644 --- a/Documentation/devicetree/bindings/arm/cpus.txt +++ b/Documentation/devicetree/bindings/arm/cpus.txt @@ -190,6 +190,7 @@ nodes to be present and contain the properties described below. "allwinner,sun6i-a31" "allwinner,sun8i-a23" "arm,psci" + "arm,realview-smp" "brcm,brahma-b15" "marvell,armada-375-smp" "marvell,armada-380-smp" diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index edbc925e42c2..7316fff0f3ba 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -5,11 +5,13 @@ config REALVIEW_DT bool "Support RealView(R) Device Tree based boot" select ARM_GIC select CLK_SP810 + select HAVE_SMP select ICST select MFD_SYSCON select POWER_RESET select POWER_RESET_VERSATILE select POWER_SUPPLY + select SMP_ON_UP select SOC_REALVIEW select USE_OF help diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile index e07fdf7ae8a7..a46fa694cf07 100644 --- a/arch/arm/mach-realview/Makefile +++ b/arch/arm/mach-realview/Makefile @@ -3,7 +3,7 @@ # obj-y := core.o -obj-$(CONFIG_REALVIEW_DT) += realview-dt.o +obj-$(CONFIG_REALVIEW_DT) += realview-dt.o platsmp-dt.o obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o obj-$(CONFIG_MACH_REALVIEW_PB11MP) += realview_pb11mp.o obj-$(CONFIG_MACH_REALVIEW_PB1176) += realview_pb1176.o diff --git a/arch/arm/mach-realview/platsmp-dt.c b/arch/arm/mach-realview/platsmp-dt.c new file mode 100644 index 000000000000..65585392655b --- /dev/null +++ b/arch/arm/mach-realview/platsmp-dt.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2015 Linus Walleij + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "core.h" + +#define REALVIEW_SYS_FLAGSSET_OFFSET 0x30 + +static const struct of_device_id realview_scu_match[] = { + { .compatible = "arm,arm11mp-scu", }, + { .compatible = "arm,cortex-a9-scu", }, + { .compatible = "arm,cortex-a5-scu", }, + { } +}; + +static const struct of_device_id realview_syscon_match[] = { + { .compatible = "arm,core-module-integrator", }, + { .compatible = "arm,realview-eb-syscon", }, + { .compatible = "arm,realview-pb11mp-syscon", }, + { .compatible = "arm,realview-pbx-syscon", }, + { }, +}; + +static void __init realview_smp_prepare_cpus(unsigned int max_cpus) +{ + struct device_node *np; + void __iomem *scu_base; + struct regmap *map; + unsigned int ncores; + int i; + + np = of_find_matching_node(NULL, realview_scu_match); + if (!np) { + pr_err("PLATSMP: No SCU base address\n"); + return; + } + scu_base = of_iomap(np, 0); + of_node_put(np); + if (!scu_base) { + pr_err("PLATSMP: No SCU remap\n"); + return; + } + + scu_enable(scu_base); + ncores = scu_get_core_count(scu_base); + pr_info("SCU: %d cores detected\n", ncores); + for (i = 0; i < ncores; i++) + set_cpu_possible(i, true); + iounmap(scu_base); + + /* The syscon contains the magic SMP start address registers */ + np = of_find_matching_node(NULL, realview_syscon_match); + if (!np) { + pr_err("PLATSMP: No syscon match\n"); + return; + } + map = syscon_node_to_regmap(np); + if (IS_ERR(map)) { + pr_err("PLATSMP: No syscon regmap\n"); + return; + } + /* Put the boot address in this magic register */ + regmap_write(map, REALVIEW_SYS_FLAGSSET_OFFSET, + virt_to_phys(versatile_secondary_startup)); +} + +struct smp_operations realview_dt_smp_ops __initdata = { + .smp_prepare_cpus = realview_smp_prepare_cpus, + .smp_secondary_init = versatile_secondary_init, + .smp_boot_secondary = versatile_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = realview_cpu_die, +#endif +}; +CPU_METHOD_OF_DECLARE(realview_smp, "arm,realview-smp", &realview_dt_smp_ops);