mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 1/6] Documentation: add some info about the reset variants
@ 2015-06-16 11:56 Juergen Borleis
  2015-06-16 11:56 ` [PATCH 2/6] Watchdog/i.MX: make the watchdog driver a regular driver Juergen Borleis
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Juergen Borleis @ 2015-06-16 11:56 UTC (permalink / raw)
  To: barebox

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
 Documentation/user/system-reset.rst | 64 +++++++++++++++++++++++++++++++++++++
 Documentation/user/user-manual.rst  |  1 +
 2 files changed, 65 insertions(+)
 create mode 100644 Documentation/user/system-reset.rst

diff --git a/Documentation/user/system-reset.rst b/Documentation/user/system-reset.rst
new file mode 100644
index 0000000..c2ee409
--- /dev/null
+++ b/Documentation/user/system-reset.rst
@@ -0,0 +1,64 @@
+.. _system_reset:
+
+System Reset
+------------
+
+When running the reset command barebox restarts the SoC somehow. Reset can
+be done in software, but a more reliable way is to use a hard reset line, which
+really resets the SoC.
+The most common way to force such a hard reset is by using a watchdog. Its
+trigger time will be setup as short as possible and after that the software just
+waits for its reset. Very simple and most of the time it does what's expected.
+
+But there are some drawbacks within this simple approach.
+
+* most used watchdogs are built-in units in the SoCs. There is nothing wrong
+  with that, but these units can mostly reset the CPU core and sometimes a little
+  bit more of the SoC. This means this reset is not exactly the same than the
+  real POR (e.g. power on reset). In this case you must still handle different
+  hardware in a special way because it hasn't seen the reset the CPU has seen.
+  Enabled DMA units for example can continue to run and transfer data while the
+  CPU core runs through its reset code. This can trigger very strange failures.
+
+* when interacting with flash memories (mostly NOR types and used to store the
+  root filesystem) it cannot provide data (sometimes called 'array mode') the
+  CPU wants to read after a reset while it is still in some programming mode.
+  And if the software is currently changing some data inside the flash and
+  an internal reset happens the CPU and the flash memory are doing different
+  things and the system hangs until a real POR which also resets the flash
+  memory into the 'array mode'.
+
+* some SoC's boot behaviour gets parametrized by so called 'bootstrap pins'.
+  These pins can have a different meaning at reset time and at run-time later
+  on (multi purpose pins) but their correct values at reset time are very
+  important to boot the SoC sucessfully. If external devices are connected to
+  these multi purpose pins they can disturb the reset values, and so parametrizing
+  the boot behaviour differently and hence crashing the SoC until the next real
+  POR happens which also resets the external devices (and keep them away from the
+  multi purpose pins).
+
+* when power management comes into play another level of failure is
+  possible. To save power the software can lower the clock(s), but to really
+  save power, the power supply voltages must be lowered as well. Most PMICs
+  (e.g. power management controllers) are dedicated external companion devices,
+  loosely connected to their SoC. If the SoC's internal reset source now resets
+  the CPU it may increases its clock(s) back to the frequencies after a POR, but
+  the external PMIC still provides voltages related to lower frequencies. The
+  system isn't consistent any more. If you are in luck, the SoC still works
+  somehow, even if the voltages are out of their specifications for the
+  currently used clock speeds. But don't rely on it.
+
+To workaround these issues the reset signal triggered by a SoC internal source
+must be 'visible' to the external devices to also reset them like a real POR do.
+But many SoCs do not provide such a signal. So you can't use the internal reset
+source if you face one of the above listed issues!
+
+A different solution is to use the PMIC (if available) to trigger the reset.
+Many PMICs provide their own watchdog units and if they trigger a reset they
+also switch their voltages back to the real POR values. This will be a system
+wide reset, like the POR is.
+
+Drawback of the PMIC solution is, you can't use the SoC's internal mechanisms to
+detect the :ref:`reset_reason` anymore. From the SoC point of view it is always
+a POR when the PMIC handles the system reset. If you are in luck the PMIC
+instead can provide this information if you depend on it.
diff --git a/Documentation/user/user-manual.rst b/Documentation/user/user-manual.rst
index 1fc6883..0d6daee 100644
--- a/Documentation/user/user-manual.rst
+++ b/Documentation/user/user-manual.rst
@@ -29,6 +29,7 @@ Contents:
    booting-linux
    system-setup
    reset-reason
+   system-reset
 
 * :ref:`search`
 * :ref:`genindex`
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 2/6] Watchdog/i.MX: make the watchdog driver a regular driver
  2015-06-16 11:56 [PATCH 1/6] Documentation: add some info about the reset variants Juergen Borleis
@ 2015-06-16 11:56 ` Juergen Borleis
  2015-06-16 11:56 ` [PATCH 3/6] MFD/DA9053: adapt driver to the current reset source framework Juergen Borleis
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Juergen Borleis @ 2015-06-16 11:56 UTC (permalink / raw)
  To: barebox

Even if the driver for the internal watchdog unit is disabled, it gets
enabled again silently if we select an i.MX platform.

This change compiles the driver on user demand only. Barebox can handle one
watchdog and one reset source. This change enables a user to select a
different one if the built-in unit cannot be used due to hardware issues like
power management and voltage changes the internal watchdog cannot reset
correctly.

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
 arch/arm/Kconfig          |  1 -
 drivers/watchdog/Kconfig  | 15 ++++++++++++---
 drivers/watchdog/Makefile |  2 +-
 drivers/watchdog/imxwd.c  |  5 ++++-
 4 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 50f3095..b115d10 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -101,7 +101,6 @@ config ARCH_IMX
 	select GPIOLIB
 	select COMMON_CLK
 	select CLKDEV_LOOKUP
-	select WATCHDOG_IMX_RESET_SOURCE
 	select HAS_DEBUG_LL
 
 config ARCH_MVEBU
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 7f7b02e..04fad45 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1,7 +1,4 @@
 
-config WATCHDOG_IMX_RESET_SOURCE
-	bool
-
 menuconfig WATCHDOG
 	bool "Watchdog support"
 	help
@@ -22,6 +19,18 @@ config WATCHDOG_IMX
 	help
 	  Add support for watchdog found on Freescale i.MX SoCs.
 
+config WATCHDOG_IMX_RESET_SOURCE
+	depends on WATCHDOG_IMX
+	bool "Reset source provider"
+	help
+	  This watchdog unit can provide the reset reason.
+
+config WATCHDOG_IMX_RESET_FEATURE
+	depends on WATCHDOG_IMX
+	bool "Use for SoC reset"
+	help
+	  This watchdog unit can be used to reset/restart the SoC.
+
 config WATCHDOG_JZ4740
 	bool "Ingenic jz4740 SoC hardware watchdog"
 	depends on MACH_MIPS_XBURST
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 865fc47..446056d 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -1,4 +1,4 @@
 obj-$(CONFIG_WATCHDOG) += wd_core.o
 obj-$(CONFIG_WATCHDOG_MXS28) += im28wd.o
 obj-$(CONFIG_WATCHDOG_JZ4740) += jz4740.o
-obj-$(CONFIG_WATCHDOG_IMX_RESET_SOURCE) += imxwd.o
+obj-$(CONFIG_WATCHDOG_IMX) += imxwd.o
diff --git a/drivers/watchdog/imxwd.c b/drivers/watchdog/imxwd.c
index 5ffbac7..60e4c59 100644
--- a/drivers/watchdog/imxwd.c
+++ b/drivers/watchdog/imxwd.c
@@ -123,6 +123,7 @@ static int imx_watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
 
 static struct imx_wd *reset_wd;
 
+#ifdef CONFIG_WATCHDOG_IMX_RESET_FEATURE
 void __noreturn reset_cpu(unsigned long addr)
 {
 	if (reset_wd)
@@ -132,6 +133,7 @@ void __noreturn reset_cpu(unsigned long addr)
 
 	hang();
 }
+#endif
 
 static void imx_watchdog_detect_reset_source(struct imx_wd *priv)
 {
@@ -157,7 +159,8 @@ static void imx_watchdog_detect_reset_source(struct imx_wd *priv)
 
 static int imx21_wd_init(struct imx_wd *priv)
 {
-	imx_watchdog_detect_reset_source(priv);
+	if (IS_ENABLED(CONFIG_WATCHDOG_IMX_RESET_SOURCE))
+		imx_watchdog_detect_reset_source(priv);
 
 	/*
 	 * Disable watchdog powerdown counter
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 3/6] MFD/DA9053: adapt driver to the current reset source framework
  2015-06-16 11:56 [PATCH 1/6] Documentation: add some info about the reset variants Juergen Borleis
  2015-06-16 11:56 ` [PATCH 2/6] Watchdog/i.MX: make the watchdog driver a regular driver Juergen Borleis
@ 2015-06-16 11:56 ` Juergen Borleis
  2015-06-16 11:56 ` [PATCH 4/6] MFD/DA9053: provide system reset Juergen Borleis
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Juergen Borleis @ 2015-06-16 11:56 UTC (permalink / raw)
  To: barebox

Since commit 106956783018635cef9a35bcb109073513d1ead4 barebox has a generic
framework to provide the reset reason to upper layers. Use it in the
DA9053 driver as well.

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
 drivers/mfd/Kconfig  |  6 ++++
 drivers/mfd/da9053.c | 79 ++++++++++++++++++++++------------------------------
 2 files changed, 40 insertions(+), 45 deletions(-)

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 3d230f1..8c8f537 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -8,6 +8,12 @@ config MFD_DA9053
 	depends on I2C
 	bool "DA9053 PMIC driver"
 
+config MFD_DA9053_RESET_SOURCE
+	depends on MFD_DA9053
+	bool "Reset source provider"
+	help
+	  This PMIC unit can provide the reset reason.
+
 config MFD_LP3972
 	depends on I2C
 	bool "LP3972 driver"
diff --git a/drivers/mfd/da9053.c b/drivers/mfd/da9053.c
index 4bce8cc..9294a6a 100644
--- a/drivers/mfd/da9053.c
+++ b/drivers/mfd/da9053.c
@@ -25,6 +25,7 @@
 #include <i2c/i2c.h>
 
 #include <asm/byteorder.h>
+#include <reset_source.h>
 
 #define DRIVERNAME		"da9053"
 
@@ -92,7 +93,6 @@ struct da9053_priv {
 	struct watchdog		wd;
 	struct i2c_client	*client;
 	unsigned int		param_shutdown;
-	unsigned int		param_faultlog;
 };
 
 #define cdev_to_da9053_priv(x)	container_of(x, struct da9053_priv, cdev)
@@ -178,45 +178,6 @@ static struct file_operations da9053_fops = {
 	.read	= da9053_read,
 };
 
-static int da9053_set_faultlog(struct param_d *param, void *priv)
-{
-	struct da9053_priv *da9053 = priv;
-	int ret;
-	u8 val;
-
-	val = da9053->param_faultlog & 0xff;
-	if (val) {
-		ret = da9053_reg_write(da9053, DA9053_FAULTLOG_REG, val);
-		if (ret < 0)
-			return ret;
-
-		ret = da9053_park(da9053);
-		if (ret < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int da9053_get_faultlog(struct param_d *param, void *priv)
-{
-	struct da9053_priv *da9053 = priv;
-	int ret;
-	u8 val;
-
-	ret = da9053_reg_read(da9053, DA9053_FAULTLOG_REG, &val);
-	if (ret < 0)
-		return ret;
-
-	ret = da9053_park(da9053);
-	if (ret < 0)
-		return ret;
-
-	da9053->param_faultlog = val;
-
-	return 0;
-}
-
 static int da9053_set_shutdown(struct param_d *param, void *priv)
 {
 	struct da9053_priv *da9053 = priv;
@@ -308,6 +269,37 @@ static int da9053_set_timeout(struct watchdog *wd, unsigned timeout)
 	return 0;
 }
 
+static void da9053_detect_reset_source(struct da9053_priv *da9053)
+{
+	int ret;
+	u8 val;
+
+	ret = da9053_reg_read(da9053, DA9053_FAULTLOG_REG, &val);
+	if (ret < 0)
+		return;
+
+	ret = da9053_park(da9053);
+	if (ret < 0)
+		return;
+
+	if (val & DA9053_FAULTLOG_TWDERROR) {
+		reset_source_set(RESET_WDG);
+		return;
+	}
+
+	if (val & DA9053_FAULTLOG_VDDFAULT) {
+		reset_source_set(RESET_POR);
+		return;
+	}
+
+	if (val & DA9053_FAULTLOG_NSDSET) {
+		reset_source_set(RESET_RST);
+		return;
+	}
+
+	/* else keep the default 'unknown' state */
+}
+
 static int da9053_probe(struct device_d *dev)
 {
 	struct da9053_priv *da9053;
@@ -327,11 +319,6 @@ static int da9053_probe(struct device_d *dev)
 	if (ret < 0)
 		return ret;
 
-	p = dev_add_param_int(dev, "faultlog", da9053_set_faultlog, da9053_get_faultlog,
-			      &da9053->param_faultlog, "0x%02x", da9053);
-	if (IS_ERR(p))
-		return PTR_ERR(p);
-
 	p = dev_add_param_bool(dev, "shutdown", da9053_set_shutdown, NULL,
 			       &da9053->param_shutdown, da9053);
 	if (IS_ERR(p))
@@ -343,6 +330,8 @@ static int da9053_probe(struct device_d *dev)
 	if (ret)
 		return ret;
 
+	if (IS_ENABLED(CONFIG_MFD_DA9053_RESET_SOURCE))
+		da9053_detect_reset_source(da9053);
 	return 0;
 }
 
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 4/6] MFD/DA9053: provide system reset
  2015-06-16 11:56 [PATCH 1/6] Documentation: add some info about the reset variants Juergen Borleis
  2015-06-16 11:56 ` [PATCH 2/6] Watchdog/i.MX: make the watchdog driver a regular driver Juergen Borleis
  2015-06-16 11:56 ` [PATCH 3/6] MFD/DA9053: adapt driver to the current reset source framework Juergen Borleis
@ 2015-06-16 11:56 ` Juergen Borleis
  2015-06-16 11:56 ` [PATCH 5/6] MFD/DA9053: remove not required header file Juergen Borleis
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Juergen Borleis @ 2015-06-16 11:56 UTC (permalink / raw)
  To: barebox

When using power management features like voltage regulators when switching
down the CPU clock speed, a SoC reset must also reset the power supplies to
their expected values after a POR. Most internal units (like watchdogs used to
reset the SoC) are not able to signal the SoC reset to external devices. This
can end up in various and unpredictable system crashes because the CPU restarts
with the expectation the power supplies were also reset.

By using the reset feature of the PMIC unit this expectation about the power
supplies is always true.

Downside of this approach: the SoC cannot longer detect the reset reason with
its own mechanism. Each PMIC based reset looks like a POR from the SoC's point
of view.

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
 drivers/mfd/Kconfig  |  6 ++++++
 drivers/mfd/da9053.c | 61 +++++++++++++++++++++++-----------------------------
 2 files changed, 33 insertions(+), 34 deletions(-)

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 8c8f537..bf012bf 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -14,6 +14,12 @@ config MFD_DA9053_RESET_SOURCE
 	help
 	  This PMIC unit can provide the reset reason.
 
+config MFD_DA9053_RESET_FEATURE
+	depends on MFD_DA9053
+	bool "Use for system reset"
+	help
+	  This PMIC unit can be used to reset/restart the system.
+
 config MFD_LP3972
 	depends on I2C
 	bool "LP3972 driver"
diff --git a/drivers/mfd/da9053.c b/drivers/mfd/da9053.c
index 9294a6a..b376d8d 100644
--- a/drivers/mfd/da9053.c
+++ b/drivers/mfd/da9053.c
@@ -20,7 +20,6 @@
 #include <xfuncs.h>
 #include <errno.h>
 #include <watchdog.h>
-#include <linux/err.h>
 
 #include <i2c/i2c.h>
 
@@ -92,7 +91,6 @@ struct da9053_priv {
 	struct cdev		cdev;
 	struct watchdog		wd;
 	struct i2c_client	*client;
-	unsigned int		param_shutdown;
 };
 
 #define cdev_to_da9053_priv(x)	container_of(x, struct da9053_priv, cdev)
@@ -178,30 +176,6 @@ static struct file_operations da9053_fops = {
 	.read	= da9053_read,
 };
 
-static int da9053_set_shutdown(struct param_d *param, void *priv)
-{
-	struct da9053_priv *da9053 = priv;
-	int ret;
-	u8 val;
-
-	if (da9053->param_shutdown) {
-		ret = da9053_reg_read(da9053, DA9053_CONTROL_B_REG, &val);
-		if (ret < 0)
-			return ret;
-
-		val |= DA9053_CONTROLB_SHUTDOWN;
-		ret = da9053_reg_write(da9053, DA9053_CONTROL_B_REG, val);
-		if (ret < 0)
-			return ret;
-
-		ret = da9053_park(da9053);
-		if (ret < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
 static int da9053_set_timeout(struct watchdog *wd, unsigned timeout)
 {
 	struct da9053_priv *da9053 = wd_to_da9053_priv(wd);
@@ -300,10 +274,31 @@ static void da9053_detect_reset_source(struct da9053_priv *da9053)
 	/* else keep the default 'unknown' state */
 }
 
+#ifdef CONFIG_MFD_DA9053_RESET_FEATURE
+static struct da9053_priv *wd_da9053;
+void __noreturn reset_cpu(unsigned long addr)
+{
+	u8 val;
+	int ret;
+
+	ret = da9053_reg_read(wd_da9053, DA9053_CONTROL_B_REG, &val);
+	if (ret < 0)
+		hang();
+
+	val |= DA9053_CONTROLB_SHUTDOWN;
+	ret = da9053_reg_write(wd_da9053, DA9053_CONTROL_B_REG, val);
+	if (ret < 0)
+		hang();
+
+	da9053_park(wd_da9053);
+
+	hang();
+}
+#endif
+
 static int da9053_probe(struct device_d *dev)
 {
 	struct da9053_priv *da9053;
-	struct param_d *p;
 	int ret;
 
 	da9053 = xzalloc(sizeof(struct da9053_priv));
@@ -319,19 +314,17 @@ static int da9053_probe(struct device_d *dev)
 	if (ret < 0)
 		return ret;
 
-	p = dev_add_param_bool(dev, "shutdown", da9053_set_shutdown, NULL,
-			       &da9053->param_shutdown, da9053);
-	if (IS_ERR(p))
-		return PTR_ERR(p);
-
-	devfs_create(&da9053->cdev);
-
 	ret = watchdog_register(&da9053->wd);
 	if (ret)
 		return ret;
 
 	if (IS_ENABLED(CONFIG_MFD_DA9053_RESET_SOURCE))
 		da9053_detect_reset_source(da9053);
+
+#ifdef CONFIG_MFD_DA9053_RESET_FEATURE
+	if (wd_da9053 == NULL)
+		wd_da9053 = da9053;
+#endif
 	return 0;
 }
 
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 5/6] MFD/DA9053: remove not required header file
  2015-06-16 11:56 [PATCH 1/6] Documentation: add some info about the reset variants Juergen Borleis
                   ` (2 preceding siblings ...)
  2015-06-16 11:56 ` [PATCH 4/6] MFD/DA9053: provide system reset Juergen Borleis
@ 2015-06-16 11:56 ` Juergen Borleis
  2015-06-16 11:56 ` [PATCH 6/6] mfd: da9063: add da9063 watchdog and system restart driver Juergen Borleis
  2015-06-16 12:05 ` [PATCH 1/6] Documentation: add some info about the reset variants Jürgen Borleis
  5 siblings, 0 replies; 7+ messages in thread
From: Juergen Borleis @ 2015-06-16 11:56 UTC (permalink / raw)
  To: barebox

None of the the prototypes this header file provides is used in this
driver.

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
 drivers/mfd/da9053.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/mfd/da9053.c b/drivers/mfd/da9053.c
index b376d8d..bc9b184 100644
--- a/drivers/mfd/da9053.c
+++ b/drivers/mfd/da9053.c
@@ -22,8 +22,6 @@
 #include <watchdog.h>
 
 #include <i2c/i2c.h>
-
-#include <asm/byteorder.h>
 #include <reset_source.h>
 
 #define DRIVERNAME		"da9053"
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 6/6] mfd: da9063: add da9063 watchdog and system restart driver
  2015-06-16 11:56 [PATCH 1/6] Documentation: add some info about the reset variants Juergen Borleis
                   ` (3 preceding siblings ...)
  2015-06-16 11:56 ` [PATCH 5/6] MFD/DA9053: remove not required header file Juergen Borleis
@ 2015-06-16 11:56 ` Juergen Borleis
  2015-06-16 12:05 ` [PATCH 1/6] Documentation: add some info about the reset variants Jürgen Borleis
  5 siblings, 0 replies; 7+ messages in thread
From: Juergen Borleis @ 2015-06-16 11:56 UTC (permalink / raw)
  To: barebox

From: Philipp Zabel <p.zabel@pengutronix.de>

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
 drivers/mfd/Kconfig  |   4 ++
 drivers/mfd/Makefile |   1 +
 drivers/mfd/da9063.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 165 insertions(+)
 create mode 100644 drivers/mfd/da9063.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index bf012bf..1be9f61 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -20,6 +20,10 @@ config MFD_DA9053_RESET_FEATURE
 	help
 	  This PMIC unit can be used to reset/restart the system.
 
+config MFD_DA9063
+	depends on I2C
+	bool "DA9063 PMIC driver"
+
 config MFD_LP3972
 	depends on I2C
 	bool "LP3972 driver"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 2899dde..041915a 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_MFD_ACT8846)	+= act8846.o
 obj-$(CONFIG_MFD_DA9053)	+= da9053.o
+obj-$(CONFIG_MFD_DA9063)	+= da9063.o
 obj-$(CONFIG_MFD_LP3972)	+= lp3972.o
 obj-$(CONFIG_MFD_MC13XXX)	+= mc13xxx.o
 obj-$(CONFIG_MFD_MC34704)	+= mc34704.o
diff --git a/drivers/mfd/da9063.c b/drivers/mfd/da9063.c
new file mode 100644
index 0000000..65b1fad
--- /dev/null
+++ b/drivers/mfd/da9063.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2015 Pengutronix, Philipp Zabel <p.zabel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <i2c/i2c.h>
+#include <malloc.h>
+#include <notifier.h>
+#include <reset_source.h>
+#include <watchdog.h>
+
+struct da9063 {
+	struct watchdog		wd;
+	struct i2c_client	*client;
+	struct notifier_block	notify;
+};
+
+/* System Control and Event Registers */
+#define DA9063_REG_FAULT_LOG	0x05
+#define DA9063_REG_CONTROL_D	0x11
+#define DA9063_REG_CONTROL_F	0x13
+
+/* DA9063_REG_FAULT_LOG (addr=0x05) */
+#define DA9063_TWD_ERROR	0x01
+#define DA9063_POR		0x02
+#define DA9063_NSHUTDOWN	0x40
+
+/* DA9063_REG_CONTROL_D (addr=0x11) */
+#define DA9063_TWDSCALE_MASK	0x07
+
+/* DA9063_REG_CONTROL_F (addr=0x13) */
+#define DA9063_SHUTDOWN		0x02
+
+static int da9063_watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
+{
+	struct da9063 *priv = container_of(wd, struct da9063, wd);
+	struct device_d *dev = &priv->client->dev;
+	unsigned int scale = 0;
+	int ret;
+	u8 val;
+
+	if (timeout > 131)
+		return -EINVAL;
+
+	if (timeout) {
+		timeout *= 1000; /* convert to ms */
+		scale = 0;
+		while (timeout > (2048 << scale) && scale <= 6)
+			scale++;
+		dev_dbg(dev, "calculated TWDSCALE=%u (req=%ims calc=%ims)\n",
+				scale, timeout, 2048 << scale);
+		scale++; /* scale 0 disables the WD */
+	}
+
+	ret = i2c_read_reg(priv->client, DA9063_REG_CONTROL_D, &val, 1);
+	if (ret < 0)
+		return ret;
+
+	val &= ~DA9063_TWDSCALE_MASK;
+	val |= scale;
+
+	return i2c_write_reg(priv->client, DA9063_REG_CONTROL_D, &val, 1);
+}
+
+static void da9063_detect_reset_source(struct da9063 *priv)
+{
+	int ret;
+	u8 val;
+
+	ret = i2c_read_reg(priv->client, DA9063_REG_FAULT_LOG, &val, 1);
+	if (ret < 0)
+		return;
+
+	/* Write one to clear */
+	i2c_write_reg(priv->client, DA9063_REG_FAULT_LOG, &val, 1);
+
+	if (val & DA9063_TWD_ERROR) {
+		reset_source_set(RESET_WDG);
+		return;
+	}
+
+	if (val & DA9063_POR) {
+		reset_source_set(RESET_POR);
+		return;
+	}
+
+	if (val & DA9063_NSHUTDOWN) {
+		reset_source_set(RESET_RST);
+		return;
+	}
+
+	/* else keep the default 'unknown' state */
+}
+
+static int da9063_restart(struct notifier_block *nb, unsigned long event, void *data)
+{
+	struct da9063 *priv = container_of(nb, struct da9063, notify);
+	u8 val = DA9063_SHUTDOWN;
+
+	return i2c_write_reg(priv->client, DA9063_REG_CONTROL_F, &val, 1);
+}
+
+static int da9063_probe(struct device_d *dev)
+{
+	struct da9063 *priv = NULL;
+	int ret;
+
+	priv = xzalloc(sizeof(struct da9063));
+	priv->wd.set_timeout = da9063_watchdog_set_timeout;
+	priv->client = to_i2c_client(dev);
+	priv->notify.notifier_call = da9063_restart;
+
+	ret = watchdog_register(&priv->wd);
+	if (ret)
+		goto on_error;
+
+	da9063_detect_reset_source(priv);
+
+	register_restart_handler(&priv->notify);
+
+	dev->priv = priv;
+
+	return 0;
+
+on_error:
+	if (priv)
+		free(priv);
+	return ret;
+}
+
+static struct platform_device_id da9063_id[] = {
+        { "da9063", },
+	{ }
+};
+
+static struct driver_d da9063_driver = {
+	.name = "da9063",
+	.probe = da9063_probe,
+	.id_table = da9063_id,
+};
+
+static int da9063_init(void)
+{
+	return i2c_driver_register(&da9063_driver);
+}
+
+device_initcall(da9063_init);
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 1/6] Documentation: add some info about the reset variants
  2015-06-16 11:56 [PATCH 1/6] Documentation: add some info about the reset variants Juergen Borleis
                   ` (4 preceding siblings ...)
  2015-06-16 11:56 ` [PATCH 6/6] mfd: da9063: add da9063 watchdog and system restart driver Juergen Borleis
@ 2015-06-16 12:05 ` Jürgen Borleis
  5 siblings, 0 replies; 7+ messages in thread
From: Jürgen Borleis @ 2015-06-16 12:05 UTC (permalink / raw)
  To: barebox

&($//(&($)%, please ignore this series...

jbe

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

end of thread, other threads:[~2015-06-16 12:02 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-16 11:56 [PATCH 1/6] Documentation: add some info about the reset variants Juergen Borleis
2015-06-16 11:56 ` [PATCH 2/6] Watchdog/i.MX: make the watchdog driver a regular driver Juergen Borleis
2015-06-16 11:56 ` [PATCH 3/6] MFD/DA9053: adapt driver to the current reset source framework Juergen Borleis
2015-06-16 11:56 ` [PATCH 4/6] MFD/DA9053: provide system reset Juergen Borleis
2015-06-16 11:56 ` [PATCH 5/6] MFD/DA9053: remove not required header file Juergen Borleis
2015-06-16 11:56 ` [PATCH 6/6] mfd: da9063: add da9063 watchdog and system restart driver Juergen Borleis
2015-06-16 12:05 ` [PATCH 1/6] Documentation: add some info about the reset variants Jürgen Borleis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox