aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPawel Moll <pawel.moll@arm.com>2014-04-30 11:46:29 -0400
committerPawel Moll <pawel.moll@arm.com>2014-05-15 12:02:18 -0400
commit3b9334ac835bb431e2186645230c9f1eb94b5d49 (patch)
tree631e00349363927a6e49c6810332d92295103446
parentc6e126de43e7d4abfd6cf796b40589db3a046167 (diff)
mfd: vexpress: Convert custom func API to regmap
Components of the Versatile Express platform (configuration microcontrollers on motherboard and daughterboards in particular) talk to each other over a custom configuration bus. They provide miscellaneous functions (from clock generator control to energy sensors) which are represented as platform devices (and Device Tree nodes). The transactions on the bus can be generated by different "bridges" in the system, some of which are universal for the whole platform (for the price of high transfer latencies), others restricted to a subsystem (but much faster). Until now drivers for such functions were using custom "func" API, which is being replaced in this patch by regmap calls. This required: * a rework (and move to drivers/bus directory, as suggested by Samuel and Arnd) of the config bus core, which is much simpler now and uses device model infrastructure (class) to keep track of the bridges; non-DT case (soon to be retired anyway) is simply covered by a special device registration function * the new config-bus driver also takes over device population, so there is no need for special matching table for of_platform_populate nor "simple-bus" hack in the arm64 model dtsi file (relevant bindings documentation has been updated); this allows all the vexpress devices fit into normal device model, making it possible to remove plenty of early inits and other hacks in the near future * adaptation of the syscfg bridge implementation in the sysreg driver, again making it much simpler; there is a special case of the "energy" function spanning two registers, where they should be both defined in the tree now, but backward compatibility is maintained in the code * modification of the relevant drivers: * hwmon - just a straight-forward API change * power/reset driver - API change * regulator - API change plus error handling simplification * osc clock driver - this one required larger rework in order to turn in into a standard platform driver Signed-off-by: Pawel Moll <pawel.moll@arm.com> Acked-by: Mark Brown <broonie@linaro.org> Acked-by: Lee Jones <lee.jones@linaro.org> Acked-by: Guenter Roeck <linux@roeck-us.net> Acked-by: Mike Turquette <mturquette@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/arm/vexpress-sysreg.txt43
-rw-r--r--Documentation/devicetree/bindings/arm/vexpress.txt15
-rw-r--r--arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts5
-rw-r--r--arch/arm/mach-vexpress/ct-ca9x4.c10
-rw-r--r--arch/arm/mach-vexpress/v2m.c18
-rw-r--r--arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi2
-rw-r--r--drivers/bus/Kconfig9
-rw-r--r--drivers/bus/Makefile2
-rw-r--r--drivers/bus/vexpress-config.c202
-rw-r--r--drivers/clk/versatile/clk-vexpress-osc.c96
-rw-r--r--drivers/hwmon/vexpress.c17
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--drivers/mfd/vexpress-config.c287
-rw-r--r--drivers/mfd/vexpress-sysreg.c395
-rw-r--r--drivers/power/reset/vexpress-poweroff.c16
-rw-r--r--drivers/regulator/vexpress.c50
-rw-r--r--include/linux/vexpress.h79
17 files changed, 568 insertions, 680 deletions
diff --git a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
index 5580e9c4bd85..57b423f78995 100644
--- a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
+++ b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
@@ -27,24 +27,45 @@ Example:
27This block also can also act a bridge to the platform's configuration 27This block also can also act a bridge to the platform's configuration
28bus via "system control" interface, addressing devices with site number, 28bus via "system control" interface, addressing devices with site number,
29position in the board stack, config controller, function and device 29position in the board stack, config controller, function and device
30numbers - see motherboard's TRM for more details. 30numbers - see motherboard's TRM for more details. All configuration
31 31controller accessible via this interface must reference the sysreg
32The node describing a config device must refer to the sysreg node via 32node via "arm,vexpress,config-bridge" phandle and define appropriate
33"arm,vexpress,config-bridge" phandle (can be also defined in the node's 33topology properties - see main vexpress node documentation for more
34parent) and relies on the board topology properties - see main vexpress 34details. Each child of such node describes one function and must
35node documentation for more details. It must also define the following 35define the following properties:
36property: 36- compatible value : must be one of (corresponding to the TRM):
37- arm,vexpress-sysreg,func : must contain two cells: 37 "arm,vexpress-amp"
38 - first cell defines function number (eg. 1 for clock generator, 38 "arm,vexpress-dvimode"
39 2 for voltage regulators etc.) 39 "arm,vexpress-energy"
40 - device number (eg. osc 0, osc 1 etc.) 40 "arm,vexpress-muxfpga"
41 "arm,vexpress-osc"
42 "arm,vexpress-power"
43 "arm,vexpress-reboot"
44 "arm,vexpress-reset"
45 "arm,vexpress-scc"
46 "arm,vexpress-shutdown"
47 "arm,vexpress-temp"
48 "arm,vexpress-volt"
49- arm,vexpress-sysreg,func : must contain a set of two cells long groups:
50 - first cell of each group defines the function number
51 (eg. 1 for clock generator, 2 for voltage regulators etc.)
52 - second cell of each group defines device number (eg. osc 0,
53 osc 1 etc.)
54 - some functions (eg. energy meter, with its 64 bit long counter)
55 are using more than one function/device number pair
41 56
42Example: 57Example:
43 mcc { 58 mcc {
59 compatible = "arm,vexpress,config-bus";
44 arm,vexpress,config-bridge = <&v2m_sysreg>; 60 arm,vexpress,config-bridge = <&v2m_sysreg>;
45 61
46 osc@0 { 62 osc@0 {
47 compatible = "arm,vexpress-osc"; 63 compatible = "arm,vexpress-osc";
48 arm,vexpress-sysreg,func = <1 0>; 64 arm,vexpress-sysreg,func = <1 0>;
49 }; 65 };
66
67 energy@0 {
68 compatible = "arm,vexpress-energy";
69 arm,vexpress-sysreg,func = <13 0>, <13 1>;
70 };
50 }; 71 };
diff --git a/Documentation/devicetree/bindings/arm/vexpress.txt b/Documentation/devicetree/bindings/arm/vexpress.txt
index ae49161e478a..39844cd0bcce 100644
--- a/Documentation/devicetree/bindings/arm/vexpress.txt
+++ b/Documentation/devicetree/bindings/arm/vexpress.txt
@@ -80,12 +80,17 @@ but also control clock generators, voltage regulators, gather
80environmental data like temperature, power consumption etc. Even 80environmental data like temperature, power consumption etc. Even
81the video output switch (FPGA) is controlled that way. 81the video output switch (FPGA) is controlled that way.
82 82
83Nodes describing devices controlled by this infrastructure should 83The controllers are not mapped into normal memory address space
84point at the bridge device node: 84and must be accessed through bridges - other devices capable
85of generating transactions on the configuration bus.
86
87The nodes describing configuration controllers must define
88the following properties:
89- compatible value:
90 compatible = "arm,vexpress,config-bus";
85- bridge phandle: 91- bridge phandle:
86 arm,vexpress,config-bridge = <phandle>; 92 arm,vexpress,config-bridge = <phandle>;
87This property can be also defined in a parent node (eg. for a DCC) 93and children describing available functions.
88and is effective for all children.
89 94
90 95
91Platform topology 96Platform topology
@@ -197,7 +202,7 @@ Example of a VE tile description (simplified)
197 }; 202 };
198 203
199 dcc { 204 dcc {
200 compatible = "simple-bus"; 205 compatible = "arm,vexpress,config-bus";
201 arm,vexpress,config-bridge = <&v2m_sysreg>; 206 arm,vexpress,config-bridge = <&v2m_sysreg>;
202 207
203 osc@0 { 208 osc@0 {
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
index 15f98cbcb75a..a25c262326dc 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
@@ -312,6 +312,7 @@
312 arm,vexpress-sysreg,func = <12 0>; 312 arm,vexpress-sysreg,func = <12 0>;
313 label = "A15 Pcore"; 313 label = "A15 Pcore";
314 }; 314 };
315
315 power@1 { 316 power@1 {
316 /* Total power for the three A7 cores */ 317 /* Total power for the three A7 cores */
317 compatible = "arm,vexpress-power"; 318 compatible = "arm,vexpress-power";
@@ -322,14 +323,14 @@
322 energy@0 { 323 energy@0 {
323 /* Total energy for the two A15 cores */ 324 /* Total energy for the two A15 cores */
324 compatible = "arm,vexpress-energy"; 325 compatible = "arm,vexpress-energy";
325 arm,vexpress-sysreg,func = <13 0>; 326 arm,vexpress-sysreg,func = <13 0>, <13 1>;
326 label = "A15 Jcore"; 327 label = "A15 Jcore";
327 }; 328 };
328 329
329 energy@2 { 330 energy@2 {
330 /* Total energy for the three A7 cores */ 331 /* Total energy for the three A7 cores */
331 compatible = "arm,vexpress-energy"; 332 compatible = "arm,vexpress-energy";
332 arm,vexpress-sysreg,func = <13 2>; 333 arm,vexpress-sysreg,func = <13 2>, <13 3>;
333 label = "A7 Jcore"; 334 label = "A7 Jcore";
334 }; 335 };
335 }; 336 };
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 6f34497a4245..35e394aa00e5 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -128,6 +128,10 @@ static struct platform_device pmu_device = {
128 .resource = pmu_resources, 128 .resource = pmu_resources,
129}; 129};
130 130
131static struct clk_lookup osc1_lookup = {
132 .dev_id = "ct:clcd",
133};
134
131static struct platform_device osc1_device = { 135static struct platform_device osc1_device = {
132 .name = "vexpress-osc", 136 .name = "vexpress-osc",
133 .id = 1, 137 .id = 1,
@@ -135,6 +139,7 @@ static struct platform_device osc1_device = {
135 .resource = (struct resource []) { 139 .resource = (struct resource []) {
136 VEXPRESS_RES_FUNC(0xf, 1), 140 VEXPRESS_RES_FUNC(0xf, 1),
137 }, 141 },
142 .dev.platform_data = &osc1_lookup,
138}; 143};
139 144
140static void __init ct_ca9x4_init(void) 145static void __init ct_ca9x4_init(void)
@@ -155,10 +160,7 @@ static void __init ct_ca9x4_init(void)
155 amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource); 160 amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource);
156 161
157 platform_device_register(&pmu_device); 162 platform_device_register(&pmu_device);
158 platform_device_register(&osc1_device); 163 vexpress_sysreg_config_device_register(&osc1_device);
159
160 WARN_ON(clk_register_clkdev(vexpress_osc_setup(&osc1_device.dev),
161 NULL, "ct:clcd"));
162} 164}
163 165
164#ifdef CONFIG_SMP 166#ifdef CONFIG_SMP
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 4f8b8cb17ff5..ac95220a5019 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -340,11 +340,6 @@ static void __init v2m_init(void)
340 regulator_register_fixed(0, v2m_eth_supplies, 340 regulator_register_fixed(0, v2m_eth_supplies,
341 ARRAY_SIZE(v2m_eth_supplies)); 341 ARRAY_SIZE(v2m_eth_supplies));
342 342
343 platform_device_register(&v2m_muxfpga_device);
344 platform_device_register(&v2m_shutdown_device);
345 platform_device_register(&v2m_reboot_device);
346 platform_device_register(&v2m_dvimode_device);
347
348 platform_device_register(&v2m_sysreg_device); 343 platform_device_register(&v2m_sysreg_device);
349 platform_device_register(&v2m_pcie_i2c_device); 344 platform_device_register(&v2m_pcie_i2c_device);
350 platform_device_register(&v2m_ddc_i2c_device); 345 platform_device_register(&v2m_ddc_i2c_device);
@@ -356,6 +351,11 @@ static void __init v2m_init(void)
356 for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++) 351 for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++)
357 amba_device_register(v2m_amba_devs[i], &iomem_resource); 352 amba_device_register(v2m_amba_devs[i], &iomem_resource);
358 353
354 vexpress_sysreg_config_device_register(&v2m_muxfpga_device);
355 vexpress_sysreg_config_device_register(&v2m_shutdown_device);
356 vexpress_sysreg_config_device_register(&v2m_reboot_device);
357 vexpress_sysreg_config_device_register(&v2m_dvimode_device);
358
359 ct_desc->init_tile(); 359 ct_desc->init_tile();
360} 360}
361 361
@@ -423,17 +423,11 @@ void __init v2m_dt_init_early(void)
423 versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000); 423 versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000);
424} 424}
425 425
426static const struct of_device_id v2m_dt_bus_match[] __initconst = {
427 { .compatible = "simple-bus", },
428 { .compatible = "arm,amba-bus", },
429 { .compatible = "arm,vexpress,config-bus", },
430 {}
431};
432 426
433static void __init v2m_dt_init(void) 427static void __init v2m_dt_init(void)
434{ 428{
435 l2x0_of_init(0x00400000, 0xfe0fffff); 429 l2x0_of_init(0x00400000, 0xfe0fffff);
436 of_platform_populate(NULL, v2m_dt_bus_match, NULL, NULL); 430 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
437} 431}
438 432
439static const char * const v2m_dt_match[] __initconst = { 433static const char * const v2m_dt_match[] __initconst = {
diff --git a/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi b/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi
index 2f2ecd217363..ac2cb2418025 100644
--- a/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi
+++ b/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi
@@ -200,7 +200,7 @@
200 }; 200 };
201 201
202 mcc { 202 mcc {
203 compatible = "arm,vexpress,config-bus", "simple-bus"; 203 compatible = "arm,vexpress,config-bus";
204 arm,vexpress,config-bridge = <&v2m_sysreg>; 204 arm,vexpress,config-bridge = <&v2m_sysreg>;
205 205
206 v2m_oscclk1: osc@1 { 206 v2m_oscclk1: osc@1 {
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 552373c4e362..f24e79dd51bf 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -41,4 +41,13 @@ config ARM_CCI
41 help 41 help
42 Driver supporting the CCI cache coherent interconnect for ARM 42 Driver supporting the CCI cache coherent interconnect for ARM
43 platforms. 43 platforms.
44
45config VEXPRESS_CONFIG
46 bool "Versatile Express configuration bus"
47 default y if ARCH_VEXPRESS
48 depends on ARM || ARM64
49 select REGMAP
50 help
51 Platform configuration infrastructure for the ARM Ltd.
52 Versatile Express.
44endmenu 53endmenu
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index 8947bdd0de8b..f095aa771de9 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -10,3 +10,5 @@ obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
10obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o 10obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
11# CCI cache coherent interconnect for ARM platforms 11# CCI cache coherent interconnect for ARM platforms
12obj-$(CONFIG_ARM_CCI) += arm-cci.o 12obj-$(CONFIG_ARM_CCI) += arm-cci.o
13
14obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
diff --git a/drivers/bus/vexpress-config.c b/drivers/bus/vexpress-config.c
new file mode 100644
index 000000000000..27a07dfcd626
--- /dev/null
+++ b/drivers/bus/vexpress-config.c
@@ -0,0 +1,202 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * Copyright (C) 2014 ARM Limited
12 */
13
14#include <linux/err.h>
15#include <linux/init.h>
16#include <linux/of.h>
17#include <linux/of_device.h>
18#include <linux/vexpress.h>
19
20
21struct vexpress_config_bridge {
22 struct vexpress_config_bridge_ops *ops;
23 void *context;
24};
25
26
27static DEFINE_MUTEX(vexpress_config_mutex);
28static struct class *vexpress_config_class;
29static u32 vexpress_config_site_master = VEXPRESS_SITE_MASTER;
30
31
32void vexpress_config_set_master(u32 site)
33{
34 vexpress_config_site_master = site;
35}
36
37u32 vexpress_config_get_master(void)
38{
39 return vexpress_config_site_master;
40}
41
42void vexpress_config_lock(void *arg)
43{
44 mutex_lock(&vexpress_config_mutex);
45}
46
47void vexpress_config_unlock(void *arg)
48{
49 mutex_unlock(&vexpress_config_mutex);
50}
51
52
53static void vexpress_config_find_prop(struct device_node *node,
54 const char *name, u32 *val)
55{
56 /* Default value */
57 *val = 0;
58
59 of_node_get(node);
60 while (node) {
61 if (of_property_read_u32(node, name, val) == 0) {
62 of_node_put(node);
63 return;
64 }
65 node = of_get_next_parent(node);
66 }
67}
68
69int vexpress_config_get_topo(struct device_node *node, u32 *site,
70 u32 *position, u32 *dcc)
71{
72 vexpress_config_find_prop(node, "arm,vexpress,site", site);
73 if (*site == VEXPRESS_SITE_MASTER)
74 *site = vexpress_config_site_master;
75 if (WARN_ON(vexpress_config_site_master == VEXPRESS_SITE_MASTER))
76 return -EINVAL;
77 vexpress_config_find_prop(node, "arm,vexpress,position", position);
78 vexpress_config_find_prop(node, "arm,vexpress,dcc", dcc);
79
80 return 0;
81}
82
83
84static void vexpress_config_devres_release(struct device *dev, void *res)
85{
86 struct vexpress_config_bridge *bridge = dev_get_drvdata(dev->parent);
87 struct regmap *regmap = res;
88
89 bridge->ops->regmap_exit(regmap, bridge->context);
90}
91
92struct regmap *devm_regmap_init_vexpress_config(struct device *dev)
93{
94 struct vexpress_config_bridge *bridge;
95 struct regmap *regmap;
96 struct regmap **res;
97
98 if (WARN_ON(dev->parent->class != vexpress_config_class))
99 return ERR_PTR(-ENODEV);
100
101 bridge = dev_get_drvdata(dev->parent);
102 if (WARN_ON(!bridge))
103 return ERR_PTR(-EINVAL);
104
105 res = devres_alloc(vexpress_config_devres_release, sizeof(*res),
106 GFP_KERNEL);
107 if (!res)
108 return ERR_PTR(-ENOMEM);
109
110 regmap = bridge->ops->regmap_init(dev, bridge->context);
111 if (IS_ERR(regmap)) {
112 devres_free(res);
113 return regmap;
114 }
115
116 *res = regmap;
117 devres_add(dev, res);
118
119 return regmap;
120}
121
122
123struct device *vexpress_config_bridge_register(struct device *parent,
124 struct vexpress_config_bridge_ops *ops, void *context)
125{
126 struct device *dev;
127 struct vexpress_config_bridge *bridge;
128
129 if (!vexpress_config_class) {
130 vexpress_config_class = class_create(THIS_MODULE,
131 "vexpress-config");
132 if (IS_ERR(vexpress_config_class))
133 return (void *)vexpress_config_class;
134 }
135
136 dev = device_create(vexpress_config_class, parent, 0,
137 NULL, "%s.bridge", dev_name(parent));
138
139 if (IS_ERR(dev))
140 return dev;
141
142 bridge = devm_kmalloc(dev, sizeof(*bridge), GFP_KERNEL);
143 if (!bridge) {
144 put_device(dev);
145 device_unregister(dev);
146 return ERR_PTR(-ENOMEM);
147 }
148 bridge->ops = ops;
149 bridge->context = context;
150
151 dev_set_drvdata(dev, bridge);
152
153 dev_dbg(parent, "Registered bridge '%s', parent node %p\n",
154 dev_name(dev), parent->of_node);
155
156 return dev;
157}
158
159
160static int vexpress_config_node_match(struct device *dev, const void *data)
161{
162 const struct device_node *node = data;
163
164 dev_dbg(dev, "Parent node %p, looking for %p\n",
165 dev->parent->of_node, node);
166
167 return dev->parent->of_node == node;
168}
169
170static int vexpress_config_populate(struct device_node *node)
171{
172 struct device_node *bridge;
173 struct device *parent;
174
175 bridge = of_parse_phandle(node, "arm,vexpress,config-bridge", 0);
176 if (!bridge)
177 return -EINVAL;
178
179 parent = class_find_device(vexpress_config_class, NULL, bridge,
180 vexpress_config_node_match);
181 if (WARN_ON(!parent))
182 return -ENODEV;
183
184 return of_platform_populate(node, NULL, NULL, parent);
185}
186
187static int __init vexpress_config_init(void)
188{
189 int err = 0;
190 struct device_node *node;
191
192 /* Need the config devices early, before the "normal" devices... */
193 for_each_compatible_node(node, NULL, "arm,vexpress,config-bus") {
194 err = vexpress_config_populate(node);
195 if (err)
196 break;
197 }
198
199 return err;
200}
201postcore_initcall(vexpress_config_init);
202
diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c
index 422391242b39..529a59c0fbfa 100644
--- a/drivers/clk/versatile/clk-vexpress-osc.c
+++ b/drivers/clk/versatile/clk-vexpress-osc.c
@@ -11,8 +11,6 @@
11 * Copyright (C) 2012 ARM Limited 11 * Copyright (C) 2012 ARM Limited
12 */ 12 */
13 13
14#define pr_fmt(fmt) "vexpress-osc: " fmt
15
16#include <linux/clkdev.h> 14#include <linux/clkdev.h>
17#include <linux/clk-provider.h> 15#include <linux/clk-provider.h>
18#include <linux/err.h> 16#include <linux/err.h>
@@ -22,7 +20,7 @@
22#include <linux/vexpress.h> 20#include <linux/vexpress.h>
23 21
24struct vexpress_osc { 22struct vexpress_osc {
25 struct vexpress_config_func *func; 23 struct regmap *reg;
26 struct clk_hw hw; 24 struct clk_hw hw;
27 unsigned long rate_min; 25 unsigned long rate_min;
28 unsigned long rate_max; 26 unsigned long rate_max;
@@ -36,7 +34,7 @@ static unsigned long vexpress_osc_recalc_rate(struct clk_hw *hw,
36 struct vexpress_osc *osc = to_vexpress_osc(hw); 34 struct vexpress_osc *osc = to_vexpress_osc(hw);
37 u32 rate; 35 u32 rate;
38 36
39 vexpress_config_read(osc->func, 0, &rate); 37 regmap_read(osc->reg, 0, &rate);
40 38
41 return rate; 39 return rate;
42} 40}
@@ -60,7 +58,7 @@ static int vexpress_osc_set_rate(struct clk_hw *hw, unsigned long rate,
60{ 58{
61 struct vexpress_osc *osc = to_vexpress_osc(hw); 59 struct vexpress_osc *osc = to_vexpress_osc(hw);
62 60
63 return vexpress_config_write(osc->func, 0, rate); 61 return regmap_write(osc->reg, 0, rate);
64} 62}
65 63
66static struct clk_ops vexpress_osc_ops = { 64static struct clk_ops vexpress_osc_ops = {
@@ -70,58 +68,31 @@ static struct clk_ops vexpress_osc_ops = {
70}; 68};
71 69
72 70
73struct clk * __init vexpress_osc_setup(struct device *dev) 71static int vexpress_osc_probe(struct platform_device *pdev)
74{
75 struct clk_init_data init;
76 struct vexpress_osc *osc = kzalloc(sizeof(*osc), GFP_KERNEL);
77
78 if (!osc)
79 return NULL;
80
81 osc->func = vexpress_config_func_get_by_dev(dev);
82 if (!osc->func) {
83 kfree(osc);
84 return NULL;
85 }
86
87 init.name = dev_name(dev);
88 init.ops = &vexpress_osc_ops;
89 init.flags = CLK_IS_ROOT;
90 init.num_parents = 0;
91 osc->hw.init = &init;
92
93 return clk_register(NULL, &osc->hw);
94}
95
96void __init vexpress_osc_of_setup(struct device_node *node)
97{ 72{
73 struct clk_lookup *cl = pdev->dev.platform_data; /* Non-DT lookup */
98 struct clk_init_data init; 74 struct clk_init_data init;
99 struct vexpress_osc *osc; 75 struct vexpress_osc *osc;
100 struct clk *clk; 76 struct clk *clk;
101 u32 range[2]; 77 u32 range[2];
102 78
103 vexpress_sysreg_of_early_init(); 79 osc = devm_kzalloc(&pdev->dev, sizeof(*osc), GFP_KERNEL);
104
105 osc = kzalloc(sizeof(*osc), GFP_KERNEL);
106 if (!osc) 80 if (!osc)
107 return; 81 return -ENOMEM;
108 82
109 osc->func = vexpress_config_func_get_by_node(node); 83 osc->reg = devm_regmap_init_vexpress_config(&pdev->dev);
110 if (!osc->func) { 84 if (IS_ERR(osc->reg))
111 pr_err("Failed to obtain config func for node '%s'!\n", 85 return PTR_ERR(osc->reg);
112 node->full_name);
113 goto error;
114 }
115 86
116 if (of_property_read_u32_array(node, "freq-range", range, 87 if (of_property_read_u32_array(pdev->dev.of_node, "freq-range", range,
117 ARRAY_SIZE(range)) == 0) { 88 ARRAY_SIZE(range)) == 0) {
118 osc->rate_min = range[0]; 89 osc->rate_min = range[0];
119 osc->rate_max = range[1]; 90 osc->rate_max = range[1];
120 } 91 }
121 92
122 of_property_read_string(node, "clock-output-names", &init.name); 93 if (of_property_read_string(pdev->dev.of_node, "clock-output-names",
123 if (!init.name) 94 &init.name) != 0)
124 init.name = node->full_name; 95 init.name = dev_name(&pdev->dev);
125 96
126 init.ops = &vexpress_osc_ops; 97 init.ops = &vexpress_osc_ops;
127 init.flags = CLK_IS_ROOT; 98 init.flags = CLK_IS_ROOT;
@@ -130,20 +101,37 @@ void __init vexpress_osc_of_setup(struct device_node *node)
130 osc->hw.init = &init; 101 osc->hw.init = &init;
131 102
132 clk = clk_register(NULL, &osc->hw); 103 clk = clk_register(NULL, &osc->hw);
133 if (IS_ERR(clk)) { 104 if (IS_ERR(clk))
134 pr_err("Failed to register clock '%s'!\n", init.name); 105 return PTR_ERR(clk);
135 goto error; 106
107 of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, clk);
108
109 /* Only happens for non-DT cases */
110 if (cl) {
111 cl->clk = clk;
112 clkdev_add(cl);
136 } 113 }
137 114
138 of_clk_add_provider(node, of_clk_src_simple_get, clk); 115 dev_dbg(&pdev->dev, "Registered clock '%s'\n", init.name);
116
117 return 0;
118}
139 119
140 pr_debug("Registered clock '%s'\n", init.name); 120static struct of_device_id vexpress_osc_of_match[] = {
121 { .compatible = "arm,vexpress-osc", },
122 {}
123};
141 124
142 return; 125static struct platform_driver vexpress_osc_driver = {
126 .driver = {
127 .name = "vexpress-osc",
128 .of_match_table = vexpress_osc_of_match,
129 },
130 .probe = vexpress_osc_probe,
131};
143 132
144error: 133static int __init vexpress_osc_init(void)
145 if (osc->func) 134{
146 vexpress_config_func_put(osc->func); 135 return platform_driver_register(&vexpress_osc_driver);
147 kfree(osc);
148} 136}
149CLK_OF_DECLARE(vexpress_soc, "arm,vexpress-osc", vexpress_osc_of_setup); 137core_initcall(vexpress_osc_init);
diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c
index 8242b75d96c8..611f34c7333d 100644
--- a/drivers/hwmon/vexpress.c
+++ b/drivers/hwmon/vexpress.c
@@ -26,7 +26,7 @@
26 26
27struct vexpress_hwmon_data { 27struct vexpress_hwmon_data {
28 struct device *hwmon_dev; 28 struct device *hwmon_dev;
29 struct vexpress_config_func *func; 29 struct regmap *reg;
30 const char *name; 30 const char *name;
31}; 31};
32 32
@@ -53,7 +53,7 @@ static ssize_t vexpress_hwmon_u32_show(struct device *dev,
53 int err; 53 int err;
54 u32 value; 54 u32 value;
55 55
56 err = vexpress_config_read(data->func, 0, &value); 56 err = regmap_read(data->reg, 0, &value);
57 if (err) 57 if (err)
58 return err; 58 return err;
59 59
@@ -68,11 +68,11 @@ static ssize_t vexpress_hwmon_u64_show(struct device *dev,
68 int err; 68 int err;
69 u32 value_hi, value_lo; 69 u32 value_hi, value_lo;
70 70
71 err = vexpress_config_read(data->func, 0, &value_lo); 71 err = regmap_read(data->reg, 0, &value_lo);
72 if (err) 72 if (err)
73 return err; 73 return err;
74 74
75 err = vexpress_config_read(data->func, 1, &value_hi); 75 err = regmap_read(data->reg, 1, &value_hi);
76 if (err) 76 if (err)
77 return err; 77 return err;
78 78
@@ -234,9 +234,9 @@ static int vexpress_hwmon_probe(struct platform_device *pdev)
234 type = match->data; 234 type = match->data;
235 data->name = type->name; 235 data->name = type->name;
236 236
237 data->func = vexpress_config_func_get_by_dev(&pdev->dev); 237 data->reg = devm_regmap_init_vexpress_config(&pdev->dev);
238 if (!data->func) 238 if (IS_ERR(data->reg))
239 return -ENODEV; 239 return PTR_ERR(data->reg);
240 240
241 err = sysfs_create_groups(&pdev->dev.kobj, type->attr_groups); 241 err = sysfs_create_groups(&pdev->dev.kobj, type->attr_groups);
242 if (err) 242 if (err)
@@ -252,7 +252,6 @@ static int vexpress_hwmon_probe(struct platform_device *pdev)
252 252
253error: 253error:
254 sysfs_remove_group(&pdev->dev.kobj, match->data); 254 sysfs_remove_group(&pdev->dev.kobj, match->data);
255 vexpress_config_func_put(data->func);
256 return err; 255 return err;
257} 256}
258 257
@@ -266,8 +265,6 @@ static int vexpress_hwmon_remove(struct platform_device *pdev)
266 match = of_match_device(vexpress_hwmon_of_match, &pdev->dev); 265 match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
267 sysfs_remove_group(&pdev->dev.kobj, match->data); 266 sysfs_remove_group(&pdev->dev.kobj, match->data);
268 267
269 vexpress_config_func_put(data->func);
270
271 return 0; 268 return 0;
272} 269}
273 270
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 2851275e2656..9ba838eb5131 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -161,7 +161,7 @@ obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
161obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o 161obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o
162obj-$(CONFIG_MFD_SYSCON) += syscon.o 162obj-$(CONFIG_MFD_SYSCON) += syscon.o
163obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o 163obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o
164obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o vexpress-sysreg.o 164obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-sysreg.o
165obj-$(CONFIG_MFD_RETU) += retu-mfd.o 165obj-$(CONFIG_MFD_RETU) += retu-mfd.o
166obj-$(CONFIG_MFD_AS3711) += as3711.o 166obj-$(CONFIG_MFD_AS3711) += as3711.o
167obj-$(CONFIG_MFD_AS3722) += as3722.o 167obj-$(CONFIG_MFD_AS3722) += as3722.o
diff --git a/drivers/mfd/vexpress-config.c b/drivers/mfd/vexpress-config.c
deleted file mode 100644
index d0db89d13e01..000000000000
--- a/drivers/mfd/vexpress-config.c
+++ /dev/null
@@ -1,287 +0,0 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * Copyright (C) 2012 ARM Limited
12 */
13
14#define pr_fmt(fmt) "vexpress-config: " fmt
15
16#include <linux/bitops.h>
17#include <linux/completion.h>
18#include <linux/export.h>
19#include <linux/list.h>
20#include <linux/of.h>
21#include <linux/of_device.h>
22#include <linux/slab.h>
23#include <linux/string.h>
24#include <linux/vexpress.h>
25
26
27#define VEXPRESS_CONFIG_MAX_BRIDGES 2
28
29static struct vexpress_config_bridge {
30 struct device_node *node;
31 struct vexpress_config_bridge_info *info;
32 struct list_head transactions;
33 spinlock_t transactions_lock;
34} vexpress_config_bridges[VEXPRESS_CONFIG_MAX_BRIDGES];
35
36static DECLARE_BITMAP(vexpress_config_bridges_map,
37 ARRAY_SIZE(vexpress_config_bridges));
38static DEFINE_MUTEX(vexpress_config_bridges_mutex);
39
40struct vexpress_config_bridge *vexpress_config_bridge_register(
41 struct device_node *node,
42 struct vexpress_config_bridge_info *info)
43{
44 struct vexpress_config_bridge *bridge;
45 int i;
46
47 pr_debug("Registering bridge '%s'\n", info->name);
48
49 mutex_lock(&vexpress_config_bridges_mutex);
50 i = find_first_zero_bit(vexpress_config_bridges_map,
51 ARRAY_SIZE(vexpress_config_bridges));
52 if (i >= ARRAY_SIZE(vexpress_config_bridges)) {
53 pr_err("Can't register more bridges!\n");
54 mutex_unlock(&vexpress_config_bridges_mutex);
55 return NULL;
56 }
57 __set_bit(i, vexpress_config_bridges_map);
58 bridge = &vexpress_config_bridges[i];
59
60 bridge->node = node;
61 bridge->info = info;
62 INIT_LIST_HEAD(&bridge->transactions);
63 spin_lock_init(&bridge->transactions_lock);
64
65 mutex_unlock(&vexpress_config_bridges_mutex);
66
67 return bridge;
68}
69EXPORT_SYMBOL(vexpress_config_bridge_register);
70
71void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge)
72{
73 struct vexpress_config_bridge __bridge = *bridge;
74 int i;
75
76 mutex_lock(&vexpress_config_bridges_mutex);
77 for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++)
78 if (&vexpress_config_bridges[i] == bridge)
79 __clear_bit(i, vexpress_config_bridges_map);
80 mutex_unlock(&vexpress_config_bridges_mutex);
81
82 WARN_ON(!list_empty(&__bridge.transactions));
83 while (!list_empty(&__bridge.transactions))
84 cpu_relax();
85}
86EXPORT_SYMBOL(vexpress_config_bridge_unregister);
87
88
89struct vexpress_config_func {
90 struct vexpress_config_bridge *bridge;
91 void *func;
92};
93
94struct vexpress_config_func *__vexpress_config_func_get(struct device *dev,
95 struct device_node *node)
96{
97 struct device_node *bridge_node;
98 struct vexpress_config_func *func;
99 int i;
100
101 if (WARN_ON(dev && node && dev->of_node != node))
102 return NULL;
103 if (dev && !node)
104 node = dev->of_node;
105
106 func = kzalloc(sizeof(*func), GFP_KERNEL);
107 if (!func)
108 return NULL;
109
110 bridge_node = of_node_get(node);
111 while (bridge_node) {
112 const __be32 *prop = of_get_property(bridge_node,
113 "arm,vexpress,config-bridge", NULL);
114
115 if (prop) {
116 bridge_node = of_find_node_by_phandle(
117 be32_to_cpup(prop));
118 break;
119 }
120
121 bridge_node = of_get_next_parent(bridge_node);
122 }
123
124 mutex_lock(&vexpress_config_bridges_mutex);
125 for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++) {
126 struct vexpress_config_bridge *bridge =
127 &vexpress_config_bridges[i];
128
129 if (test_bit(i, vexpress_config_bridges_map) &&
130 bridge->node == bridge_node) {
131 func->bridge = bridge;
132 func->func = bridge->info->func_get(dev, node);
133 break;
134 }
135 }
136 mutex_unlock(&vexpress_config_bridges_mutex);
137
138 if (!func->func) {
139 of_node_put(node);
140 kfree(func);
141 return NULL;
142 }
143
144 return func;
145}
146EXPORT_SYMBOL(__vexpress_config_func_get);
147
148void vexpress_config_func_put(struct vexpress_config_func *func)
149{
150 func->bridge->info->func_put(func->func);
151 of_node_put(func->bridge->node);
152 kfree(func);
153}
154EXPORT_SYMBOL(vexpress_config_func_put);
155
156struct vexpress_config_trans {
157 struct vexpress_config_func *func;
158 int offset;
159 bool write;
160 u32 *data;
161 int status;
162 struct completion completion;
163 struct list_head list;
164};
165
166static void vexpress_config_dump_trans(const char *what,
167 struct vexpress_config_trans *trans)
168{
169 pr_debug("%s %s trans %p func 0x%p offset %d data 0x%x status %d\n",
170 what, trans->write ? "write" : "read", trans,
171 trans->func->func, trans->offset,
172 trans->data ? *trans->data : 0, trans->status);
173}
174
175static int vexpress_config_schedule(struct vexpress_config_trans *trans)
176{
177 int status;
178 struct vexpress_config_bridge *bridge = trans->func->bridge;
179 unsigned long flags;
180
181 init_completion(&trans->completion);
182 trans->status = -EFAULT;
183
184 spin_lock_irqsave(&bridge->transactions_lock, flags);
185
186 if (list_empty(&bridge->transactions)) {
187 vexpress_config_dump_trans("Executing", trans);
188 status = bridge->info->func_exec(trans->func->func,
189 trans->offset, trans->write, trans->data);
190 } else {
191 vexpress_config_dump_trans("Queuing", trans);
192 status = VEXPRESS_CONFIG_STATUS_WAIT;
193 }
194
195 switch (status) {
196 case VEXPRESS_CONFIG_STATUS_DONE:
197 vexpress_config_dump_trans("Finished", trans);
198 trans->status = status;
199 break;
200 case VEXPRESS_CONFIG_STATUS_WAIT:
201 list_add_tail(&trans->list, &bridge->transactions);
202 break;
203 }
204
205 spin_unlock_irqrestore(&bridge->transactions_lock, flags);
206
207 return status;
208}
209
210void vexpress_config_complete(struct vexpress_config_bridge *bridge,
211 int status)
212{
213 struct vexpress_config_trans *trans;
214 unsigned long flags;
215 const char *message = "Completed";
216
217 spin_lock_irqsave(&bridge->transactions_lock, flags);
218
219 trans = list_first_entry(&bridge->transactions,
220 struct vexpress_config_trans, list);
221 trans->status = status;
222
223 do {
224 vexpress_config_dump_trans(message, trans);
225 list_del(&trans->list);
226 complete(&trans->completion);
227
228 if (list_empty(&bridge->transactions))
229 break;
230
231 trans = list_first_entry(&bridge->transactions,
232 struct vexpress_config_trans, list);
233 vexpress_config_dump_trans("Executing pending", trans);
234 trans->status = bridge->info->func_exec(trans->func->func,
235 trans->offset, trans->write, trans->data);
236 message = "Finished pending";
237 } while (trans->status == VEXPRESS_CONFIG_STATUS_DONE);
238
239 spin_unlock_irqrestore(&bridge->transactions_lock, flags);
240}
241EXPORT_SYMBOL(vexpress_config_complete);
242
243int vexpress_config_wait(struct vexpress_config_trans *trans)
244{
245 wait_for_completion(&trans->completion);
246
247 return trans->status;
248}
249EXPORT_SYMBOL(vexpress_config_wait);
250
251int vexpress_config_read(struct vexpress_config_func *func, int offset,
252 u32 *data)
253{
254 struct vexpress_config_trans trans = {
255 .func = func,
256 .offset = offset,
257 .write = false,
258 .data = data,
259 .status = 0,
260 };
261 int status = vexpress_config_schedule(&trans);
262
263 if (status == VEXPRESS_CONFIG_STATUS_WAIT)
264 status = vexpress_config_wait(&trans);
265
266 return status;
267}
268EXPORT_SYMBOL(vexpress_config_read);
269
270int vexpress_config_write(struct vexpress_config_func *func, int offset,
271 u32 data)
272{
273 struct vexpress_config_trans trans = {
274 .func = func,
275 .offset = offset,
276 .write = true,
277 .data = &data,
278 .status = 0,
279 };
280 int status = vexpress_config_schedule(&trans);
281
282 if (status == VEXPRESS_CONFIG_STATUS_WAIT)
283 status = vexpress_config_wait(&trans);
284
285 return status;
286}
287EXPORT_SYMBOL(vexpress_config_write);
diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c
index 35281e804e7e..b4138a7168db 100644
--- a/drivers/mfd/vexpress-sysreg.c
+++ b/drivers/mfd/vexpress-sysreg.c
@@ -16,8 +16,10 @@
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/leds.h> 17#include <linux/leds.h>
18#include <linux/of_address.h> 18#include <linux/of_address.h>
19#include <linux/of_platform.h>
19#include <linux/platform_device.h> 20#include <linux/platform_device.h>
20#include <linux/regulator/driver.h> 21#include <linux/regulator/driver.h>
22#include <linux/sched.h>
21#include <linux/slab.h> 23#include <linux/slab.h>
22#include <linux/stat.h> 24#include <linux/stat.h>
23#include <linux/timer.h> 25#include <linux/timer.h>
@@ -72,9 +74,18 @@
72 74
73static void __iomem *vexpress_sysreg_base; 75static void __iomem *vexpress_sysreg_base;
74static struct device *vexpress_sysreg_dev; 76static struct device *vexpress_sysreg_dev;
75static int vexpress_master_site; 77static LIST_HEAD(vexpress_sysreg_config_funcs);
78static struct device *vexpress_sysreg_config_bridge;
76 79
77 80
81static int vexpress_sysreg_get_master(void)
82{
83 if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE)
84 return VEXPRESS_SITE_DB2;
85
86 return VEXPRESS_SITE_DB1;
87}
88
78void vexpress_flags_set(u32 data) 89void vexpress_flags_set(u32 data)
79{ 90{
80 writel(~0, vexpress_sysreg_base + SYS_FLAGSCLR); 91 writel(~0, vexpress_sysreg_base + SYS_FLAGSCLR);
@@ -84,7 +95,7 @@ void vexpress_flags_set(u32 data)
84u32 vexpress_get_procid(int site) 95u32 vexpress_get_procid(int site)
85{ 96{
86 if (site == VEXPRESS_SITE_MASTER) 97 if (site == VEXPRESS_SITE_MASTER)
87 site = vexpress_master_site; 98 site = vexpress_sysreg_get_master();
88 99
89 return readl(vexpress_sysreg_base + (site == VEXPRESS_SITE_DB1 ? 100 return readl(vexpress_sysreg_base + (site == VEXPRESS_SITE_DB1 ?
90 SYS_PROCID0 : SYS_PROCID1)); 101 SYS_PROCID0 : SYS_PROCID1));
@@ -114,130 +125,33 @@ void __iomem *vexpress_get_24mhz_clock_base(void)
114} 125}
115 126
116 127
117static void vexpress_sysreg_find_prop(struct device_node *node,
118 const char *name, u32 *val)
119{
120 of_node_get(node);
121 while (node) {
122 if (of_property_read_u32(node, name, val) == 0) {
123 of_node_put(node);
124 return;
125 }
126 node = of_get_next_parent(node);
127 }
128}
129
130unsigned __vexpress_get_site(struct device *dev, struct device_node *node)
131{
132 u32 site = 0;
133
134 WARN_ON(dev && node && dev->of_node != node);
135 if (dev && !node)
136 node = dev->of_node;
137
138 if (node) {
139 vexpress_sysreg_find_prop(node, "arm,vexpress,site", &site);
140 } else if (dev && dev->bus == &platform_bus_type) {
141 struct platform_device *pdev = to_platform_device(dev);
142
143 if (pdev->num_resources == 1 &&
144 pdev->resource[0].flags == IORESOURCE_BUS)
145 site = pdev->resource[0].start;
146 } else if (dev && strncmp(dev_name(dev), "ct:", 3) == 0) {
147 site = VEXPRESS_SITE_MASTER;
148 }
149
150 if (site == VEXPRESS_SITE_MASTER)
151 site = vexpress_master_site;
152
153 return site;
154}
155
156
157struct vexpress_sysreg_config_func { 128struct vexpress_sysreg_config_func {
158 u32 template; 129 struct list_head list;
159 u32 device; 130 struct regmap *regmap;
131 int num_templates;
132 u32 template[0]; /* Keep this last */
160}; 133};
161 134
162static struct vexpress_config_bridge *vexpress_sysreg_config_bridge; 135static int vexpress_sysreg_config_exec(struct vexpress_sysreg_config_func *func,
163static struct timer_list vexpress_sysreg_config_timer; 136 int index, bool write, u32 *data)
164static u32 *vexpress_sysreg_config_data;
165static int vexpress_sysreg_config_tries;
166
167static void *vexpress_sysreg_config_func_get(struct device *dev,
168 struct device_node *node)
169{ 137{
170 struct vexpress_sysreg_config_func *config_func; 138 u32 command, status;
171 u32 site = 0; 139 int tries;
172 u32 position = 0; 140 long timeout;
173 u32 dcc = 0;
174 u32 func_device[2];
175 int err = -EFAULT;
176
177 if (node) {
178 of_node_get(node);
179 vexpress_sysreg_find_prop(node, "arm,vexpress,site", &site);
180 vexpress_sysreg_find_prop(node, "arm,vexpress,position",
181 &position);
182 vexpress_sysreg_find_prop(node, "arm,vexpress,dcc", &dcc);
183 err = of_property_read_u32_array(node,
184 "arm,vexpress-sysreg,func", func_device,
185 ARRAY_SIZE(func_device));
186 of_node_put(node);
187 } else if (dev && dev->bus == &platform_bus_type) {
188 struct platform_device *pdev = to_platform_device(dev);
189
190 if (pdev->num_resources == 1 &&
191 pdev->resource[0].flags == IORESOURCE_BUS) {
192 site = pdev->resource[0].start;
193 func_device[0] = pdev->resource[0].end;
194 func_device[1] = pdev->id;
195 err = 0;
196 }
197 }
198 if (err)
199 return NULL;
200
201 config_func = kzalloc(sizeof(*config_func), GFP_KERNEL);
202 if (!config_func)
203 return NULL;
204
205 config_func->template = SYS_CFGCTRL_DCC(dcc);
206 config_func->template |= SYS_CFGCTRL_FUNC(func_device[0]);
207 config_func->template |= SYS_CFGCTRL_SITE(site == VEXPRESS_SITE_MASTER ?
208 vexpress_master_site : site);
209 config_func->template |= SYS_CFGCTRL_POSITION(position);
210 config_func->device |= func_device[1];
211
212 dev_dbg(vexpress_sysreg_dev, "func 0x%p = 0x%x, %d\n", config_func,
213 config_func->template, config_func->device);
214
215 return config_func;
216}
217
218static void vexpress_sysreg_config_func_put(void *func)
219{
220 kfree(func);
221}
222
223static int vexpress_sysreg_config_func_exec(void *func, int offset,
224 bool write, u32 *data)
225{
226 int status;
227 struct vexpress_sysreg_config_func *config_func = func;
228 u32 command;
229 141
230 if (WARN_ON(!vexpress_sysreg_base)) 142 if (WARN_ON(!vexpress_sysreg_base))
231 return -ENOENT; 143 return -ENOENT;
232 144
145 if (WARN_ON(index > func->num_templates))
146 return -EINVAL;
147
233 command = readl(vexpress_sysreg_base + SYS_CFGCTRL); 148 command = readl(vexpress_sysreg_base + SYS_CFGCTRL);
234 if (WARN_ON(command & SYS_CFGCTRL_START)) 149 if (WARN_ON(command & SYS_CFGCTRL_START))
235 return -EBUSY; 150 return -EBUSY;
236 151
237 command = SYS_CFGCTRL_START; 152 command = func->template[index];
153 command |= SYS_CFGCTRL_START;
238 command |= write ? SYS_CFGCTRL_WRITE : 0; 154 command |= write ? SYS_CFGCTRL_WRITE : 0;
239 command |= config_func->template;
240 command |= SYS_CFGCTRL_DEVICE(config_func->device + offset);
241 155
242 /* Use a canary for reads */ 156 /* Use a canary for reads */
243 if (!write) 157 if (!write)
@@ -250,90 +164,190 @@ static int vexpress_sysreg_config_func_exec(void *func, int offset,
250 writel(command, vexpress_sysreg_base + SYS_CFGCTRL); 164 writel(command, vexpress_sysreg_base + SYS_CFGCTRL);
251 mb(); 165 mb();
252 166
253 if (vexpress_sysreg_dev) { 167 /* The operation can take ages... Go to sleep, 100us initially */
254 /* Schedule completion check */ 168 tries = 100;
255 if (!write) 169 timeout = 100;
256 vexpress_sysreg_config_data = data; 170 do {
257 vexpress_sysreg_config_tries = 100; 171 set_current_state(TASK_INTERRUPTIBLE);
258 mod_timer(&vexpress_sysreg_config_timer, 172 schedule_timeout(usecs_to_jiffies(timeout));
259 jiffies + usecs_to_jiffies(100)); 173 if (signal_pending(current))
260 status = VEXPRESS_CONFIG_STATUS_WAIT; 174 return -EINTR;
261 } else { 175
262 /* Early execution, no timer available, have to spin */ 176 status = readl(vexpress_sysreg_base + SYS_CFGSTAT);
263 u32 cfgstat; 177 if (status & SYS_CFGSTAT_ERR)
178 return -EFAULT;
179
180 if (timeout > 20)
181 timeout -= 20;
182 } while (--tries && !(status & SYS_CFGSTAT_COMPLETE));
183 if (WARN_ON_ONCE(!tries))
184 return -ETIMEDOUT;
185
186 if (!write) {
187 *data = readl(vexpress_sysreg_base + SYS_CFGDATA);
188 dev_dbg(vexpress_sysreg_dev, "func %p, read data %x\n",
189 func, *data);
190 }
264 191
265 do { 192 return 0;
266 cpu_relax(); 193}
267 cfgstat = readl(vexpress_sysreg_base + SYS_CFGSTAT);
268 } while (!cfgstat);
269 194
270 if (!write && (cfgstat & SYS_CFGSTAT_COMPLETE)) 195static int vexpress_sysreg_config_read(void *context, unsigned int index,
271 *data = readl(vexpress_sysreg_base + SYS_CFGDATA); 196 unsigned int *val)
272 status = VEXPRESS_CONFIG_STATUS_DONE; 197{
198 struct vexpress_sysreg_config_func *func = context;
273 199
274 if (cfgstat & SYS_CFGSTAT_ERR) 200 return vexpress_sysreg_config_exec(func, index, false, val);
275 status = -EINVAL; 201}
276 }
277 202
278 return status; 203static int vexpress_sysreg_config_write(void *context, unsigned int index,
204 unsigned int val)
205{
206 struct vexpress_sysreg_config_func *func = context;
207
208 return vexpress_sysreg_config_exec(func, index, true, &val);
279} 209}
280 210
281struct vexpress_config_bridge_info vexpress_sysreg_config_bridge_info = { 211struct regmap_config vexpress_sysreg_regmap_config = {
282 .name = "vexpress-sysreg", 212 .lock = vexpress_config_lock,
283 .func_get = vexpress_sysreg_config_func_get, 213 .unlock = vexpress_config_unlock,
284 .func_put = vexpress_sysreg_config_func_put, 214 .reg_bits = 32,
285 .func_exec = vexpress_sysreg_config_func_exec, 215 .val_bits = 32,
216 .reg_read = vexpress_sysreg_config_read,
217 .reg_write = vexpress_sysreg_config_write,
218 .reg_format_endian = REGMAP_ENDIAN_LITTLE,
219 .val_format_endian = REGMAP_ENDIAN_LITTLE,
286}; 220};
287 221
288static void vexpress_sysreg_config_complete(unsigned long data) 222static struct regmap *vexpress_sysreg_config_regmap_init(struct device *dev,
223 void *context)
289{ 224{
290 int status = VEXPRESS_CONFIG_STATUS_DONE; 225 struct platform_device *pdev = to_platform_device(dev);
291 u32 cfgstat = readl(vexpress_sysreg_base + SYS_CFGSTAT); 226 struct vexpress_sysreg_config_func *func;
292 227 struct property *prop;
293 if (cfgstat & SYS_CFGSTAT_ERR) 228 const __be32 *val = NULL;
294 status = -EINVAL; 229 __be32 energy_quirk[4];
295 if (!vexpress_sysreg_config_tries--) 230 int num;
296 status = -ETIMEDOUT; 231 u32 site, position, dcc;
297 232 int err;
298 if (status < 0) { 233 int i;
299 dev_err(vexpress_sysreg_dev, "error %d\n", status); 234
300 } else if (!(cfgstat & SYS_CFGSTAT_COMPLETE)) { 235 if (dev->of_node) {
301 mod_timer(&vexpress_sysreg_config_timer, 236 err = vexpress_config_get_topo(dev->of_node, &site, &position,
302 jiffies + usecs_to_jiffies(50)); 237 &dcc);
303 return; 238 if (err)
239 return ERR_PTR(err);
240
241 prop = of_find_property(dev->of_node,
242 "arm,vexpress-sysreg,func", NULL);
243 if (!prop)
244 return ERR_PTR(-EINVAL);
245
246 num = prop->length / sizeof(u32) / 2;
247 val = prop->value;
248 } else {
249 if (pdev->num_resources != 1 ||
250 pdev->resource[0].flags != IORESOURCE_BUS)
251 return ERR_PTR(-EFAULT);
252
253 site = pdev->resource[0].start;
254 if (site == VEXPRESS_SITE_MASTER)
255 site = vexpress_sysreg_get_master();
256 position = 0;
257 dcc = 0;
258 num = 1;
304 } 259 }
305 260
306 if (vexpress_sysreg_config_data) { 261 /*
307 *vexpress_sysreg_config_data = readl(vexpress_sysreg_base + 262 * "arm,vexpress-energy" function used to be described
308 SYS_CFGDATA); 263 * by its first device only, now it requires both
309 dev_dbg(vexpress_sysreg_dev, "read data %x\n", 264 */
310 *vexpress_sysreg_config_data); 265 if (num == 1 && of_device_is_compatible(dev->of_node,
311 vexpress_sysreg_config_data = NULL; 266 "arm,vexpress-energy")) {
267 num = 2;
268 energy_quirk[0] = *val;
269 energy_quirk[2] = *val++;
270 energy_quirk[1] = *val;
271 energy_quirk[3] = cpu_to_be32(be32_to_cpup(val) + 1);
272 val = energy_quirk;
312 } 273 }
313 274
314 vexpress_config_complete(vexpress_sysreg_config_bridge, status); 275 func = kzalloc(sizeof(*func) + sizeof(*func->template) * num,
315} 276 GFP_KERNEL);
277 if (!func)
278 return NULL;
316 279
280 func->num_templates = num;
317 281
318void vexpress_sysreg_setup(struct device_node *node) 282 for (i = 0; i < num; i++) {
319{ 283 u32 function, device;
320 if (WARN_ON(!vexpress_sysreg_base))
321 return;
322 284
323 if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE) 285 if (dev->of_node) {
324 vexpress_master_site = VEXPRESS_SITE_DB2; 286 function = be32_to_cpup(val++);
287 device = be32_to_cpup(val++);
288 } else {
289 function = pdev->resource[0].end;
290 device = pdev->id;
291 }
292
293 dev_dbg(dev, "func %p: %u/%u/%u/%u/%u\n",
294 func, site, position, dcc,
295 function, device);
296
297 func->template[i] = SYS_CFGCTRL_DCC(dcc);
298 func->template[i] |= SYS_CFGCTRL_SITE(site);
299 func->template[i] |= SYS_CFGCTRL_POSITION(position);
300 func->template[i] |= SYS_CFGCTRL_FUNC(function);
301 func->template[i] |= SYS_CFGCTRL_DEVICE(device);
302 }
303
304 vexpress_sysreg_regmap_config.max_register = num - 1;
305
306 func->regmap = regmap_init(dev, NULL, func,
307 &vexpress_sysreg_regmap_config);
308
309 if (IS_ERR(func->regmap))
310 kfree(func);
325 else 311 else
326 vexpress_master_site = VEXPRESS_SITE_DB1; 312 list_add(&func->list, &vexpress_sysreg_config_funcs);
327 313
328 vexpress_sysreg_config_bridge = vexpress_config_bridge_register( 314 return func->regmap;
329 node, &vexpress_sysreg_config_bridge_info); 315}
330 WARN_ON(!vexpress_sysreg_config_bridge); 316
317static void vexpress_sysreg_config_regmap_exit(struct regmap *regmap,
318 void *context)
319{
320 struct vexpress_sysreg_config_func *func, *tmp;
321
322 regmap_exit(regmap);
323
324 list_for_each_entry_safe(func, tmp, &vexpress_sysreg_config_funcs,
325 list) {
326 if (func->regmap == regmap) {
327 list_del(&vexpress_sysreg_config_funcs);
328 kfree(func);
329 break;
330 }
331 }
332}
333
334static struct vexpress_config_bridge_ops vexpress_sysreg_config_bridge_ops = {
335 .regmap_init = vexpress_sysreg_config_regmap_init,
336 .regmap_exit = vexpress_sysreg_config_regmap_exit,
337};
338
339int vexpress_sysreg_config_device_register(struct platform_device *pdev)
340{
341 pdev->dev.parent = vexpress_sysreg_config_bridge;
342
343 return platform_device_register(pdev);
331} 344}
332 345
346
333void __init vexpress_sysreg_early_init(void __iomem *base) 347void __init vexpress_sysreg_early_init(void __iomem *base)
334{ 348{
335 vexpress_sysreg_base = base; 349 vexpress_sysreg_base = base;
336 vexpress_sysreg_setup(NULL); 350 vexpress_config_set_master(vexpress_sysreg_get_master());
337} 351}
338 352
339void __init vexpress_sysreg_of_early_init(void) 353void __init vexpress_sysreg_of_early_init(void)
@@ -344,10 +358,14 @@ void __init vexpress_sysreg_of_early_init(void)
344 return; 358 return;
345 359
346 node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg"); 360 node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg");
347 if (node) { 361 if (WARN_ON(!node))
348 vexpress_sysreg_base = of_iomap(node, 0); 362 return;
349 vexpress_sysreg_setup(node); 363
350 } 364 vexpress_sysreg_base = of_iomap(node, 0);
365 if (WARN_ON(!vexpress_sysreg_base))
366 return;
367
368 vexpress_config_set_master(vexpress_sysreg_get_master());
351} 369}
352 370
353 371
@@ -470,28 +488,22 @@ static int vexpress_sysreg_probe(struct platform_device *pdev)
470 return -EBUSY; 488 return -EBUSY;
471 } 489 }
472 490
473 if (!vexpress_sysreg_base) { 491 if (!vexpress_sysreg_base)
474 vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start, 492 vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start,
475 resource_size(res)); 493 resource_size(res));
476 vexpress_sysreg_setup(pdev->dev.of_node);
477 }
478 494
479 if (!vexpress_sysreg_base) { 495 if (!vexpress_sysreg_base) {
480 dev_err(&pdev->dev, "Failed to obtain base address!\n"); 496 dev_err(&pdev->dev, "Failed to obtain base address!\n");
481 return -EFAULT; 497 return -EFAULT;
482 } 498 }
483 499
484 setup_timer(&vexpress_sysreg_config_timer, 500 vexpress_config_set_master(vexpress_sysreg_get_master());
485 vexpress_sysreg_config_complete, 0);
486
487 vexpress_sysreg_dev = &pdev->dev; 501 vexpress_sysreg_dev = &pdev->dev;
488 502
489#ifdef CONFIG_GPIOLIB 503#ifdef CONFIG_GPIOLIB
490 vexpress_sysreg_gpio_chip.dev = &pdev->dev; 504 vexpress_sysreg_gpio_chip.dev = &pdev->dev;
491 err = gpiochip_add(&vexpress_sysreg_gpio_chip); 505 err = gpiochip_add(&vexpress_sysreg_gpio_chip);
492 if (err) { 506 if (err) {
493 vexpress_config_bridge_unregister(
494 vexpress_sysreg_config_bridge);
495 dev_err(&pdev->dev, "Failed to register GPIO chip! (%d)\n", 507 dev_err(&pdev->dev, "Failed to register GPIO chip! (%d)\n",
496 err); 508 err);
497 return err; 509 return err;
@@ -502,6 +514,10 @@ static int vexpress_sysreg_probe(struct platform_device *pdev)
502 sizeof(vexpress_sysreg_leds_pdata)); 514 sizeof(vexpress_sysreg_leds_pdata));
503#endif 515#endif
504 516
517 vexpress_sysreg_config_bridge = vexpress_config_bridge_register(
518 &pdev->dev, &vexpress_sysreg_config_bridge_ops, NULL);
519 WARN_ON(!vexpress_sysreg_config_bridge);
520
505 device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id); 521 device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id);
506 522
507 return 0; 523 return 0;
@@ -522,7 +538,12 @@ static struct platform_driver vexpress_sysreg_driver = {
522 538
523static int __init vexpress_sysreg_init(void) 539static int __init vexpress_sysreg_init(void)
524{ 540{
525 vexpress_sysreg_of_early_init(); 541 struct device_node *node;
542
543 /* Need the sysreg early, before any other device... */
544 for_each_matching_node(node, vexpress_sysreg_match)
545 of_platform_device_create(node, NULL, NULL);
546
526 return platform_driver_register(&vexpress_sysreg_driver); 547 return platform_driver_register(&vexpress_sysreg_driver);
527} 548}
528core_initcall(vexpress_sysreg_init); 549core_initcall(vexpress_sysreg_init);
diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c
index b95cf71ed695..4dc102e2b230 100644
--- a/drivers/power/reset/vexpress-poweroff.c
+++ b/drivers/power/reset/vexpress-poweroff.c
@@ -23,10 +23,10 @@
23static void vexpress_reset_do(struct device *dev, const char *what) 23static void vexpress_reset_do(struct device *dev, const char *what)
24{ 24{
25 int err = -ENOENT; 25 int err = -ENOENT;
26 struct vexpress_config_func *func = dev_get_drvdata(dev); 26 struct regmap *reg = dev_get_drvdata(dev);
27 27
28 if (func) { 28 if (reg) {
29 err = vexpress_config_write(func, 0, 0); 29 err = regmap_write(reg, 0, 0);
30 if (!err) 30 if (!err)
31 mdelay(1000); 31 mdelay(1000);
32 } 32 }
@@ -91,17 +91,17 @@ static int vexpress_reset_probe(struct platform_device *pdev)
91 enum vexpress_reset_func func; 91 enum vexpress_reset_func func;
92 const struct of_device_id *match = 92 const struct of_device_id *match =
93 of_match_device(vexpress_reset_of_match, &pdev->dev); 93 of_match_device(vexpress_reset_of_match, &pdev->dev);
94 struct vexpress_config_func *config_func; 94 struct regmap *regmap;
95 95
96 if (match) 96 if (match)
97 func = (enum vexpress_reset_func)match->data; 97 func = (enum vexpress_reset_func)match->data;
98 else 98 else
99 func = pdev->id_entry->driver_data; 99 func = pdev->id_entry->driver_data;
100 100
101 config_func = vexpress_config_func_get_by_dev(&pdev->dev); 101 regmap = devm_regmap_init_vexpress_config(&pdev->dev);
102 if (!config_func) 102 if (IS_ERR(regmap))
103 return -EINVAL; 103 return PTR_ERR(regmap);
104 dev_set_drvdata(&pdev->dev, config_func); 104 dev_set_drvdata(&pdev->dev, regmap);
105 105
106 switch (func) { 106 switch (func) {
107 case FUNC_SHUTDOWN: 107 case FUNC_SHUTDOWN:
diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c
index f3ae28a7e663..2863428813e4 100644
--- a/drivers/regulator/vexpress.c
+++ b/drivers/regulator/vexpress.c
@@ -26,14 +26,14 @@
26struct vexpress_regulator { 26struct vexpress_regulator {
27 struct regulator_desc desc; 27 struct regulator_desc desc;
28 struct regulator_dev *regdev; 28 struct regulator_dev *regdev;
29 struct vexpress_config_func *func; 29 struct regmap *regmap;
30}; 30};
31 31
32static int vexpress_regulator_get_voltage(struct regulator_dev *regdev) 32static int vexpress_regulator_get_voltage(struct regulator_dev *regdev)
33{ 33{
34 struct vexpress_regulator *reg = rdev_get_drvdata(regdev); 34 struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
35 u32 uV; 35 u32 uV;
36 int err = vexpress_config_read(reg->func, 0, &uV); 36 int err = regmap_read(reg->regmap, 0, &uV);
37 37
38 return err ? err : uV; 38 return err ? err : uV;
39} 39}
@@ -43,7 +43,7 @@ static int vexpress_regulator_set_voltage(struct regulator_dev *regdev,
43{ 43{
44 struct vexpress_regulator *reg = rdev_get_drvdata(regdev); 44 struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
45 45
46 return vexpress_config_write(reg->func, 0, min_uV); 46 return regmap_write(reg->regmap, 0, min_uV);
47} 47}
48 48
49static struct regulator_ops vexpress_regulator_ops_ro = { 49static struct regulator_ops vexpress_regulator_ops_ro = {
@@ -57,22 +57,17 @@ static struct regulator_ops vexpress_regulator_ops = {
57 57
58static int vexpress_regulator_probe(struct platform_device *pdev) 58static int vexpress_regulator_probe(struct platform_device *pdev)
59{ 59{
60 int err;
61 struct vexpress_regulator *reg; 60 struct vexpress_regulator *reg;
62 struct regulator_init_data *init_data; 61 struct regulator_init_data *init_data;
63 struct regulator_config config = { }; 62 struct regulator_config config = { };
64 63
65 reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL); 64 reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL);
66 if (!reg) { 65 if (!reg)
67 err = -ENOMEM; 66 return -ENOMEM;
68 goto error_kzalloc;
69 }
70 67
71 reg->func = vexpress_config_func_get_by_dev(&pdev->dev); 68 reg->regmap = devm_regmap_init_vexpress_config(&pdev->dev);
72 if (!reg->func) { 69 if (IS_ERR(reg->regmap))
73 err = -ENXIO; 70 return PTR_ERR(reg->regmap);
74 goto error_get_func;
75 }
76 71
77 reg->desc.name = dev_name(&pdev->dev); 72 reg->desc.name = dev_name(&pdev->dev);
78 reg->desc.type = REGULATOR_VOLTAGE; 73 reg->desc.type = REGULATOR_VOLTAGE;
@@ -80,10 +75,8 @@ static int vexpress_regulator_probe(struct platform_device *pdev)
80 reg->desc.continuous_voltage_range = true; 75 reg->desc.continuous_voltage_range = true;
81 76
82 init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node); 77 init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
83 if (!init_data) { 78 if (!init_data)
84 err = -EINVAL; 79 return -EINVAL;
85 goto error_get_regulator_init_data;
86 }
87 80
88 init_data->constraints.apply_uV = 0; 81 init_data->constraints.apply_uV = 0;
89 if (init_data->constraints.min_uV && init_data->constraints.max_uV) 82 if (init_data->constraints.min_uV && init_data->constraints.max_uV)
@@ -97,30 +90,12 @@ static int vexpress_regulator_probe(struct platform_device *pdev)
97 config.of_node = pdev->dev.of_node; 90 config.of_node = pdev->dev.of_node;
98 91
99 reg->regdev = devm_regulator_register(&pdev->dev, &reg->desc, &config); 92 reg->regdev = devm_regulator_register(&pdev->dev, &reg->desc, &config);
100 if (IS_ERR(reg->regdev)) { 93 if (IS_ERR(reg->regdev))
101 err = PTR_ERR(reg->regdev); 94 return PTR_ERR(reg->regdev);
102 goto error_regulator_register;
103 }
104 95
105 platform_set_drvdata(pdev, reg); 96 platform_set_drvdata(pdev, reg);
106 97
107 return 0; 98 return 0;
108
109error_regulator_register:
110error_get_regulator_init_data:
111 vexpress_config_func_put(reg->func);
112error_get_func:
113error_kzalloc:
114 return err;
115}
116
117static int vexpress_regulator_remove(struct platform_device *pdev)
118{
119 struct vexpress_regulator *reg = platform_get_drvdata(pdev);
120
121 vexpress_config_func_put(reg->func);
122
123 return 0;
124} 99}
125 100
126static struct of_device_id vexpress_regulator_of_match[] = { 101static struct of_device_id vexpress_regulator_of_match[] = {
@@ -130,7 +105,6 @@ static struct of_device_id vexpress_regulator_of_match[] = {
130 105
131static struct platform_driver vexpress_regulator_driver = { 106static struct platform_driver vexpress_regulator_driver = {
132 .probe = vexpress_regulator_probe, 107 .probe = vexpress_regulator_probe,
133 .remove = vexpress_regulator_remove,
134 .driver = { 108 .driver = {
135 .name = DRVNAME, 109 .name = DRVNAME,
136 .owner = THIS_MODULE, 110 .owner = THIS_MODULE,
diff --git a/include/linux/vexpress.h b/include/linux/vexpress.h
index 617c01b8f74a..6b206ba6aa0e 100644
--- a/include/linux/vexpress.h
+++ b/include/linux/vexpress.h
@@ -15,16 +15,15 @@
15#define _LINUX_VEXPRESS_H 15#define _LINUX_VEXPRESS_H
16 16
17#include <linux/device.h> 17#include <linux/device.h>
18#include <linux/platform_device.h>
18#include <linux/reboot.h> 19#include <linux/reboot.h>
20#include <linux/regmap.h>
19 21
20#define VEXPRESS_SITE_MB 0 22#define VEXPRESS_SITE_MB 0
21#define VEXPRESS_SITE_DB1 1 23#define VEXPRESS_SITE_DB1 1
22#define VEXPRESS_SITE_DB2 2 24#define VEXPRESS_SITE_DB2 2
23#define VEXPRESS_SITE_MASTER 0xf 25#define VEXPRESS_SITE_MASTER 0xf
24 26
25#define VEXPRESS_CONFIG_STATUS_DONE 0
26#define VEXPRESS_CONFIG_STATUS_WAIT 1
27
28#define VEXPRESS_GPIO_MMC_CARDIN 0 27#define VEXPRESS_GPIO_MMC_CARDIN 0
29#define VEXPRESS_GPIO_MMC_WPROT 1 28#define VEXPRESS_GPIO_MMC_WPROT 1
30#define VEXPRESS_GPIO_FLASH_WPn 2 29#define VEXPRESS_GPIO_FLASH_WPn 2
@@ -44,63 +43,30 @@
44 .flags = IORESOURCE_BUS, \ 43 .flags = IORESOURCE_BUS, \
45} 44}
46 45
47/* Config bridge API */ 46/* Config infrastructure */
48 47
49/** 48void vexpress_config_set_master(u32 site);
50 * struct vexpress_config_bridge_info - description of the platform 49u32 vexpress_config_get_master(void);
51 * configuration infrastructure bridge.
52 *
53 * @name: Bridge name
54 *
55 * @func_get: Obtains pointer to a configuration function for a given
56 * device or a Device Tree node, to be used with @func_put
57 * and @func_exec. The node pointer should take precedence
58 * over device pointer when both are passed.
59 *
60 * @func_put: Tells the bridge that the function will not be used any
61 * more, so all allocated resources can be released.
62 *
63 * @func_exec: Executes a configuration function read or write operation.
64 * The offset selects a 32 bit word of the value accessed.
65 * Must return VEXPRESS_CONFIG_STATUS_DONE when operation
66 * is finished immediately, VEXPRESS_CONFIG_STATUS_WAIT when
67 * will be completed in some time or negative value in case
68 * of error.
69 */
70struct vexpress_config_bridge_info {
71 const char *name;
72 void *(*func_get)(struct device *dev, struct device_node *node);
73 void (*func_put)(void *func);
74 int (*func_exec)(void *func, int offset, bool write, u32 *data);
75};
76 50
77struct vexpress_config_bridge; 51void vexpress_config_lock(void *arg);
52void vexpress_config_unlock(void *arg);
78 53
79struct vexpress_config_bridge *vexpress_config_bridge_register( 54int vexpress_config_get_topo(struct device_node *node, u32 *site,
80 struct device_node *node, 55 u32 *position, u32 *dcc);
81 struct vexpress_config_bridge_info *info);
82void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge);
83 56
84void vexpress_config_complete(struct vexpress_config_bridge *bridge, 57/* Config bridge API */
85 int status);
86 58
87/* Config function API */ 59struct vexpress_config_bridge_ops {
60 struct regmap * (*regmap_init)(struct device *dev, void *context);
61 void (*regmap_exit)(struct regmap *regmap, void *context);
62};
88 63
89struct vexpress_config_func; 64struct device *vexpress_config_bridge_register(struct device *parent,
65 struct vexpress_config_bridge_ops *ops, void *context);
90 66
91struct vexpress_config_func *__vexpress_config_func_get(struct device *dev, 67/* Config regmap API */
92 struct device_node *node);
93#define vexpress_config_func_get_by_dev(dev) \
94 __vexpress_config_func_get(dev, NULL)
95#define vexpress_config_func_get_by_node(node) \
96 __vexpress_config_func_get(NULL, node)
97void vexpress_config_func_put(struct vexpress_config_func *func);
98 68
99/* Both may sleep! */ 69struct regmap *devm_regmap_init_vexpress_config(struct device *dev);
100int vexpress_config_read(struct vexpress_config_func *func, int offset,
101 u32 *data);
102int vexpress_config_write(struct vexpress_config_func *func, int offset,
103 u32 data);
104 70
105/* Platform control */ 71/* Platform control */
106 72
@@ -109,19 +75,12 @@ u32 vexpress_get_hbi(int site);
109void *vexpress_get_24mhz_clock_base(void); 75void *vexpress_get_24mhz_clock_base(void);
110void vexpress_flags_set(u32 data); 76void vexpress_flags_set(u32 data);
111 77
112#define vexpress_get_site_by_node(node) __vexpress_get_site(NULL, node)
113#define vexpress_get_site_by_dev(dev) __vexpress_get_site(dev, NULL)
114unsigned __vexpress_get_site(struct device *dev, struct device_node *node);
115
116void vexpress_sysreg_early_init(void __iomem *base); 78void vexpress_sysreg_early_init(void __iomem *base);
117void vexpress_sysreg_of_early_init(void); 79void vexpress_sysreg_of_early_init(void);
80int vexpress_sysreg_config_device_register(struct platform_device *pdev);
118 81
119/* Clocks */ 82/* Clocks */
120 83
121struct clk *vexpress_osc_setup(struct device *dev);
122void vexpress_osc_of_setup(struct device_node *node);
123
124void vexpress_clk_init(void __iomem *sp810_base); 84void vexpress_clk_init(void __iomem *sp810_base);
125void vexpress_clk_of_init(void);
126 85
127#endif 86#endif