aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2015-12-15 18:02:54 -0500
committerArnd Bergmann <arnd@arndb.de>2015-12-15 18:56:18 -0500
commit22ba14f41ca6b7f96fe3d4a8eb116358060595fd (patch)
treefbc59ebf82556cd604b1946304c61e64c4469caf
parent7379d96bdabdfb2bf619c174fb6160a9c0a00ca3 (diff)
parent5420b4b156179ec634d9e42279b6898b85852960 (diff)
Merge tag 'realview-base-armsoc-1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator into next/multiplatform
Merge "Realview multiplatform support" from Linus Walleij: The board and infrastructure changes for RealView multiplatform and extended DT support. * tag 'realview-base-armsoc-1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator: ARM: realview: add an DT SMP boot method ARM: realview: select SP810 and ICST for the DT variant soc: versatile: add support for the PB11MPCore clk: versatile-icst: add device tree support clk: versatile-icst: refactor to allocate regmap separately clk: versatile-icst: convert to use regmap ARM: realview: remove private barrier implementation ARM: no longer force unbuffered DMA for realview clk/realview: stop using machine headers ARM: realview: don't map undefined PCI registers ARM: realview: remove sparsemem hack Conflicts: drivers/clk/versatile/Kconfig
-rw-r--r--Documentation/devicetree/bindings/arm/cpus.txt1
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/mach-realview/Kconfig11
-rw-r--r--arch/arm/mach-realview/Makefile2
-rw-r--r--arch/arm/mach-realview/include/mach/barriers.h8
-rw-r--r--arch/arm/mach-realview/include/mach/memory.h64
-rw-r--r--arch/arm/mach-realview/platsmp-dt.c91
-rw-r--r--arch/arm/mach-realview/realview_eb.c7
-rw-r--r--arch/arm/mach-realview/realview_pb11mp.c6
-rw-r--r--arch/arm/mach-realview/realview_pba8.c8
-rw-r--r--arch/arm/mach-realview/realview_pbx.c8
-rw-r--r--arch/arm/mm/Kconfig2
-rw-r--r--drivers/clk/versatile/Kconfig1
-rw-r--r--drivers/clk/versatile/clk-icst.c194
-rw-r--r--drivers/clk/versatile/clk-realview.c10
-rw-r--r--drivers/soc/versatile/soc-realview.c4
16 files changed, 285 insertions, 134 deletions
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.
190 "allwinner,sun6i-a31" 190 "allwinner,sun6i-a31"
191 "allwinner,sun8i-a23" 191 "allwinner,sun8i-a23"
192 "arm,psci" 192 "arm,psci"
193 "arm,realview-smp"
193 "brcm,brahma-b15" 194 "brcm,brahma-b15"
194 "marvell,armada-375-smp" 195 "marvell,armada-375-smp"
195 "marvell,armada-380-smp" 196 "marvell,armada-380-smp"
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index aebe283a4275..70eb100b56e7 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -241,7 +241,6 @@ config ARM_PATCH_PHYS_VIRT
241 bool "Patch physical to virtual translations at runtime" if EMBEDDED 241 bool "Patch physical to virtual translations at runtime" if EMBEDDED
242 default y 242 default y
243 depends on !XIP_KERNEL && MMU 243 depends on !XIP_KERNEL && MMU
244 depends on !ARCH_REALVIEW || !SPARSEMEM
245 help 244 help
246 Patch phys-to-virt and virt-to-phys translation functions at 245 Patch phys-to-virt and virt-to-phys translation functions at
247 boot and module load time according to the position of the 246 boot and module load time according to the position of the
@@ -356,7 +355,6 @@ config ARCH_REALVIEW
356 select GENERIC_CLOCKEVENTS 355 select GENERIC_CLOCKEVENTS
357 select GPIO_PL061 if GPIOLIB 356 select GPIO_PL061 if GPIOLIB
358 select ICST 357 select ICST
359 select NEED_MACH_MEMORY_H
360 select PLAT_VERSATILE 358 select PLAT_VERSATILE
361 select PLAT_VERSATILE_SCHED_CLOCK 359 select PLAT_VERSATILE_SCHED_CLOCK
362 help 360 help
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index 565925f37dc5..7316fff0f3ba 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -4,10 +4,14 @@ menu "RealView platform type"
4config REALVIEW_DT 4config REALVIEW_DT
5 bool "Support RealView(R) Device Tree based boot" 5 bool "Support RealView(R) Device Tree based boot"
6 select ARM_GIC 6 select ARM_GIC
7 select CLK_SP810
8 select HAVE_SMP
9 select ICST
7 select MFD_SYSCON 10 select MFD_SYSCON
8 select POWER_RESET 11 select POWER_RESET
9 select POWER_RESET_VERSATILE 12 select POWER_RESET_VERSATILE
10 select POWER_SUPPLY 13 select POWER_SUPPLY
14 select SMP_ON_UP
11 select SOC_REALVIEW 15 select SOC_REALVIEW
12 select USE_OF 16 select USE_OF
13 help 17 help
@@ -36,7 +40,6 @@ config REALVIEW_EB_A9MP
36config REALVIEW_EB_ARM11MP 40config REALVIEW_EB_ARM11MP
37 bool "Support ARM11MPCore Tile" 41 bool "Support ARM11MPCore Tile"
38 depends on MACH_REALVIEW_EB 42 depends on MACH_REALVIEW_EB
39 select ARCH_HAS_BARRIERS if SMP
40 select CPU_V6K 43 select CPU_V6K
41 select HAVE_ARM_SCU if SMP 44 select HAVE_ARM_SCU if SMP
42 select HAVE_ARM_TWD if SMP 45 select HAVE_ARM_TWD if SMP
@@ -57,7 +60,6 @@ config REALVIEW_EB_ARM11MP_REVB
57 60
58config MACH_REALVIEW_PB11MP 61config MACH_REALVIEW_PB11MP
59 bool "Support RealView(R) Platform Baseboard for ARM11MPCore" 62 bool "Support RealView(R) Platform Baseboard for ARM11MPCore"
60 select ARCH_HAS_BARRIERS if SMP
61 select ARM_GIC 63 select ARM_GIC
62 select CPU_V6K 64 select CPU_V6K
63 select HAVE_ARM_SCU if SMP 65 select HAVE_ARM_SCU if SMP
@@ -102,14 +104,13 @@ config MACH_REALVIEW_PBA8
102 104
103config MACH_REALVIEW_PBX 105config MACH_REALVIEW_PBX
104 bool "Support RealView(R) Platform Baseboard Explore" 106 bool "Support RealView(R) Platform Baseboard Explore"
105 select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET
106 select ARM_GIC 107 select ARM_GIC
107 select HAVE_ARM_SCU if SMP 108 select HAVE_ARM_SCU if SMP
108 select HAVE_ARM_TWD if SMP 109 select HAVE_ARM_TWD if SMP
109 select HAVE_PATA_PLATFORM 110 select HAVE_PATA_PLATFORM
110 select HAVE_SMP 111 select HAVE_SMP
111 select MIGHT_HAVE_CACHE_L2X0 112 select MIGHT_HAVE_CACHE_L2X0
112 select ZONE_DMA if SPARSEMEM 113 select ZONE_DMA
113 help 114 help
114 Include support for the ARM(R) RealView(R) Platform Baseboard 115 Include support for the ARM(R) RealView(R) Platform Baseboard
115 Explore. 116 Explore.
@@ -124,6 +125,6 @@ config REALVIEW_HIGH_PHYS_OFFSET
124 the board supports 512MB of RAM, this option allows the 125 the board supports 512MB of RAM, this option allows the
125 memory to be accessed contiguously at the high physical 126 memory to be accessed contiguously at the high physical
126 offset. On the PBX board, disabling this option allows 1GB of 127 offset. On the PBX board, disabling this option allows 1GB of
127 RAM to be used with SPARSEMEM. 128 RAM to be used with HIGHMEM.
128 129
129endmenu 130endmenu
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 @@
3# 3#
4 4
5obj-y := core.o 5obj-y := core.o
6obj-$(CONFIG_REALVIEW_DT) += realview-dt.o 6obj-$(CONFIG_REALVIEW_DT) += realview-dt.o platsmp-dt.o
7obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o 7obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o
8obj-$(CONFIG_MACH_REALVIEW_PB11MP) += realview_pb11mp.o 8obj-$(CONFIG_MACH_REALVIEW_PB11MP) += realview_pb11mp.o
9obj-$(CONFIG_MACH_REALVIEW_PB1176) += realview_pb1176.o 9obj-$(CONFIG_MACH_REALVIEW_PB1176) += realview_pb1176.o
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 @@
1/*
2 * Barriers redefined for RealView ARM11MPCore platforms with L220 cache
3 * controller to work around hardware errata causing the outer_sync()
4 * operation to deadlock the system.
5 */
6#define mb() dsb()
7#define rmb() dsb()
8#define wmb() mb()
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 @@
1/*
2 * arch/arm/mach-realview/include/mach/memory.h
3 *
4 * Copyright (C) 2003 ARM Limited
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#ifndef __ASM_ARCH_MEMORY_H
21#define __ASM_ARCH_MEMORY_H
22
23#ifdef CONFIG_SPARSEMEM
24
25/*
26 * Sparsemem definitions for RealView PBX.
27 *
28 * The RealView PBX board has another block of 512MB of RAM at 0x20000000,
29 * however only the block at 0x70000000 (or the 256MB mirror at 0x00000000)
30 * may be used for DMA.
31 *
32 * The macros below define a section size of 256MB and a non-linear virtual to
33 * physical mapping:
34 *
35 * 256MB @ 0x00000000 -> PAGE_OFFSET
36 * 512MB @ 0x20000000 -> PAGE_OFFSET + 0x10000000
37 * 256MB @ 0x80000000 -> PAGE_OFFSET + 0x30000000
38 */
39#ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET
40#error "SPARSEMEM not available with REALVIEW_HIGH_PHYS_OFFSET"
41#endif
42
43#define MAX_PHYSMEM_BITS 32
44#define SECTION_SIZE_BITS 28
45
46/* bank page offsets */
47#define PAGE_OFFSET1 (PAGE_OFFSET + 0x10000000)
48#define PAGE_OFFSET2 (PAGE_OFFSET + 0x30000000)
49
50#define PHYS_OFFSET PLAT_PHYS_OFFSET
51
52#define __phys_to_virt(phys) \
53 ((phys) >= 0x80000000 ? (phys) - 0x80000000 + PAGE_OFFSET2 : \
54 (phys) >= 0x20000000 ? (phys) - 0x20000000 + PAGE_OFFSET1 : \
55 (phys) + PAGE_OFFSET)
56
57#define __virt_to_phys(virt) \
58 ((virt) >= PAGE_OFFSET2 ? (virt) - PAGE_OFFSET2 + 0x80000000 : \
59 (virt) >= PAGE_OFFSET1 ? (virt) - PAGE_OFFSET1 + 0x20000000 : \
60 (virt) - PAGE_OFFSET)
61
62#endif /* CONFIG_SPARSEMEM */
63
64#endif
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 @@
1/*
2 * Copyright (C) 2015 Linus Walleij
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/smp.h>
9#include <linux/io.h>
10#include <linux/of.h>
11#include <linux/of_address.h>
12#include <linux/regmap.h>
13#include <linux/mfd/syscon.h>
14
15#include <asm/cacheflush.h>
16#include <asm/smp_plat.h>
17#include <asm/smp_scu.h>
18
19#include <plat/platsmp.h>
20
21#include "core.h"
22
23#define REALVIEW_SYS_FLAGSSET_OFFSET 0x30
24
25static const struct of_device_id realview_scu_match[] = {
26 { .compatible = "arm,arm11mp-scu", },
27 { .compatible = "arm,cortex-a9-scu", },
28 { .compatible = "arm,cortex-a5-scu", },
29 { }
30};
31
32static const struct of_device_id realview_syscon_match[] = {
33 { .compatible = "arm,core-module-integrator", },
34 { .compatible = "arm,realview-eb-syscon", },
35 { .compatible = "arm,realview-pb11mp-syscon", },
36 { .compatible = "arm,realview-pbx-syscon", },
37 { },
38};
39
40static void __init realview_smp_prepare_cpus(unsigned int max_cpus)
41{
42 struct device_node *np;
43 void __iomem *scu_base;
44 struct regmap *map;
45 unsigned int ncores;
46 int i;
47
48 np = of_find_matching_node(NULL, realview_scu_match);
49 if (!np) {
50 pr_err("PLATSMP: No SCU base address\n");
51 return;
52 }
53 scu_base = of_iomap(np, 0);
54 of_node_put(np);
55 if (!scu_base) {
56 pr_err("PLATSMP: No SCU remap\n");
57 return;
58 }
59
60 scu_enable(scu_base);
61 ncores = scu_get_core_count(scu_base);
62 pr_info("SCU: %d cores detected\n", ncores);
63 for (i = 0; i < ncores; i++)
64 set_cpu_possible(i, true);
65 iounmap(scu_base);
66
67 /* The syscon contains the magic SMP start address registers */
68 np = of_find_matching_node(NULL, realview_syscon_match);
69 if (!np) {
70 pr_err("PLATSMP: No syscon match\n");
71 return;
72 }
73 map = syscon_node_to_regmap(np);
74 if (IS_ERR(map)) {
75 pr_err("PLATSMP: No syscon regmap\n");
76 return;
77 }
78 /* Put the boot address in this magic register */
79 regmap_write(map, REALVIEW_SYS_FLAGSSET_OFFSET,
80 virt_to_phys(versatile_secondary_startup));
81}
82
83struct smp_operations realview_dt_smp_ops __initdata = {
84 .smp_prepare_cpus = realview_smp_prepare_cpus,
85 .smp_secondary_init = versatile_secondary_init,
86 .smp_boot_secondary = versatile_boot_secondary,
87#ifdef CONFIG_HOTPLUG_CPU
88 .cpu_die = realview_cpu_die,
89#endif
90};
91CPU_METHOD_OF_DECLARE(realview_smp, "arm,realview-smp", &realview_dt_smp_ops);
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 @@
38#include <asm/hardware/cache-l2x0.h> 38#include <asm/hardware/cache-l2x0.h>
39#include <asm/smp_twd.h> 39#include <asm/smp_twd.h>
40#include <asm/system_info.h> 40#include <asm/system_info.h>
41#include <asm/outercache.h>
41 42
42#include <asm/mach/arch.h> 43#include <asm/mach/arch.h>
43#include <asm/mach/map.h> 44#include <asm/mach/map.h>
@@ -450,6 +451,12 @@ static void __init realview_eb_init(void)
450 * Bits: .... ...0 0111 1001 0000 .... .... .... 451 * Bits: .... ...0 0111 1001 0000 .... .... ....
451 */ 452 */
452 l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff); 453 l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff);
454
455 /*
456 * due to a bug in the l220 cache controller, we must not call
457 * the sync function. stub it out here instead!
458 */
459 outer_cache.sync = NULL;
453#endif 460#endif
454 pmu_device.name = core_tile_a9mp() ? "armv7-pmu" : "armv6-pmu"; 461 pmu_device.name = core_tile_a9mp() ? "armv7-pmu" : "armv6-pmu";
455 platform_device_register(&pmu_device); 462 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 @@
42#include <asm/mach/flash.h> 42#include <asm/mach/flash.h>
43#include <asm/mach/map.h> 43#include <asm/mach/map.h>
44#include <asm/mach/time.h> 44#include <asm/mach/time.h>
45#include <asm/outercache.h>
45 46
46#include <mach/board-pb11mp.h> 47#include <mach/board-pb11mp.h>
47#include <mach/irqs.h> 48#include <mach/irqs.h>
@@ -345,6 +346,11 @@ static void __init realview_pb11mp_init(void)
345 * Bits: .... ...0 0111 1001 0000 .... .... .... 346 * Bits: .... ...0 0111 1001 0000 .... .... ....
346 */ 347 */
347 l2x0_init(__io_address(REALVIEW_TC11MP_L220_BASE), 0x00790000, 0xfe000fff); 348 l2x0_init(__io_address(REALVIEW_TC11MP_L220_BASE), 0x00790000, 0xfe000fff);
349 /*
350 * due to a bug in the l220 cache controller, we must not call
351 * the sync function. stub it out here instead!
352 */
353 outer_cache.sync = NULL;
348#endif 354#endif
349 355
350 realview_flash_register(realview_pb11mp_flash_resource, 356 realview_flash_register(realview_pb11mp_flash_resource,
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 = {
77 .length = SZ_4K, 77 .length = SZ_4K,
78 .type = MT_DEVICE, 78 .type = MT_DEVICE,
79 }, 79 },
80#ifdef CONFIG_PCI
81 {
82 .virtual = PCIX_UNIT_BASE,
83 .pfn = __phys_to_pfn(REALVIEW_PBA8_PCI_BASE),
84 .length = REALVIEW_PBA8_PCI_BASE_SIZE,
85 .type = MT_DEVICE
86 },
87#endif
88#ifdef CONFIG_DEBUG_LL 80#ifdef CONFIG_DEBUG_LL
89 { 81 {
90 .virtual = IO_ADDRESS(REALVIEW_PBA8_UART0_BASE), 82 .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 = {
79 .length = SZ_4K, 79 .length = SZ_4K,
80 .type = MT_DEVICE, 80 .type = MT_DEVICE,
81 }, 81 },
82#ifdef CONFIG_PCI
83 {
84 .virtual = PCIX_UNIT_BASE,
85 .pfn = __phys_to_pfn(REALVIEW_PBX_PCI_BASE),
86 .length = REALVIEW_PBX_PCI_BASE_SIZE,
87 .type = MT_DEVICE,
88 },
89#endif
90#ifdef CONFIG_DEBUG_LL 82#ifdef CONFIG_DEBUG_LL
91 { 83 {
92 .virtual = IO_ADDRESS(REALVIEW_PBX_UART0_BASE), 84 .virtual = IO_ADDRESS(REALVIEW_PBX_UART0_BASE),
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
1005 1005
1006config ARM_DMA_MEM_BUFFERABLE 1006config ARM_DMA_MEM_BUFFERABLE
1007 bool "Use non-cacheable memory for DMA" if (CPU_V6 || CPU_V6K) && !CPU_V7 1007 bool "Use non-cacheable memory for DMA" if (CPU_V6 || CPU_V6K) && !CPU_V7
1008 depends on !(MACH_REALVIEW_PB1176 || REALVIEW_EB_ARM11MP || \
1009 MACH_REALVIEW_PB11MP)
1010 default y if CPU_V6 || CPU_V6K || CPU_V7 1008 default y if CPU_V6 || CPU_V6K || CPU_V7
1011 help 1009 help
1012 Historically, the kernel has used strongly ordered mappings to 1010 Historically, the kernel has used strongly ordered mappings to
diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig
index 369a2dc50f74..a6da2aa09f83 100644
--- a/drivers/clk/versatile/Kconfig
+++ b/drivers/clk/versatile/Kconfig
@@ -3,6 +3,7 @@ config COMMON_CLK_VERSATILE
3 depends on ARCH_INTEGRATOR || ARCH_REALVIEW || \ 3 depends on ARCH_INTEGRATOR || ARCH_REALVIEW || \
4 ARCH_VERSATILE || ARCH_VEXPRESS || ARM64 || \ 4 ARCH_VERSATILE || ARCH_VEXPRESS || ARM64 || \
5 COMPILE_TEST 5 COMPILE_TEST
6 select REGMAP_MMIO
6 ---help--- 7 ---help---
7 Supports clocking on ARM Reference designs: 8 Supports clocking on ARM Reference designs:
8 - Integrator/AP and Integrator/CP 9 - Integrator/AP and Integrator/CP
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c
index 08c5ee976879..e62f8cb2c9b5 100644
--- a/drivers/clk/versatile/clk-icst.c
+++ b/drivers/clk/versatile/clk-icst.c
@@ -3,7 +3,7 @@
3 * We wrap the custom interface from <asm/hardware/icst.h> into the generic 3 * We wrap the custom interface from <asm/hardware/icst.h> into the generic
4 * clock framework. 4 * clock framework.
5 * 5 *
6 * Copyright (C) 2012 Linus Walleij 6 * Copyright (C) 2012-2015 Linus Walleij
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -19,9 +19,14 @@
19#include <linux/err.h> 19#include <linux/err.h>
20#include <linux/clk-provider.h> 20#include <linux/clk-provider.h>
21#include <linux/io.h> 21#include <linux/io.h>
22#include <linux/regmap.h>
23#include <linux/mfd/syscon.h>
22 24
23#include "clk-icst.h" 25#include "clk-icst.h"
24 26
27/* Magic unlocking token used on all Versatile boards */
28#define VERSATILE_LOCK_VAL 0xA05F
29
25/** 30/**
26 * struct clk_icst - ICST VCO clock wrapper 31 * struct clk_icst - ICST VCO clock wrapper
27 * @hw: corresponding clock hardware entry 32 * @hw: corresponding clock hardware entry
@@ -32,8 +37,9 @@
32 */ 37 */
33struct clk_icst { 38struct clk_icst {
34 struct clk_hw hw; 39 struct clk_hw hw;
35 void __iomem *vcoreg; 40 struct regmap *map;
36 void __iomem *lockreg; 41 u32 vcoreg_off;
42 u32 lockreg_off;
37 struct icst_params *params; 43 struct icst_params *params;
38 unsigned long rate; 44 unsigned long rate;
39}; 45};
@@ -41,53 +47,67 @@ struct clk_icst {
41#define to_icst(_hw) container_of(_hw, struct clk_icst, hw) 47#define to_icst(_hw) container_of(_hw, struct clk_icst, hw)
42 48
43/** 49/**
44 * vco_get() - get ICST VCO settings from a certain register 50 * vco_get() - get ICST VCO settings from a certain ICST
45 * @vcoreg: register containing the VCO settings 51 * @icst: the ICST clock to get
52 * @vco: the VCO struct to return the value in
46 */ 53 */
47static struct icst_vco vco_get(void __iomem *vcoreg) 54static int vco_get(struct clk_icst *icst, struct icst_vco *vco)
48{ 55{
49 u32 val; 56 u32 val;
50 struct icst_vco vco; 57 int ret;
51 58
52 val = readl(vcoreg); 59 ret = regmap_read(icst->map, icst->vcoreg_off, &val);
53 vco.v = val & 0x1ff; 60 if (ret)
54 vco.r = (val >> 9) & 0x7f; 61 return ret;
55 vco.s = (val >> 16) & 03; 62 vco->v = val & 0x1ff;
56 return vco; 63 vco->r = (val >> 9) & 0x7f;
64 vco->s = (val >> 16) & 03;
65 return 0;
57} 66}
58 67
59/** 68/**
60 * vco_set() - commit changes to an ICST VCO 69 * vco_set() - commit changes to an ICST VCO
61 * @locreg: register to poke to unlock the VCO for writing 70 * @icst: the ICST clock to set
62 * @vcoreg: register containing the VCO settings 71 * @vco: the VCO struct to set the changes from
63 * @vco: ICST VCO parameters to commit
64 */ 72 */
65static void vco_set(void __iomem *lockreg, 73static int vco_set(struct clk_icst *icst, struct icst_vco vco)
66 void __iomem *vcoreg,
67 struct icst_vco vco)
68{ 74{
69 u32 val; 75 u32 val;
76 int ret;
70 77
71 val = readl(vcoreg) & ~0x7ffff; 78 ret = regmap_read(icst->map, icst->vcoreg_off, &val);
79 if (ret)
80 return ret;
72 val |= vco.v | (vco.r << 9) | (vco.s << 16); 81 val |= vco.v | (vco.r << 9) | (vco.s << 16);
73 82
74 /* This magic unlocks the VCO so it can be controlled */ 83 /* This magic unlocks the VCO so it can be controlled */
75 writel(0xa05f, lockreg); 84 ret = regmap_write(icst->map, icst->lockreg_off, VERSATILE_LOCK_VAL);
76 writel(val, vcoreg); 85 if (ret)
86 return ret;
87 ret = regmap_write(icst->map, icst->vcoreg_off, val);
88 if (ret)
89 return ret;
77 /* This locks the VCO again */ 90 /* This locks the VCO again */
78 writel(0, lockreg); 91 ret = regmap_write(icst->map, icst->lockreg_off, 0);
92 if (ret)
93 return ret;
94 return 0;
79} 95}
80 96
81
82static unsigned long icst_recalc_rate(struct clk_hw *hw, 97static unsigned long icst_recalc_rate(struct clk_hw *hw,
83 unsigned long parent_rate) 98 unsigned long parent_rate)
84{ 99{
85 struct clk_icst *icst = to_icst(hw); 100 struct clk_icst *icst = to_icst(hw);
86 struct icst_vco vco; 101 struct icst_vco vco;
102 int ret;
87 103
88 if (parent_rate) 104 if (parent_rate)
89 icst->params->ref = parent_rate; 105 icst->params->ref = parent_rate;
90 vco = vco_get(icst->vcoreg); 106 ret = vco_get(icst, &vco);
107 if (ret) {
108 pr_err("ICST: could not get VCO setting\n");
109 return 0;
110 }
91 icst->rate = icst_hz(icst->params, vco); 111 icst->rate = icst_hz(icst->params, vco);
92 return icst->rate; 112 return icst->rate;
93} 113}
@@ -112,8 +132,7 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate,
112 icst->params->ref = parent_rate; 132 icst->params->ref = parent_rate;
113 vco = icst_hz_to_vco(icst->params, rate); 133 vco = icst_hz_to_vco(icst->params, rate);
114 icst->rate = icst_hz(icst->params, vco); 134 icst->rate = icst_hz(icst->params, vco);
115 vco_set(icst->lockreg, icst->vcoreg, vco); 135 return vco_set(icst, vco);
116 return 0;
117} 136}
118 137
119static const struct clk_ops icst_ops = { 138static const struct clk_ops icst_ops = {
@@ -122,11 +141,11 @@ static const struct clk_ops icst_ops = {
122 .set_rate = icst_set_rate, 141 .set_rate = icst_set_rate,
123}; 142};
124 143
125struct clk *icst_clk_register(struct device *dev, 144static struct clk *icst_clk_setup(struct device *dev,
126 const struct clk_icst_desc *desc, 145 const struct clk_icst_desc *desc,
127 const char *name, 146 const char *name,
128 const char *parent_name, 147 const char *parent_name,
129 void __iomem *base) 148 struct regmap *map)
130{ 149{
131 struct clk *clk; 150 struct clk *clk;
132 struct clk_icst *icst; 151 struct clk_icst *icst;
@@ -151,10 +170,11 @@ struct clk *icst_clk_register(struct device *dev,
151 init.flags = CLK_IS_ROOT; 170 init.flags = CLK_IS_ROOT;
152 init.parent_names = (parent_name ? &parent_name : NULL); 171 init.parent_names = (parent_name ? &parent_name : NULL);
153 init.num_parents = (parent_name ? 1 : 0); 172 init.num_parents = (parent_name ? 1 : 0);
173 icst->map = map;
154 icst->hw.init = &init; 174 icst->hw.init = &init;
155 icst->params = pclone; 175 icst->params = pclone;
156 icst->vcoreg = base + desc->vco_offset; 176 icst->vcoreg_off = desc->vco_offset;
157 icst->lockreg = base + desc->lock_offset; 177 icst->lockreg_off = desc->lock_offset;
158 178
159 clk = clk_register(dev, &icst->hw); 179 clk = clk_register(dev, &icst->hw);
160 if (IS_ERR(clk)) { 180 if (IS_ERR(clk)) {
@@ -164,4 +184,112 @@ struct clk *icst_clk_register(struct device *dev,
164 184
165 return clk; 185 return clk;
166} 186}
187
188struct clk *icst_clk_register(struct device *dev,
189 const struct clk_icst_desc *desc,
190 const char *name,
191 const char *parent_name,
192 void __iomem *base)
193{
194 struct regmap_config icst_regmap_conf = {
195 .reg_bits = 32,
196 .val_bits = 32,
197 .reg_stride = 4,
198 };
199 struct regmap *map;
200
201 map = regmap_init_mmio(dev, base, &icst_regmap_conf);
202 if (IS_ERR(map)) {
203 pr_err("could not initialize ICST regmap\n");
204 return ERR_CAST(map);
205 }
206 return icst_clk_setup(dev, desc, name, parent_name, map);
207}
167EXPORT_SYMBOL_GPL(icst_clk_register); 208EXPORT_SYMBOL_GPL(icst_clk_register);
209
210#ifdef CONFIG_OF
211/*
212 * In a device tree, an memory-mapped ICST clock appear as a child
213 * of a syscon node. Assume this and probe it only as a child of a
214 * syscon.
215 */
216
217static const struct icst_params icst525_params = {
218 .vco_max = ICST525_VCO_MAX_5V,
219 .vco_min = ICST525_VCO_MIN,
220 .vd_min = 8,
221 .vd_max = 263,
222 .rd_min = 3,
223 .rd_max = 65,
224 .s2div = icst525_s2div,
225 .idx2s = icst525_idx2s,
226};
227
228static const struct icst_params icst307_params = {
229 .vco_max = ICST307_VCO_MAX,
230 .vco_min = ICST307_VCO_MIN,
231 .vd_min = 4 + 8,
232 .vd_max = 511 + 8,
233 .rd_min = 1 + 2,
234 .rd_max = 127 + 2,
235 .s2div = icst307_s2div,
236 .idx2s = icst307_idx2s,
237};
238
239static void __init of_syscon_icst_setup(struct device_node *np)
240{
241 struct device_node *parent;
242 struct regmap *map;
243 struct clk_icst_desc icst_desc;
244 const char *name = np->name;
245 const char *parent_name;
246 struct clk *regclk;
247
248 /* We do not release this reference, we are using it perpetually */
249 parent = of_get_parent(np);
250 if (!parent) {
251 pr_err("no parent node for syscon ICST clock\n");
252 return;
253 }
254 map = syscon_node_to_regmap(parent);
255 if (IS_ERR(map)) {
256 pr_err("no regmap for syscon ICST clock parent\n");
257 return;
258 }
259
260 if (of_property_read_u32(np, "vco-offset", &icst_desc.vco_offset)) {
261 pr_err("no VCO register offset for ICST clock\n");
262 return;
263 }
264 if (of_property_read_u32(np, "lock-offset", &icst_desc.lock_offset)) {
265 pr_err("no lock register offset for ICST clock\n");
266 return;
267 }
268
269 if (of_device_is_compatible(np, "arm,syscon-icst525"))
270 icst_desc.params = &icst525_params;
271 else if (of_device_is_compatible(np, "arm,syscon-icst307"))
272 icst_desc.params = &icst307_params;
273 else {
274 pr_err("unknown ICST clock %s\n", name);
275 return;
276 }
277
278 /* Parent clock name is not the same as node parent */
279 parent_name = of_clk_get_parent_name(np, 0);
280
281 regclk = icst_clk_setup(NULL, &icst_desc, name, parent_name, map);
282 if (IS_ERR(regclk)) {
283 pr_err("error setting up syscon ICST clock %s\n", name);
284 return;
285 }
286 of_clk_add_provider(np, of_clk_src_simple_get, regclk);
287 pr_debug("registered syscon ICST clock %s\n", name);
288}
289
290CLK_OF_DECLARE(arm_syscon_icst525_clk,
291 "arm,syscon-icst525", of_syscon_icst_setup);
292CLK_OF_DECLARE(arm_syscon_icst307_clk,
293 "arm,syscon-icst307", of_syscon_icst_setup);
294
295#endif
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 @@
11#include <linux/io.h> 11#include <linux/io.h>
12#include <linux/clk-provider.h> 12#include <linux/clk-provider.h>
13 13
14#include <mach/hardware.h>
15#include <mach/platform.h>
16
17#include "clk-icst.h" 14#include "clk-icst.h"
18 15
16#define REALVIEW_SYS_OSC0_OFFSET 0x0C
17#define REALVIEW_SYS_OSC1_OFFSET 0x10
18#define REALVIEW_SYS_OSC2_OFFSET 0x14
19#define REALVIEW_SYS_OSC3_OFFSET 0x18
20#define REALVIEW_SYS_OSC4_OFFSET 0x1C /* OSC1 for RealView/AB */
21#define REALVIEW_SYS_LOCK_OFFSET 0x20
22
19/* 23/*
20 * Implementation of the ARM RealView clock trees. 24 * Implementation of the ARM RealView clock trees.
21 */ 25 */
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)
36 switch ((id >> 16) & 0xfff) { 36 switch ((id >> 16) & 0xfff) {
37 case 0x0147: 37 case 0x0147:
38 return "HBI-0147"; 38 return "HBI-0147";
39 case 0x0159:
40 return "HBI-0159";
39 default: 41 default:
40 return "Unknown"; 42 return "Unknown";
41 } 43 }
@@ -44,6 +46,8 @@ static const char *realview_board_str(u32 id)
44static const char *realview_arch_str(u32 id) 46static const char *realview_arch_str(u32 id)
45{ 47{
46 switch ((id >> 8) & 0xf) { 48 switch ((id >> 8) & 0xf) {
49 case 0x04:
50 return "AHB";
47 case 0x05: 51 case 0x05:
48 return "Multi-layer AXI"; 52 return "Multi-layer AXI";
49 default: 53 default: