[PATCH RFC 01/10] drivers: reset: STi SoC system configuration reset controller support

2013-11-12 Thread srinivas.kandagatla
From: Stephen Gallimore 

This patch adds a reset controller implementation for STMicroelectronics
STi family SoCs; it allows a group of related reset like controls found
in multiple system configuration registers to be represented by a single
controller device. System configuration registers are accessed through
the regmap framework and the mfd/syscon driver.

The implementation optionally supports waiting for the reset action to
be acknowledged in a separate status register and supports both
active high and active low reset lines. These properties are common across
all the reset channels in a specific reset controller instance, hence
all channels in a paritcular controller are expected to behave in the
same way.

Signed-off-by: Stephen Gallimore 
---
 drivers/reset/Kconfig|2 +
 drivers/reset/Makefile   |3 +
 drivers/reset/sti/Kconfig|7 ++
 drivers/reset/sti/Makefile   |1 +
 drivers/reset/sti/reset-syscfg.c |  186 ++
 drivers/reset/sti/reset-syscfg.h |   69 ++
 6 files changed, 268 insertions(+), 0 deletions(-)
 create mode 100644 drivers/reset/sti/Kconfig
 create mode 100644 drivers/reset/sti/Makefile
 create mode 100644 drivers/reset/sti/reset-syscfg.c
 create mode 100644 drivers/reset/sti/reset-syscfg.h

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index c9d04f7..0615f50 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -11,3 +11,5 @@ menuconfig RESET_CONTROLLER
  via GPIOs or SoC-internal reset controller modules.
 
  If unsure, say no.
+
+source "drivers/reset/sti/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 1e2d83f..2b2a57c 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -1 +1,4 @@
 obj-$(CONFIG_RESET_CONTROLLER) += core.o
+
+# SoC specific
+obj-$(CONFIG_ARCH_STI) += sti/
diff --git a/drivers/reset/sti/Kconfig b/drivers/reset/sti/Kconfig
new file mode 100644
index 000..ba13796
--- /dev/null
+++ b/drivers/reset/sti/Kconfig
@@ -0,0 +1,7 @@
+if ARCH_STI
+
+config STI_RESET_SYSCFG
+   bool
+   select RESET_CONTROLLER
+
+endif
diff --git a/drivers/reset/sti/Makefile b/drivers/reset/sti/Makefile
new file mode 100644
index 000..c4a51d9
--- /dev/null
+++ b/drivers/reset/sti/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_STI_RESET_SYSCFG) += reset-syscfg.o
diff --git a/drivers/reset/sti/reset-syscfg.c b/drivers/reset/sti/reset-syscfg.c
new file mode 100644
index 000..a145cc0
--- /dev/null
+++ b/drivers/reset/sti/reset-syscfg.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics Limited
+ * Author: Stephen Gallimore 
+ *
+ * Inspired by mach-imx/src.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "reset-syscfg.h"
+
+/**
+ * Reset channel regmap configuration
+ *
+ * @reset: regmap field for the channel's reset bit.
+ * @ack: regmap field for the channel's ack bit (optional).
+ */
+struct syscfg_reset_channel {
+   struct regmap_field *reset;
+   struct regmap_field *ack;
+};
+
+/**
+ * A reset controller which groups together a set of related reset bits, which
+ * may be located in different system configuration registers.
+ *
+ * @rst: base reset controller structure.
+ * @active_low: are the resets in this controller active low, i.e. clearing
+ *  the reset bit puts the hardware into reset.
+ * @channels: An array of reset channels for this controller.
+ */
+struct syscfg_reset_controller {
+   struct reset_controller_dev rst;
+   bool active_low;
+   struct syscfg_reset_channel *channels;
+};
+
+#define to_syscfg_reset_controller(_rst) \
+   container_of(_rst, struct syscfg_reset_controller, rst)
+
+static int syscfg_reset_program_hw(struct reset_controller_dev *rcdev,
+  unsigned long idx, int assert)
+{
+   struct syscfg_reset_controller *rst = to_syscfg_reset_controller(rcdev);
+   const struct syscfg_reset_channel *ch;
+   u32 ctrl_val = rst->active_low ? !assert : !!assert;
+   int err;
+
+   if (idx >= rcdev->nr_resets)
+   return -EINVAL;
+
+   ch = >channels[idx];
+
+   err = regmap_field_write(ch->reset, ctrl_val);
+   if (err)
+   return err;
+
+   if (ch->ack) {
+   unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+   u32 ack_val;
+
+   while (true) {
+   err = regmap_field_read(ch->ack, _val);
+   if (err)
+   return err;
+
+   if (ack_val == ctrl_val)
+   break;
+
+ 

[PATCH RFC 01/10] drivers: reset: STi SoC system configuration reset controller support

2013-11-12 Thread srinivas.kandagatla
From: Stephen Gallimore stephen.gallim...@st.com

This patch adds a reset controller implementation for STMicroelectronics
STi family SoCs; it allows a group of related reset like controls found
in multiple system configuration registers to be represented by a single
controller device. System configuration registers are accessed through
the regmap framework and the mfd/syscon driver.

The implementation optionally supports waiting for the reset action to
be acknowledged in a separate status register and supports both
active high and active low reset lines. These properties are common across
all the reset channels in a specific reset controller instance, hence
all channels in a paritcular controller are expected to behave in the
same way.

Signed-off-by: Stephen Gallimore stephen.gallim...@st.com
---
 drivers/reset/Kconfig|2 +
 drivers/reset/Makefile   |3 +
 drivers/reset/sti/Kconfig|7 ++
 drivers/reset/sti/Makefile   |1 +
 drivers/reset/sti/reset-syscfg.c |  186 ++
 drivers/reset/sti/reset-syscfg.h |   69 ++
 6 files changed, 268 insertions(+), 0 deletions(-)
 create mode 100644 drivers/reset/sti/Kconfig
 create mode 100644 drivers/reset/sti/Makefile
 create mode 100644 drivers/reset/sti/reset-syscfg.c
 create mode 100644 drivers/reset/sti/reset-syscfg.h

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index c9d04f7..0615f50 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -11,3 +11,5 @@ menuconfig RESET_CONTROLLER
  via GPIOs or SoC-internal reset controller modules.
 
  If unsure, say no.
+
+source drivers/reset/sti/Kconfig
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 1e2d83f..2b2a57c 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -1 +1,4 @@
 obj-$(CONFIG_RESET_CONTROLLER) += core.o
+
+# SoC specific
+obj-$(CONFIG_ARCH_STI) += sti/
diff --git a/drivers/reset/sti/Kconfig b/drivers/reset/sti/Kconfig
new file mode 100644
index 000..ba13796
--- /dev/null
+++ b/drivers/reset/sti/Kconfig
@@ -0,0 +1,7 @@
+if ARCH_STI
+
+config STI_RESET_SYSCFG
+   bool
+   select RESET_CONTROLLER
+
+endif
diff --git a/drivers/reset/sti/Makefile b/drivers/reset/sti/Makefile
new file mode 100644
index 000..c4a51d9
--- /dev/null
+++ b/drivers/reset/sti/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_STI_RESET_SYSCFG) += reset-syscfg.o
diff --git a/drivers/reset/sti/reset-syscfg.c b/drivers/reset/sti/reset-syscfg.c
new file mode 100644
index 000..a145cc0
--- /dev/null
+++ b/drivers/reset/sti/reset-syscfg.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics Limited
+ * Author: Stephen Gallimore stephen.gallim...@st.com
+ *
+ * Inspired by mach-imx/src.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include linux/kernel.h
+#include linux/platform_device.h
+#include linux/module.h
+#include linux/err.h
+#include linux/types.h
+#include linux/of_device.h
+#include linux/regmap.h
+#include linux/mfd/syscon.h
+
+#include reset-syscfg.h
+
+/**
+ * Reset channel regmap configuration
+ *
+ * @reset: regmap field for the channel's reset bit.
+ * @ack: regmap field for the channel's ack bit (optional).
+ */
+struct syscfg_reset_channel {
+   struct regmap_field *reset;
+   struct regmap_field *ack;
+};
+
+/**
+ * A reset controller which groups together a set of related reset bits, which
+ * may be located in different system configuration registers.
+ *
+ * @rst: base reset controller structure.
+ * @active_low: are the resets in this controller active low, i.e. clearing
+ *  the reset bit puts the hardware into reset.
+ * @channels: An array of reset channels for this controller.
+ */
+struct syscfg_reset_controller {
+   struct reset_controller_dev rst;
+   bool active_low;
+   struct syscfg_reset_channel *channels;
+};
+
+#define to_syscfg_reset_controller(_rst) \
+   container_of(_rst, struct syscfg_reset_controller, rst)
+
+static int syscfg_reset_program_hw(struct reset_controller_dev *rcdev,
+  unsigned long idx, int assert)
+{
+   struct syscfg_reset_controller *rst = to_syscfg_reset_controller(rcdev);
+   const struct syscfg_reset_channel *ch;
+   u32 ctrl_val = rst-active_low ? !assert : !!assert;
+   int err;
+
+   if (idx = rcdev-nr_resets)
+   return -EINVAL;
+
+   ch = rst-channels[idx];
+
+   err = regmap_field_write(ch-reset, ctrl_val);
+   if (err)
+   return err;
+
+   if (ch-ack) {
+   unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+   u32 ack_val;
+
+   while (true) {
+   err = regmap_field_read(ch-ack,