linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 00/18] Versatile Express config rework
@ 2013-12-23 16:23 Pawel Moll
       [not found] ` < 1387815830-8794-5-git-send-email-pawel.moll@arm.com>
                   ` (19 more replies)
  0 siblings, 20 replies; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll

Greetings,

When I promised to rework vexpress' MFD & co. components,
I did't expect it would take almost half a year to post
some patches... The worst thing is that I got most of this
stuff done months ago, but not until the usual holiday
period came I got a chance to post it.

Anyway, the following series retires custom "function"
interface, replacing it with regmap. For a price of
a single WARN_ON removed (05/18 "driver core: Do not WARN 
when devres list is not empty at probe time"), I've managed
to hide all possible VE-specific ways of talking to the
peripherals behind regmap, creating platform devices with
platform-specific regmap config added as devm.

I also had to solve a problem of early initialization
required for the core components, where early doesn't mean
"very early" but simply "earlier than the other ones".
The main issue was of_platform_populate() instantiating
devices for nodes that already has been serviced. There
were some attempts to fix it in the past (including a
struct device pointer in struct device_node). My proposal
is just an extra "already populated" flag in device_node,
set by generic device functions, which makes the
of_platform_populate() to skip such node.

In the end the vexpress-sysreg is almost exclusively
a "pure" MFD device, creating mfd_cells for other drivers.
The system config interface has been split into a "misc"
driver (may become a "soc" driver if the directory
materializes) and the config bus core (using standard
device "class" now) went of course into "bus".

There is also a bunch of other, less important patches
all around the place. I would appreciate the respective
maintainers having a look at them. If anyone wants to
take the small changes in for 3.16 that's cool, if not
I'd more than happy to recieve an ack and merge it with
the whole series in the future.

This series is based on 3.15-rc5 and my hope is to get it
polished enough in time for 3.17 merge window.

Have a great time whatever your plans are for the next
2 weeks!

Pawel

Pawel Moll (17):
  mfd: syscon: Consider platform data a regmap config name
  power/reset: vexpress: Use sched_clock as the time source
  GPIO: gpio-generic: Add label to platform data
  driver core & of: Mark of_nodes of added device as populated
  driver core: Do not WARN when devres list is not empty at probe time
  regmap: Formalise use of non-bus context
  regmap: debugfs: Always create "registers" & "access" files
  hwmon: vexpress: Use regmap instead of custom interface
  power/reset: vexpress: Use regmap instead of custom interface
  regulator: vexpress: Use regmap instead of custom interface
  clocksource: Sched clock source for Versatile Express
  clk: versatile: Split config options for sp810 and vexpress_osc
  clk: versatile: Use regmap instead of custom interface
  ARM: vexpress: Simplify SMP operations for DT-powered system
  bus: Versatile Express configuration bus
  misc: Versatile Express System Config interface driver
  mfd: vexpress: Split sysreg functions into MFD cells

Sudeep KarkadaNagesha (1):
  ARM: vexpress: remove redundant vexpress_dt_cpus_num to get cpu count

 .../devicetree/bindings/arm/vexpress-sysreg.txt    |  37 +-
 arch/arm/boot/dts/vexpress-v2m-rs1.dtsi            |  76 ++-
 arch/arm/boot/dts/vexpress-v2m.dtsi                |  76 ++-
 arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts         |   5 +-
 arch/arm/mach-vexpress/core.h                      |   3 +-
 arch/arm/mach-vexpress/ct-ca9x4.c                  |   8 +-
 arch/arm/mach-vexpress/platsmp.c                   | 187 ++-----
 arch/arm/mach-vexpress/v2m.c                       |  74 +--
 arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi       |   2 +-
 drivers/base/core.c                                |   4 +
 drivers/base/dd.c                                  |   1 -
 drivers/base/regmap/internal.h                     |   3 +-
 drivers/base/regmap/regmap-debugfs.c               |  10 +-
 drivers/base/regmap/regmap.c                       |  34 +-
 drivers/bus/Kconfig                                |   8 +
 drivers/bus/Makefile                               |   2 +
 drivers/bus/vexpress-config.c                      | 178 +++++++
 drivers/clk/Kconfig                                |   9 +-
 drivers/clk/versatile/Kconfig                      |  26 +
 drivers/clk/versatile/Makefile                     |   5 +-
 drivers/clk/versatile/clk-vexpress-osc.c           |  70 +--
 drivers/clocksource/Kconfig                        |   9 +
 drivers/clocksource/Makefile                       |   1 +
 drivers/clocksource/vexpress.c                     |  40 ++
 drivers/gpio/gpio-generic.c                        |   2 +
 drivers/hwmon/Kconfig                              |   3 +-
 drivers/hwmon/vexpress.c                           |  29 +-
 drivers/mfd/Kconfig                                |  15 +-
 drivers/mfd/Makefile                               |   2 +-
 drivers/mfd/syscon.c                               |   1 +
 drivers/mfd/vexpress-config.c                      | 288 -----------
 drivers/mfd/vexpress-sysreg.c                      | 563 ++++++---------------
 drivers/misc/Kconfig                               |   9 +
 drivers/misc/Makefile                              |   1 +
 drivers/misc/vexpress-syscfg.c                     | 322 ++++++++++++
 drivers/of/device.c                                |  16 +
 drivers/of/platform.c                              |   6 +-
 drivers/power/reset/Kconfig                        |   2 +-
 drivers/power/reset/vexpress-poweroff.c            |  15 +-
 drivers/regulator/Kconfig                          |   3 +-
 drivers/regulator/vexpress.c                       |  52 +-
 include/linux/basic_mmio_gpio.h                    |   1 +
 include/linux/of.h                                 |   6 +
 include/linux/of_device.h                          |  11 +
 include/linux/regmap.h                             |   6 +-
 include/linux/vexpress.h                           | 101 +---
 46 files changed, 1168 insertions(+), 1154 deletions(-)
 create mode 100644 drivers/bus/vexpress-config.c
 create mode 100644 drivers/clk/versatile/Kconfig
 create mode 100644 drivers/clocksource/vexpress.c
 delete mode 100644 drivers/mfd/vexpress-config.c
 create mode 100644 drivers/misc/vexpress-syscfg.c

-- 
1.8.3.2



^ permalink raw reply	[flat|nested] 47+ messages in thread

* [RFC 01/18] mfd: syscon: Consider platform data a regmap config name
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
       [not found] ` < 1387815830-8794-5-git-send-email-pawel.moll@arm.com>
       [not found] ` < 1387815830-8794-7-git-send-email-pawel.moll@arm.com>
@ 2013-12-23 16:23 ` Pawel Moll
  2014-01-06  9:48   ` Lee Jones
  2013-12-23 16:23 ` [RFC 02/18] power/reset: vexpress: Use sched_clock as the time source Pawel Moll
                   ` (16 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll, Lee Jones

Use the device platform data as a regmap config
name. This is particularly useful in the regmap
debugfs when there is more than one syscon device
registered, to distinguish the register blocks.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Lee Jones <lee.jones@linaro.org>
---
 drivers/mfd/syscon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 71841f9..ea1770b 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -143,6 +143,7 @@ static int syscon_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	syscon_regmap_config.max_register = res->end - res->start - 3;
+	syscon_regmap_config.name = dev_get_platdata(&pdev->dev);
 	syscon->regmap = devm_regmap_init_mmio(dev, base,
 					&syscon_regmap_config);
 	if (IS_ERR(syscon->regmap)) {
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 02/18] power/reset: vexpress: Use sched_clock as the time source
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (2 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 01/18] mfd: syscon: Consider platform data a regmap config name Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2013-12-23 19:28   ` John Stultz
  2013-12-23 16:23 ` [RFC 03/18] GPIO: gpio-generic: Add label to platform data Pawel Moll
                   ` (15 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll, Anton Vorontsov, David Woodhouse

At this stage of system shutdown procedure the jiffies may
not be updated anymore, so have to base on raw sched_clock
values.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Cc: Anton Vorontsov <anton@enomsg.org>
Cc: David Woodhouse <dwmw2@infradead.org>
---
 drivers/power/reset/vexpress-poweroff.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c
index 476aa49..d752233 100644
--- a/drivers/power/reset/vexpress-poweroff.c
+++ b/drivers/power/reset/vexpress-poweroff.c
@@ -15,6 +15,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/sched.h>
 #include <linux/stat.h>
 #include <linux/vexpress.h>
 
@@ -27,12 +28,12 @@ static void vexpress_reset_do(struct device *dev, const char *what)
 			vexpress_config_func_get_by_dev(dev);
 
 	if (func) {
-		unsigned long timeout;
+		unsigned long long timeout_ns;
 
 		err = vexpress_config_write(func, 0, 0);
 
-		timeout = jiffies + HZ;
-		while (time_before(jiffies, timeout))
+		timeout_ns = sched_clock() + 50000000;
+		while (!err && time_before64(sched_clock(), timeout_ns))
 			cpu_relax();
 	}
 
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 03/18] GPIO: gpio-generic: Add label to platform data
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (3 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 02/18] power/reset: vexpress: Use sched_clock as the time source Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2013-12-23 17:26   ` Linus Walleij
  2013-12-23 16:23 ` [RFC 04/18] driver core & of: Mark of_nodes of added device as populated Pawel Moll
                   ` (14 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll, Linus Walleij, Alexandre Courbot, Anton Vorontsov

When registering more than one platform device, it is
useful to set the gpio chip label in the platform data.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Alexandre Courbot <gnurou@gmail.com>
Cc: Anton Vorontsov <anton@enomsg.org>
---
 drivers/gpio/gpio-generic.c     | 2 ++
 include/linux/basic_mmio_gpio.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
index d2196bf..8c778af 100644
--- a/drivers/gpio/gpio-generic.c
+++ b/drivers/gpio/gpio-generic.c
@@ -531,6 +531,8 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
 		return err;
 
 	if (pdata) {
+		if (pdata->label)
+			bgc->gc.label = pdata->label;
 		bgc->gc.base = pdata->base;
 		if (pdata->ngpio > 0)
 			bgc->gc.ngpio = pdata->ngpio;
diff --git a/include/linux/basic_mmio_gpio.h b/include/linux/basic_mmio_gpio.h
index d8a97ec..0e97856 100644
--- a/include/linux/basic_mmio_gpio.h
+++ b/include/linux/basic_mmio_gpio.h
@@ -19,6 +19,7 @@
 #include <linux/spinlock_types.h>
 
 struct bgpio_pdata {
+	const char *label;
 	int base;
 	int ngpio;
 };
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 04/18] driver core & of: Mark of_nodes of added device as populated
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (4 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 03/18] GPIO: gpio-generic: Add label to platform data Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2014-01-08 17:28   ` Rob Herring
  2013-12-23 16:23 ` [RFC 05/18] driver core: Do not WARN when devres list is not empty at probe time Pawel Moll
                   ` (13 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll, Greg Kroah-Hartman, Grant Likely, Rob Herring,
	devicetree

In "Device Tree powered" systems, platform devices are usually
massively populated with of_platform_populate() call, executed
at some level of initcalls, either by generic architecture
or by platform-specific code.

There are situations though where certain devices must be
created (and bound with drivers) before all the others.
This presents small challenge in DT-driven systems, as
devices explicitly created in early code would be created
again by of_platform_populate().

This patch tries to solve that issue in a generic way,
adding a "populated" flag which is set in the device_node
structure when a device is being created in the core.
Later, of_platform_populate() skips such nodes (and
its children) in a similar way to the non-available ones.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: devicetree@vger.kernel.org
---
 drivers/base/core.c       |  4 ++++
 drivers/of/device.c       | 16 ++++++++++++++++
 drivers/of/platform.c     |  6 ++++--
 include/linux/of.h        |  6 ++++++
 include/linux/of_device.h | 11 +++++++++++
 5 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/drivers/base/core.c b/drivers/base/core.c
index 67b180d..50dd8f3 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1086,6 +1086,8 @@ int device_add(struct device *dev)
 				class_intf->add_dev(dev, class_intf);
 		mutex_unlock(&dev->class->p->mutex);
 	}
+
+	of_device_populate(dev);
 done:
 	put_device(dev);
 	return error;
@@ -1188,6 +1190,8 @@ void device_del(struct device *dev)
 	struct device *parent = dev->parent;
 	struct class_interface *class_intf;
 
+	of_device_depopulate(dev);
+
 	/* Notify clients of device removal.  This call must come
 	 * before dpm_sysfs_remove().
 	 */
diff --git a/drivers/of/device.c b/drivers/of/device.c
index f685e55..dae092a 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -187,3 +187,19 @@ int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
 
 	return 0;
 }
+
+void of_device_populate(struct device *dev)
+{
+	if ((!dev) || (!dev->of_node))
+		return;
+
+	of_node_set_flag(dev->of_node, OF_POPULATED);
+}
+
+void of_device_depopulate(struct device *dev)
+{
+	if ((!dev) || (!dev->of_node))
+		return;
+
+	of_node_clear_flag(dev->of_node, OF_POPULATED);
+}
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 404d1da..ad43ee0 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -204,7 +204,8 @@ static struct platform_device *of_platform_device_create_pdata(
 {
 	struct platform_device *dev;
 
-	if (!of_device_is_available(np))
+	if (!of_device_is_available(np) ||
+			of_node_check_flag(np, OF_POPULATED))
 		return NULL;
 
 	dev = of_device_alloc(np, bus_id, parent);
@@ -262,7 +263,8 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
 
 	pr_debug("Creating amba device %s\n", node->full_name);
 
-	if (!of_device_is_available(node))
+	if (!of_device_is_available(node) ||
+			of_node_check_flag(node, OF_POPULATED))
 		return NULL;
 
 	dev = amba_device_alloc(NULL, 0, 0);
diff --git a/include/linux/of.h b/include/linux/of.h
index 276c546..53989cf 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -114,6 +114,11 @@ static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
 	set_bit(flag, &n->_flags);
 }
 
+static inline void of_node_clear_flag(struct device_node *n, unsigned long flag)
+{
+	clear_bit(flag, &n->_flags);
+}
+
 extern struct device_node *of_find_all_nodes(struct device_node *prev);
 
 /*
@@ -156,6 +161,7 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
 /* flag descriptions */
 #define OF_DYNAMIC	1 /* node and properties were allocated via kmalloc */
 #define OF_DETACHED	2 /* node has been detached from the device tree */
+#define OF_POPULATED	3 /* device already created for the node */
 
 #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
 #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 82ce324..bfb4a48 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -44,6 +44,9 @@ static inline void of_device_node_put(struct device *dev)
 	of_node_put(dev->of_node);
 }
 
+extern void of_device_populate(struct device *dev);
+extern void of_device_depopulate(struct device *dev);
+
 static inline struct device_node *of_cpu_device_node_get(int cpu)
 {
 	struct device *cpu_dev;
@@ -78,6 +81,14 @@ static inline const struct of_device_id *of_match_device(
 	return NULL;
 }
 
+static inline void of_device_populate(struct device *dev)
+{
+}
+
+static inline void of_device_depopulate(struct device *dev)
+{
+}
+
 static inline struct device_node *of_cpu_device_node_get(int cpu)
 {
 	return NULL;
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 05/18] driver core: Do not WARN when devres list is not empty at probe time
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (5 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 04/18] driver core & of: Mark of_nodes of added device as populated Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2013-12-23 16:23 ` [RFC 06/18] regmap: Formalise use of non-bus context Pawel Moll
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll, Greg Kroah-Hartman

regmap_init() adds the initialised map to the device resources,
which can be then obtained in the driver->probe function in a
generic way with dev_reg_regmap(), which makes it independent
from underlying hardware interface. This is useful when
platform_devices are not simply memory mapped but must use
custom way of accessing the registers.

Unfortunately the device core WARNs in a situation when probed
devices has a non-empty resources list. This patch simply
removes this check and doesn't seem to have any side effects.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/base/dd.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 0605176..07b8419 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -269,7 +269,6 @@ static int really_probe(struct device *dev, struct device_driver *drv)
 	atomic_inc(&probe_count);
 	pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
 		 drv->bus->name, __func__, drv->name, dev_name(dev));
-	WARN_ON(!list_empty(&dev->devres_head));
 
 	dev->driver = drv;
 
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 06/18] regmap: Formalise use of non-bus context
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (6 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 05/18] driver core: Do not WARN when devres list is not empty at probe time Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2013-12-24 12:45   ` Mark Brown
  2013-12-23 16:23 ` [RFC 07/18] regmap: debugfs: Always create "registers" & "access" files Pawel Moll
                   ` (11 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll, Mark Brown, Greg Kroah-Hartman

Bus-less maps (ones with reg_read and reg_write functions
defined in regmap_config) were given the context passed
in regmap_init(), but it was still called "bus_context".

This patch formalises this aspect by renaming it to simple
"context" and adds the missing link, free_context function
in regmap_config, which allows bus-less maps to use the
context in classic way.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/base/regmap/internal.h |  3 ++-
 drivers/base/regmap/regmap.c   | 34 ++++++++++++++++++----------------
 include/linux/regmap.h         |  6 ++++--
 3 files changed, 24 insertions(+), 19 deletions(-)

diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 33414b1..3a8527d 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -60,7 +60,7 @@ struct regmap {
 	void *work_buf;     /* Scratch buffer used to format I/O */
 	struct regmap_format format;  /* Buffer format */
 	const struct regmap_bus *bus;
-	void *bus_context;
+	void *context;
 	const char *name;
 
 	bool async;
@@ -94,6 +94,7 @@ struct regmap {
 
 	int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
 	int (*reg_write)(void *context, unsigned int reg, unsigned int val);
+	void (*free_context)(void *context);
 
 	bool defer_caching;
 
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index c2e0021..9b00531 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -385,7 +385,7 @@ static void regmap_range_exit(struct regmap *map)
  *
  * @dev: Device that will be interacted with
  * @bus: Bus-specific callbacks to use with device
- * @bus_context: Data passed to bus-specific callbacks
+ * @context: Data passed to callbacks
  * @config: Configuration for register map
  *
  * The return value will be an ERR_PTR() on error or a valid pointer to
@@ -394,7 +394,7 @@ static void regmap_range_exit(struct regmap *map)
  */
 struct regmap *regmap_init(struct device *dev,
 			   const struct regmap_bus *bus,
-			   void *bus_context,
+			   void *context,
 			   const struct regmap_config *config)
 {
 	struct regmap *map, **m;
@@ -441,7 +441,7 @@ struct regmap *regmap_init(struct device *dev,
 	map->use_single_rw = config->use_single_rw;
 	map->dev = dev;
 	map->bus = bus;
-	map->bus_context = bus_context;
+	map->context = context;
 	map->max_register = config->max_register;
 	map->wr_table = config->wr_table;
 	map->rd_table = config->rd_table;
@@ -469,11 +469,13 @@ struct regmap *regmap_init(struct device *dev,
 	if (!bus) {
 		map->reg_read  = config->reg_read;
 		map->reg_write = config->reg_write;
+		map->free_context = config->free_context;
 
 		map->defer_caching = false;
 		goto skip_format_initialization;
 	} else {
 		map->reg_read  = _regmap_bus_read;
+		map->free_context = bus->free_context;
 	}
 
 	reg_endian = config->reg_format_endian;
@@ -774,7 +776,7 @@ static void devm_regmap_release(struct device *dev, void *res)
  *
  * @dev: Device that will be interacted with
  * @bus: Bus-specific callbacks to use with device
- * @bus_context: Data passed to bus-specific callbacks
+ * @context: Data passed to callbacks
  * @config: Configuration for register map
  *
  * The return value will be an ERR_PTR() on error or a valid pointer
@@ -784,7 +786,7 @@ static void devm_regmap_release(struct device *dev, void *res)
  */
 struct regmap *devm_regmap_init(struct device *dev,
 				const struct regmap_bus *bus,
-				void *bus_context,
+				void *context,
 				const struct regmap_config *config)
 {
 	struct regmap **ptr, *regmap;
@@ -793,7 +795,7 @@ struct regmap *devm_regmap_init(struct device *dev,
 	if (!ptr)
 		return ERR_PTR(-ENOMEM);
 
-	regmap = regmap_init(dev, bus, bus_context, config);
+	regmap = regmap_init(dev, bus, context, config);
 	if (!IS_ERR(regmap)) {
 		*ptr = regmap;
 		devres_add(dev, ptr);
@@ -941,8 +943,8 @@ void regmap_exit(struct regmap *map)
 	regcache_exit(map);
 	regmap_debugfs_exit(map);
 	regmap_range_exit(map);
-	if (map->bus && map->bus->free_context)
-		map->bus->free_context(map->bus_context);
+	if (map->free_context)
+		map->free_context(map->context);
 	kfree(map->work_buf);
 	while (!list_empty(&map->async_free)) {
 		async = list_first_entry_or_null(&map->async_free,
@@ -1165,13 +1167,13 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
 		spin_unlock_irqrestore(&map->async_lock, flags);
 
 		if (val != work_val)
-			ret = map->bus->async_write(map->bus_context,
+			ret = map->bus->async_write(map->context,
 						    async->work_buf,
 						    map->format.reg_bytes +
 						    map->format.pad_bytes,
 						    val, val_len, async);
 		else
-			ret = map->bus->async_write(map->bus_context,
+			ret = map->bus->async_write(map->context,
 						    async->work_buf,
 						    map->format.reg_bytes +
 						    map->format.pad_bytes +
@@ -1197,12 +1199,12 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
 	 * write.
 	 */
 	if (val == work_val)
-		ret = map->bus->write(map->bus_context, map->work_buf,
+		ret = map->bus->write(map->context, map->work_buf,
 				      map->format.reg_bytes +
 				      map->format.pad_bytes +
 				      val_len);
 	else if (map->bus->gather_write)
-		ret = map->bus->gather_write(map->bus_context, map->work_buf,
+		ret = map->bus->gather_write(map->context, map->work_buf,
 					     map->format.reg_bytes +
 					     map->format.pad_bytes,
 					     val, val_len);
@@ -1217,7 +1219,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
 		memcpy(buf, map->work_buf, map->format.reg_bytes);
 		memcpy(buf + map->format.reg_bytes + map->format.pad_bytes,
 		       val, val_len);
-		ret = map->bus->write(map->bus_context, buf, len);
+		ret = map->bus->write(map->context, buf, len);
 
 		kfree(buf);
 	}
@@ -1259,7 +1261,7 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,
 
 	trace_regmap_hw_write_start(map->dev, reg, 1);
 
-	ret = map->bus->write(map->bus_context, map->work_buf,
+	ret = map->bus->write(map->context, map->work_buf,
 			      map->format.buf_size);
 
 	trace_regmap_hw_write_done(map->dev, reg, 1);
@@ -1285,7 +1287,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg,
 
 static inline void *_regmap_map_get_context(struct regmap *map)
 {
-	return (map->bus) ? map : map->bus_context;
+	return (map->bus) ? map : map->context;
 }
 
 int _regmap_write(struct regmap *map, unsigned int reg,
@@ -1681,7 +1683,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
 	trace_regmap_hw_read_start(map->dev, reg,
 				   val_len / map->format.val_bytes);
 
-	ret = map->bus->read(map->bus_context, map->work_buf,
+	ret = map->bus->read(map->context, map->work_buf,
 			     map->format.reg_bytes + map->format.pad_bytes,
 			     val, val_len);
 
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index e559078..376b6bf 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -140,6 +140,7 @@ typedef void (*regmap_unlock)(void *);
  *		  operation on a bus such as SPI, I2C, etc. Most of the devices do
  * 		  not need this.
  * @reg_write:	  Same as above for writing.
+ * @free_context: Same as above, called when regmap is destroyed.
  * @fast_io:	  Register IO is fast. Use a spinlock instead of a mutex
  *	     	  to perform locking. This field is ignored if custom lock/unlock
  *	     	  functions are used (see fields lock/unlock of struct regmap_config).
@@ -197,6 +198,7 @@ struct regmap_config {
 
 	int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
 	int (*reg_write)(void *context, unsigned int reg, unsigned int val);
+	void (*free_context)(void *context);
 
 	bool fast_io;
 
@@ -315,7 +317,7 @@ struct regmap_bus {
 
 struct regmap *regmap_init(struct device *dev,
 			   const struct regmap_bus *bus,
-			   void *bus_context,
+			   void *context,
 			   const struct regmap_config *config);
 struct regmap *regmap_init_i2c(struct i2c_client *i2c,
 			       const struct regmap_config *config);
@@ -329,7 +331,7 @@ struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id,
 
 struct regmap *devm_regmap_init(struct device *dev,
 				const struct regmap_bus *bus,
-				void *bus_context,
+				void *context,
 				const struct regmap_config *config);
 struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c,
 				    const struct regmap_config *config);
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 07/18] regmap: debugfs: Always create "registers" & "access" files
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (7 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 06/18] regmap: Formalise use of non-bus context Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2013-12-24 12:19   ` Mark Brown
  2013-12-23 16:23 ` [RFC 08/18] hwmon: vexpress: Use regmap instead of custom interface Pawel Moll
                   ` (10 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll, Mark Brown, Greg Kroah-Hartman

When a map covers a single register, max_register is equal
to 0, so the "registers" & "access" files were not created.

This patch is removing this restriction. It should be save,
as the maps not without register 0 should return false
for regmap_readable(map, 0).

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/base/regmap/regmap-debugfs.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index c5471cd..17cd35a 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -511,12 +511,10 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
 	debugfs_create_file("range", 0400, map->debugfs,
 			    map, &regmap_reg_ranges_fops);
 
-	if (map->max_register) {
-		debugfs_create_file("registers", 0400, map->debugfs,
-				    map, &regmap_map_fops);
-		debugfs_create_file("access", 0400, map->debugfs,
-				    map, &regmap_access_fops);
-	}
+	debugfs_create_file("registers", 0400, map->debugfs,
+			map, &regmap_map_fops);
+	debugfs_create_file("access", 0400, map->debugfs,
+			map, &regmap_access_fops);
 
 	if (map->cache_type) {
 		debugfs_create_bool("cache_only", 0400, map->debugfs,
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 08/18] hwmon: vexpress: Use regmap instead of custom interface
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (8 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 07/18] regmap: debugfs: Always create "registers" & "access" files Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2013-12-23 17:31   ` Guenter Roeck
  2013-12-23 16:23 ` [RFC 09/18] power/reset: " Pawel Moll
                   ` (9 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll, Jean Delvare, Guenter Roeck, lm-sensors

This patch makes the Versatile Express hwmon driver
use regmap interface, instead of custom vexpress config
one. It will request the regmap resource associated
with the device, which makes it pretty much hardware
agnostic.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: lm-sensors@lm-sensors.org
---
 drivers/hwmon/Kconfig    |  3 ++-
 drivers/hwmon/vexpress.c | 29 +++++++++++------------------
 2 files changed, 13 insertions(+), 19 deletions(-)

diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 52d548f..7747a47 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1324,7 +1324,8 @@ config SENSORS_TWL4030_MADC
 
 config SENSORS_VEXPRESS
 	tristate "Versatile Express"
-	depends on VEXPRESS_CONFIG
+	depends on ARM || ARM64
+	depends on REGMAP
 	help
 	  This driver provides support for hardware sensors available on
 	  the ARM Ltd's Versatile Express platform. It can provide wide
diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c
index d867e6b..b58cf1c 100644
--- a/drivers/hwmon/vexpress.c
+++ b/drivers/hwmon/vexpress.c
@@ -22,11 +22,11 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
-#include <linux/vexpress.h>
+#include <linux/regmap.h>
 
 struct vexpress_hwmon_data {
 	struct device *hwmon_dev;
-	struct vexpress_config_func *func;
+	struct regmap *reg;
 };
 
 static ssize_t vexpress_hwmon_name_show(struct device *dev,
@@ -56,7 +56,7 @@ static ssize_t vexpress_hwmon_u32_show(struct device *dev,
 	int err;
 	u32 value;
 
-	err = vexpress_config_read(data->func, 0, &value);
+	err = regmap_read(data->reg, 0, &value);
 	if (err)
 		return err;
 
@@ -69,13 +69,13 @@ static ssize_t vexpress_hwmon_u64_show(struct device *dev,
 {
 	struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
 	int err;
-	u32 value_hi, value_lo;
+	unsigned int value_hi, value_lo;
 
-	err = vexpress_config_read(data->func, 0, &value_lo);
+	err = regmap_read(data->reg, 0, &value_lo);
 	if (err)
 		return err;
 
-	err = vexpress_config_read(data->func, 1, &value_hi);
+	err = regmap_read(data->reg, 1, &value_hi);
 	if (err)
 		return err;
 
@@ -175,26 +175,21 @@ static int vexpress_hwmon_probe(struct platform_device *pdev)
 	if (!match)
 		return -ENODEV;
 
-	data->func = vexpress_config_func_get_by_dev(&pdev->dev);
-	if (!data->func)
+	data->reg = dev_get_regmap(&pdev->dev, NULL);
+	if (!data->reg)
 		return -ENODEV;
 
 	err = sysfs_create_group(&pdev->dev.kobj, match->data);
 	if (err)
-		goto error;
+		return err;
 
 	data->hwmon_dev = hwmon_device_register(&pdev->dev);
 	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto error;
+		sysfs_remove_group(&pdev->dev.kobj, match->data);
+		return PTR_ERR(data->hwmon_dev);
 	}
 
 	return 0;
-
-error:
-	sysfs_remove_group(&pdev->dev.kobj, match->data);
-	vexpress_config_func_put(data->func);
-	return err;
 }
 
 static int vexpress_hwmon_remove(struct platform_device *pdev)
@@ -207,8 +202,6 @@ static int vexpress_hwmon_remove(struct platform_device *pdev)
 	match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
 	sysfs_remove_group(&pdev->dev.kobj, match->data);
 
-	vexpress_config_func_put(data->func);
-
 	return 0;
 }
 
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 09/18] power/reset: vexpress: Use regmap instead of custom interface
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (9 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 08/18] hwmon: vexpress: Use regmap instead of custom interface Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2013-12-23 16:23 ` [RFC 10/18] regulator: " Pawel Moll
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll, Anton Vorontsov, David Woodhouse

This patch makes the Versatile Express reboot/reset driver
use regmap interface, instead of custom vexpress config
one. It will request the regmap resource associated
with the device, which makes it pretty much hardware
agnostic.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Cc: Anton Vorontsov <anton@enomsg.org>
Cc: David Woodhouse <dwmw2@infradead.org>
---
 drivers/power/reset/Kconfig             | 2 +-
 drivers/power/reset/vexpress-poweroff.c | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 9b3ea53..98f64dc 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -40,7 +40,7 @@ config POWER_RESET_RESTART
 config POWER_RESET_VEXPRESS
 	bool "ARM Versatile Express power-off and reset driver"
 	depends on ARM || ARM64
-	depends on POWER_RESET && VEXPRESS_CONFIG
+	depends on POWER_RESET && REGMAP
 	help
 	  Power off and reset support for the ARM Ltd. Versatile
 	  Express boards.
diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c
index d752233..a7fc882 100644
--- a/drivers/power/reset/vexpress-poweroff.c
+++ b/drivers/power/reset/vexpress-poweroff.c
@@ -15,6 +15,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/sched.h>
 #include <linux/stat.h>
 #include <linux/vexpress.h>
@@ -24,13 +25,12 @@
 static void vexpress_reset_do(struct device *dev, const char *what)
 {
 	int err = -ENOENT;
-	struct vexpress_config_func *func =
-			vexpress_config_func_get_by_dev(dev);
+	struct regmap *reg = dev_get_regmap(dev, NULL);
 
-	if (func) {
+	if (reg) {
 		unsigned long long timeout_ns;
 
-		err = vexpress_config_write(func, 0, 0);
+		err = regmap_write(reg, 0, 0);
 
 		timeout_ns = sched_clock() + 50000000;
 		while (!err && time_before64(sched_clock(), timeout_ns))
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 10/18] regulator: vexpress: Use regmap instead of custom interface
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (10 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 09/18] power/reset: " Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2013-12-24 12:24   ` Mark Brown
  2013-12-23 16:23 ` [RFC 11/18] clocksource: Sched clock source for Versatile Express Pawel Moll
                   ` (7 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll, Liam Girdwood, Mark Brown

This patch makes the Versatile Express regulator driver
use regmap interface, instead of custom vexpress config
one. It will request the regmap resource associated
with the device, which makes it pretty much hardware
agnostic.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Cc: Liam Girdwood <lgirdwood@gmail.com>
Cc: Mark Brown <broonie@kernel.org>
---
 drivers/regulator/Kconfig    |  3 ++-
 drivers/regulator/vexpress.c | 52 +++++++++++---------------------------------
 2 files changed, 15 insertions(+), 40 deletions(-)

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index ce785f4..19a3eea 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -544,7 +544,8 @@ config REGULATOR_TWL4030
 
 config REGULATOR_VEXPRESS
 	tristate "Versatile Express regulators"
-	depends on VEXPRESS_CONFIG
+	depends on ARM || ARM64
+	depends on REGMAP
 	help
 	  This driver provides support for voltage regulators available
 	  on the ARM Ltd's Versatile Express platform.
diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c
index f3ae28a..d73857b 100644
--- a/drivers/regulator/vexpress.c
+++ b/drivers/regulator/vexpress.c
@@ -18,22 +18,22 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/regmap.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/of_regulator.h>
-#include <linux/vexpress.h>
 
 struct vexpress_regulator {
 	struct regulator_desc desc;
 	struct regulator_dev *regdev;
-	struct vexpress_config_func *func;
+	struct regmap *regmap;
 };
 
 static int vexpress_regulator_get_voltage(struct regulator_dev *regdev)
 {
 	struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
 	u32 uV;
-	int err = vexpress_config_read(reg->func, 0, &uV);
+	int err = regmap_read(reg->regmap, 0, &uV);
 
 	return err ? err : uV;
 }
@@ -43,7 +43,7 @@ static int vexpress_regulator_set_voltage(struct regulator_dev *regdev,
 {
 	struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
 
-	return vexpress_config_write(reg->func, 0, min_uV);
+	return regmap_write(reg->regmap, 0, min_uV);
 }
 
 static struct regulator_ops vexpress_regulator_ops_ro = {
@@ -57,22 +57,17 @@ static struct regulator_ops vexpress_regulator_ops = {
 
 static int vexpress_regulator_probe(struct platform_device *pdev)
 {
-	int err;
 	struct vexpress_regulator *reg;
 	struct regulator_init_data *init_data;
 	struct regulator_config config = { };
 
 	reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL);
-	if (!reg) {
-		err = -ENOMEM;
-		goto error_kzalloc;
-	}
+	if (!reg)
+		return -ENOMEM;
 
-	reg->func = vexpress_config_func_get_by_dev(&pdev->dev);
-	if (!reg->func) {
-		err = -ENXIO;
-		goto error_get_func;
-	}
+	reg->regmap = dev_get_regmap(&pdev->dev, NULL);
+	if (!reg->regmap)
+		return -ENXIO;
 
 	reg->desc.name = dev_name(&pdev->dev);
 	reg->desc.type = REGULATOR_VOLTAGE;
@@ -80,10 +75,8 @@ static int vexpress_regulator_probe(struct platform_device *pdev)
 	reg->desc.continuous_voltage_range = true;
 
 	init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
-	if (!init_data) {
-		err = -EINVAL;
-		goto error_get_regulator_init_data;
-	}
+	if (!init_data)
+		return -EINVAL;
 
 	init_data->constraints.apply_uV = 0;
 	if (init_data->constraints.min_uV && init_data->constraints.max_uV)
@@ -97,30 +90,12 @@ static int vexpress_regulator_probe(struct platform_device *pdev)
 	config.of_node = pdev->dev.of_node;
 
 	reg->regdev = devm_regulator_register(&pdev->dev, &reg->desc, &config);
-	if (IS_ERR(reg->regdev)) {
-		err = PTR_ERR(reg->regdev);
-		goto error_regulator_register;
-	}
+	if (IS_ERR(reg->regdev))
+		return PTR_ERR(reg->regdev);
 
 	platform_set_drvdata(pdev, reg);
 
 	return 0;
-
-error_regulator_register:
-error_get_regulator_init_data:
-	vexpress_config_func_put(reg->func);
-error_get_func:
-error_kzalloc:
-	return err;
-}
-
-static int vexpress_regulator_remove(struct platform_device *pdev)
-{
-	struct vexpress_regulator *reg = platform_get_drvdata(pdev);
-
-	vexpress_config_func_put(reg->func);
-
-	return 0;
 }
 
 static struct of_device_id vexpress_regulator_of_match[] = {
@@ -130,7 +105,6 @@ static struct of_device_id vexpress_regulator_of_match[] = {
 
 static struct platform_driver vexpress_regulator_driver = {
 	.probe = vexpress_regulator_probe,
-	.remove = vexpress_regulator_remove,
 	.driver	= {
 		.name = DRVNAME,
 		.owner = THIS_MODULE,
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 11/18] clocksource: Sched clock source for Versatile Express
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (11 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 10/18] regulator: " Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2013-12-23 16:23 ` [RFC 12/18] clk: versatile: Split config options for sp810 and vexpress_osc Pawel Moll
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll, Daniel Lezcano, Thomas Gleixner

This patch adds a trival sched clock source using free
running, 24MHz clocked counter present in the ARM Ltd.
Versatile Express platform's System Registers block.

This code replaces the call in the VE machine code.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
---
 arch/arm/mach-vexpress/v2m.c   |  2 --
 drivers/clocksource/Kconfig    |  9 +++++++++
 drivers/clocksource/Makefile   |  1 +
 drivers/clocksource/vexpress.c | 40 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 50 insertions(+), 2 deletions(-)
 create mode 100644 drivers/clocksource/vexpress.c

diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 4f8b8cb..8e0e872 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -419,8 +419,6 @@ void __init v2m_dt_init_early(void)
 			pr_warning("vexpress: DT HBI (%x) is not matching "
 					"hardware (%x)!\n", dt_hbi, hbi);
 	}
-
-	versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000);
 }
 
 static const struct of_device_id v2m_dt_bus_match[] __initconst = {
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 634c4d6..93204e0 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -136,3 +136,12 @@ config VF_PIT_TIMER
 	bool
 	help
 	  Support for Period Interrupt Timer on Freescale Vybrid Family SoCs.
+
+config CLKSRC_VEXPRESS
+	bool
+	depends on MFD_VEXPRESS_SYSREG
+	depends on GENERIC_SCHED_CLOCK
+	select CLKSRC_OF
+	default y
+	help
+	  Simple provider of sched clock on ARM Versatile Express platform.
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 33621ef..7c2e338 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -36,3 +36,4 @@ obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
 obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
 obj-$(CONFIG_CLKSRC_METAG_GENERIC)	+= metag_generic.o
 obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST)	+= dummy_timer.o
+obj-$(CONFIG_CLKSRC_VEXPRESS)	+= vexpress.o
diff --git a/drivers/clocksource/vexpress.c b/drivers/clocksource/vexpress.c
new file mode 100644
index 0000000..55b8ab4
--- /dev/null
+++ b/drivers/clocksource/vexpress.c
@@ -0,0 +1,40 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2013 ARM Limited
+ */
+
+#include <linux/clocksource.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/sched_clock.h>
+
+#define SYS_24MHZ 0x05c
+
+static void __iomem *vexpress_sys_24mhz;
+
+static u32 notrace vexpress_sys_24mhz_read(void)
+{
+	return readl(vexpress_sys_24mhz);
+}
+
+static void __init vexpress_sched_clock_init(struct device_node *node)
+{
+	void __iomem *base = of_iomap(node, 0);
+
+	if (!base)
+		return;
+
+	vexpress_sys_24mhz = base + SYS_24MHZ;
+
+	setup_sched_clock(vexpress_sys_24mhz_read, 32, 24000000);
+}
+CLOCKSOURCE_OF_DECLARE(vexpress, "arm,vexpress-sysreg",
+		vexpress_sched_clock_init);
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 12/18] clk: versatile: Split config options for sp810 and vexpress_osc
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (12 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 11/18] clocksource: Sched clock source for Versatile Express Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2013-12-23 20:05   ` Mike Turquette
  2013-12-23 16:23 ` [RFC 13/18] clk: versatile: Use regmap instead of custom interface Pawel Moll
                   ` (5 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll, Mike Turquette

Move the Kconfig entry for Versatile (& Express) clock drivers
into a separate file and add individual options for sp810
and vexpress_osc drivers, as they are optional in some
configurations and may have separate dependencies.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Cc: Mike Turquette <mturquette@linaro.org>
---
 drivers/clk/Kconfig            |  9 +--------
 drivers/clk/versatile/Kconfig  | 26 ++++++++++++++++++++++++++
 drivers/clk/versatile/Makefile |  5 +++--
 3 files changed, 30 insertions(+), 10 deletions(-)
 create mode 100644 drivers/clk/versatile/Kconfig

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 5c51115..f5486a4 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -40,14 +40,7 @@ config COMMON_CLK_WM831X
           Supports the clocking subsystem of the WM831x/2x series of
 	  PMICs from Wolfson Microlectronics.
 
-config COMMON_CLK_VERSATILE
-	bool "Clock driver for ARM Reference designs"
-	depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS || ARM64
-	---help---
-          Supports clocking on ARM Reference designs:
-	  - Integrator/AP and Integrator/CP
-	  - RealView PB1176, EB, PB11MP and PBX
-	  - Versatile Express
+source "drivers/clk/versatile/Kconfig"
 
 config COMMON_CLK_MAX77686
 	tristate "Clock driver for Maxim 77686 MFD"
diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig
new file mode 100644
index 0000000..1530c93
--- /dev/null
+++ b/drivers/clk/versatile/Kconfig
@@ -0,0 +1,26 @@
+config COMMON_CLK_VERSATILE
+	bool "Clock driver for ARM Reference designs"
+	depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS || ARM64
+	---help---
+          Supports clocking on ARM Reference designs:
+	  - Integrator/AP and Integrator/CP
+	  - RealView PB1176, EB, PB11MP and PBX
+	  - Versatile Express
+
+config CLK_SP810
+	bool "Clock driver for ARM SP810 System Controller"
+	depends on COMMON_CLK_VERSATILE
+	default y if ARCH_VEXPRESS
+	---help---
+	  Supports clock muxing (REFCLK/TIMCLK to TIMERCLKEN0-3) capabilities
+	  of the ARM SP810 System Controller cell.
+
+config CLK_VEXPRESS_OSC
+	bool "Clock driver for Versatile Express OSC clock generators"
+	depends on COMMON_CLK_VERSATILE
+	depends on VEXPRESS_CONFIG
+	default y if ARCH_VEXPRESS
+	---help---
+	  Simple regmap-based driver driving clock generators on Versatile
+	  Express platforms hidden behind its configuration infrastructure,
+	  commonly known as OSCs.
diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile
index c16ca78..fd449f9 100644
--- a/drivers/clk/versatile/Makefile
+++ b/drivers/clk/versatile/Makefile
@@ -3,5 +3,6 @@ obj-$(CONFIG_ICST)		+= clk-icst.o
 obj-$(CONFIG_ARCH_INTEGRATOR)	+= clk-integrator.o
 obj-$(CONFIG_INTEGRATOR_IMPD1)	+= clk-impd1.o
 obj-$(CONFIG_ARCH_REALVIEW)	+= clk-realview.o
-obj-$(CONFIG_ARCH_VEXPRESS)	+= clk-vexpress.o clk-sp810.o
-obj-$(CONFIG_VEXPRESS_CONFIG)	+= clk-vexpress-osc.o
+obj-$(CONFIG_ARCH_VEXPRESS)	+= clk-vexpress.o
+obj-$(CONFIG_CLK_SP810)		+= clk-sp810.o
+obj-$(CONFIG_CLK_VEXPRESS_OSC)	+= clk-vexpress-osc.o
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 13/18] clk: versatile: Use regmap instead of custom interface
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (13 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 12/18] clk: versatile: Split config options for sp810 and vexpress_osc Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2013-12-23 16:23 ` [RFC 14/18] ARM: vexpress: remove redundant vexpress_dt_cpus_num to get cpu count Pawel Moll
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll, Mike Turquette

This patch makes the Versatile Express clock generators
driver use regmap interface, instead of custom vexpress
config one. This required it to become a standard platform
driver (although registered very early, at core_initcall
level), which better fits the reality (dependencies on
other devices, mainly config infrastructure bridges).

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Cc: Mike Turquette <mturquette@linaro.org> 
---
 drivers/clk/versatile/Kconfig            |  2 +-
 drivers/clk/versatile/clk-vexpress-osc.c | 70 ++++++++++++++++++--------------
 include/linux/vexpress.h                 |  3 --
 3 files changed, 40 insertions(+), 35 deletions(-)

diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig
index 1530c93..3c694f0 100644
--- a/drivers/clk/versatile/Kconfig
+++ b/drivers/clk/versatile/Kconfig
@@ -18,7 +18,7 @@ config CLK_SP810
 config CLK_VEXPRESS_OSC
 	bool "Clock driver for Versatile Express OSC clock generators"
 	depends on COMMON_CLK_VERSATILE
-	depends on VEXPRESS_CONFIG
+	depends on REGMAP
 	default y if ARCH_VEXPRESS
 	---help---
 	  Simple regmap-based driver driving clock generators on Versatile
diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c
index 2dc8b41..e668cb2 100644
--- a/drivers/clk/versatile/clk-vexpress-osc.c
+++ b/drivers/clk/versatile/clk-vexpress-osc.c
@@ -11,18 +11,17 @@
  * Copyright (C) 2012 ARM Limited
  */
 
-#define pr_fmt(fmt) "vexpress-osc: " fmt
 
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
-#include <linux/vexpress.h>
 
 struct vexpress_osc {
-	struct vexpress_config_func *func;
+	struct regmap *reg;
 	struct clk_hw hw;
 	unsigned long rate_min;
 	unsigned long rate_max;
@@ -36,7 +35,7 @@ static unsigned long vexpress_osc_recalc_rate(struct clk_hw *hw,
 	struct vexpress_osc *osc = to_vexpress_osc(hw);
 	u32 rate;
 
-	vexpress_config_read(osc->func, 0, &rate);
+	regmap_read(osc->reg, 0, &rate);
 
 	return rate;
 }
@@ -60,7 +59,7 @@ static int vexpress_osc_set_rate(struct clk_hw *hw, unsigned long rate,
 {
 	struct vexpress_osc *osc = to_vexpress_osc(hw);
 
-	return vexpress_config_write(osc->func, 0, rate);
+	return regmap_write(osc->reg, 0, rate);
 }
 
 static struct clk_ops vexpress_osc_ops = {
@@ -78,8 +77,8 @@ struct clk * __init vexpress_osc_setup(struct device *dev)
 	if (!osc)
 		return NULL;
 
-	osc->func = vexpress_config_func_get_by_dev(dev);
-	if (!osc->func) {
+	osc->reg = dev_get_regmap(dev, NULL);
+	if (!osc->reg) {
 		kfree(osc);
 		return NULL;
 	}
@@ -93,33 +92,31 @@ struct clk * __init vexpress_osc_setup(struct device *dev)
 	return clk_register(NULL, &osc->hw);
 }
 
-void __init vexpress_osc_of_setup(struct device_node *node)
+static int vexpress_osc_probe(struct platform_device *pdev)
 {
 	struct clk_init_data init;
 	struct vexpress_osc *osc;
 	struct clk *clk;
 	u32 range[2];
 
-	osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+	osc = devm_kzalloc(&pdev->dev, sizeof(*osc), GFP_KERNEL);
 	if (!osc)
-		goto error;
+		return -ENOMEM;
 
-	osc->func = vexpress_config_func_get_by_node(node);
-	if (!osc->func) {
-		pr_err("Failed to obtain config func for node '%s'!\n",
-				node->full_name);
-		goto error;
-	}
+	osc->reg = dev_get_regmap(&pdev->dev, NULL);
+	if (!osc->reg)
+		return -ENXIO;
 
-	if (of_property_read_u32_array(node, "freq-range", range,
+	if (of_property_read_u32_array(pdev->dev.of_node, "freq-range", range,
 			ARRAY_SIZE(range)) == 0) {
 		osc->rate_min = range[0];
 		osc->rate_max = range[1];
 	}
 
-	of_property_read_string(node, "clock-output-names", &init.name);
+	of_property_read_string(pdev->dev.of_node, "clock-output-names",
+			&init.name);
 	if (!init.name)
-		init.name = node->full_name;
+		init.name = dev_name(&pdev->dev);
 
 	init.ops = &vexpress_osc_ops;
 	init.flags = CLK_IS_ROOT;
@@ -128,20 +125,31 @@ void __init vexpress_osc_of_setup(struct device_node *node)
 	osc->hw.init = &init;
 
 	clk = clk_register(NULL, &osc->hw);
-	if (IS_ERR(clk)) {
-		pr_err("Failed to register clock '%s'!\n", init.name);
-		goto error;
-	}
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, clk);
+
+	dev_dbg(&pdev->dev, "Registered clock '%s'\n", init.name);
 
-	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	return 0;
+}
 
-	pr_debug("Registered clock '%s'\n", init.name);
+static struct of_device_id vexpress_osc_of_match[] = {
+	{ .compatible = "arm,vexpress-osc", },
+	{}
+};
 
-	return;
+static struct platform_driver vexpress_osc_driver = {
+	.driver	= {
+		.name = "vexpress-osc",
+		.of_match_table = vexpress_osc_of_match,
+	},
+	.probe = vexpress_osc_probe,
+};
 
-error:
-	if (osc->func)
-		vexpress_config_func_put(osc->func);
-	kfree(osc);
+static int __init vexpress_osc_init(void)
+{
+	return platform_driver_register(&vexpress_osc_driver);
 }
-CLK_OF_DECLARE(vexpress_soc, "arm,vexpress-osc", vexpress_osc_of_setup);
+core_initcall(vexpress_osc_init);
diff --git a/include/linux/vexpress.h b/include/linux/vexpress.h
index 617c01b..45037f1 100644
--- a/include/linux/vexpress.h
+++ b/include/linux/vexpress.h
@@ -119,9 +119,6 @@ void vexpress_sysreg_of_early_init(void);
 /* Clocks */
 
 struct clk *vexpress_osc_setup(struct device *dev);
-void vexpress_osc_of_setup(struct device_node *node);
-
 void vexpress_clk_init(void __iomem *sp810_base);
-void vexpress_clk_of_init(void);
 
 #endif
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 14/18] ARM: vexpress: remove redundant vexpress_dt_cpus_num to get cpu count
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (14 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 13/18] clk: versatile: Use regmap instead of custom interface Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2013-12-23 16:23 ` [RFC 15/18] ARM: vexpress: Simplify SMP operations for DT-powered system Pawel Moll
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Sudeep KarkadaNagesha

From: Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>

arm_dt_init_cpu_maps parses the device tree, validates and sets the
cpu_possible_mask appropriately. It is unnecessary to do another DT
parse to get the number of cpus, use num_possible_cpus instead.

This patch also removes setting cpu_present_mask as platforms should
only re-initialize it in smp_prepare_cpus() if present != possible.

Acked-by: Pawel Moll <pawel.moll@arm.com>
Signed-off-by: Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
---
 arch/arm/mach-vexpress/platsmp.c | 31 +------------------------------
 1 file changed, 1 insertion(+), 30 deletions(-)

diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
index 993c9ae..12a8751 100644
--- a/arch/arm/mach-vexpress/platsmp.c
+++ b/arch/arm/mach-vexpress/platsmp.c
@@ -77,39 +77,13 @@ void __init vexpress_dt_smp_map_io(void)
 		WARN_ON(of_scan_flat_dt(vexpress_dt_find_scu, NULL));
 }
 
-static int __init vexpress_dt_cpus_num(unsigned long node, const char *uname,
-		int depth, void *data)
-{
-	static int prev_depth = -1;
-	static int nr_cpus = -1;
-
-	if (prev_depth > depth && nr_cpus > 0)
-		return nr_cpus;
-
-	if (nr_cpus < 0 && strcmp(uname, "cpus") == 0)
-		nr_cpus = 0;
-
-	if (nr_cpus >= 0) {
-		const char *device_type = of_get_flat_dt_prop(node,
-				"device_type", NULL);
-
-		if (device_type && strcmp(device_type, "cpu") == 0)
-			nr_cpus++;
-	}
-
-	prev_depth = depth;
-
-	return 0;
-}
-
 static void __init vexpress_dt_smp_init_cpus(void)
 {
 	int ncores = 0, i;
 
 	switch (vexpress_dt_scu) {
 	case GENERIC_SCU:
-		ncores = of_scan_flat_dt(vexpress_dt_cpus_num, NULL);
-		break;
+		return;
 	case CORTEX_A9_SCU:
 		ncores = scu_get_core_count(vexpress_dt_cortex_a9_scu_base);
 		break;
@@ -133,12 +107,9 @@ static void __init vexpress_dt_smp_init_cpus(void)
 
 static void __init vexpress_dt_smp_prepare_cpus(unsigned int max_cpus)
 {
-	int i;
 
 	switch (vexpress_dt_scu) {
 	case GENERIC_SCU:
-		for (i = 0; i < max_cpus; i++)
-			set_cpu_present(i, true);
 		break;
 	case CORTEX_A9_SCU:
 		scu_enable(vexpress_dt_cortex_a9_scu_base);
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 15/18] ARM: vexpress: Simplify SMP operations for DT-powered system
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (15 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 14/18] ARM: vexpress: remove redundant vexpress_dt_cpus_num to get cpu count Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2013-12-23 16:23 ` [RFC 16/18] bus: Versatile Express configuration bus Pawel Moll
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll

As all cores must be properly described in the Device Tree,
there is no point in getting their numbers from SCU on
A5/A9 platforms. This significantly simplifies the code,
removing the need for flat-tree scanning and early static
mapping.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
 arch/arm/mach-vexpress/core.h    |   3 +-
 arch/arm/mach-vexpress/platsmp.c | 158 ++++++++++-----------------------------
 arch/arm/mach-vexpress/v2m.c     |   6 +-
 3 files changed, 41 insertions(+), 126 deletions(-)

diff --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h
index bde4374..152fad9 100644
--- a/arch/arm/mach-vexpress/core.h
+++ b/arch/arm/mach-vexpress/core.h
@@ -4,10 +4,9 @@
 /* Tile's peripherals static mappings should start here */
 #define V2T_PERIPH 0xf8200000
 
-void vexpress_dt_smp_map_io(void);
-
 bool vexpress_smp_init_ops(void);
 
 extern struct smp_operations	vexpress_smp_ops;
+extern struct smp_operations	vexpress_smp_dt_ops;
 
 extern void vexpress_cpu_die(unsigned int cpu);
diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
index 12a8751..a1f3804 100644
--- a/arch/arm/mach-vexpress/platsmp.c
+++ b/arch/arm/mach-vexpress/platsmp.c
@@ -12,8 +12,7 @@
 #include <linux/errno.h>
 #include <linux/smp.h>
 #include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_fdt.h>
+#include <linux/of_address.h>
 #include <linux/vexpress.h>
 
 #include <asm/mcpm.h>
@@ -26,125 +25,13 @@
 
 #include "core.h"
 
-#if defined(CONFIG_OF)
-
-static enum {
-	GENERIC_SCU,
-	CORTEX_A9_SCU,
-} vexpress_dt_scu __initdata = GENERIC_SCU;
-
-static struct map_desc vexpress_dt_cortex_a9_scu_map __initdata = {
-	.virtual	= V2T_PERIPH,
-	/* .pfn	set in vexpress_dt_init_cortex_a9_scu() */
-	.length		= SZ_128,
-	.type		= MT_DEVICE,
-};
-
-static void *vexpress_dt_cortex_a9_scu_base __initdata;
-
-const static char *vexpress_dt_cortex_a9_match[] __initconst = {
-	"arm,cortex-a5-scu",
-	"arm,cortex-a9-scu",
-	NULL
-};
-
-static int __init vexpress_dt_find_scu(unsigned long node,
-		const char *uname, int depth, void *data)
-{
-	if (of_flat_dt_match(node, vexpress_dt_cortex_a9_match)) {
-		phys_addr_t phys_addr;
-		__be32 *reg = of_get_flat_dt_prop(node, "reg", NULL);
-
-		if (WARN_ON(!reg))
-			return -EINVAL;
-
-		phys_addr = be32_to_cpup(reg);
-		vexpress_dt_scu = CORTEX_A9_SCU;
-
-		vexpress_dt_cortex_a9_scu_map.pfn = __phys_to_pfn(phys_addr);
-		iotable_init(&vexpress_dt_cortex_a9_scu_map, 1);
-		vexpress_dt_cortex_a9_scu_base = ioremap(phys_addr, SZ_256);
-		if (WARN_ON(!vexpress_dt_cortex_a9_scu_base))
-			return -EFAULT;
-	}
-
-	return 0;
-}
-
-void __init vexpress_dt_smp_map_io(void)
-{
-	if (initial_boot_params)
-		WARN_ON(of_scan_flat_dt(vexpress_dt_find_scu, NULL));
-}
-
-static void __init vexpress_dt_smp_init_cpus(void)
-{
-	int ncores = 0, i;
-
-	switch (vexpress_dt_scu) {
-	case GENERIC_SCU:
-		return;
-	case CORTEX_A9_SCU:
-		ncores = scu_get_core_count(vexpress_dt_cortex_a9_scu_base);
-		break;
-	default:
-		WARN_ON(1);
-		break;
-	}
-
-	if (ncores < 2)
-		return;
-
-	if (ncores > nr_cpu_ids) {
-		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
-				ncores, nr_cpu_ids);
-		ncores = nr_cpu_ids;
-	}
-
-	for (i = 0; i < ncores; ++i)
-		set_cpu_possible(i, true);
-}
-
-static void __init vexpress_dt_smp_prepare_cpus(unsigned int max_cpus)
-{
-
-	switch (vexpress_dt_scu) {
-	case GENERIC_SCU:
-		break;
-	case CORTEX_A9_SCU:
-		scu_enable(vexpress_dt_cortex_a9_scu_base);
-		break;
-	default:
-		WARN_ON(1);
-		break;
-	}
-}
-
-#else
-
-static void __init vexpress_dt_smp_init_cpus(void)
-{
-	WARN_ON(1);
-}
-
-void __init vexpress_dt_smp_prepare_cpus(unsigned int max_cpus)
-{
-	WARN_ON(1);
-}
-
-#endif
-
 /*
  * Initialise the CPU possible map early - this describes the CPUs
  * which may be present or become present in the system.
  */
 static void __init vexpress_smp_init_cpus(void)
 {
-	if (ct_desc)
-		ct_desc->init_cpu_map();
-	else
-		vexpress_dt_smp_init_cpus();
-
+	ct_desc->init_cpu_map();
 }
 
 static void __init vexpress_smp_prepare_cpus(unsigned int max_cpus)
@@ -153,10 +40,7 @@ static void __init vexpress_smp_prepare_cpus(unsigned int max_cpus)
 	 * Initialise the present map, which describes the set of CPUs
 	 * actually populated at the present time.
 	 */
-	if (ct_desc)
-		ct_desc->smp_enable(max_cpus);
-	else
-		vexpress_dt_smp_prepare_cpus(max_cpus);
+	ct_desc->smp_enable(max_cpus);
 
 	/*
 	 * Write the address of secondary startup into the
@@ -194,3 +78,39 @@ bool __init vexpress_smp_init_ops(void)
 #endif
 	return false;
 }
+
+#if defined(CONFIG_OF)
+
+static const struct of_device_id vexpress_smp_dt_scu_match[] __initconst = {
+	{ .compatible = "arm,cortex-a5-scu", },
+	{ .compatible = "arm,cortex-a9-scu", },
+	{}
+};
+
+static void __init vexpress_smp_dt_prepare_cpus(unsigned int max_cpus)
+{
+	struct device_node *scu = of_find_matching_node(NULL,
+			vexpress_smp_dt_scu_match);
+
+	if (scu)
+		scu_enable(of_iomap(scu, 0));
+
+	/*
+	 * Write the address of secondary startup into the
+	 * system-wide flags register. The boot monitor waits
+	 * until it receives a soft interrupt, and then the
+	 * secondary CPU branches to this address.
+	 */
+	vexpress_flags_set(virt_to_phys(versatile_secondary_startup));
+}
+
+struct smp_operations __initdata vexpress_smp_dt_ops = {
+	.smp_prepare_cpus	= vexpress_smp_dt_prepare_cpus,
+	.smp_secondary_init	= versatile_secondary_init,
+	.smp_boot_secondary	= versatile_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= vexpress_cpu_die,
+#endif
+};
+
+#endif
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 8e0e872..746d35d 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -399,10 +399,6 @@ void __init v2m_dt_map_io(void)
 		iotable_init(&v2m_rs1_io_desc, 1);
 	else
 		iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
-
-#if defined(CONFIG_SMP)
-	vexpress_dt_smp_map_io();
-#endif
 }
 
 void __init v2m_dt_init_early(void)
@@ -441,7 +437,7 @@ static const char * const v2m_dt_match[] __initconst = {
 
 DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
 	.dt_compat	= v2m_dt_match,
-	.smp		= smp_ops(vexpress_smp_ops),
+	.smp		= smp_ops(vexpress_smp_dt_ops),
 	.smp_init	= smp_init_ops(vexpress_smp_init_ops),
 	.map_io		= v2m_dt_map_io,
 	.init_early	= v2m_dt_init_early,
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 16/18] bus: Versatile Express configuration bus
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (16 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 15/18] ARM: vexpress: Simplify SMP operations for DT-powered system Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2013-12-23 16:23 ` [RFC 17/18] misc: Versatile Express System Config interface driver Pawel Moll
  2013-12-23 16:23 ` [RFC 18/18] mfd: vexpress: Split sysreg functions into MFD cells Pawel Moll
  19 siblings, 0 replies; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll

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).

This patch creates a class for such devices, instantiating
them from "arm,vexpress,config-bus"-compatible Device Tree
nodes and providing a bridge-specific regmap resource.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
 arch/arm/mach-vexpress/v2m.c                 |   8 +-
 arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi |   2 +-
 drivers/bus/Kconfig                          |   8 +
 drivers/bus/Makefile                         |   2 +
 drivers/bus/vexpress-config.c                | 178 ++++++++++++
 drivers/mfd/Kconfig                          |   6 -
 drivers/mfd/Makefile                         |   2 +-
 drivers/mfd/vexpress-config.c                | 288 --------------------
 drivers/mfd/vexpress-sysreg.c                | 390 +--------------------------
 include/linux/vexpress.h                     |  71 +----
 10 files changed, 204 insertions(+), 751 deletions(-)
 create mode 100644 drivers/bus/vexpress-config.c
 delete mode 100644 drivers/mfd/vexpress-config.c

diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 746d35d..5437956 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -417,17 +417,11 @@ void __init v2m_dt_init_early(void)
 	}
 }
 
-static const struct of_device_id v2m_dt_bus_match[] __initconst = {
-	{ .compatible = "simple-bus", },
-	{ .compatible = "arm,amba-bus", },
-	{ .compatible = "arm,vexpress,config-bus", },
-	{}
-};
 
 static void __init v2m_dt_init(void)
 {
 	l2x0_of_init(0x00400000, 0xfe0fffff);
-	of_platform_populate(NULL, v2m_dt_bus_match, NULL, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static 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 b45e5f3..21bf0bc 100644
--- a/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi
+++ b/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi
@@ -194,7 +194,7 @@
 		};
 
 		mcc {
-			compatible = "arm,vexpress,config-bus", "simple-bus";
+			compatible = "arm,vexpress,config-bus";
 			arm,vexpress,config-bridge = <&v2m_sysreg>;
 
 			v2m_oscclk1: osc@1 {
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 552373c..2fa6781 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -41,4 +41,12 @@ config ARM_CCI
 	help
 	  Driver supporting the CCI cache coherent interconnect for ARM
 	  platforms.
+
+config VEXPRESS_CONFIG
+	bool "Versatile Express configuration bus"
+	depends on ARM || ARM64
+	select REGMAP
+	help
+	  Platform configuration infrastructure for the ARM Ltd.
+	  Versatile Express.
 endmenu
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index 8947bdd..16b7505 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -10,3 +10,5 @@ obj-$(CONFIG_OMAP_OCP2SCP)	+= omap-ocp2scp.o
 obj-$(CONFIG_OMAP_INTERCONNECT)	+= omap_l3_smx.o omap_l3_noc.o
 # CCI cache coherent interconnect for ARM platforms
 obj-$(CONFIG_ARM_CCI)		+= arm-cci.o
+
+obj-$(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 0000000..5d138f9
--- /dev/null
+++ b/drivers/bus/vexpress-config.c
@@ -0,0 +1,178 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2013 ARM Limited
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/vexpress.h>
+
+
+static DEFINE_MUTEX(vexpress_config_mutex);
+static struct class *vexpress_config_class;
+static u32 vexpress_config_site_master = VEXPRESS_SITE_MASTER;
+
+
+void vexpress_config_set_master(u32 site)
+{
+	vexpress_config_site_master = site;
+}
+
+u32 vexpress_config_get_master(void)
+{
+	return vexpress_config_site_master;
+}
+
+void vexpress_config_lock(void *arg)
+{
+	mutex_lock(&vexpress_config_mutex);
+}
+
+void vexpress_config_unlock(void *arg)
+{
+	mutex_unlock(&vexpress_config_mutex);
+}
+
+
+static void vexpress_config_find_prop(struct device_node *node,
+		const char *name, u32 *val)
+{
+	/* Default value */
+	*val = 0;
+
+	of_node_get(node);
+	while (node) {
+		if (of_property_read_u32(node, name, val) == 0) {
+			of_node_put(node);
+			return;
+		}
+		node = of_get_next_parent(node);
+	}
+}
+
+int vexpress_config_get_topo(struct device_node *node, u32 *site,
+		u32 *position, u32 *dcc)
+{
+	vexpress_config_find_prop(node, "arm,vexpress,site", site);
+	if (*site == VEXPRESS_SITE_MASTER)
+		*site = vexpress_config_site_master;
+	if (WARN_ON(vexpress_config_site_master == VEXPRESS_SITE_MASTER))
+		return -EINVAL;
+	vexpress_config_find_prop(node, "arm,vexpress,position", position);
+	vexpress_config_find_prop(node, "arm,vexpress,dcc", dcc);
+
+	return 0;
+}
+
+
+static int vexpress_config_node_match(struct device *dev, const void *data)
+{
+	const struct device_node *node = data;
+
+	return dev->parent->of_node == node;
+}
+
+struct device *vexpress_config_bridge_register(struct device *parent,
+		int (*bridge_regmap_init)(struct device *dev, void *context),
+		void *context)
+{
+	struct device *bridge;
+
+	if (!vexpress_config_class) {
+		vexpress_config_class = class_create(THIS_MODULE,
+				"vexpress-config");
+		if (IS_ERR(vexpress_config_class))
+			return (void *)vexpress_config_class;
+	}
+
+	bridge = device_create(vexpress_config_class, parent, 0, "%s.bridge",
+			dev_name(parent));
+
+	if (!IS_ERR(bridge)) {
+		bridge->platform_data = bridge_regmap_init;
+		dev_set_drvdata(bridge, context);
+	}
+
+	return bridge;
+}
+
+
+static int vexpress_config_populate(struct platform_device *parent)
+{
+	int err;
+	struct device_node *bridge_node, *node;
+	struct device *bridge;
+	int (*bridge_regmap_init)(struct device *dev, void *context);
+	void *context;
+
+	bridge_node = of_parse_phandle(parent->dev.of_node,
+			"arm,vexpress,config-bridge", 0);
+	if (!bridge_node)
+		return -ENODEV;
+
+	bridge = class_find_device(vexpress_config_class, NULL, bridge_node,
+			vexpress_config_node_match);
+	if (!bridge)
+		return -ENODEV;
+
+	WARN_ON(sysfs_create_link(&parent->dev.kobj, &bridge->kobj, "bridge"));
+
+	bridge_regmap_init = dev_get_platdata(bridge);
+	context = dev_get_drvdata(bridge);
+
+	for_each_child_of_node(parent->dev.of_node, node) {
+		struct platform_device *child;
+
+		child = of_device_alloc(node, NULL, &parent->dev);
+		if (!child)
+			return -ENOMEM;
+
+		child->dev.bus = &platform_bus_type;
+		err = bridge_regmap_init(&child->dev, dev_get_drvdata(bridge));
+		if (!err)
+			err = of_device_add(child);
+		if (err) {
+			platform_device_put(child);
+			return err;
+		}
+
+		WARN_ON(sysfs_create_link(&bridge->kobj, &child->dev.kobj,
+				dev_name(&child->dev)));
+	}
+
+	return 0;
+}
+
+static int __init vexpress_config_init(void)
+{
+	int err = 0;
+	struct device_node *node;
+	struct device *root = root_device_register("vexpress-config");
+
+	for_each_compatible_node(node, NULL, "arm,vexpress,config-bus") {
+		struct platform_device *pdev;
+
+		pdev = of_platform_device_create(node, NULL, root);
+		if (!pdev){
+			err = -ENODEV;
+			break;
+		}
+
+		err = vexpress_config_populate(pdev);
+		if (err)
+			break;
+	}
+
+	return err;
+}
+postcore_initcall(vexpress_config_init);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index dd67158..4c8cdc3 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1200,9 +1200,3 @@ config MCP_UCB1200_TS
 
 endmenu
 
-config VEXPRESS_CONFIG
-	bool "ARM Versatile Express platform infrastructure"
-	depends on ARM || ARM64
-	help
-	  Platform configuration infrastructure for the ARM Ltd.
-	  Versatile Express.
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 8a28dc9..0277aa8 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -159,7 +159,7 @@ obj-$(CONFIG_MFD_RC5T583)	+= rc5t583.o rc5t583-irq.o
 obj-$(CONFIG_MFD_SEC_CORE)	+= sec-core.o sec-irq.o
 obj-$(CONFIG_MFD_SYSCON)	+= syscon.o
 obj-$(CONFIG_MFD_LM3533)	+= lm3533-core.o lm3533-ctrlbank.o
-obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o vexpress-sysreg.o
+obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-sysreg.o
 obj-$(CONFIG_MFD_RETU)		+= retu-mfd.o
 obj-$(CONFIG_MFD_AS3711)	+= as3711.o
 obj-$(CONFIG_MFD_AS3722)	+= as3722.o
diff --git a/drivers/mfd/vexpress-config.c b/drivers/mfd/vexpress-config.c
deleted file mode 100644
index 84ce6b9..0000000
--- a/drivers/mfd/vexpress-config.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * Copyright (C) 2012 ARM Limited
- */
-
-#define pr_fmt(fmt) "vexpress-config: " fmt
-
-#include <linux/bitops.h>
-#include <linux/completion.h>
-#include <linux/export.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/vexpress.h>
-
-
-#define VEXPRESS_CONFIG_MAX_BRIDGES 2
-
-struct vexpress_config_bridge {
-	struct device_node *node;
-	struct vexpress_config_bridge_info *info;
-	struct list_head transactions;
-	spinlock_t transactions_lock;
-} vexpress_config_bridges[VEXPRESS_CONFIG_MAX_BRIDGES];
-
-static DECLARE_BITMAP(vexpress_config_bridges_map,
-		ARRAY_SIZE(vexpress_config_bridges));
-static DEFINE_MUTEX(vexpress_config_bridges_mutex);
-
-struct vexpress_config_bridge *vexpress_config_bridge_register(
-		struct device_node *node,
-		struct vexpress_config_bridge_info *info)
-{
-	struct vexpress_config_bridge *bridge;
-	int i;
-
-	pr_debug("Registering bridge '%s'\n", info->name);
-
-	mutex_lock(&vexpress_config_bridges_mutex);
-	i = find_first_zero_bit(vexpress_config_bridges_map,
-			ARRAY_SIZE(vexpress_config_bridges));
-	if (i >= ARRAY_SIZE(vexpress_config_bridges)) {
-		pr_err("Can't register more bridges!\n");
-		mutex_unlock(&vexpress_config_bridges_mutex);
-		return NULL;
-	}
-	__set_bit(i, vexpress_config_bridges_map);
-	bridge = &vexpress_config_bridges[i];
-
-	bridge->node = node;
-	bridge->info = info;
-	INIT_LIST_HEAD(&bridge->transactions);
-	spin_lock_init(&bridge->transactions_lock);
-
-	mutex_unlock(&vexpress_config_bridges_mutex);
-
-	return bridge;
-}
-EXPORT_SYMBOL(vexpress_config_bridge_register);
-
-void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge)
-{
-	struct vexpress_config_bridge __bridge = *bridge;
-	int i;
-
-	mutex_lock(&vexpress_config_bridges_mutex);
-	for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++)
-		if (&vexpress_config_bridges[i] == bridge)
-			__clear_bit(i, vexpress_config_bridges_map);
-	mutex_unlock(&vexpress_config_bridges_mutex);
-
-	WARN_ON(!list_empty(&__bridge.transactions));
-	while (!list_empty(&__bridge.transactions))
-		cpu_relax();
-}
-EXPORT_SYMBOL(vexpress_config_bridge_unregister);
-
-
-struct vexpress_config_func {
-	struct vexpress_config_bridge *bridge;
-	void *func;
-};
-
-struct vexpress_config_func *__vexpress_config_func_get(struct device *dev,
-		struct device_node *node)
-{
-	struct device_node *bridge_node;
-	struct vexpress_config_func *func;
-	int i;
-
-	if (WARN_ON(dev && node && dev->of_node != node))
-		return NULL;
-	if (dev && !node)
-		node = dev->of_node;
-
-	func = kzalloc(sizeof(*func), GFP_KERNEL);
-	if (!func)
-		return NULL;
-
-	bridge_node = of_node_get(node);
-	while (bridge_node) {
-		const __be32 *prop = of_get_property(bridge_node,
-				"arm,vexpress,config-bridge", NULL);
-
-		if (prop) {
-			bridge_node = of_find_node_by_phandle(
-					be32_to_cpup(prop));
-			break;
-		}
-
-		bridge_node = of_get_next_parent(bridge_node);
-	}
-
-	mutex_lock(&vexpress_config_bridges_mutex);
-	for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++) {
-		struct vexpress_config_bridge *bridge =
-				&vexpress_config_bridges[i];
-
-		if (test_bit(i, vexpress_config_bridges_map) &&
-				bridge->node == bridge_node) {
-			func->bridge = bridge;
-			func->func = bridge->info->func_get(dev, node);
-			break;
-		}
-	}
-	mutex_unlock(&vexpress_config_bridges_mutex);
-
-	if (!func->func) {
-		of_node_put(node);
-		kfree(func);
-		return NULL;
-	}
-
-	return func;
-}
-EXPORT_SYMBOL(__vexpress_config_func_get);
-
-void vexpress_config_func_put(struct vexpress_config_func *func)
-{
-	func->bridge->info->func_put(func->func);
-	of_node_put(func->bridge->node);
-	kfree(func);
-}
-EXPORT_SYMBOL(vexpress_config_func_put);
-
-struct vexpress_config_trans {
-	struct vexpress_config_func *func;
-	int offset;
-	bool write;
-	u32 *data;
-	int status;
-	struct completion completion;
-	struct list_head list;
-};
-
-static void vexpress_config_dump_trans(const char *what,
-		struct vexpress_config_trans *trans)
-{
-	pr_debug("%s %s trans %p func 0x%p offset %d data 0x%x status %d\n",
-			what, trans->write ? "write" : "read", trans,
-			trans->func->func, trans->offset,
-			trans->data ? *trans->data : 0, trans->status);
-}
-
-static int vexpress_config_schedule(struct vexpress_config_trans *trans)
-{
-	int status;
-	struct vexpress_config_bridge *bridge = trans->func->bridge;
-	unsigned long flags;
-
-	init_completion(&trans->completion);
-	trans->status = -EFAULT;
-
-	spin_lock_irqsave(&bridge->transactions_lock, flags);
-
-	if (list_empty(&bridge->transactions)) {
-		vexpress_config_dump_trans("Executing", trans);
-		status = bridge->info->func_exec(trans->func->func,
-				trans->offset, trans->write, trans->data);
-	} else {
-		vexpress_config_dump_trans("Queuing", trans);
-		status = VEXPRESS_CONFIG_STATUS_WAIT;
-	}
-
-	switch (status) {
-	case VEXPRESS_CONFIG_STATUS_DONE:
-		vexpress_config_dump_trans("Finished", trans);
-		trans->status = status;
-		break;
-	case VEXPRESS_CONFIG_STATUS_WAIT:
-		list_add_tail(&trans->list, &bridge->transactions);
-		break;
-	}
-
-	spin_unlock_irqrestore(&bridge->transactions_lock, flags);
-
-	return status;
-}
-
-void vexpress_config_complete(struct vexpress_config_bridge *bridge,
-		int status)
-{
-	struct vexpress_config_trans *trans;
-	unsigned long flags;
-	const char *message = "Completed";
-
-	spin_lock_irqsave(&bridge->transactions_lock, flags);
-
-	trans = list_first_entry(&bridge->transactions,
-			struct vexpress_config_trans, list);
-	trans->status = status;
-
-	do {
-		vexpress_config_dump_trans(message, trans);
-		list_del(&trans->list);
-		complete(&trans->completion);
-
-		if (list_empty(&bridge->transactions))
-			break;
-
-		trans = list_first_entry(&bridge->transactions,
-				struct vexpress_config_trans, list);
-		vexpress_config_dump_trans("Executing pending", trans);
-		trans->status = bridge->info->func_exec(trans->func->func,
-				trans->offset, trans->write, trans->data);
-		message = "Finished pending";
-	} while (trans->status == VEXPRESS_CONFIG_STATUS_DONE);
-
-	spin_unlock_irqrestore(&bridge->transactions_lock, flags);
-}
-EXPORT_SYMBOL(vexpress_config_complete);
-
-int vexpress_config_wait(struct vexpress_config_trans *trans)
-{
-	wait_for_completion(&trans->completion);
-
-	return trans->status;
-}
-EXPORT_SYMBOL(vexpress_config_wait);
-
-int vexpress_config_read(struct vexpress_config_func *func, int offset,
-		u32 *data)
-{
-	struct vexpress_config_trans trans = {
-		.func = func,
-		.offset = offset,
-		.write = false,
-		.data = data,
-		.status = 0,
-	};
-	int status = vexpress_config_schedule(&trans);
-
-	if (status == VEXPRESS_CONFIG_STATUS_WAIT)
-		status = vexpress_config_wait(&trans);
-
-	return status;
-}
-EXPORT_SYMBOL(vexpress_config_read);
-
-int vexpress_config_write(struct vexpress_config_func *func, int offset,
-		u32 data)
-{
-	struct vexpress_config_trans trans = {
-		.func = func,
-		.offset = offset,
-		.write = true,
-		.data = &data,
-		.status = 0,
-	};
-	int status = vexpress_config_schedule(&trans);
-
-	if (status == VEXPRESS_CONFIG_STATUS_WAIT)
-		status = vexpress_config_wait(&trans);
-
-	return status;
-}
-EXPORT_SYMBOL(vexpress_config_write);
diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c
index 981bef4..31b3290 100644
--- a/drivers/mfd/vexpress-sysreg.c
+++ b/drivers/mfd/vexpress-sysreg.c
@@ -71,8 +71,6 @@
 
 
 static void __iomem *vexpress_sysreg_base;
-static struct device *vexpress_sysreg_dev;
-static int vexpress_master_site;
 
 
 void vexpress_flags_set(u32 data)
@@ -84,7 +82,7 @@ void vexpress_flags_set(u32 data)
 u32 vexpress_get_procid(int site)
 {
 	if (site == VEXPRESS_SITE_MASTER)
-		site = vexpress_master_site;
+		site = vexpress_config_get_master();
 
 	return readl(vexpress_sysreg_base + (site == VEXPRESS_SITE_DB1 ?
 			SYS_PROCID0 : SYS_PROCID1));
@@ -114,220 +112,15 @@ void __iomem *vexpress_get_24mhz_clock_base(void)
 }
 
 
-static void vexpress_sysreg_find_prop(struct device_node *node,
-		const char *name, u32 *val)
-{
-	of_node_get(node);
-	while (node) {
-		if (of_property_read_u32(node, name, val) == 0) {
-			of_node_put(node);
-			return;
-		}
-		node = of_get_next_parent(node);
-	}
-}
-
-unsigned __vexpress_get_site(struct device *dev, struct device_node *node)
-{
-	u32 site = 0;
-
-	WARN_ON(dev && node && dev->of_node != node);
-	if (dev && !node)
-		node = dev->of_node;
-
-	if (node) {
-		vexpress_sysreg_find_prop(node, "arm,vexpress,site", &site);
-	} else if (dev && dev->bus == &platform_bus_type) {
-		struct platform_device *pdev = to_platform_device(dev);
-
-		if (pdev->num_resources == 1 &&
-				pdev->resource[0].flags == IORESOURCE_BUS)
-			site = pdev->resource[0].start;
-	} else if (dev && strncmp(dev_name(dev), "ct:", 3) == 0) {
-		site = VEXPRESS_SITE_MASTER;
-	}
-
-	if (site == VEXPRESS_SITE_MASTER)
-		site = vexpress_master_site;
-
-	return site;
-}
-
-
-struct vexpress_sysreg_config_func {
-	u32 template;
-	u32 device;
-};
-
-static struct vexpress_config_bridge *vexpress_sysreg_config_bridge;
-static struct timer_list vexpress_sysreg_config_timer;
-static u32 *vexpress_sysreg_config_data;
-static int vexpress_sysreg_config_tries;
-
-static void *vexpress_sysreg_config_func_get(struct device *dev,
-		struct device_node *node)
-{
-	struct vexpress_sysreg_config_func *config_func;
-	u32 site;
-	u32 position = 0;
-	u32 dcc = 0;
-	u32 func_device[2];
-	int err = -EFAULT;
-
-	if (node) {
-		of_node_get(node);
-		vexpress_sysreg_find_prop(node, "arm,vexpress,site", &site);
-		vexpress_sysreg_find_prop(node, "arm,vexpress,position",
-				&position);
-		vexpress_sysreg_find_prop(node, "arm,vexpress,dcc", &dcc);
-		err = of_property_read_u32_array(node,
-				"arm,vexpress-sysreg,func", func_device,
-				ARRAY_SIZE(func_device));
-		of_node_put(node);
-	} else if (dev && dev->bus == &platform_bus_type) {
-		struct platform_device *pdev = to_platform_device(dev);
-
-		if (pdev->num_resources == 1 &&
-				pdev->resource[0].flags == IORESOURCE_BUS) {
-			site = pdev->resource[0].start;
-			func_device[0] = pdev->resource[0].end;
-			func_device[1] = pdev->id;
-			err = 0;
-		}
-	}
-	if (err)
-		return NULL;
-
-	config_func = kzalloc(sizeof(*config_func), GFP_KERNEL);
-	if (!config_func)
-		return NULL;
-
-	config_func->template = SYS_CFGCTRL_DCC(dcc);
-	config_func->template |= SYS_CFGCTRL_FUNC(func_device[0]);
-	config_func->template |= SYS_CFGCTRL_SITE(site == VEXPRESS_SITE_MASTER ?
-			vexpress_master_site : site);
-	config_func->template |= SYS_CFGCTRL_POSITION(position);
-	config_func->device |= func_device[1];
-
-	dev_dbg(vexpress_sysreg_dev, "func 0x%p = 0x%x, %d\n", config_func,
-			config_func->template, config_func->device);
-
-	return config_func;
-}
-
-static void vexpress_sysreg_config_func_put(void *func)
-{
-	kfree(func);
-}
-
-static int vexpress_sysreg_config_func_exec(void *func, int offset,
-		bool write, u32 *data)
-{
-	int status;
-	struct vexpress_sysreg_config_func *config_func = func;
-	u32 command;
-
-	if (WARN_ON(!vexpress_sysreg_base))
-		return -ENOENT;
-
-	command = readl(vexpress_sysreg_base + SYS_CFGCTRL);
-	if (WARN_ON(command & SYS_CFGCTRL_START))
-		return -EBUSY;
-
-	command = SYS_CFGCTRL_START;
-	command |= write ? SYS_CFGCTRL_WRITE : 0;
-	command |= config_func->template;
-	command |= SYS_CFGCTRL_DEVICE(config_func->device + offset);
-
-	/* Use a canary for reads */
-	if (!write)
-		*data = 0xdeadbeef;
-
-	dev_dbg(vexpress_sysreg_dev, "command %x, data %x\n",
-			command, *data);
-	writel(*data, vexpress_sysreg_base + SYS_CFGDATA);
-	writel(0, vexpress_sysreg_base + SYS_CFGSTAT);
-	writel(command, vexpress_sysreg_base + SYS_CFGCTRL);
-	mb();
-
-	if (vexpress_sysreg_dev) {
-		/* Schedule completion check */
-		if (!write)
-			vexpress_sysreg_config_data = data;
-		vexpress_sysreg_config_tries = 100;
-		mod_timer(&vexpress_sysreg_config_timer,
-				jiffies + usecs_to_jiffies(100));
-		status = VEXPRESS_CONFIG_STATUS_WAIT;
-	} else {
-		/* Early execution, no timer available, have to spin */
-		u32 cfgstat;
-
-		do {
-			cpu_relax();
-			cfgstat = readl(vexpress_sysreg_base + SYS_CFGSTAT);
-		} while (!cfgstat);
-
-		if (!write && (cfgstat & SYS_CFGSTAT_COMPLETE))
-			*data = readl(vexpress_sysreg_base + SYS_CFGDATA);
-		status = VEXPRESS_CONFIG_STATUS_DONE;
-
-		if (cfgstat & SYS_CFGSTAT_ERR)
-			status = -EINVAL;
-	}
-
-	return status;
-}
-
-struct vexpress_config_bridge_info vexpress_sysreg_config_bridge_info = {
-	.name = "vexpress-sysreg",
-	.func_get = vexpress_sysreg_config_func_get,
-	.func_put = vexpress_sysreg_config_func_put,
-	.func_exec = vexpress_sysreg_config_func_exec,
-};
-
-static void vexpress_sysreg_config_complete(unsigned long data)
-{
-	int status = VEXPRESS_CONFIG_STATUS_DONE;
-	u32 cfgstat = readl(vexpress_sysreg_base + SYS_CFGSTAT);
-
-	if (cfgstat & SYS_CFGSTAT_ERR)
-		status = -EINVAL;
-	if (!vexpress_sysreg_config_tries--)
-		status = -ETIMEDOUT;
-
-	if (status < 0) {
-		dev_err(vexpress_sysreg_dev, "error %d\n", status);
-	} else if (!(cfgstat & SYS_CFGSTAT_COMPLETE)) {
-		mod_timer(&vexpress_sysreg_config_timer,
-				jiffies + usecs_to_jiffies(50));
-		return;
-	}
-
-	if (vexpress_sysreg_config_data) {
-		*vexpress_sysreg_config_data = readl(vexpress_sysreg_base +
-				SYS_CFGDATA);
-		dev_dbg(vexpress_sysreg_dev, "read data %x\n",
-				*vexpress_sysreg_config_data);
-		vexpress_sysreg_config_data = NULL;
-	}
-
-	vexpress_config_complete(vexpress_sysreg_config_bridge, status);
-}
-
-
 void vexpress_sysreg_setup(struct device_node *node)
 {
 	if (WARN_ON(!vexpress_sysreg_base))
 		return;
 
 	if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE)
-		vexpress_master_site = VEXPRESS_SITE_DB2;
+		vexpress_config_set_master(VEXPRESS_SITE_DB2);
 	else
-		vexpress_master_site = VEXPRESS_SITE_DB1;
-
-	vexpress_sysreg_config_bridge = vexpress_config_bridge_register(
-			node, &vexpress_sysreg_config_bridge_info);
-	WARN_ON(!vexpress_sysreg_config_bridge);
+		vexpress_config_set_master(VEXPRESS_SITE_DB1);
 }
 
 void __init vexpress_sysreg_early_init(void __iomem *base)
@@ -349,180 +142,3 @@ void __init vexpress_sysreg_of_early_init(void)
 		vexpress_sysreg_setup(node);
 	}
 }
-
-
-#ifdef CONFIG_GPIOLIB
-
-#define VEXPRESS_SYSREG_GPIO(_name, _reg, _value) \
-	[VEXPRESS_GPIO_##_name] = { \
-		.reg = _reg, \
-		.value = _reg##_##_value, \
-	}
-
-static struct vexpress_sysreg_gpio {
-	unsigned long reg;
-	u32 value;
-} vexpress_sysreg_gpios[] = {
-	VEXPRESS_SYSREG_GPIO(MMC_CARDIN,	SYS_MCI,	CARDIN),
-	VEXPRESS_SYSREG_GPIO(MMC_WPROT,		SYS_MCI,	WPROT),
-	VEXPRESS_SYSREG_GPIO(FLASH_WPn,		SYS_FLASH,	WPn),
-	VEXPRESS_SYSREG_GPIO(LED0,		SYS_LED,	LED(0)),
-	VEXPRESS_SYSREG_GPIO(LED1,		SYS_LED,	LED(1)),
-	VEXPRESS_SYSREG_GPIO(LED2,		SYS_LED,	LED(2)),
-	VEXPRESS_SYSREG_GPIO(LED3,		SYS_LED,	LED(3)),
-	VEXPRESS_SYSREG_GPIO(LED4,		SYS_LED,	LED(4)),
-	VEXPRESS_SYSREG_GPIO(LED5,		SYS_LED,	LED(5)),
-	VEXPRESS_SYSREG_GPIO(LED6,		SYS_LED,	LED(6)),
-	VEXPRESS_SYSREG_GPIO(LED7,		SYS_LED,	LED(7)),
-};
-
-static int vexpress_sysreg_gpio_direction_input(struct gpio_chip *chip,
-				       unsigned offset)
-{
-	return 0;
-}
-
-static int vexpress_sysreg_gpio_get(struct gpio_chip *chip,
-				       unsigned offset)
-{
-	struct vexpress_sysreg_gpio *gpio = &vexpress_sysreg_gpios[offset];
-	u32 reg_value = readl(vexpress_sysreg_base + gpio->reg);
-
-	return !!(reg_value & gpio->value);
-}
-
-static void vexpress_sysreg_gpio_set(struct gpio_chip *chip,
-				       unsigned offset, int value)
-{
-	struct vexpress_sysreg_gpio *gpio = &vexpress_sysreg_gpios[offset];
-	u32 reg_value = readl(vexpress_sysreg_base + gpio->reg);
-
-	if (value)
-		reg_value |= gpio->value;
-	else
-		reg_value &= ~gpio->value;
-
-	writel(reg_value, vexpress_sysreg_base + gpio->reg);
-}
-
-static int vexpress_sysreg_gpio_direction_output(struct gpio_chip *chip,
-						unsigned offset, int value)
-{
-	vexpress_sysreg_gpio_set(chip, offset, value);
-
-	return 0;
-}
-
-static struct gpio_chip vexpress_sysreg_gpio_chip = {
-	.label = "vexpress-sysreg",
-	.direction_input = vexpress_sysreg_gpio_direction_input,
-	.direction_output = vexpress_sysreg_gpio_direction_output,
-	.get = vexpress_sysreg_gpio_get,
-	.set = vexpress_sysreg_gpio_set,
-	.ngpio = ARRAY_SIZE(vexpress_sysreg_gpios),
-	.base = 0,
-};
-
-
-#define VEXPRESS_SYSREG_GREEN_LED(_name, _default_trigger, _gpio) \
-	{ \
-		.name = "v2m:green:"_name, \
-		.default_trigger = _default_trigger, \
-		.gpio = VEXPRESS_GPIO_##_gpio, \
-	}
-
-struct gpio_led vexpress_sysreg_leds[] = {
-	VEXPRESS_SYSREG_GREEN_LED("user1",	"heartbeat",	LED0),
-	VEXPRESS_SYSREG_GREEN_LED("user2",	"mmc0",		LED1),
-	VEXPRESS_SYSREG_GREEN_LED("user3",	"cpu0",		LED2),
-	VEXPRESS_SYSREG_GREEN_LED("user4",	"cpu1",		LED3),
-	VEXPRESS_SYSREG_GREEN_LED("user5",	"cpu2",		LED4),
-	VEXPRESS_SYSREG_GREEN_LED("user6",	"cpu3",		LED5),
-	VEXPRESS_SYSREG_GREEN_LED("user7",	"cpu4",		LED6),
-	VEXPRESS_SYSREG_GREEN_LED("user8",	"cpu5",		LED7),
-};
-
-struct gpio_led_platform_data vexpress_sysreg_leds_pdata = {
-	.num_leds = ARRAY_SIZE(vexpress_sysreg_leds),
-	.leds = vexpress_sysreg_leds,
-};
-
-#endif
-
-
-static ssize_t vexpress_sysreg_sys_id_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf, "0x%08x\n", readl(vexpress_sysreg_base + SYS_ID));
-}
-
-DEVICE_ATTR(sys_id, S_IRUGO, vexpress_sysreg_sys_id_show, NULL);
-
-static int vexpress_sysreg_probe(struct platform_device *pdev)
-{
-	int err;
-	struct resource *res = platform_get_resource(pdev,
-			IORESOURCE_MEM, 0);
-
-	if (!devm_request_mem_region(&pdev->dev, res->start,
-			resource_size(res), pdev->name)) {
-		dev_err(&pdev->dev, "Failed to request memory region!\n");
-		return -EBUSY;
-	}
-
-	if (!vexpress_sysreg_base) {
-		vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start,
-				resource_size(res));
-		vexpress_sysreg_setup(pdev->dev.of_node);
-	}
-
-	if (!vexpress_sysreg_base) {
-		dev_err(&pdev->dev, "Failed to obtain base address!\n");
-		return -EFAULT;
-	}
-
-	setup_timer(&vexpress_sysreg_config_timer,
-			vexpress_sysreg_config_complete, 0);
-
-	vexpress_sysreg_dev = &pdev->dev;
-
-#ifdef CONFIG_GPIOLIB
-	vexpress_sysreg_gpio_chip.dev = &pdev->dev;
-	err = gpiochip_add(&vexpress_sysreg_gpio_chip);
-	if (err) {
-		vexpress_config_bridge_unregister(
-				vexpress_sysreg_config_bridge);
-		dev_err(&pdev->dev, "Failed to register GPIO chip! (%d)\n",
-				err);
-		return err;
-	}
-
-	platform_device_register_data(vexpress_sysreg_dev, "leds-gpio",
-			PLATFORM_DEVID_AUTO, &vexpress_sysreg_leds_pdata,
-			sizeof(vexpress_sysreg_leds_pdata));
-#endif
-
-	device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id);
-
-	return 0;
-}
-
-static const struct of_device_id vexpress_sysreg_match[] = {
-	{ .compatible = "arm,vexpress-sysreg", },
-	{},
-};
-
-static struct platform_driver vexpress_sysreg_driver = {
-	.driver = {
-		.name = "vexpress-sysreg",
-		.of_match_table = vexpress_sysreg_match,
-	},
-	.probe = vexpress_sysreg_probe,
-};
-
-static int __init vexpress_sysreg_init(void)
-{
-	vexpress_sysreg_of_early_init();
-	return platform_driver_register(&vexpress_sysreg_driver);
-}
-core_initcall(vexpress_sysreg_init);
diff --git a/include/linux/vexpress.h b/include/linux/vexpress.h
index 45037f1..1b8889f 100644
--- a/include/linux/vexpress.h
+++ b/include/linux/vexpress.h
@@ -22,9 +22,6 @@
 #define VEXPRESS_SITE_DB2		2
 #define VEXPRESS_SITE_MASTER		0xf
 
-#define VEXPRESS_CONFIG_STATUS_DONE	0
-#define VEXPRESS_CONFIG_STATUS_WAIT	1
-
 #define VEXPRESS_GPIO_MMC_CARDIN	0
 #define VEXPRESS_GPIO_MMC_WPROT		1
 #define VEXPRESS_GPIO_FLASH_WPn		2
@@ -44,63 +41,19 @@
 	.flags = IORESOURCE_BUS,	\
 }
 
-/* Config bridge API */
-
-/**
- * struct vexpress_config_bridge_info - description of the platform
- * configuration infrastructure bridge.
- *
- * @name:	Bridge name
- *
- * @func_get:	Obtains pointer to a configuration function for a given
- *		device or a Device Tree node, to be used with @func_put
- *		and @func_exec. The node pointer should take precedence
- *		over device pointer when both are passed.
- *
- * @func_put:	Tells the bridge that the function will not be used any
- *		more, so all allocated resources can be released.
- *
- * @func_exec:	Executes a configuration function read or write operation.
- *		The offset selects a 32 bit word of the value accessed.
- *		Must return VEXPRESS_CONFIG_STATUS_DONE when operation
- *		is finished immediately, VEXPRESS_CONFIG_STATUS_WAIT when
- *		will be completed in some time or negative value in case
- *		of error.
- */
-struct vexpress_config_bridge_info {
-	const char *name;
-	void *(*func_get)(struct device *dev, struct device_node *node);
-	void (*func_put)(void *func);
-	int (*func_exec)(void *func, int offset, bool write, u32 *data);
-};
-
-struct vexpress_config_bridge;
-
-struct vexpress_config_bridge *vexpress_config_bridge_register(
-		struct device_node *node,
-		struct vexpress_config_bridge_info *info);
-void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge);
+/* Config infrastructure */
 
-void vexpress_config_complete(struct vexpress_config_bridge *bridge,
-		int status);
+void vexpress_config_set_master(u32 site);
+u32 vexpress_config_get_master(void);
 
-/* Config function API */
+void vexpress_config_lock(void *arg);
+void vexpress_config_unlock(void *arg);
+int vexpress_config_get_topo(struct device_node *node, u32 *site,
+		u32 *position, u32 *dcc);
 
-struct vexpress_config_func;
-
-struct vexpress_config_func *__vexpress_config_func_get(struct device *dev,
-		struct device_node *node);
-#define vexpress_config_func_get_by_dev(dev) \
-		__vexpress_config_func_get(dev, NULL)
-#define vexpress_config_func_get_by_node(node) \
-		__vexpress_config_func_get(NULL, node)
-void vexpress_config_func_put(struct vexpress_config_func *func);
-
-/* Both may sleep! */
-int vexpress_config_read(struct vexpress_config_func *func, int offset,
-		u32 *data);
-int vexpress_config_write(struct vexpress_config_func *func, int offset,
-		u32 data);
+struct device *vexpress_config_bridge_register(struct device *parent,
+		int (*bridge_regmap_init)(struct device *dev, void *context),
+		void *context);
 
 /* Platform control */
 
@@ -109,10 +62,6 @@ u32 vexpress_get_hbi(int site);
 void *vexpress_get_24mhz_clock_base(void);
 void vexpress_flags_set(u32 data);
 
-#define vexpress_get_site_by_node(node) __vexpress_get_site(NULL, node)
-#define vexpress_get_site_by_dev(dev) __vexpress_get_site(dev, NULL)
-unsigned __vexpress_get_site(struct device *dev, struct device_node *node);
-
 void vexpress_sysreg_early_init(void __iomem *base);
 void vexpress_sysreg_of_early_init(void);
 
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 17/18] misc: Versatile Express System Config interface driver
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (17 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 16/18] bus: Versatile Express configuration bus Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2013-12-23 16:23 ` [RFC 18/18] mfd: vexpress: Split sysreg functions into MFD cells Pawel Moll
  19 siblings, 0 replies; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll

Versatile Express System Config (syscfg) interface, usually
part of the System Registers (sysreg) block, can be used
to generate transactions on the platform configuration bus.

The driver registers itself as a bridge in the VE config
core and provides a regmap abstraction for the components
functions.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
 arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts |   5 +-
 arch/arm/mach-vexpress/ct-ca9x4.c          |   8 +-
 arch/arm/mach-vexpress/v2m.c               |  35 ++--
 drivers/misc/Kconfig                       |   9 +
 drivers/misc/Makefile                      |   1 +
 drivers/misc/vexpress-syscfg.c             | 322 +++++++++++++++++++++++++++++
 include/linux/vexpress.h                   |  11 +-
 7 files changed, 356 insertions(+), 35 deletions(-)
 create mode 100644 drivers/misc/vexpress-syscfg.c

diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
index 15f98cb..a25c262 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 @@
 			arm,vexpress-sysreg,func = <12 0>;
 			label = "A15 Pcore";
 		};
+
 		power@1 {
 			/* Total power for the three A7 cores */
 			compatible = "arm,vexpress-power";
@@ -322,14 +323,14 @@
 		energy@0 {
 			/* Total energy for the two A15 cores */
 			compatible = "arm,vexpress-energy";
-			arm,vexpress-sysreg,func = <13 0>;
+			arm,vexpress-sysreg,func = <13 0>, <13 1>;
 			label = "A15 Jcore";
 		};
 
 		energy@2 {
 			/* Total energy for the three A7 cores */
 			compatible = "arm,vexpress-energy";
-			arm,vexpress-sysreg,func = <13 2>;
+			arm,vexpress-sysreg,func = <13 2>, <13 3>;
 			label = "A7 Jcore";
 		};
 	};
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 6f34497..0df4bf6 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -130,11 +130,7 @@ static struct platform_device pmu_device = {
 
 static struct platform_device osc1_device = {
 	.name		= "vexpress-osc",
-	.id		= 1,
-	.num_resources	= 1,
-	.resource	= (struct resource []) {
-		VEXPRESS_RES_FUNC(0xf, 1),
-	},
+	.id		= -1,
 };
 
 static void __init ct_ca9x4_init(void)
@@ -156,6 +152,8 @@ static void __init ct_ca9x4_init(void)
 
 	platform_device_register(&pmu_device);
 	platform_device_register(&osc1_device);
+	devm_vexpress_syscfg_regmap_init(&osc1_device.dev,
+			vexpress_config_get_master(), 0, 0, 1, 1);
 
 	WARN_ON(clk_register_clkdev(vexpress_osc_setup(&osc1_device.dev),
 			NULL, "ct:clcd"));
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 5437956..325ae06 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -222,38 +222,22 @@ static struct platform_device v2m_sysreg_device = {
 
 static struct platform_device v2m_muxfpga_device = {
 	.name		= "vexpress-muxfpga",
-	.id		= 0,
-	.num_resources	= 1,
-	.resource	= (struct resource []) {
-		VEXPRESS_RES_FUNC(0, 7),
-	}
+	.id		= -1,
 };
 
 static struct platform_device v2m_shutdown_device = {
 	.name		= "vexpress-shutdown",
-	.id		= 0,
-	.num_resources	= 1,
-	.resource	= (struct resource []) {
-		VEXPRESS_RES_FUNC(0, 8),
-	}
+	.id		= -1,
 };
 
 static struct platform_device v2m_reboot_device = {
 	.name		= "vexpress-reboot",
-	.id		= 0,
-	.num_resources	= 1,
-	.resource	= (struct resource []) {
-		VEXPRESS_RES_FUNC(0, 9),
-	}
+	.id		= -1,
 };
 
 static struct platform_device v2m_dvimode_device = {
 	.name		= "vexpress-dvimode",
-	.id		= 0,
-	.num_resources	= 1,
-	.resource	= (struct resource []) {
-		VEXPRESS_RES_FUNC(0, 11),
-	}
+	.id		= -1,
 };
 
 static AMBA_APB_DEVICE(aaci,  "mb:aaci",  0, V2M_AACI, IRQ_V2M_AACI, NULL);
@@ -340,12 +324,21 @@ static void __init v2m_init(void)
 	regulator_register_fixed(0, v2m_eth_supplies,
 			ARRAY_SIZE(v2m_eth_supplies));
 
+	platform_device_register(&v2m_sysreg_device);
+
 	platform_device_register(&v2m_muxfpga_device);
+	devm_vexpress_syscfg_regmap_init(&v2m_muxfpga_device.dev,
+			VEXPRESS_SITE_MB, 0, 0, 7, 0);
 	platform_device_register(&v2m_shutdown_device);
+	devm_vexpress_syscfg_regmap_init(&v2m_shutdown_device.dev,
+			VEXPRESS_SITE_MB, 0, 0, 8, 0);
 	platform_device_register(&v2m_reboot_device);
+	devm_vexpress_syscfg_regmap_init(&v2m_reboot_device.dev,
+			VEXPRESS_SITE_MB, 0, 0, 9, 0);
 	platform_device_register(&v2m_dvimode_device);
+	devm_vexpress_syscfg_regmap_init(&v2m_dvimode_device.dev,
+			VEXPRESS_SITE_MB, 0, 0, 11, 0);
 
-	platform_device_register(&v2m_sysreg_device);
 	platform_device_register(&v2m_pcie_i2c_device);
 	platform_device_register(&v2m_ddc_i2c_device);
 	platform_device_register(&v2m_flash_device);
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index a3e291d..7c53770 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -515,6 +515,15 @@ config SRAM
 	  the genalloc API. It is supposed to be used for small on-chip SRAM
 	  areas found on many SoCs.
 
+config VEXPRESS_SYSCFG
+	bool "Versatile Express System Configuration driver"
+	depends on VEXPRESS_CONFIG
+	default y
+	help
+	  ARM Ltd. Versatile Express uses specialised platform configuration
+	  bus. System Configuration registers are one of the possible means
+	  of generating transactions on this bus.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f45473e..ca3338d 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
+obj-$(CONFIG_VEXPRESS_SYSCFG)	+= vexpress-syscfg.o
diff --git a/drivers/misc/vexpress-syscfg.c b/drivers/misc/vexpress-syscfg.c
new file mode 100644
index 0000000..6c4632d
--- /dev/null
+++ b/drivers/misc/vexpress-syscfg.c
@@ -0,0 +1,322 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2013 ARM Limited
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/syscore_ops.h>
+#include <linux/vexpress.h>
+
+
+#define SYS_CFGDATA		0x0
+
+#define SYS_CFGCTRL		0x4
+#define SYS_CFGCTRL_START	(1 << 31)
+#define SYS_CFGCTRL_WRITE	(1 << 30)
+#define SYS_CFGCTRL_DCC(n)	(((n) & 0xf) << 26)
+#define SYS_CFGCTRL_FUNC(n)	(((n) & 0x3f) << 20)
+#define SYS_CFGCTRL_SITE(n)	(((n) & 0x3) << 16)
+#define SYS_CFGCTRL_POSITION(n)	(((n) & 0xf) << 12)
+#define SYS_CFGCTRL_DEVICE(n)	(((n) & 0xfff) << 0)
+
+#define SYS_CFGSTAT		0x8
+#define SYS_CFGSTAT_ERR		(1 << 1)
+#define SYS_CFGSTAT_COMPLETE	(1 << 0)
+
+
+struct vexpress_syscfg {
+	struct device *dev;
+	void __iomem *base;
+};
+
+struct vexpress_syscfg_reg {
+	struct vexpress_syscfg *syscfg;
+	int regs_num;
+	u32 templates[0];
+};
+
+
+static int vexpress_syscfg_delay_schedule(unsigned int us)
+{
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(usecs_to_jiffies(us));
+	if (signal_pending(current))
+		return -EINTR;
+
+	return 0;
+}
+
+static int vexpress_syscfg_delay_loop(unsigned int us)
+{
+	unsigned long long timeout_ns = sched_clock() + us * 1000;
+
+	while (time_before64(sched_clock(), timeout_ns))
+		cpu_relax();
+
+	return 0;
+}
+
+static int (*vexpress_syscfg_delay)(unsigned int us) =
+		vexpress_syscfg_delay_schedule;
+
+static void vexpress_syscfg_shutdown(void)
+{
+	/* Can't relay on the scheduler when the system is going down */
+	vexpress_syscfg_delay = vexpress_syscfg_delay_loop;
+}
+
+static struct syscore_ops vexpress_syscfg_syscore_ops = {
+	.shutdown = vexpress_syscfg_shutdown,
+};
+
+
+static int vexpress_syscfg_exec(struct vexpress_syscfg_reg *reg,
+		int index, bool write, u32 *data)
+{
+	struct vexpress_syscfg *syscfg = reg->syscfg;
+	u32 command, status;
+	int tries;
+	long timeout;
+
+	if (WARN_ON(index > reg->regs_num))
+		return -EINVAL;
+
+	command = readl(syscfg->base + SYS_CFGCTRL);
+	if (WARN_ON(command & SYS_CFGCTRL_START))
+		return -EBUSY;
+
+	command = reg->templates[index];
+	command |= SYS_CFGCTRL_START;
+	command |= write ? SYS_CFGCTRL_WRITE : 0;
+
+	/* Use a canary for reads */
+	if (!write)
+		*data = 0xdeadbeef;
+
+	dev_dbg(syscfg->dev, "command %x, data %x\n",
+			command, *data);
+	writel(*data, syscfg->base + SYS_CFGDATA);
+	writel(0, syscfg->base + SYS_CFGSTAT);
+	writel(command, syscfg->base + SYS_CFGCTRL);
+	mb();
+
+	/* The operation can take ages... Go to sleep, 100us initially */
+	tries = 100;
+	timeout = 100;
+	do {
+		int err = vexpress_syscfg_delay(timeout);
+		if (err)
+			return err;
+
+		status = readl(syscfg->base + SYS_CFGSTAT);
+		if (status & SYS_CFGSTAT_ERR)
+			return -EFAULT;
+
+		if (timeout > 20)
+			timeout -= 20;
+	} while (--tries && !(status & SYS_CFGSTAT_COMPLETE));
+	if (WARN_ON_ONCE(!tries))
+		return -ETIMEDOUT;
+
+	if (!write) {
+		*data = readl(syscfg->base + SYS_CFGDATA);
+		dev_dbg(syscfg->dev, "read data %x\n", *data);
+	}
+
+	return 0;
+}
+
+static int vexpress_syscfg_reg_read(void *context, unsigned int index,
+		unsigned int *val)
+{
+	struct vexpress_syscfg_reg *reg = context;
+
+	return vexpress_syscfg_exec(reg, index, false, val);
+}
+
+static int vexpress_syscfg_reg_write(void *context, unsigned int index,
+		unsigned int val)
+{
+	struct vexpress_syscfg_reg *reg = context;
+
+	return vexpress_syscfg_exec(reg, index, true, &val);
+}
+
+static struct vexpress_syscfg_reg *vexpress_syscfg_alloc_reg(
+		struct vexpress_syscfg *syscfg,
+		int site, int position, int dcc, int regs_num)
+{
+	struct vexpress_syscfg_reg *reg;
+	int i;
+
+	reg = kzalloc(sizeof(*reg) + sizeof(*reg->templates) * regs_num,
+			GFP_KERNEL);
+	if (!reg)
+		return NULL;
+
+	reg->syscfg = syscfg;
+	reg->regs_num = regs_num;
+
+	for (i = 0; i < regs_num; i++) {
+		reg->templates[i] = SYS_CFGCTRL_DCC(dcc);
+		reg->templates[i] |= SYS_CFGCTRL_SITE(site);
+		reg->templates[i] |= SYS_CFGCTRL_POSITION(position);
+	}
+
+	return reg;
+}
+
+static void vexpress_syscfg_set_reg(struct vexpress_syscfg_reg *reg,
+		int index, u32 function, u32 device)
+{
+	if (WARN_ON(index >= reg->regs_num))
+		return;
+
+	reg->templates[index] |= SYS_CFGCTRL_FUNC(function);
+	reg->templates[index] |= SYS_CFGCTRL_DEVICE(device);
+}
+
+static void vexpress_syscfg_free_reg(void *reg)
+{
+	kfree(reg);
+}
+
+struct regmap_config vexpress_syscfg_regmap_config = {
+	.lock = vexpress_config_lock,
+	.unlock = vexpress_config_unlock,
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_read = vexpress_syscfg_reg_read,
+	.reg_write = vexpress_syscfg_reg_write,
+	.free_context = vexpress_syscfg_free_reg,
+	.reg_format_endian = REGMAP_ENDIAN_LITTLE,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
+};
+
+
+/* Non-DT hack, to be gone... */
+static struct vexpress_syscfg *vexpress_syscfg_not_of;
+
+struct regmap *devm_vexpress_syscfg_regmap_init(struct device *dev,
+		u32 site, u32 position, u32 dcc, u32 function, u32 device)
+{
+	struct vexpress_syscfg_reg *reg;
+
+	reg = vexpress_syscfg_alloc_reg(vexpress_syscfg_not_of,
+			site, position, dcc, 1);
+	if (!reg)
+		return NULL;
+
+	vexpress_syscfg_set_reg(reg, 0, function, device);
+
+	return devm_regmap_init(dev, NULL, reg, &vexpress_syscfg_regmap_config);
+}
+
+
+static int vexpress_syscfg_bridge_regmap_init(struct device *dev, void *context)
+{
+	struct vexpress_syscfg *syscfg = context;
+	int err;
+	u32 site, position, dcc;
+	struct property *prop;
+	int regs_num;
+	struct vexpress_syscfg_reg *reg;
+	const __be32 *val;
+	int i;
+	struct regmap *regmap;
+
+	if (!dev->of_node)
+		return -EINVAL;
+
+	err = vexpress_config_get_topo(dev->of_node, &site, &position, &dcc);
+	if (err)
+		return err;
+
+	prop = of_find_property(dev->of_node, "arm,vexpress-sysreg,func", NULL);
+	if (!prop)
+		return -EINVAL;
+
+	/* Each "register" is defined by two numbers - function and device */
+	regs_num = prop->length / sizeof(u32) / 2;
+	reg = vexpress_syscfg_alloc_reg(syscfg, site, position, dcc,
+			regs_num);
+	if (!reg)
+		return -ENOMEM;
+
+	for (i = 0, val = prop->value; i < regs_num; i++) {
+		u32 function = be32_to_cpup(val++);
+		u32 device = be32_to_cpup(val++);
+
+		vexpress_syscfg_set_reg(reg, i, function, device);
+	}
+	if (err)
+		return err;
+
+	vexpress_syscfg_regmap_config.max_register = regs_num - 1;
+	regmap = devm_regmap_init(dev, NULL, reg,
+			&vexpress_syscfg_regmap_config);
+	return IS_ERR(regmap) ? PTR_ERR(regmap) : 0;
+}
+
+int vexpress_syscfg_probe(struct platform_device *pdev)
+{
+	struct vexpress_syscfg *syscfg;
+	struct resource *res;
+	struct device *bridge;
+
+	syscfg = devm_kzalloc(&pdev->dev, sizeof(*syscfg), GFP_KERNEL);
+	if (!syscfg)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+			resource_size(res), pdev->name))
+		return -EBUSY;
+
+	syscfg->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!syscfg->base)
+		return -EFAULT;
+
+	bridge = vexpress_config_bridge_register(pdev->dev.parent,
+			vexpress_syscfg_bridge_regmap_init, syscfg);
+	if (IS_ERR(bridge))
+		return PTR_ERR(bridge);
+
+	if (!pdev->dev.of_node)
+		vexpress_syscfg_not_of = syscfg;
+
+	register_syscore_ops(&vexpress_syscfg_syscore_ops);
+
+	return 0;
+}
+
+static const struct platform_device_id vexpress_syscfg_id_table[] = {
+	{ "vexpress-syscfg", },
+	{},
+};
+
+static struct platform_driver vexpress_syscfg_driver = {
+	.driver.name = "vexpress-syscfg",
+	.id_table = vexpress_syscfg_id_table,
+	.probe = vexpress_syscfg_probe,
+};
+
+static int __init vexpress_syscfg_init(void)
+{
+	return platform_driver_register(&vexpress_syscfg_driver);
+}
+core_initcall(vexpress_syscfg_init);
diff --git a/include/linux/vexpress.h b/include/linux/vexpress.h
index 1b8889f..203f63a 100644
--- a/include/linux/vexpress.h
+++ b/include/linux/vexpress.h
@@ -16,6 +16,7 @@
 
 #include <linux/device.h>
 #include <linux/reboot.h>
+#include <linux/regmap.h>
 
 #define VEXPRESS_SITE_MB		0
 #define VEXPRESS_SITE_DB1		1
@@ -34,13 +35,6 @@
 #define VEXPRESS_GPIO_LED6		9
 #define VEXPRESS_GPIO_LED7		10
 
-#define VEXPRESS_RES_FUNC(_site, _func)	\
-{					\
-	.start = (_site),		\
-	.end = (_func),			\
-	.flags = IORESOURCE_BUS,	\
-}
-
 /* Config infrastructure */
 
 void vexpress_config_set_master(u32 site);
@@ -57,6 +51,9 @@ struct device *vexpress_config_bridge_register(struct device *parent,
 
 /* Platform control */
 
+struct regmap *devm_vexpress_syscfg_regmap_init(struct device *dev,
+               u32 site, u32 position, u32 dcc, u32 function, u32 device);
+
 u32 vexpress_get_procid(int site);
 u32 vexpress_get_hbi(int site);
 void *vexpress_get_24mhz_clock_base(void);
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [RFC 18/18] mfd: vexpress: Split sysreg functions into MFD cells
  2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
                   ` (18 preceding siblings ...)
  2013-12-23 16:23 ` [RFC 17/18] misc: Versatile Express System Config interface driver Pawel Moll
@ 2013-12-23 16:23 ` Pawel Moll
  2014-01-06 10:40   ` Lee Jones
  19 siblings, 1 reply; 47+ messages in thread
From: Pawel Moll @ 2013-12-23 16:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll

This patch splits individual sysreg functions into
separate MFD cells, which then become individual
platform devices with their own drivers.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
 .../devicetree/bindings/arm/vexpress-sysreg.txt    |  37 ++-
 arch/arm/boot/dts/vexpress-v2m-rs1.dtsi            |  76 ++++++-
 arch/arm/boot/dts/vexpress-v2m.dtsi                |  76 ++++++-
 arch/arm/mach-vexpress/v2m.c                       |  23 +-
 drivers/mfd/Kconfig                                |  11 +
 drivers/mfd/Makefile                               |   2 +-
 drivers/mfd/vexpress-sysreg.c                      | 247 +++++++++++++++------
 include/linux/vexpress.h                           |  16 +-
 8 files changed, 377 insertions(+), 111 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
index 5580e9c..8caefec6 100644
--- a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
+++ b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
@@ -8,6 +8,8 @@ interrupt generation, MMC and NOR Flash control etc.
 Required node properties:
 - compatible value : = "arm,vexpress,sysreg";
 - reg : physical base address and the size of the registers window
+
+Deprecated properties, replaced by GPIO subnodes (see below):
 - gpio-controller : specifies that the node is a GPIO controller
 - #gpio-cells : size of the GPIO specifier, should be 2:
   - first cell is the pseudo-GPIO line number:
@@ -16,12 +18,42 @@ Required node properties:
     2 - NOR FLASH WPn
   - second cell can take standard GPIO flags (currently ignored).
 
+Control registers providing pseudo-GPIO lines must be represented
+by subnodes, each of them requiring the following properties:
+- compatible value : one of
+			"arm,vexpress-sysreg,sys_led"
+			"arm,vexpress-sysreg,sys_mci"
+			"arm,vexpress-sysreg,sys_flash"
+- gpio-controller : makes the node a GPIO controller
+- #gpio-cells : size of the GPIO specifier, must be 2:
+  - first cell is the function number:
+    - for sys_led : 0..7 = LED 0..7
+    - for sys_mci : 0 = MMC CARDIN, 1 = MMC WPROT
+    - for sys_flash : 0 = NOR FLASH WPn
+  - second cell can take standard GPIO flags (currently ignored).
+
 Example:
 	v2m_sysreg: sysreg@10000000 {
  		compatible = "arm,vexpress-sysreg";
  		reg = <0x10000000 0x1000>;
-		gpio-controller;
-		#gpio-cells = <2>;
+
+		v2m_led_gpios: sys_led@08 {
+			compatible = "arm,vexpress-sysreg,sys_led";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		v2m_mmc_gpios: sys_mci@48 {
+			compatible = "arm,vexpress-sysreg,sys_mci";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		v2m_flash_gpios: sys_flash@4c {
+			compatible = "arm,vexpress-sysreg,sys_flash";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
  	};
 
 This block also can also act a bridge to the platform's configuration
@@ -41,6 +73,7 @@ property:
 
 Example:
 	mcc {
+		compatible = "arm,vexpress,config-bus";
 		arm,vexpress,config-bridge = <&v2m_sysreg>;
 
 		osc@0 {
diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
index ac870fb..756c986 100644
--- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
+++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
@@ -74,8 +74,24 @@
 			v2m_sysreg: sysreg@010000 {
 				compatible = "arm,vexpress-sysreg";
 				reg = <0x010000 0x1000>;
-				gpio-controller;
-				#gpio-cells = <2>;
+
+				v2m_led_gpios: sys_led@08 {
+					compatible = "arm,vexpress-sysreg,sys_led";
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+
+				v2m_mmc_gpios: sys_mci@48 {
+					compatible = "arm,vexpress-sysreg,sys_mci";
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+
+				v2m_flash_gpios: sys_flash@4c {
+					compatible = "arm,vexpress-sysreg,sys_flash";
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
 			};
 
 			v2m_sysctl: sysctl@020000 {
@@ -113,8 +129,8 @@
 				compatible = "arm,pl180", "arm,primecell";
 				reg = <0x050000 0x1000>;
 				interrupts = <9 10>;
-				cd-gpios = <&v2m_sysreg 0 0>;
-				wp-gpios = <&v2m_sysreg 1 0>;
+				cd-gpios = <&v2m_mmc_gpios 0 0>;
+				wp-gpios = <&v2m_mmc_gpios 1 0>;
 				max-frequency = <12000000>;
 				vmmc-supply = <&v2m_fixed_3v3>;
 				clocks = <&v2m_clk24mhz>, <&smbclk>;
@@ -265,6 +281,58 @@
 			clock-output-names = "v2m:refclk32khz";
 		};
 
+		leds {
+			compatible = "gpio-leds";
+
+			user@1 {
+				label = "v2m:green:user1";
+				gpios = <&v2m_led_gpios 0 0>;
+				linux,default-trigger = "heartbeat";
+			};
+
+			user@2 {
+				label = "v2m:green:user2";
+				gpios = <&v2m_led_gpios 1 0>;
+				linux,default-trigger = "mmc0";
+			};
+
+			user@3 {
+				label = "v2m:green:user3";
+				gpios = <&v2m_led_gpios 2 0>;
+				linux,default-trigger = "cpu0";
+			};
+
+			user@4 {
+				label = "v2m:green:user4";
+				gpios = <&v2m_led_gpios 3 0>;
+				linux,default-trigger = "cpu1";
+			};
+
+			user@5 {
+				label = "v2m:green:user5";
+				gpios = <&v2m_led_gpios 4 0>;
+				linux,default-trigger = "cpu2";
+			};
+
+			user@6 {
+				label = "v2m:green:user6";
+				gpios = <&v2m_led_gpios 5 0>;
+				linux,default-trigger = "cpu3";
+			};
+
+			user@7 {
+				label = "v2m:green:user7";
+				gpios = <&v2m_led_gpios 6 0>;
+				linux,default-trigger = "cpu4";
+			};
+
+			user@8 {
+				label = "v2m:green:user8";
+				gpios = <&v2m_led_gpios 7 0>;
+				linux,default-trigger = "cpu5";
+			};
+		};
+
 		mcc {
 			compatible = "arm,vexpress,config-bus";
 			arm,vexpress,config-bridge = <&v2m_sysreg>;
diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi
index f142036..ba856d6 100644
--- a/arch/arm/boot/dts/vexpress-v2m.dtsi
+++ b/arch/arm/boot/dts/vexpress-v2m.dtsi
@@ -73,8 +73,24 @@
 			v2m_sysreg: sysreg@00000 {
 				compatible = "arm,vexpress-sysreg";
 				reg = <0x00000 0x1000>;
-				gpio-controller;
-				#gpio-cells = <2>;
+
+				v2m_led_gpios: sys_led@08 {
+					compatible = "arm,vexpress-sysreg,sys_led";
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+
+				v2m_mmc_gpios: sys_mci@48 {
+					compatible = "arm,vexpress-sysreg,sys_mci";
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+
+				v2m_flash_gpios: sys_flash@4c {
+					compatible = "arm,vexpress-sysreg,sys_flash";
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
 			};
 
 			v2m_sysctl: sysctl@01000 {
@@ -112,8 +128,8 @@
 				compatible = "arm,pl180", "arm,primecell";
 				reg = <0x05000 0x1000>;
 				interrupts = <9 10>;
-				cd-gpios = <&v2m_sysreg 0 0>;
-				wp-gpios = <&v2m_sysreg 1 0>;
+				cd-gpios = <&v2m_mmc_gpios 0 0>;
+				wp-gpios = <&v2m_mmc_gpios 1 0>;
 				max-frequency = <12000000>;
 				vmmc-supply = <&v2m_fixed_3v3>;
 				clocks = <&v2m_clk24mhz>, <&smbclk>;
@@ -264,6 +280,58 @@
 			clock-output-names = "v2m:refclk32khz";
 		};
 
+		leds {
+			compatible = "gpio-leds";
+
+			user@1 {
+				label = "v2m:green:user1";
+				gpios = <&v2m_led_gpios 0 0>;
+				linux,default-trigger = "heartbeat";
+			};
+
+			user@2 {
+				label = "v2m:green:user2";
+				gpios = <&v2m_led_gpios 1 0>;
+				linux,default-trigger = "mmc0";
+			};
+
+			user@3 {
+				label = "v2m:green:user3";
+				gpios = <&v2m_led_gpios 2 0>;
+				linux,default-trigger = "cpu0";
+			};
+
+			user@4 {
+				label = "v2m:green:user4";
+				gpios = <&v2m_led_gpios 3 0>;
+				linux,default-trigger = "cpu1";
+			};
+
+			user@5 {
+				label = "v2m:green:user5";
+				gpios = <&v2m_led_gpios 4 0>;
+				linux,default-trigger = "cpu2";
+			};
+
+			user@6 {
+				label = "v2m:green:user6";
+				gpios = <&v2m_led_gpios 5 0>;
+				linux,default-trigger = "cpu3";
+			};
+
+			user@7 {
+				label = "v2m:green:user7";
+				gpios = <&v2m_led_gpios 6 0>;
+				linux,default-trigger = "cpu4";
+			};
+
+			user@8 {
+				label = "v2m:green:user8";
+				gpios = <&v2m_led_gpios 7 0>;
+				linux,default-trigger = "cpu5";
+			};
+		};
+
 		mcc {
 			compatible = "arm,vexpress,config-bus";
 			arm,vexpress,config-bridge = <&v2m_sysreg>;
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 325ae06..c39b14a 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -201,8 +201,9 @@ static struct platform_device v2m_cf_device = {
 
 static struct mmci_platform_data v2m_mmci_data = {
 	.ocr_mask	= MMC_VDD_32_33|MMC_VDD_33_34,
-	.gpio_wp	= VEXPRESS_GPIO_MMC_WPROT,
-	.gpio_cd	= VEXPRESS_GPIO_MMC_CARDIN,
+	.status		= vexpress_get_mci_cardin,
+	.gpio_cd	= -1,
+	.gpio_wp	= -1,
 };
 
 static struct resource v2m_sysreg_resources[] = {
@@ -394,23 +395,6 @@ void __init v2m_dt_map_io(void)
 		iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
 }
 
-void __init v2m_dt_init_early(void)
-{
-	u32 dt_hbi;
-
-	vexpress_sysreg_of_early_init();
-
-	/* Confirm board type against DT property, if available */
-	if (of_property_read_u32(of_allnodes, "arm,hbi", &dt_hbi) == 0) {
-		u32 hbi = vexpress_get_hbi(VEXPRESS_SITE_MASTER);
-
-		if (WARN_ON(dt_hbi != hbi))
-			pr_warning("vexpress: DT HBI (%x) is not matching "
-					"hardware (%x)!\n", dt_hbi, hbi);
-	}
-}
-
-
 static void __init v2m_dt_init(void)
 {
 	l2x0_of_init(0x00400000, 0xfe0fffff);
@@ -427,6 +411,5 @@ DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
 	.smp		= smp_ops(vexpress_smp_dt_ops),
 	.smp_init	= smp_init_ops(vexpress_smp_init_ops),
 	.map_io		= v2m_dt_map_io,
-	.init_early	= v2m_dt_init_early,
 	.init_machine	= v2m_dt_init,
 MACHINE_END
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 4c8cdc3..a4effd4 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1200,3 +1200,14 @@ config MCP_UCB1200_TS
 
 endmenu
 
+config MFD_VEXPRESS_SYSREG
+	bool "Versatile Express System Registers"
+	depends on VEXPRESS_CONFIG
+	default y
+	select CLKSRC_MMIO
+	select GPIO_GENERIC_PLATFORM
+	select MFD_CORE
+	select MFD_SYSCON
+	help
+	  System Registers are the platform configuration block
+	  on the ARM Ltd. Versatile Express board.
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 0277aa8..b6c9c32 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -159,7 +159,7 @@ obj-$(CONFIG_MFD_RC5T583)	+= rc5t583.o rc5t583-irq.o
 obj-$(CONFIG_MFD_SEC_CORE)	+= sec-core.o sec-irq.o
 obj-$(CONFIG_MFD_SYSCON)	+= syscon.o
 obj-$(CONFIG_MFD_LM3533)	+= lm3533-core.o lm3533-ctrlbank.o
-obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-sysreg.o
+obj-$(CONFIG_MFD_VEXPRESS_SYSREG)	+= vexpress-sysreg.o
 obj-$(CONFIG_MFD_RETU)		+= retu-mfd.o
 obj-$(CONFIG_MFD_AS3711)	+= as3711.o
 obj-$(CONFIG_MFD_AS3722)	+= as3722.o
diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c
index 31b3290..2258344 100644
--- a/drivers/mfd/vexpress-sysreg.c
+++ b/drivers/mfd/vexpress-sysreg.c
@@ -8,26 +8,24 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * Copyright (C) 2012 ARM Limited
+ * Copyright (C) 2013 ARM Limited
  */
 
+#include <linux/basic_mmio_gpio.h>
 #include <linux/err.h>
-#include <linux/gpio.h>
 #include <linux/io.h>
-#include <linux/leds.h>
+#include <linux/mfd/core.h>
 #include <linux/of_address.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
-#include <linux/regulator/driver.h>
 #include <linux/slab.h>
 #include <linux/stat.h>
-#include <linux/timer.h>
 #include <linux/vexpress.h>
 
 #define SYS_ID			0x000
 #define SYS_SW			0x004
 #define SYS_LED			0x008
 #define SYS_100HZ		0x024
-#define SYS_FLAGS		0x030
 #define SYS_FLAGSSET		0x030
 #define SYS_FLAGSCLR		0x034
 #define SYS_NVFLAGS		0x038
@@ -45,65 +43,34 @@
 #define SYS_CFGCTRL		0x0a4
 #define SYS_CFGSTAT		0x0a8
 
-#define SYS_HBI_MASK		0xfff
-#define SYS_ID_HBI_SHIFT	16
-#define SYS_PROCIDx_HBI_SHIFT	0
-
-#define SYS_LED_LED(n)		(1 << (n))
-
-#define SYS_MCI_CARDIN		(1 << 0)
-#define SYS_MCI_WPROT		(1 << 1)
-
-#define SYS_FLASH_WPn		(1 << 0)
-
 #define SYS_MISC_MASTERSITE	(1 << 14)
 
-#define SYS_CFGCTRL_START	(1 << 31)
-#define SYS_CFGCTRL_WRITE	(1 << 30)
-#define SYS_CFGCTRL_DCC(n)	(((n) & 0xf) << 26)
-#define SYS_CFGCTRL_FUNC(n)	(((n) & 0x3f) << 20)
-#define SYS_CFGCTRL_SITE(n)	(((n) & 0x3) << 16)
-#define SYS_CFGCTRL_POSITION(n)	(((n) & 0xf) << 12)
-#define SYS_CFGCTRL_DEVICE(n)	(((n) & 0xfff) << 0)
 
-#define SYS_CFGSTAT_ERR		(1 << 1)
-#define SYS_CFGSTAT_COMPLETE	(1 << 0)
+static int vexpress_sysreg_get_master(void __iomem *base)
+{
+	if (readl(base + SYS_MISC) & SYS_MISC_MASTERSITE)
+		return VEXPRESS_SITE_DB2;
 
+	return VEXPRESS_SITE_DB1;
+}
 
-static void __iomem *vexpress_sysreg_base;
 
+/* Non-DT case platform functions, to be gone... */
 
-void vexpress_flags_set(u32 data)
-{
-	writel(~0, vexpress_sysreg_base + SYS_FLAGSCLR);
-	writel(data, vexpress_sysreg_base + SYS_FLAGSSET);
-}
+static void __iomem *vexpress_sysreg_base;
 
 u32 vexpress_get_procid(int site)
 {
 	if (site == VEXPRESS_SITE_MASTER)
-		site = vexpress_config_get_master();
+		site = vexpress_sysreg_get_master(vexpress_sysreg_base);
 
 	return readl(vexpress_sysreg_base + (site == VEXPRESS_SITE_DB1 ?
 			SYS_PROCID0 : SYS_PROCID1));
 }
 
-u32 vexpress_get_hbi(int site)
+unsigned int vexpress_get_mci_cardin(struct device *dev)
 {
-	u32 id;
-
-	switch (site) {
-	case VEXPRESS_SITE_MB:
-		id = readl(vexpress_sysreg_base + SYS_ID);
-		return (id >> SYS_ID_HBI_SHIFT) & SYS_HBI_MASK;
-	case VEXPRESS_SITE_MASTER:
-	case VEXPRESS_SITE_DB1:
-	case VEXPRESS_SITE_DB2:
-		id = vexpress_get_procid(site);
-		return (id >> SYS_PROCIDx_HBI_SHIFT) & SYS_HBI_MASK;
-	}
-
-	return ~0;
+	return readl(vexpress_sysreg_base + SYS_MCI) & 1;
 }
 
 void __iomem *vexpress_get_24mhz_clock_base(void)
@@ -111,34 +78,184 @@ void __iomem *vexpress_get_24mhz_clock_base(void)
 	return vexpress_sysreg_base + SYS_24MHZ;
 }
 
-
-void vexpress_sysreg_setup(struct device_node *node)
+void __init vexpress_sysreg_early_init(void __iomem *base)
 {
-	if (WARN_ON(!vexpress_sysreg_base))
+	if (WARN_ON(!base))
 		return;
 
-	if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE)
-		vexpress_config_set_master(VEXPRESS_SITE_DB2);
+	vexpress_sysreg_base = base;
+
+	vexpress_config_set_master(vexpress_sysreg_get_master(base));
+}
+
+
+/* Versatile SMP boot protocol helper */
+
+void vexpress_flags_set(u32 data)
+{
+	struct device_node *node = of_find_compatible_node(NULL, NULL,
+			"arm,vexpress-sysreg");
+	void __iomem *base;
+
+	if (node)
+		base = of_iomap(node, 0);
 	else
-		vexpress_config_set_master(VEXPRESS_SITE_DB1);
+		base = vexpress_sysreg_base;
+
+	if (WARN_ON(!base))
+		return;
+
+	writel(~0, base + SYS_FLAGSCLR);
+	writel(data, base + SYS_FLAGSSET);
+
+	if (node)
+		iounmap(base);
 }
 
-void __init vexpress_sysreg_early_init(void __iomem *base)
+
+/* The sysreg block is just a random collection of various functions... */
+
+static const char vexpress_sysreg_sys_id_pdata[] = "sys_id";
+
+static struct bgpio_pdata vexpress_sysreg_sys_led_pdata = {
+	.label = "sys_led",
+	.base = -1,
+	.ngpio = 8,
+};
+
+static struct bgpio_pdata vexpress_sysreg_sys_mci_pdata = {
+	.label = "sys_mci",
+	.base = -1,
+	.ngpio = 2,
+};
+
+static struct bgpio_pdata vexpress_sysreg_sys_flash_pdata = {
+	.label = "sys_flash",
+	.base = -1,
+	.ngpio = 1,
+};
+
+static const char vexpress_sysreg_sys_misc_pdata[] = "sys_misc";
+
+static const char vexpress_sysreg_sys_procid_pdata[] = "sys_procid";
+
+static struct mfd_cell vexpress_sysreg_cells[] = {
+	{
+		.name = "syscon",
+		.of_compatible = "arm,vexpress-sysreg,sys_id",
+		.num_resources = 1,
+		.resources = (struct resource []) {
+			DEFINE_RES_MEM(SYS_ID, 0x4),
+		},
+		.platform_data = &vexpress_sysreg_sys_id_pdata,
+		.pdata_size = sizeof(vexpress_sysreg_sys_id_pdata),
+	}, {
+		.name = "basic-mmio-gpio",
+		.of_compatible = "arm,vexpress-sysreg,sys_led",
+		.num_resources = 1,
+		.resources = (struct resource []) {
+			DEFINE_RES_MEM_NAMED(SYS_LED, 0x4, "dat"),
+		},
+		.platform_data = &vexpress_sysreg_sys_led_pdata,
+		.pdata_size = sizeof(vexpress_sysreg_sys_led_pdata),
+	}, {
+		.name = "basic-mmio-gpio",
+		.of_compatible = "arm,vexpress-sysreg,sys_mci",
+		.num_resources = 1,
+		.resources = (struct resource []) {
+			DEFINE_RES_MEM_NAMED(SYS_MCI, 0x4, "dat"),
+		},
+		.platform_data = &vexpress_sysreg_sys_mci_pdata,
+		.pdata_size = sizeof(vexpress_sysreg_sys_mci_pdata),
+	}, {
+		.name = "basic-mmio-gpio",
+		.of_compatible = "arm,vexpress-sysreg,sys_flash",
+		.num_resources = 1,
+		.resources = (struct resource []) {
+			DEFINE_RES_MEM_NAMED(SYS_FLASH, 0x4, "dat"),
+		},
+		.platform_data = &vexpress_sysreg_sys_flash_pdata,
+		.pdata_size = sizeof(vexpress_sysreg_sys_flash_pdata),
+	}, {
+		.name = "syscon",
+		.num_resources = 1,
+		.resources = (struct resource []) {
+			DEFINE_RES_MEM(SYS_MISC, 0x4),
+		},
+		.platform_data = &vexpress_sysreg_sys_misc_pdata,
+		.pdata_size = sizeof(vexpress_sysreg_sys_misc_pdata),
+	}, {
+		.name = "syscon",
+		.num_resources = 1,
+		.resources = (struct resource []) {
+			DEFINE_RES_MEM(SYS_PROCID0, 0x8),
+		},
+		.platform_data = &vexpress_sysreg_sys_procid_pdata,
+		.pdata_size = sizeof(vexpress_sysreg_sys_procid_pdata),
+	}, {
+		.name = "vexpress-syscfg",
+		.num_resources = 1,
+		.resources = (struct resource []) {
+			DEFINE_RES_MEM(SYS_CFGDATA, 0xc),
+		},
+	}
+};
+
+static int vexpress_sysreg_probe(struct platform_device *pdev)
 {
-	vexpress_sysreg_base = base;
-	vexpress_sysreg_setup(NULL);
+	struct resource *mem;
+	void __iomem *base;
+	struct bgpio_chip *mmc_gpio_chip;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -EINVAL;
+
+	base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+	if (!base)
+		return -ENOMEM;
+
+	vexpress_config_set_master(vexpress_sysreg_get_master(base));
+
+	/*
+	 * Duplicated SYS_MCI pseudo-GPIO controller for compatibility with
+	 * older trees using sysreg node for MMC control lines.
+	 */
+	mmc_gpio_chip = devm_kzalloc(&pdev->dev, sizeof(*mmc_gpio_chip),
+			GFP_KERNEL);
+	if (!mmc_gpio_chip)
+		return -ENOMEM;
+	bgpio_init(mmc_gpio_chip, &pdev->dev, 0x4, base + SYS_MCI, NULL,
+			NULL, NULL, NULL, 0);
+	mmc_gpio_chip->gc.ngpio = 2;
+	gpiochip_add(&mmc_gpio_chip->gc);
+
+	return mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
+			vexpress_sysreg_cells,
+			ARRAY_SIZE(vexpress_sysreg_cells), mem, 0, 0);
 }
 
-void __init vexpress_sysreg_of_early_init(void)
+static const struct of_device_id vexpress_sysreg_match[] = {
+	{ .compatible = "arm,vexpress-sysreg", },
+	{},
+};
+
+static struct platform_driver vexpress_sysreg_driver = {
+	.driver = {
+		.name = "vexpress-sysreg",
+		.of_match_table = vexpress_sysreg_match,
+	},
+	.probe = vexpress_sysreg_probe,
+};
+
+static int __init vexpress_sysreg_init(void)
 {
 	struct device_node *node;
 
-	if (vexpress_sysreg_base)
-		return;
+	/* Need the sysreg early, before any other device... */
+	for_each_matching_node(node, vexpress_sysreg_match)
+		of_platform_device_create(node, NULL, NULL);
 
-	node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg");
-	if (node) {
-		vexpress_sysreg_base = of_iomap(node, 0);
-		vexpress_sysreg_setup(node);
-	}
+	return platform_driver_register(&vexpress_sysreg_driver);
 }
+core_initcall(vexpress_sysreg_init);
diff --git a/include/linux/vexpress.h b/include/linux/vexpress.h
index 203f63a..72dd902 100644
--- a/include/linux/vexpress.h
+++ b/include/linux/vexpress.h
@@ -23,18 +23,6 @@
 #define VEXPRESS_SITE_DB2		2
 #define VEXPRESS_SITE_MASTER		0xf
 
-#define VEXPRESS_GPIO_MMC_CARDIN	0
-#define VEXPRESS_GPIO_MMC_WPROT		1
-#define VEXPRESS_GPIO_FLASH_WPn		2
-#define VEXPRESS_GPIO_LED0		3
-#define VEXPRESS_GPIO_LED1		4
-#define VEXPRESS_GPIO_LED2		5
-#define VEXPRESS_GPIO_LED3		6
-#define VEXPRESS_GPIO_LED4		7
-#define VEXPRESS_GPIO_LED5		8
-#define VEXPRESS_GPIO_LED6		9
-#define VEXPRESS_GPIO_LED7		10
-
 /* Config infrastructure */
 
 void vexpress_config_set_master(u32 site);
@@ -55,12 +43,10 @@ struct regmap *devm_vexpress_syscfg_regmap_init(struct device *dev,
                u32 site, u32 position, u32 dcc, u32 function, u32 device);
 
 u32 vexpress_get_procid(int site);
-u32 vexpress_get_hbi(int site);
+unsigned int vexpress_get_mci_cardin(struct device *dev);
 void *vexpress_get_24mhz_clock_base(void);
 void vexpress_flags_set(u32 data);
-
 void vexpress_sysreg_early_init(void __iomem *base);
-void vexpress_sysreg_of_early_init(void);
 
 /* Clocks */
 
-- 
1.8.3.2



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [RFC 03/18] GPIO: gpio-generic: Add label to platform data
  2013-12-23 16:23 ` [RFC 03/18] GPIO: gpio-generic: Add label to platform data Pawel Moll
@ 2013-12-23 17:26   ` Linus Walleij
  2014-01-08 15:57     ` Pawel Moll
  0 siblings, 1 reply; 47+ messages in thread
From: Linus Walleij @ 2013-12-23 17:26 UTC (permalink / raw)
  To: Pawel Moll
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Alexandre Courbot,
	Anton Vorontsov

On Mon, Dec 23, 2013 at 5:23 PM, Pawel Moll <pawel.moll@arm.com> wrote:

> When registering more than one platform device, it is
> useful to set the gpio chip label in the platform data.
>
> Signed-off-by: Pawel Moll <pawel.moll@arm.com>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Alexandre Courbot <gnurou@gmail.com>
> Cc: Anton Vorontsov <anton@enomsg.org>

Good point. But what about also adding device tree support for
naming the chips while you're at it?

I imagine a generic gpiochip property in
Documentation/devicetree/bindings/gpio/gpio.txt

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 08/18] hwmon: vexpress: Use regmap instead of custom interface
  2013-12-23 16:23 ` [RFC 08/18] hwmon: vexpress: Use regmap instead of custom interface Pawel Moll
@ 2013-12-23 17:31   ` Guenter Roeck
  2014-01-08 15:57     ` Pawel Moll
  0 siblings, 1 reply; 47+ messages in thread
From: Guenter Roeck @ 2013-12-23 17:31 UTC (permalink / raw)
  To: Pawel Moll
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Jean Delvare, lm-sensors

On Mon, Dec 23, 2013 at 04:23:40PM +0000, Pawel Moll wrote:
> This patch makes the Versatile Express hwmon driver
> use regmap interface, instead of custom vexpress config
> one. It will request the regmap resource associated
> with the device, which makes it pretty much hardware
> agnostic.
> 
> Signed-off-by: Pawel Moll <pawel.moll@arm.com>
> Cc: Jean Delvare <khali@linux-fr.org>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: lm-sensors@lm-sensors.org
> ---
>  drivers/hwmon/Kconfig    |  3 ++-
>  drivers/hwmon/vexpress.c | 29 +++++++++++------------------
>  2 files changed, 13 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 52d548f..7747a47 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -1324,7 +1324,8 @@ config SENSORS_TWL4030_MADC
>  
>  config SENSORS_VEXPRESS
>  	tristate "Versatile Express"
> -	depends on VEXPRESS_CONFIG
> +	depends on ARM || ARM64
> +	depends on REGMAP
>  	help
>  	  This driver provides support for hardware sensors available on
>  	  the ARM Ltd's Versatile Express platform. It can provide wide
> diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c
> index d867e6b..b58cf1c 100644
> --- a/drivers/hwmon/vexpress.c
> +++ b/drivers/hwmon/vexpress.c
> @@ -22,11 +22,11 @@
>  #include <linux/of.h>
>  #include <linux/of_device.h>
>  #include <linux/platform_device.h>
> -#include <linux/vexpress.h>
> +#include <linux/regmap.h>
>  
>  struct vexpress_hwmon_data {
>  	struct device *hwmon_dev;
> -	struct vexpress_config_func *func;
> +	struct regmap *reg;
>  };
>  
>  static ssize_t vexpress_hwmon_name_show(struct device *dev,
> @@ -56,7 +56,7 @@ static ssize_t vexpress_hwmon_u32_show(struct device *dev,
>  	int err;
>  	u32 value;
>  
> -	err = vexpress_config_read(data->func, 0, &value);
> +	err = regmap_read(data->reg, 0, &value);
>  	if (err)
>  		return err;
>  
> @@ -69,13 +69,13 @@ static ssize_t vexpress_hwmon_u64_show(struct device *dev,
>  {
>  	struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
>  	int err;
> -	u32 value_hi, value_lo;
> +	unsigned int value_hi, value_lo;
>  
> -	err = vexpress_config_read(data->func, 0, &value_lo);
> +	err = regmap_read(data->reg, 0, &value_lo);
>  	if (err)
>  		return err;
>  
> -	err = vexpress_config_read(data->func, 1, &value_hi);
> +	err = regmap_read(data->reg, 1, &value_hi);
>  	if (err)
>  		return err;
>  
> @@ -175,26 +175,21 @@ static int vexpress_hwmon_probe(struct platform_device *pdev)
>  	if (!match)
>  		return -ENODEV;
>  
> -	data->func = vexpress_config_func_get_by_dev(&pdev->dev);
> -	if (!data->func)
> +	data->reg = dev_get_regmap(&pdev->dev, NULL);
> +	if (!data->reg)
>  		return -ENODEV;
>  
>  	err = sysfs_create_group(&pdev->dev.kobj, match->data);
>  	if (err)
> -		goto error;
> +		return err;
>  
>  	data->hwmon_dev = hwmon_device_register(&pdev->dev);
>  	if (IS_ERR(data->hwmon_dev)) {
> -		err = PTR_ERR(data->hwmon_dev);
> -		goto error;
> +		sysfs_remove_group(&pdev->dev.kobj, match->data);
> +		return PTR_ERR(data->hwmon_dev);

This change is unrelated and violates coding style. If the goto disturbs you,
I would suggest to convert the driver to use devm_hwmon_device_register_with_groups() 
in a separate patch and get rid of the error handling and the entire remove() function.

Thanks,
Guenter

>  	}
>  
>  	return 0;
> -
> -error:
> -	sysfs_remove_group(&pdev->dev.kobj, match->data);
> -	vexpress_config_func_put(data->func);
> -	return err;
>  }
>  
>  static int vexpress_hwmon_remove(struct platform_device *pdev)
> @@ -207,8 +202,6 @@ static int vexpress_hwmon_remove(struct platform_device *pdev)
>  	match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
>  	sysfs_remove_group(&pdev->dev.kobj, match->data);
>  
> -	vexpress_config_func_put(data->func);
> -
>  	return 0;
>  }
>  
> -- 
> 1.8.3.2
> 
> 
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 02/18] power/reset: vexpress: Use sched_clock as the time source
  2013-12-23 16:23 ` [RFC 02/18] power/reset: vexpress: Use sched_clock as the time source Pawel Moll
@ 2013-12-23 19:28   ` John Stultz
  2014-01-08 16:01     ` Pawel Moll
  0 siblings, 1 reply; 47+ messages in thread
From: John Stultz @ 2013-12-23 19:28 UTC (permalink / raw)
  To: Pawel Moll
  Cc: Linux Kernel Mailing List, linux-arm-kernel, Samuel Ortiz,
	Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Anton Vorontsov, David Woodhouse

On Mon, Dec 23, 2013 at 8:23 AM, Pawel Moll <pawel.moll@arm.com> wrote:
> At this stage of system shutdown procedure the jiffies may
> not be updated anymore, so have to base on raw sched_clock
> values.
>
> Signed-off-by: Pawel Moll <pawel.moll@arm.com>
> Cc: Anton Vorontsov <anton@enomsg.org>
> Cc: David Woodhouse <dwmw2@infradead.org>
> ---
>  drivers/power/reset/vexpress-poweroff.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c
> index 476aa49..d752233 100644
> --- a/drivers/power/reset/vexpress-poweroff.c
> +++ b/drivers/power/reset/vexpress-poweroff.c
> @@ -15,6 +15,7 @@
>  #include <linux/of.h>
>  #include <linux/of_device.h>
>  #include <linux/platform_device.h>
> +#include <linux/sched.h>
>  #include <linux/stat.h>
>  #include <linux/vexpress.h>
>
> @@ -27,12 +28,12 @@ static void vexpress_reset_do(struct device *dev, const char *what)
>                         vexpress_config_func_get_by_dev(dev);
>
>         if (func) {
> -               unsigned long timeout;
> +               unsigned long long timeout_ns;
>
>                 err = vexpress_config_write(func, 0, 0);
>
> -               timeout = jiffies + HZ;
> -               while (time_before(jiffies, timeout))
> +               timeout_ns = sched_clock() + 50000000;
> +               while (!err && time_before64(sched_clock(), timeout_ns))
>                         cpu_relax();
>         }

So this may not be a problem in this particular case, but sched_clock
could be backed by jiffies on some hardware, causing the same problem
to appear.

Might udelay/mdelay be a better fit for this sort of case (since
udelay may be counter backed, but may also be loop backed on hardware
without continuous counters)?

thanks
-john

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 12/18] clk: versatile: Split config options for sp810 and vexpress_osc
  2013-12-23 16:23 ` [RFC 12/18] clk: versatile: Split config options for sp810 and vexpress_osc Pawel Moll
@ 2013-12-23 20:05   ` Mike Turquette
  2014-01-08 16:06     ` Pawel Moll
  0 siblings, 1 reply; 47+ messages in thread
From: Mike Turquette @ 2013-12-23 20:05 UTC (permalink / raw)
  To: Pawel Moll, linux-kernel, linux-arm-kernel
  Cc: Samuel Ortiz, Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Pawel Moll

Quoting Pawel Moll (2013-12-23 08:23:44)
> Move the Kconfig entry for Versatile (& Express) clock drivers
> into a separate file and add individual options for sp810
> and vexpress_osc drivers, as they are optional in some
> configurations and may have separate dependencies.
> 
> Signed-off-by: Pawel Moll <pawel.moll@arm.com>
> Cc: Mike Turquette <mturquette@linaro.org>

Is there a reason to continue to expose these as user-visible config
options? I guess that with Device Tree we can just include clock nodes
(or not) for boards that use these clocks (or do not use them).

And it seems for many configurations COMMON_CLK_VERSATILE is always
selected, so what is the point of the other two sub-options?

Thanks,
Mike

> ---
>  drivers/clk/Kconfig            |  9 +--------
>  drivers/clk/versatile/Kconfig  | 26 ++++++++++++++++++++++++++
>  drivers/clk/versatile/Makefile |  5 +++--
>  3 files changed, 30 insertions(+), 10 deletions(-)
>  create mode 100644 drivers/clk/versatile/Kconfig
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 5c51115..f5486a4 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -40,14 +40,7 @@ config COMMON_CLK_WM831X
>            Supports the clocking subsystem of the WM831x/2x series of
>           PMICs from Wolfson Microlectronics.
>  
> -config COMMON_CLK_VERSATILE
> -       bool "Clock driver for ARM Reference designs"
> -       depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS || ARM64
> -       ---help---
> -          Supports clocking on ARM Reference designs:
> -         - Integrator/AP and Integrator/CP
> -         - RealView PB1176, EB, PB11MP and PBX
> -         - Versatile Express
> +source "drivers/clk/versatile/Kconfig"
>  
>  config COMMON_CLK_MAX77686
>         tristate "Clock driver for Maxim 77686 MFD"
> diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig
> new file mode 100644
> index 0000000..1530c93
> --- /dev/null
> +++ b/drivers/clk/versatile/Kconfig
> @@ -0,0 +1,26 @@
> +config COMMON_CLK_VERSATILE
> +       bool "Clock driver for ARM Reference designs"
> +       depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS || ARM64
> +       ---help---
> +          Supports clocking on ARM Reference designs:
> +         - Integrator/AP and Integrator/CP
> +         - RealView PB1176, EB, PB11MP and PBX
> +         - Versatile Express
> +
> +config CLK_SP810
> +       bool "Clock driver for ARM SP810 System Controller"
> +       depends on COMMON_CLK_VERSATILE
> +       default y if ARCH_VEXPRESS
> +       ---help---
> +         Supports clock muxing (REFCLK/TIMCLK to TIMERCLKEN0-3) capabilities
> +         of the ARM SP810 System Controller cell.
> +
> +config CLK_VEXPRESS_OSC
> +       bool "Clock driver for Versatile Express OSC clock generators"
> +       depends on COMMON_CLK_VERSATILE
> +       depends on VEXPRESS_CONFIG
> +       default y if ARCH_VEXPRESS
> +       ---help---
> +         Simple regmap-based driver driving clock generators on Versatile
> +         Express platforms hidden behind its configuration infrastructure,
> +         commonly known as OSCs.
> diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile
> index c16ca78..fd449f9 100644
> --- a/drivers/clk/versatile/Makefile
> +++ b/drivers/clk/versatile/Makefile
> @@ -3,5 +3,6 @@ obj-$(CONFIG_ICST)              += clk-icst.o
>  obj-$(CONFIG_ARCH_INTEGRATOR)  += clk-integrator.o
>  obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o
>  obj-$(CONFIG_ARCH_REALVIEW)    += clk-realview.o
> -obj-$(CONFIG_ARCH_VEXPRESS)    += clk-vexpress.o clk-sp810.o
> -obj-$(CONFIG_VEXPRESS_CONFIG)  += clk-vexpress-osc.o
> +obj-$(CONFIG_ARCH_VEXPRESS)    += clk-vexpress.o
> +obj-$(CONFIG_CLK_SP810)                += clk-sp810.o
> +obj-$(CONFIG_CLK_VEXPRESS_OSC) += clk-vexpress-osc.o
> -- 
> 1.8.3.2
> 
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 07/18] regmap: debugfs: Always create "registers" & "access" files
  2013-12-23 16:23 ` [RFC 07/18] regmap: debugfs: Always create "registers" & "access" files Pawel Moll
@ 2013-12-24 12:19   ` Mark Brown
  2014-01-08 17:31     ` Pawel Moll
  0 siblings, 1 reply; 47+ messages in thread
From: Mark Brown @ 2013-12-24 12:19 UTC (permalink / raw)
  To: Pawel Moll
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Greg Kroah-Hartman

On Mon, Dec 23, 2013 at 04:23:39PM +0000, Pawel Moll wrote:
> When a map covers a single register, max_register is equal
> to 0, so the "registers" & "access" files were not created.
> 
> This patch is removing this restriction. It should be save,
> as the maps not without register 0 should return false
> for regmap_readable(map, 0).

No, we need to find a better way of doing this such as checking to see
if register zero is accessible in some way.  We want to avoid having
those files if there's no way of populating them since this is useful
information for tooling.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 10/18] regulator: vexpress: Use regmap instead of custom interface
  2013-12-23 16:23 ` [RFC 10/18] regulator: " Pawel Moll
@ 2013-12-24 12:24   ` Mark Brown
  2014-01-08 18:25     ` Pawel Moll
  0 siblings, 1 reply; 47+ messages in thread
From: Mark Brown @ 2013-12-24 12:24 UTC (permalink / raw)
  To: Pawel Moll
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Liam Girdwood

On Mon, Dec 23, 2013 at 04:23:42PM +0000, Pawel Moll wrote:

> This patch makes the Versatile Express regulator driver
> use regmap interface, instead of custom vexpress config
> one. It will request the regmap resource associated
> with the device, which makes it pretty much hardware
> agnostic.

If this change is making the operations hardware agnostic regmap based
ones then they should be being either replaced with standard operations
or standard operations being added.  It looks like you should be able to
use the existing linear map operations.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 06/18] regmap: Formalise use of non-bus context
  2013-12-23 16:23 ` [RFC 06/18] regmap: Formalise use of non-bus context Pawel Moll
@ 2013-12-24 12:45   ` Mark Brown
  2014-01-09 13:08     ` Pawel Moll
  0 siblings, 1 reply; 47+ messages in thread
From: Mark Brown @ 2013-12-24 12:45 UTC (permalink / raw)
  To: Pawel Moll
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Greg Kroah-Hartman

On Mon, Dec 23, 2013 at 04:23:38PM +0000, Pawel Moll wrote:

I'd note that I wasn't CCed on most of this series so I'm not entirely
sure what it's trying to do.

> Bus-less maps (ones with reg_read and reg_write functions
> defined in regmap_config) were given the context passed
> in regmap_init(), but it was still called "bus_context".
> 
> This patch formalises this aspect by renaming it to simple
> "context" and adds the missing link, free_context function
> in regmap_config, which allows bus-less maps to use the
> context in classic way.

This should be two patches, one patch to do the rename and one to add
the operation.  The obvious question here is why is this callback useful
- what is being allocated in a regmap specific context that needs to be
lifetime managed separately to the thing doing the creation?  I can't
see any obvious reason why this would ever get used.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 01/18] mfd: syscon: Consider platform data a regmap config name
  2013-12-23 16:23 ` [RFC 01/18] mfd: syscon: Consider platform data a regmap config name Pawel Moll
@ 2014-01-06  9:48   ` Lee Jones
  2014-01-06 10:20     ` Lee Jones
  0 siblings, 1 reply; 47+ messages in thread
From: Lee Jones @ 2014-01-06  9:48 UTC (permalink / raw)
  To: Pawel Moll
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson

> Use the device platform data as a regmap config
> name. This is particularly useful in the regmap
> debugfs when there is more than one syscon device
> registered, to distinguish the register blocks.
> 
> Signed-off-by: Pawel Moll <pawel.moll@arm.com>
> Cc: Samuel Ortiz <sameo@linux.intel.com>
> Cc: Lee Jones <lee.jones@linaro.org>
> ---
>  drivers/mfd/syscon.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
> index 71841f9..ea1770b 100644
> --- a/drivers/mfd/syscon.c
> +++ b/drivers/mfd/syscon.c
> @@ -143,6 +143,7 @@ static int syscon_probe(struct platform_device *pdev)
>  		return -ENOMEM;
>  
>  	syscon_regmap_config.max_register = res->end - res->start - 3;
> +	syscon_regmap_config.name = dev_get_platdata(&pdev->dev);
>  	syscon->regmap = devm_regmap_init_mmio(dev, base,
>  					&syscon_regmap_config);
>  	if (IS_ERR(syscon->regmap)) {

This smells a bit fishy to me. Can you point me to the piece of code
or patch where you set the platform_data pointer as a string?

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 01/18] mfd: syscon: Consider platform data a regmap config name
  2014-01-06  9:48   ` Lee Jones
@ 2014-01-06 10:20     ` Lee Jones
  0 siblings, 0 replies; 47+ messages in thread
From: Lee Jones @ 2014-01-06 10:20 UTC (permalink / raw)
  To: Pawel Moll
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson

On Mon, 06 Jan 2014, Lee Jones wrote:

> > Use the device platform data as a regmap config
> > name. This is particularly useful in the regmap
> > debugfs when there is more than one syscon device
> > registered, to distinguish the register blocks.
> > 
> > Signed-off-by: Pawel Moll <pawel.moll@arm.com>
> > Cc: Samuel Ortiz <sameo@linux.intel.com>
> > Cc: Lee Jones <lee.jones@linaro.org>
> > ---
> >  drivers/mfd/syscon.c | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
> > index 71841f9..ea1770b 100644
> > --- a/drivers/mfd/syscon.c
> > +++ b/drivers/mfd/syscon.c
> > @@ -143,6 +143,7 @@ static int syscon_probe(struct platform_device *pdev)
> >  		return -ENOMEM;
> >  
> >  	syscon_regmap_config.max_register = res->end - res->start - 3;
> > +	syscon_regmap_config.name = dev_get_platdata(&pdev->dev);
> >  	syscon->regmap = devm_regmap_init_mmio(dev, base,
> >  					&syscon_regmap_config);
> >  	if (IS_ERR(syscon->regmap)) {
> 
> This smells a bit fishy to me. Can you point me to the piece of code
> or patch where you set the platform_data pointer as a string?

Scrap that, I see it.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 18/18] mfd: vexpress: Split sysreg functions into MFD cells
  2013-12-23 16:23 ` [RFC 18/18] mfd: vexpress: Split sysreg functions into MFD cells Pawel Moll
@ 2014-01-06 10:40   ` Lee Jones
  2014-01-08 16:17     ` Pawel Moll
  0 siblings, 1 reply; 47+ messages in thread
From: Lee Jones @ 2014-01-06 10:40 UTC (permalink / raw)
  To: Pawel Moll
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson

> This patch splits individual sysreg functions into
> separate MFD cells, which then become individual
> platform devices with their own drivers.
> 
> Signed-off-by: Pawel Moll <pawel.moll@arm.com>
> ---
>  .../devicetree/bindings/arm/vexpress-sysreg.txt    |  37 ++-
>  arch/arm/boot/dts/vexpress-v2m-rs1.dtsi            |  76 ++++++-
>  arch/arm/boot/dts/vexpress-v2m.dtsi                |  76 ++++++-
>  arch/arm/mach-vexpress/v2m.c                       |  23 +-
>  drivers/mfd/Kconfig                                |  11 +
>  drivers/mfd/Makefile                               |   2 +-
>  drivers/mfd/vexpress-sysreg.c                      | 247 +++++++++++++++------
>  include/linux/vexpress.h                           |  16 +-
>  8 files changed, 377 insertions(+), 111 deletions(-)

<snip>

> +static struct mfd_cell vexpress_sysreg_cells[] = {
> +	{
> +		.name = "syscon",
> +		.of_compatible = "arm,vexpress-sysreg,sys_id",
> +		.num_resources = 1,
> +		.resources = (struct resource []) {
> +			DEFINE_RES_MEM(SYS_ID, 0x4),
> +		},
> +		.platform_data = &vexpress_sysreg_sys_id_pdata,
> +		.pdata_size = sizeof(vexpress_sysreg_sys_id_pdata),

Not sure how comfortable I am with using Device Tree and populating
platform_data with information which by the looks of it you're
planning to make persistent. What's stopping you from using a DT
property to name the block, or better yet, just use the compatible
string? Also, won't naming these blocks in DT also aid other OSes?

<snip>

> +static int vexpress_sysreg_probe(struct platform_device *pdev)
>  {
> -	vexpress_sysreg_base = base;
> -	vexpress_sysreg_setup(NULL);
> +	struct resource *mem;
> +	void __iomem *base;
> +	struct bgpio_chip *mmc_gpio_chip;
> +
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!mem)
> +		return -EINVAL;
> +
> +	base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
> +	if (!base)
> +		return -ENOMEM;
> +
> +	vexpress_config_set_master(vexpress_sysreg_get_master(base));
> +
> +	/*
> +	 * Duplicated SYS_MCI pseudo-GPIO controller for compatibility with
> +	 * older trees using sysreg node for MMC control lines.
> +	 */
> +	mmc_gpio_chip = devm_kzalloc(&pdev->dev, sizeof(*mmc_gpio_chip),
> +			GFP_KERNEL);
> +	if (!mmc_gpio_chip)
> +		return -ENOMEM;
> +	bgpio_init(mmc_gpio_chip, &pdev->dev, 0x4, base + SYS_MCI, NULL,
> +			NULL, NULL, NULL, 0);
> +	mmc_gpio_chip->gc.ngpio = 2;
> +	gpiochip_add(&mmc_gpio_chip->gc);
> +
> +	return mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
> +			vexpress_sysreg_cells,
> +			ARRAY_SIZE(vexpress_sysreg_cells), mem, 0, 0);

Don't use 0 as NULL, you will cause a sparse error.

<snip>

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 03/18] GPIO: gpio-generic: Add label to platform data
  2013-12-23 17:26   ` Linus Walleij
@ 2014-01-08 15:57     ` Pawel Moll
  2014-01-14 10:30       ` Linus Walleij
  0 siblings, 1 reply; 47+ messages in thread
From: Pawel Moll @ 2014-01-08 15:57 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Alexandre Courbot,
	Anton Vorontsov

Greetings (and the usual: Happy New Year!)

On Mon, 2013-12-23 at 17:26 +0000, Linus Walleij wrote:
> On Mon, Dec 23, 2013 at 5:23 PM, Pawel Moll <pawel.moll@arm.com> wrote:
> 
> > When registering more than one platform device, it is
> > useful to set the gpio chip label in the platform data.
> >
> > Signed-off-by: Pawel Moll <pawel.moll@arm.com>
> > Cc: Linus Walleij <linus.walleij@linaro.org>
> > Cc: Alexandre Courbot <gnurou@gmail.com>
> > Cc: Anton Vorontsov <anton@enomsg.org>
> 
> Good point. But what about also adding device tree support for
> naming the chips while you're at it?
> 
> I imagine a generic gpiochip property in
> Documentation/devicetree/bindings/gpio/gpio.txt

Well, this has been discussed almost to death already (as you may
remember ;-) in the thread:

http://www.spinics.net/lists/devicetree/msg00072.html

(only portions survived)

Although I was in favour of the generic binding (as were you if I
remember correctly), the final non-conclusion was not to open the
"generic door". Fair enough with me, I went the defined-in-code way
here...

Paweł


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 08/18] hwmon: vexpress: Use regmap instead of custom interface
  2013-12-23 17:31   ` Guenter Roeck
@ 2014-01-08 15:57     ` Pawel Moll
  0 siblings, 0 replies; 47+ messages in thread
From: Pawel Moll @ 2014-01-08 15:57 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Jean Delvare, lm-sensors

On Mon, 2013-12-23 at 17:31 +0000, Guenter Roeck wrote:
> On Mon, Dec 23, 2013 at 04:23:40PM +0000, Pawel Moll wrote:
> > This patch makes the Versatile Express hwmon driver
> > use regmap interface, instead of custom vexpress config
> > one. It will request the regmap resource associated
> > with the device, which makes it pretty much hardware
> > agnostic.
> > 
> > Signed-off-by: Pawel Moll <pawel.moll@arm.com>
> > Cc: Jean Delvare <khali@linux-fr.org>
> > Cc: Guenter Roeck <linux@roeck-us.net>
> > Cc: lm-sensors@lm-sensors.org
> > ---
> >  drivers/hwmon/Kconfig    |  3 ++-
> >  drivers/hwmon/vexpress.c | 29 +++++++++++------------------
> >  2 files changed, 13 insertions(+), 19 deletions(-)
> > 
> > diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> > index 52d548f..7747a47 100644
> > --- a/drivers/hwmon/Kconfig
> > +++ b/drivers/hwmon/Kconfig
> > @@ -1324,7 +1324,8 @@ config SENSORS_TWL4030_MADC
> >  
> >  config SENSORS_VEXPRESS
> >  	tristate "Versatile Express"
> > -	depends on VEXPRESS_CONFIG
> > +	depends on ARM || ARM64
> > +	depends on REGMAP
> >  	help
> >  	  This driver provides support for hardware sensors available on
> >  	  the ARM Ltd's Versatile Express platform. It can provide wide
> > diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c
> > index d867e6b..b58cf1c 100644
> > --- a/drivers/hwmon/vexpress.c
> > +++ b/drivers/hwmon/vexpress.c
> > @@ -22,11 +22,11 @@
> >  #include <linux/of.h>
> >  #include <linux/of_device.h>
> >  #include <linux/platform_device.h>
> > -#include <linux/vexpress.h>
> > +#include <linux/regmap.h>
> >  
> >  struct vexpress_hwmon_data {
> >  	struct device *hwmon_dev;
> > -	struct vexpress_config_func *func;
> > +	struct regmap *reg;
> >  };
> >  
> >  static ssize_t vexpress_hwmon_name_show(struct device *dev,
> > @@ -56,7 +56,7 @@ static ssize_t vexpress_hwmon_u32_show(struct device *dev,
> >  	int err;
> >  	u32 value;
> >  
> > -	err = vexpress_config_read(data->func, 0, &value);
> > +	err = regmap_read(data->reg, 0, &value);
> >  	if (err)
> >  		return err;
> >  
> > @@ -69,13 +69,13 @@ static ssize_t vexpress_hwmon_u64_show(struct device *dev,
> >  {
> >  	struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
> >  	int err;
> > -	u32 value_hi, value_lo;
> > +	unsigned int value_hi, value_lo;
> >  
> > -	err = vexpress_config_read(data->func, 0, &value_lo);
> > +	err = regmap_read(data->reg, 0, &value_lo);
> >  	if (err)
> >  		return err;
> >  
> > -	err = vexpress_config_read(data->func, 1, &value_hi);
> > +	err = regmap_read(data->reg, 1, &value_hi);
> >  	if (err)
> >  		return err;
> >  
> > @@ -175,26 +175,21 @@ static int vexpress_hwmon_probe(struct platform_device *pdev)
> >  	if (!match)
> >  		return -ENODEV;
> >  
> > -	data->func = vexpress_config_func_get_by_dev(&pdev->dev);
> > -	if (!data->func)
> > +	data->reg = dev_get_regmap(&pdev->dev, NULL);
> > +	if (!data->reg)
> >  		return -ENODEV;
> >  
> >  	err = sysfs_create_group(&pdev->dev.kobj, match->data);
> >  	if (err)
> > -		goto error;
> > +		return err;
> >  
> >  	data->hwmon_dev = hwmon_device_register(&pdev->dev);
> >  	if (IS_ERR(data->hwmon_dev)) {
> > -		err = PTR_ERR(data->hwmon_dev);
> > -		goto error;
> > +		sysfs_remove_group(&pdev->dev.kobj, match->data);
> > +		return PTR_ERR(data->hwmon_dev);
> 
> This change is unrelated and violates coding style. If the goto disturbs you,
> I would suggest to convert the driver to use devm_hwmon_device_register_with_groups() 
> in a separate patch and get rid of the error handling and the entire remove() function.

Ok, will do, thanks!

Paweł


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 02/18] power/reset: vexpress: Use sched_clock as the time source
  2013-12-23 19:28   ` John Stultz
@ 2014-01-08 16:01     ` Pawel Moll
  0 siblings, 0 replies; 47+ messages in thread
From: Pawel Moll @ 2014-01-08 16:01 UTC (permalink / raw)
  To: John Stultz
  Cc: Linux Kernel Mailing List, linux-arm-kernel, Samuel Ortiz,
	Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Anton Vorontsov, David Woodhouse

On Mon, 2013-12-23 at 19:28 +0000, John Stultz wrote:
> On Mon, Dec 23, 2013 at 8:23 AM, Pawel Moll <pawel.moll@arm.com> wrote:
> > At this stage of system shutdown procedure the jiffies may
> > not be updated anymore, so have to base on raw sched_clock
> > values.
> >
> > Signed-off-by: Pawel Moll <pawel.moll@arm.com>
> > Cc: Anton Vorontsov <anton@enomsg.org>
> > Cc: David Woodhouse <dwmw2@infradead.org>
> > ---
> >  drivers/power/reset/vexpress-poweroff.c | 7 ++++---
> >  1 file changed, 4 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c
> > index 476aa49..d752233 100644
> > --- a/drivers/power/reset/vexpress-poweroff.c
> > +++ b/drivers/power/reset/vexpress-poweroff.c
> > @@ -15,6 +15,7 @@
> >  #include <linux/of.h>
> >  #include <linux/of_device.h>
> >  #include <linux/platform_device.h>
> > +#include <linux/sched.h>
> >  #include <linux/stat.h>
> >  #include <linux/vexpress.h>
> >
> > @@ -27,12 +28,12 @@ static void vexpress_reset_do(struct device *dev, const char *what)
> >                         vexpress_config_func_get_by_dev(dev);
> >
> >         if (func) {
> > -               unsigned long timeout;
> > +               unsigned long long timeout_ns;
> >
> >                 err = vexpress_config_write(func, 0, 0);
> >
> > -               timeout = jiffies + HZ;
> > -               while (time_before(jiffies, timeout))
> > +               timeout_ns = sched_clock() + 50000000;
> > +               while (!err && time_before64(sched_clock(), timeout_ns))
> >                         cpu_relax();
> >         }
> 
> So this may not be a problem in this particular case, but sched_clock
> could be backed by jiffies on some hardware, causing the same problem
> to appear.

Uh, right. As you guessed, on vexpress sched_clock, once registered, is
always available. But of course I shouldn't fully rely on this.

> Might udelay/mdelay be a better fit for this sort of case (since
> udelay may be counter backed, but may also be loop backed on hardware
> without continuous counters)?

I'm sure I though about udelay, but for some reason decided against it.
The reason may be already invalid, so I'll check it again :-)

Thanks!

Paweł


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 12/18] clk: versatile: Split config options for sp810 and vexpress_osc
  2013-12-23 20:05   ` Mike Turquette
@ 2014-01-08 16:06     ` Pawel Moll
  0 siblings, 0 replies; 47+ messages in thread
From: Pawel Moll @ 2014-01-08 16:06 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson

On Mon, 2013-12-23 at 20:05 +0000, Mike Turquette wrote:
> Quoting Pawel Moll (2013-12-23 08:23:44)
> > Move the Kconfig entry for Versatile (& Express) clock drivers
> > into a separate file and add individual options for sp810
> > and vexpress_osc drivers, as they are optional in some
> > configurations and may have separate dependencies.
> > 
> > Signed-off-by: Pawel Moll <pawel.moll@arm.com>
> > Cc: Mike Turquette <mturquette@linaro.org>
> 
> Is there a reason to continue to expose these as user-visible config
> options? I guess that with Device Tree we can just include clock nodes
> (or not) for boards that use these clocks (or do not use them).
>
> And it seems for many configurations COMMON_CLK_VERSATILE is always
> selected, so what is the point of the other two sub-options?

It's mostly for arm64, where all the bits and pieces are individually
selected (and SP810 is not present in some vexpress configurations).

Paweł


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 18/18] mfd: vexpress: Split sysreg functions into MFD cells
  2014-01-06 10:40   ` Lee Jones
@ 2014-01-08 16:17     ` Pawel Moll
  0 siblings, 0 replies; 47+ messages in thread
From: Pawel Moll @ 2014-01-08 16:17 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson

On Mon, 2014-01-06 at 10:40 +0000, Lee Jones wrote:
> > +static struct mfd_cell vexpress_sysreg_cells[] = {
> > +	{
> > +		.name = "syscon",
> > +		.of_compatible = "arm,vexpress-sysreg,sys_id",
> > +		.num_resources = 1,
> > +		.resources = (struct resource []) {
> > +			DEFINE_RES_MEM(SYS_ID, 0x4),
> > +		},
> > +		.platform_data = &vexpress_sysreg_sys_id_pdata,
> > +		.pdata_size = sizeof(vexpress_sysreg_sys_id_pdata),
> 
> Not sure how comfortable I am with using Device Tree and populating
> platform_data with information which by the looks of it you're
> planning to make persistent. What's stopping you from using a DT
> property to name the block, or better yet, just use the compatible
> string? Also, won't naming these blocks in DT also aid other OSes?

Right. This particular of_compatible string in the *_cells is a leftover
from previous versions of the patch. Only the gpio-related ones, as
mentioned in the example:

>  Example:
>         v2m_sysreg: sysreg@10000000 {
>                 compatible = "arm,vexpress-sysreg";
>                 reg = <0x10000000 0x1000>;
> -               gpio-controller;
> -               #gpio-cells = <2>;
> +
> +               v2m_led_gpios: sys_led@08 {
> +                       compatible = "arm,vexpress-sysreg,sys_led";
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +               };
> +
> +               v2m_mmc_gpios: sys_mci@48 {
> +                       compatible = "arm,vexpress-sysreg,sys_mci";
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +               };
> +
> +               v2m_flash_gpios: sys_flash@4c {
> +                       compatible = "arm,vexpress-sysreg,sys_flash";
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +               };
>         };

are supposed for the sake the gpio users (and some of them don't exist
in some version of the sysregs).

> > +	return mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
> > +			vexpress_sysreg_cells,
> > +			ARRAY_SIZE(vexpress_sysreg_cells), mem, 0, 0);
> 
> Don't use 0 as NULL, you will cause a sparse error.

... and rightly so! ;-) Well spotted, thanks!

Paweł


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 04/18] driver core & of: Mark of_nodes of added device as populated
  2013-12-23 16:23 ` [RFC 04/18] driver core & of: Mark of_nodes of added device as populated Pawel Moll
@ 2014-01-08 17:28   ` Rob Herring
  2014-01-16 17:03     ` Grant Likely
  0 siblings, 1 reply; 47+ messages in thread
From: Rob Herring @ 2014-01-08 17:28 UTC (permalink / raw)
  To: Pawel Moll
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Greg Kroah-Hartman,
	Grant Likely, Rob Herring, devicetree

On Mon, Dec 23, 2013 at 10:23 AM, Pawel Moll <pawel.moll@arm.com> wrote:
> In "Device Tree powered" systems, platform devices are usually
> massively populated with of_platform_populate() call, executed
> at some level of initcalls, either by generic architecture
> or by platform-specific code.
>
> There are situations though where certain devices must be
> created (and bound with drivers) before all the others.
> This presents small challenge in DT-driven systems, as
> devices explicitly created in early code would be created
> again by of_platform_populate().

Isn't this already at least partially solved with the aux data
support? I'm guessing the difference here is how the early device is
created.

> This patch tries to solve that issue in a generic way,
> adding a "populated" flag which is set in the device_node
> structure when a device is being created in the core.
> Later, of_platform_populate() skips such nodes (and
> its children) in a similar way to the non-available ones.

Couldn't you store a struct device ptr in struct device_node instead?

In any case I'd like to see this contained within the DT code. I don't
see why the driver core needs to be modified for a DT specific
problem.

Rob

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 07/18] regmap: debugfs: Always create "registers" & "access" files
  2013-12-24 12:19   ` Mark Brown
@ 2014-01-08 17:31     ` Pawel Moll
  2014-01-08 18:00       ` Mark Brown
  0 siblings, 1 reply; 47+ messages in thread
From: Pawel Moll @ 2014-01-08 17:31 UTC (permalink / raw)
  To: Mark Brown
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Greg Kroah-Hartman

On Tue, 2013-12-24 at 12:19 +0000, Mark Brown wrote:
> On Mon, Dec 23, 2013 at 04:23:39PM +0000, Pawel Moll wrote:
> > When a map covers a single register, max_register is equal
> > to 0, so the "registers" & "access" files were not created.
> > 
> > This patch is removing this restriction. It should be save,
> > as the maps not without register 0 should return false
> > for regmap_readable(map, 0).
> 
> No, we need to find a better way of doing this such as checking to see
> if register zero is accessible in some way.  We want to avoid having
> those files if there's no way of populating them since this is useful
> information for tooling.

Something like this then?

diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index c5471cd..45d812c 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -511,7 +511,7 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
 	debugfs_create_file("range", 0400, map->debugfs,
 			    map, &regmap_reg_ranges_fops);
 
-	if (map->max_register) {
+	if (map->max_register || regmap_readable(map, 0)) {
 		debugfs_create_file("registers", 0400, map->debugfs,
 				    map, &regmap_map_fops);
 		debugfs_create_file("access", 0400, map->debugfs,

Other possibility would be replacing max_register with registers_num,
but it looks a massive job...

Paweł


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [RFC 07/18] regmap: debugfs: Always create "registers" & "access" files
  2014-01-08 17:31     ` Pawel Moll
@ 2014-01-08 18:00       ` Mark Brown
  0 siblings, 0 replies; 47+ messages in thread
From: Mark Brown @ 2014-01-08 18:00 UTC (permalink / raw)
  To: Pawel Moll
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Greg Kroah-Hartman

[-- Attachment #1: Type: text/plain, Size: 906 bytes --]

On Wed, Jan 08, 2014 at 05:31:37PM +0000, Pawel Moll wrote:
> On Tue, 2013-12-24 at 12:19 +0000, Mark Brown wrote:

> > No, we need to find a better way of doing this such as checking to see
> > if register zero is accessible in some way.  We want to avoid having
> > those files if there's no way of populating them since this is useful
> > information for tooling.

> Something like this then?

> diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
> index c5471cd..45d812c 100644
> --- a/drivers/base/regmap/regmap-debugfs.c
> +++ b/drivers/base/regmap/regmap-debugfs.c
> @@ -511,7 +511,7 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
>  	debugfs_create_file("range", 0400, map->debugfs,
>  			    map, &regmap_reg_ranges_fops);
>  
> -	if (map->max_register) {
> +	if (map->max_register || regmap_readable(map, 0)) {

Yes.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 10/18] regulator: vexpress: Use regmap instead of custom interface
  2013-12-24 12:24   ` Mark Brown
@ 2014-01-08 18:25     ` Pawel Moll
  2014-01-09 13:35       ` Mark Brown
  0 siblings, 1 reply; 47+ messages in thread
From: Pawel Moll @ 2014-01-08 18:25 UTC (permalink / raw)
  To: Mark Brown
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Liam Girdwood

On Tue, 2013-12-24 at 12:24 +0000, Mark Brown wrote:
> On Mon, Dec 23, 2013 at 04:23:42PM +0000, Pawel Moll wrote:
> 
> > This patch makes the Versatile Express regulator driver
> > use regmap interface, instead of custom vexpress config
> > one. It will request the regmap resource associated
> > with the device, which makes it pretty much hardware
> > agnostic.
> 
> If this change is making the operations hardware agnostic regmap based
> ones then they should be being either replaced with standard operations
> or standard operations being added.  It looks like you should be able to
> use the existing linear map operations.

Bad wording on my side. What I meant was: it doesn't matter what wacky
VE-specific interface is hidden behind the regmap, not it's a generic
regulator driver.

Having said that, I could create helpers for continuous (linear won't
cut - if you remember the continuous_voltage_range was introduced for
VE's sake) regulator, which would simply read/write value to a specified
register. Not sure how useful would that be, though. I doubt that such
"regulator" will appear anywhere outside VE world. And if so, this would
probably call for a "generic continuous regulator" driver and a relevant
DT binding, which I don't think anyone really wants. If your opinion
differs, I'm happy to botch something up.

Cheers!

Paweł



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 06/18] regmap: Formalise use of non-bus context
  2013-12-24 12:45   ` Mark Brown
@ 2014-01-09 13:08     ` Pawel Moll
  2014-01-09 13:34       ` Mark Brown
  2014-01-16 17:09       ` Grant Likely
  0 siblings, 2 replies; 47+ messages in thread
From: Pawel Moll @ 2014-01-09 13:08 UTC (permalink / raw)
  To: Mark Brown
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Greg Kroah-Hartman

On Tue, 2013-12-24 at 12:45 +0000, Mark Brown wrote:
> I'd note that I wasn't CCed on most of this series so I'm not entirely
> sure what it's trying to do.

Apologies. The series is quite long and I didn't want to bother too many
people with mostly irrelevant changes. Will copy you on the whole thing
next time.

> > Bus-less maps (ones with reg_read and reg_write functions
> > defined in regmap_config) were given the context passed
> > in regmap_init(), but it was still called "bus_context".
> > 
> > This patch formalises this aspect by renaming it to simple
> > "context" and adds the missing link, free_context function
> > in regmap_config, which allows bus-less maps to use the
> > context in classic way.
> 
> This should be two patches, one patch to do the rename and one to add
> the operation.  

Sure, will do.

> The obvious question here is why is this callback useful
> - what is being allocated in a regmap specific context that needs to be
> lifetime managed separately to the thing doing the creation?  I can't
> see any obvious reason why this would ever get used.

First of all, it's just a generalization of the free_context already
existing in regmap_bus (and used by regmap-mmio). And in case of this
series it is being used to release extra resource added allocated for a
"busless" regmap_config. Briefly, I'm using devm_regmap_init() to
"attach" a custom regmap configuration to a device when it is being
created (which is then dev_get_regmap()-ed in the driver, as you saw in
the regulator patch) and its context is a pointer to kzallocated data.
free_context is used to release it when devm resource is being removed.

Does it make any sense?

Paweł


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 06/18] regmap: Formalise use of non-bus context
  2014-01-09 13:08     ` Pawel Moll
@ 2014-01-09 13:34       ` Mark Brown
  2014-01-09 15:47         ` Pawel Moll
  2014-01-16 17:09       ` Grant Likely
  1 sibling, 1 reply; 47+ messages in thread
From: Mark Brown @ 2014-01-09 13:34 UTC (permalink / raw)
  To: Pawel Moll
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Greg Kroah-Hartman

[-- Attachment #1: Type: text/plain, Size: 1277 bytes --]

On Thu, Jan 09, 2014 at 01:08:31PM +0000, Pawel Moll wrote:
> On Tue, 2013-12-24 at 12:45 +0000, Mark Brown wrote:

> > The obvious question here is why is this callback useful
> > - what is being allocated in a regmap specific context that needs to be
> > lifetime managed separately to the thing doing the creation?  I can't
> > see any obvious reason why this would ever get used.

> First of all, it's just a generalization of the free_context already
> existing in regmap_bus (and used by regmap-mmio). And in case of this
> series it is being used to release extra resource added allocated for a
> "busless" regmap_config. Briefly, I'm using devm_regmap_init() to
> "attach" a custom regmap configuration to a device when it is being
> created (which is then dev_get_regmap()-ed in the driver, as you saw in
> the regulator patch) and its context is a pointer to kzallocated data.
> free_context is used to release it when devm resource is being removed.

> Does it make any sense?

To be honest not really - the above sounds like you should've allocated
the memory using devm_kzalloc() or just embedding the allocated data in
the driver data for the parent.  Internal things need to clean up after
themselves but users should already have a larger context of some kind.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 10/18] regulator: vexpress: Use regmap instead of custom interface
  2014-01-08 18:25     ` Pawel Moll
@ 2014-01-09 13:35       ` Mark Brown
  0 siblings, 0 replies; 47+ messages in thread
From: Mark Brown @ 2014-01-09 13:35 UTC (permalink / raw)
  To: Pawel Moll
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Liam Girdwood

[-- Attachment #1: Type: text/plain, Size: 559 bytes --]

On Wed, Jan 08, 2014 at 06:25:31PM +0000, Pawel Moll wrote:
> On Tue, 2013-12-24 at 12:24 +0000, Mark Brown wrote:

> > If this change is making the operations hardware agnostic regmap based
> > ones then they should be being either replaced with standard operations
> > or standard operations being added.  It looks like you should be able to
> > use the existing linear map operations.

> Bad wording on my side. What I meant was: it doesn't matter what wacky
> VE-specific interface is hidden behind the regmap, not it's a generic
> regulator driver.

OK.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 06/18] regmap: Formalise use of non-bus context
  2014-01-09 13:34       ` Mark Brown
@ 2014-01-09 15:47         ` Pawel Moll
  0 siblings, 0 replies; 47+ messages in thread
From: Pawel Moll @ 2014-01-09 15:47 UTC (permalink / raw)
  To: Mark Brown
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Greg Kroah-Hartman

On Thu, 2014-01-09 at 13:34 +0000, Mark Brown wrote:
> > First of all, it's just a generalization of the free_context already
> > existing in regmap_bus (and used by regmap-mmio). And in case of this
> > series it is being used to release extra resource added allocated for a
> > "busless" regmap_config. Briefly, I'm using devm_regmap_init() to
> > "attach" a custom regmap configuration to a device when it is being
> > created (which is then dev_get_regmap()-ed in the driver, as you saw in
> > the regulator patch) and its context is a pointer to kzallocated data.
> > free_context is used to release it when devm resource is being removed.
> 
> > Does it make any sense?
> 
> To be honest not really - the above sounds like you should've allocated
> the memory using devm_kzalloc() or just embedding the allocated data in
> the driver data for the parent.  Internal things need to clean up after
> themselves but users should already have a larger context of some kind.

I've started with regmap_bus so the free_context did fit well like in
regmap-mmio, but you're right - with the current approach I should be
able to simply use devm_kzalloc(). I'll give it a try and if it works,
I'll drop this patch completely.

Paweł


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 03/18] GPIO: gpio-generic: Add label to platform data
  2014-01-08 15:57     ` Pawel Moll
@ 2014-01-14 10:30       ` Linus Walleij
  2014-01-14 10:44         ` Pawel Moll
  0 siblings, 1 reply; 47+ messages in thread
From: Linus Walleij @ 2014-01-14 10:30 UTC (permalink / raw)
  To: Pawel Moll
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Alexandre Courbot,
	Anton Vorontsov

On Wed, Jan 8, 2014 at 4:57 PM, Pawel Moll <pawel.moll@arm.com> wrote:
> On Mon, 2013-12-23 at 17:26 +0000, Linus Walleij wrote:

>> Good point. But what about also adding device tree support for
>> naming the chips while you're at it?
>>
>> I imagine a generic gpiochip property in
>> Documentation/devicetree/bindings/gpio/gpio.txt
>
> Well, this has been discussed almost to death already (as you may
> remember ;-) in the thread:
>
> http://www.spinics.net/lists/devicetree/msg00072.html
>
> (only portions survived)
>
> Although I was in favour of the generic binding (as were you if I
> remember correctly), the final non-conclusion was not to open the
> "generic door". Fair enough with me, I went the defined-in-code way
> here...

OK I buy this. I am willing to apply this patch. Just a problem:

Content-Type: text/plain; charset=WINDOWS-1252
Content-Transfer-Encoding: quoted-printable

I can't apply this patch :-)

Please consult your fellow upstream developers on how to get
the mail out of the ARM offices in a form that I can apply...

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 03/18] GPIO: gpio-generic: Add label to platform data
  2014-01-14 10:30       ` Linus Walleij
@ 2014-01-14 10:44         ` Pawel Moll
  0 siblings, 0 replies; 47+ messages in thread
From: Pawel Moll @ 2014-01-14 10:44 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Alexandre Courbot,
	Anton Vorontsov

On Tue, 2014-01-14 at 10:30 +0000, Linus Walleij wrote:
> Please consult your fellow upstream developers on how to get
> the mail out of the ARM offices in a form that I can apply...

They were exactly in the same position :-)

Fortunately we've got a Christmas gift of a normal SMTP server, so when
I re-post the series, it should be already fine.

Thanks!

Paweł


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 04/18] driver core & of: Mark of_nodes of added device as populated
  2014-01-08 17:28   ` Rob Herring
@ 2014-01-16 17:03     ` Grant Likely
  0 siblings, 0 replies; 47+ messages in thread
From: Grant Likely @ 2014-01-16 17:03 UTC (permalink / raw)
  To: Rob Herring, Pawel Moll
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Greg Kroah-Hartman,
	Rob Herring, devicetree

On Wed, 8 Jan 2014 11:28:01 -0600, Rob Herring <robherring2@gmail.com> wrote:
> On Mon, Dec 23, 2013 at 10:23 AM, Pawel Moll <pawel.moll@arm.com> wrote:
> > In "Device Tree powered" systems, platform devices are usually
> > massively populated with of_platform_populate() call, executed
> > at some level of initcalls, either by generic architecture
> > or by platform-specific code.
> >
> > There are situations though where certain devices must be
> > created (and bound with drivers) before all the others.
> > This presents small challenge in DT-driven systems, as
> > devices explicitly created in early code would be created
> > again by of_platform_populate().
> 
> Isn't this already at least partially solved with the aux data
> support? I'm guessing the difference here is how the early device is
> created.

Still, creating a device early and then trying to remember that it has
been done does nothing but add complexity for a very small number of use
cases. I still would much rather see things that need really early setup
to avoid the device model entirely and do the bare minimum needed to
allow the kernel to get to initcall time. In the cases where a subsystem
API requires a struct device, I would consider using a dummy throwaway
struct device for the early bits.

g.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 06/18] regmap: Formalise use of non-bus context
  2014-01-09 13:08     ` Pawel Moll
  2014-01-09 13:34       ` Mark Brown
@ 2014-01-16 17:09       ` Grant Likely
  2014-01-16 17:20         ` Pawel Moll
  1 sibling, 1 reply; 47+ messages in thread
From: Grant Likely @ 2014-01-16 17:09 UTC (permalink / raw)
  To: Pawel Moll, Mark Brown
  Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Arnd Bergmann,
	Jon Medhurst, arm, Olof Johansson, Greg Kroah-Hartman

On Thu, 09 Jan 2014 13:08:31 +0000, Pawel Moll <pawel.moll@arm.com> wrote:
> On Tue, 2013-12-24 at 12:45 +0000, Mark Brown wrote:
> > I'd note that I wasn't CCed on most of this series so I'm not entirely
> > sure what it's trying to do.
> 
> Apologies. The series is quite long and I didn't want to bother too many
> people with mostly irrelevant changes. Will copy you on the whole thing
> next time.
> 
> > > Bus-less maps (ones with reg_read and reg_write functions
> > > defined in regmap_config) were given the context passed
> > > in regmap_init(), but it was still called "bus_context".
> > > 
> > > This patch formalises this aspect by renaming it to simple
> > > "context" and adds the missing link, free_context function
> > > in regmap_config, which allows bus-less maps to use the
> > > context in classic way.
> > 
> > This should be two patches, one patch to do the rename and one to add
> > the operation.  
> 
> Sure, will do.
> 
> > The obvious question here is why is this callback useful
> > - what is being allocated in a regmap specific context that needs to be
> > lifetime managed separately to the thing doing the creation?  I can't
> > see any obvious reason why this would ever get used.
> 
> First of all, it's just a generalization of the free_context already
> existing in regmap_bus (and used by regmap-mmio). And in case of this
> series it is being used to release extra resource added allocated for a
> "busless" regmap_config. Briefly, I'm using devm_regmap_init() to
> "attach" a custom regmap configuration to a device when it is being
> created (which is then dev_get_regmap()-ed in the driver, as you saw in
> the regulator patch) and its context is a pointer to kzallocated data.
> free_context is used to release it when devm resource is being removed.

Have you thought through all the implications here? What you've
described effectively changes the devm model. devm operates under the
assumption that devm data only exists between probe() and remove() time.
If you 'preload' devm data then the preloaded data will get discarded at
remove() time which breaks if the driver is remove and probed again at
runtime.

g.


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [RFC 06/18] regmap: Formalise use of non-bus context
  2014-01-16 17:09       ` Grant Likely
@ 2014-01-16 17:20         ` Pawel Moll
  0 siblings, 0 replies; 47+ messages in thread
From: Pawel Moll @ 2014-01-16 17:20 UTC (permalink / raw)
  To: Grant Likely
  Cc: Mark Brown, linux-kernel, linux-arm-kernel, Samuel Ortiz,
	Arnd Bergmann, Jon Medhurst, arm, Olof Johansson,
	Greg Kroah-Hartman

On Thu, 2014-01-16 at 17:09 +0000, Grant Likely wrote:
> > First of all, it's just a generalization of the free_context already
> > existing in regmap_bus (and used by regmap-mmio). And in case of this
> > series it is being used to release extra resource added allocated for a
> > "busless" regmap_config. Briefly, I'm using devm_regmap_init() to
> > "attach" a custom regmap configuration to a device when it is being
> > created (which is then dev_get_regmap()-ed in the driver, as you saw in
> > the regulator patch) and its context is a pointer to kzallocated data.
> > free_context is used to release it when devm resource is being removed.
> 
> Have you thought through all the implications here? What you've
> described effectively changes the devm model. devm operates under the
> assumption that devm data only exists between probe() and remove() time.
> If you 'preload' devm data then the preloaded data will get discarded at
> remove() time which breaks if the driver is remove and probed again at
> runtime.

Uh. Right, you're correct, I've missed that (obvious) fact :-(

I will get the drivers back to "vexpress_regmap_init()" model or try to
find a way of "attaching" a regmap pointer(s?) to a struct device. If it
makes sense at all...

Paweł


^ permalink raw reply	[flat|nested] 47+ messages in thread

end of thread, other threads:[~2014-01-16 17:20 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-23 16:23 [RFC 00/18] Versatile Express config rework Pawel Moll
     [not found] ` < 1387815830-8794-5-git-send-email-pawel.moll@arm.com>
     [not found] ` < 1387815830-8794-7-git-send-email-pawel.moll@arm.com>
2013-12-23 16:23 ` [RFC 01/18] mfd: syscon: Consider platform data a regmap config name Pawel Moll
2014-01-06  9:48   ` Lee Jones
2014-01-06 10:20     ` Lee Jones
2013-12-23 16:23 ` [RFC 02/18] power/reset: vexpress: Use sched_clock as the time source Pawel Moll
2013-12-23 19:28   ` John Stultz
2014-01-08 16:01     ` Pawel Moll
2013-12-23 16:23 ` [RFC 03/18] GPIO: gpio-generic: Add label to platform data Pawel Moll
2013-12-23 17:26   ` Linus Walleij
2014-01-08 15:57     ` Pawel Moll
2014-01-14 10:30       ` Linus Walleij
2014-01-14 10:44         ` Pawel Moll
2013-12-23 16:23 ` [RFC 04/18] driver core & of: Mark of_nodes of added device as populated Pawel Moll
2014-01-08 17:28   ` Rob Herring
2014-01-16 17:03     ` Grant Likely
2013-12-23 16:23 ` [RFC 05/18] driver core: Do not WARN when devres list is not empty at probe time Pawel Moll
2013-12-23 16:23 ` [RFC 06/18] regmap: Formalise use of non-bus context Pawel Moll
2013-12-24 12:45   ` Mark Brown
2014-01-09 13:08     ` Pawel Moll
2014-01-09 13:34       ` Mark Brown
2014-01-09 15:47         ` Pawel Moll
2014-01-16 17:09       ` Grant Likely
2014-01-16 17:20         ` Pawel Moll
2013-12-23 16:23 ` [RFC 07/18] regmap: debugfs: Always create "registers" & "access" files Pawel Moll
2013-12-24 12:19   ` Mark Brown
2014-01-08 17:31     ` Pawel Moll
2014-01-08 18:00       ` Mark Brown
2013-12-23 16:23 ` [RFC 08/18] hwmon: vexpress: Use regmap instead of custom interface Pawel Moll
2013-12-23 17:31   ` Guenter Roeck
2014-01-08 15:57     ` Pawel Moll
2013-12-23 16:23 ` [RFC 09/18] power/reset: " Pawel Moll
2013-12-23 16:23 ` [RFC 10/18] regulator: " Pawel Moll
2013-12-24 12:24   ` Mark Brown
2014-01-08 18:25     ` Pawel Moll
2014-01-09 13:35       ` Mark Brown
2013-12-23 16:23 ` [RFC 11/18] clocksource: Sched clock source for Versatile Express Pawel Moll
2013-12-23 16:23 ` [RFC 12/18] clk: versatile: Split config options for sp810 and vexpress_osc Pawel Moll
2013-12-23 20:05   ` Mike Turquette
2014-01-08 16:06     ` Pawel Moll
2013-12-23 16:23 ` [RFC 13/18] clk: versatile: Use regmap instead of custom interface Pawel Moll
2013-12-23 16:23 ` [RFC 14/18] ARM: vexpress: remove redundant vexpress_dt_cpus_num to get cpu count Pawel Moll
2013-12-23 16:23 ` [RFC 15/18] ARM: vexpress: Simplify SMP operations for DT-powered system Pawel Moll
2013-12-23 16:23 ` [RFC 16/18] bus: Versatile Express configuration bus Pawel Moll
2013-12-23 16:23 ` [RFC 17/18] misc: Versatile Express System Config interface driver Pawel Moll
2013-12-23 16:23 ` [RFC 18/18] mfd: vexpress: Split sysreg functions into MFD cells Pawel Moll
2014-01-06 10:40   ` Lee Jones
2014-01-08 16:17     ` Pawel Moll

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).