* [PATCH v2 1/9] mfd: dt-bindings: Provide human readable defines for LPC mode choosing
2015-01-22 11:55 [PATCH v2 0/9] mfd: watchdog: rtc: New driver for ST's LPC IP Lee Jones
@ 2015-01-22 11:55 ` Lee Jones
2015-01-22 11:56 ` [PATCH v2 2/9] ARM: multi_v7_defconfig: Enable support for ST's LPC Watchdog Lee Jones
` (7 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Lee Jones @ 2015-01-22 11:55 UTC (permalink / raw)
To: linux-arm-kernel
ST's Low Power Controller can currently operate in two supported modes;
Watchdog and Real Time Clock. These defines will aid engineers to easily
identify the selected mode.
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
include/dt-bindings/mfd/st-lpc.h | 15 +++++++++++++++
1 file changed, 15 insertions(+)
create mode 100644 include/dt-bindings/mfd/st-lpc.h
diff --git a/include/dt-bindings/mfd/st-lpc.h b/include/dt-bindings/mfd/st-lpc.h
new file mode 100644
index 0000000..e3e6c75
--- /dev/null
+++ b/include/dt-bindings/mfd/st-lpc.h
@@ -0,0 +1,15 @@
+/*
+ * This header provides shared DT/Driver defines for ST's LPC device
+ *
+ * Copyright (C) 2014 STMicroelectronics -- All Rights Reserved
+ *
+ * Author: Lee Jones <lee.jones@linaro.org> for STMicroelectronics
+ */
+
+#ifndef __DT_BINDINGS_ST_LPC_H__
+#define __DT_BINDINGS_ST_LPC_H__
+
+#define ST_LPC_MODE_RTC 0
+#define ST_LPC_MODE_WDT 1
+
+#endif /* __DT_BINDINGS_ST_LPC_H__ */
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 2/9] ARM: multi_v7_defconfig: Enable support for ST's LPC Watchdog
2015-01-22 11:55 [PATCH v2 0/9] mfd: watchdog: rtc: New driver for ST's LPC IP Lee Jones
2015-01-22 11:55 ` [PATCH v2 1/9] mfd: dt-bindings: Provide human readable defines for LPC mode choosing Lee Jones
@ 2015-01-22 11:56 ` Lee Jones
2015-01-22 11:56 ` [PATCH v2 3/9] ARM: multi_v7_defconfig: Enable support for ST's LPC RTC Lee Jones
` (6 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Lee Jones @ 2015-01-22 11:56 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
arch/arm/configs/multi_v7_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 7afc0a2..561ca4f 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -274,6 +274,7 @@ CONFIG_WATCHDOG=y
CONFIG_XILINX_WATCHDOG=y
CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ORION_WATCHDOG=y
+CONFIG_ST_LPC_WATCHDOG=y
CONFIG_SUNXI_WATCHDOG=y
CONFIG_MESON_WATCHDOG=y
CONFIG_MFD_AS3722=y
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 3/9] ARM: multi_v7_defconfig: Enable support for ST's LPC RTC
2015-01-22 11:55 [PATCH v2 0/9] mfd: watchdog: rtc: New driver for ST's LPC IP Lee Jones
2015-01-22 11:55 ` [PATCH v2 1/9] mfd: dt-bindings: Provide human readable defines for LPC mode choosing Lee Jones
2015-01-22 11:56 ` [PATCH v2 2/9] ARM: multi_v7_defconfig: Enable support for ST's LPC Watchdog Lee Jones
@ 2015-01-22 11:56 ` Lee Jones
2015-01-22 11:56 ` [PATCH v2 4/9] ARM: STi: DT: STiH407: Add Device Tree node for the LPC Lee Jones
` (5 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Lee Jones @ 2015-01-22 11:56 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
arch/arm/configs/multi_v7_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 561ca4f..4e45e53 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -405,6 +405,7 @@ CONFIG_RTC_DRV_DS1307=y
CONFIG_RTC_DRV_MAX8907=y
CONFIG_RTC_DRV_MAX77686=y
CONFIG_RTC_DRV_PALMAS=y
+CONFIG_RTC_DRV_ST_LPC=y
CONFIG_RTC_DRV_TWL4030=y
CONFIG_RTC_DRV_TPS6586X=y
CONFIG_RTC_DRV_TPS65910=y
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 4/9] ARM: STi: DT: STiH407: Add Device Tree node for the LPC
2015-01-22 11:55 [PATCH v2 0/9] mfd: watchdog: rtc: New driver for ST's LPC IP Lee Jones
` (2 preceding siblings ...)
2015-01-22 11:56 ` [PATCH v2 3/9] ARM: multi_v7_defconfig: Enable support for ST's LPC RTC Lee Jones
@ 2015-01-22 11:56 ` Lee Jones
2015-01-23 8:39 ` David Paris
2015-01-22 11:56 ` [PATCH v2 5/9] watchdog: bindings: Provide ST bindings for ST's LPC Watchdog device Lee Jones
` (4 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Lee Jones @ 2015-01-22 11:56 UTC (permalink / raw)
To: linux-arm-kernel
On current ST platforms the LPC controls a number of functions. This
patch enables support for the LPC Watchdog and LPC RTC devices on LPC1
and LPC2 respectively.
Signed-off-by: David Paris <david.paris@st.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
arch/arm/boot/dts/stih407-family.dtsi | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
index 3e31d32..04448a7 100644
--- a/arch/arm/boot/dts/stih407-family.dtsi
+++ b/arch/arm/boot/dts/stih407-family.dtsi
@@ -7,6 +7,7 @@
* publishhed by the Free Software Foundation.
*/
#include "stih407-pinctrl.dtsi"
+#include <dt-bindings/mfd/st-lpc.h>
#include <dt-bindings/reset-controller/stih407-resets.h>
/ {
#address-cells = <1>;
@@ -274,5 +275,24 @@
status = "disabled";
};
+
+ /* Watchdog and Real-Time Clock */
+ lpc at 8787000 {
+ compatible = "st,stih407-lpc";
+ reg = <0x8787000 0x1000>;
+ interrupts = <GIC_SPI 129 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clk_s_d3_flexgen CLK_LPC_0>;
+ timeout-sec = <120>;
+ st,syscfg = <&syscfg_core>;
+ st,lpc-mode = <ST_LPC_MODE_WDT>;
+ };
+
+ lpc at 8788000 {
+ compatible = "st,stih407-lpc";
+ reg = <0x8788000 0x1000>;
+ interrupts = <GIC_SPI 130 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clk_s_d3_flexgen CLK_LPC_1>;
+ st,lpc-mode = <ST_LPC_MODE_RTC>;
+ };
};
};
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 4/9] ARM: STi: DT: STiH407: Add Device Tree node for the LPC
2015-01-22 11:56 ` [PATCH v2 4/9] ARM: STi: DT: STiH407: Add Device Tree node for the LPC Lee Jones
@ 2015-01-23 8:39 ` David Paris
2015-01-23 9:43 ` Lee Jones
2015-02-18 9:34 ` Lee Jones
0 siblings, 2 replies; 16+ messages in thread
From: David Paris @ 2015-01-23 8:39 UTC (permalink / raw)
To: linux-arm-kernel
Hi Lee,
Just a minor remark/question,
David
On 01/22/2015 12:56 PM, Lee Jones wrote:
> On current ST platforms the LPC controls a number of functions. This
> patch enables support for the LPC Watchdog and LPC RTC devices on LPC1
> and LPC2 respectively.
>
> Signed-off-by: David Paris <david.paris@st.com>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> ---
> arch/arm/boot/dts/stih407-family.dtsi | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
>
> diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
> index 3e31d32..04448a7 100644
> --- a/arch/arm/boot/dts/stih407-family.dtsi
> +++ b/arch/arm/boot/dts/stih407-family.dtsi
> @@ -7,6 +7,7 @@
> * publishhed by the Free Software Foundation.
> */
> #include "stih407-pinctrl.dtsi"
> +#include <dt-bindings/mfd/st-lpc.h>
> #include <dt-bindings/reset-controller/stih407-resets.h>
> / {
> #address-cells = <1>;
> @@ -274,5 +275,24 @@
>
> status = "disabled";
> };
> +
> + /* Watchdog and Real-Time Clock */
> + lpc at 8787000 {
> + compatible = "st,stih407-lpc";
> + reg = <0x8787000 0x1000>;
> + interrupts = <GIC_SPI 129 IRQ_TYPE_EDGE_RISING>;
In case of Watchdog, "interrupt" property is not used. So I think we can
remove it ?
> + clocks = <&clk_s_d3_flexgen CLK_LPC_0>;
> + timeout-sec = <120>;
> + st,syscfg = <&syscfg_core>;
> + st,lpc-mode = <ST_LPC_MODE_WDT>;
> + };
> +
> + lpc at 8788000 {
> + compatible = "st,stih407-lpc";
> + reg = <0x8788000 0x1000>;
> + interrupts = <GIC_SPI 130 IRQ_TYPE_EDGE_RISING>;
> + clocks = <&clk_s_d3_flexgen CLK_LPC_1>;
> + st,lpc-mode = <ST_LPC_MODE_RTC>;
> + };
> };
> };
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 4/9] ARM: STi: DT: STiH407: Add Device Tree node for the LPC
2015-01-23 8:39 ` David Paris
@ 2015-01-23 9:43 ` Lee Jones
2015-02-18 9:34 ` Lee Jones
1 sibling, 0 replies; 16+ messages in thread
From: Lee Jones @ 2015-01-23 9:43 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, 23 Jan 2015, David Paris wrote:
> Hi Lee,
>
> Just a minor remark/question,
>
> David
>
> On 01/22/2015 12:56 PM, Lee Jones wrote:
> >On current ST platforms the LPC controls a number of functions. This
> >patch enables support for the LPC Watchdog and LPC RTC devices on LPC1
> >and LPC2 respectively.
> >
> >Signed-off-by: David Paris <david.paris@st.com>
> >Signed-off-by: Lee Jones <lee.jones@linaro.org>
> >---
> > arch/arm/boot/dts/stih407-family.dtsi | 20 ++++++++++++++++++++
> > 1 file changed, 20 insertions(+)
> >
> >diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
> >index 3e31d32..04448a7 100644
> >--- a/arch/arm/boot/dts/stih407-family.dtsi
> >+++ b/arch/arm/boot/dts/stih407-family.dtsi
> >@@ -7,6 +7,7 @@
> > * publishhed by the Free Software Foundation.
> > */
> > #include "stih407-pinctrl.dtsi"
> >+#include <dt-bindings/mfd/st-lpc.h>
> > #include <dt-bindings/reset-controller/stih407-resets.h>
> > / {
> > #address-cells = <1>;
> >@@ -274,5 +275,24 @@
> > status = "disabled";
> > };
> >+
> >+ /* Watchdog and Real-Time Clock */
> >+ lpc at 8787000 {
> >+ compatible = "st,stih407-lpc";
> >+ reg = <0x8787000 0x1000>;
> >+ interrupts = <GIC_SPI 129 IRQ_TYPE_EDGE_RISING>;
> In case of Watchdog, "interrupt" property is not used. So I think we
> can remove it ?
Sure thing.
> >+ clocks = <&clk_s_d3_flexgen CLK_LPC_0>;
> >+ timeout-sec = <120>;
> >+ st,syscfg = <&syscfg_core>;
> >+ st,lpc-mode = <ST_LPC_MODE_WDT>;
> >+ };
> >+
> >+ lpc at 8788000 {
> >+ compatible = "st,stih407-lpc";
> >+ reg = <0x8788000 0x1000>;
> >+ interrupts = <GIC_SPI 130 IRQ_TYPE_EDGE_RISING>;
> >+ clocks = <&clk_s_d3_flexgen CLK_LPC_1>;
> >+ st,lpc-mode = <ST_LPC_MODE_RTC>;
> >+ };
> > };
> > };
>
--
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] 16+ messages in thread
* [PATCH v2 4/9] ARM: STi: DT: STiH407: Add Device Tree node for the LPC
2015-01-23 8:39 ` David Paris
2015-01-23 9:43 ` Lee Jones
@ 2015-02-18 9:34 ` Lee Jones
1 sibling, 0 replies; 16+ messages in thread
From: Lee Jones @ 2015-02-18 9:34 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, 23 Jan 2015, David Paris wrote:
> On 01/22/2015 12:56 PM, Lee Jones wrote:
> >On current ST platforms the LPC controls a number of functions. This
> >patch enables support for the LPC Watchdog and LPC RTC devices on LPC1
> >and LPC2 respectively.
> >
> >Signed-off-by: David Paris <david.paris@st.com>
> >Signed-off-by: Lee Jones <lee.jones@linaro.org>
> >---
> > arch/arm/boot/dts/stih407-family.dtsi | 20 ++++++++++++++++++++
> > 1 file changed, 20 insertions(+)
> >
> >diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
> >index 3e31d32..04448a7 100644
> >--- a/arch/arm/boot/dts/stih407-family.dtsi
> >+++ b/arch/arm/boot/dts/stih407-family.dtsi
> >@@ -7,6 +7,7 @@
> > * publishhed by the Free Software Foundation.
> > */
> > #include "stih407-pinctrl.dtsi"
> >+#include <dt-bindings/mfd/st-lpc.h>
> > #include <dt-bindings/reset-controller/stih407-resets.h>
> > / {
> > #address-cells = <1>;
> >@@ -274,5 +275,24 @@
> > status = "disabled";
> > };
> >+
> >+ /* Watchdog and Real-Time Clock */
> >+ lpc at 8787000 {
> >+ compatible = "st,stih407-lpc";
> >+ reg = <0x8787000 0x1000>;
> >+ interrupts = <GIC_SPI 129 IRQ_TYPE_EDGE_RISING>;
> In case of Watchdog, "interrupt" property is not used. So I think we
> can remove it ?
Although we don't use it, this still accurately describes the h/w, so
unless there are any severe objections, I think it can stay.
> >+ clocks = <&clk_s_d3_flexgen CLK_LPC_0>;
> >+ timeout-sec = <120>;
> >+ st,syscfg = <&syscfg_core>;
> >+ st,lpc-mode = <ST_LPC_MODE_WDT>;
> >+ };
> >+
> >+ lpc at 8788000 {
> >+ compatible = "st,stih407-lpc";
> >+ reg = <0x8788000 0x1000>;
> >+ interrupts = <GIC_SPI 130 IRQ_TYPE_EDGE_RISING>;
> >+ clocks = <&clk_s_d3_flexgen CLK_LPC_1>;
> >+ st,lpc-mode = <ST_LPC_MODE_RTC>;
> >+ };
> > };
> > };
>
--
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] 16+ messages in thread
* [PATCH v2 5/9] watchdog: bindings: Provide ST bindings for ST's LPC Watchdog device
2015-01-22 11:55 [PATCH v2 0/9] mfd: watchdog: rtc: New driver for ST's LPC IP Lee Jones
` (3 preceding siblings ...)
2015-01-22 11:56 ` [PATCH v2 4/9] ARM: STi: DT: STiH407: Add Device Tree node for the LPC Lee Jones
@ 2015-01-22 11:56 ` Lee Jones
2015-01-22 11:56 ` [PATCH v2 6/9] watchdog: st_wdt: Add new driver for ST's LPC Watchdog Lee Jones
` (3 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Lee Jones @ 2015-01-22 11:56 UTC (permalink / raw)
To: linux-arm-kernel
On current ST platforms the LPC controls a number of functions including
Watchdog and Real Time Clock. This patch provides the bindings used to
configure LPC in Watchdog mode.
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
.../devicetree/bindings/watchdog/st_lpc_wdt.txt | 38 ++++++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 Documentation/devicetree/bindings/watchdog/st_lpc_wdt.txt
diff --git a/Documentation/devicetree/bindings/watchdog/st_lpc_wdt.txt b/Documentation/devicetree/bindings/watchdog/st_lpc_wdt.txt
new file mode 100644
index 0000000..1bdf023
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/st_lpc_wdt.txt
@@ -0,0 +1,38 @@
+STMicroelectronics Low Power Controller (LPC) - Watchdog
+========================================================
+
+LPC currently supports Watchdog OR Real Time Clock functionality.
+
+[See: ../rtc/rtc-st-lpc.txt for RTC options]
+
+Required properties
+
+- compatible : Must be one of: "st,stih407-lpc" "st,stih416-lpc"
+ "st,stih415-lpc" "st,stid127-lpc"
+- reg : LPC registers base address + size
+- interrupts : LPC interrupt line number and associated flags
+- clocks : Clock used by LPC device (See: ../clock/clock-bindings.txt)
+- st,lpc-mode : The LPC can run either one of two modes ST_LPC_MODE_RTC [0] or
+ ST_LPC_MODE_WDT [1]. One (and only one) mode must be
+ selected.
+
+Required properties [watchdog mode]
+
+- st,syscfg : Phandle to syscfg node used to enable watchdog and configure
+ CPU reset type.
+- timeout-sec : Watchdog timeout in seconds
+
+Optional properties [watchdog mode]
+
+- st,warm-reset : If present reset type will be 'warm' - if not it will be cold
+
+Example:
+ lpc at fde05000 {
+ compatible = "st,stih416-lpc-watchdog";
+ reg = <0xfde05000 0x1000>;
+ clocks = <&clk_s_d3_flexgen CLK_LPC_0>;
+ st,syscfg = <&syscfg_core>;
+ timeout-sec = <120>;
+ st,lpc-mode = <ST_LPC_MODE_WDT>;
+ st,warm-reset;
+ };
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 6/9] watchdog: st_wdt: Add new driver for ST's LPC Watchdog
2015-01-22 11:55 [PATCH v2 0/9] mfd: watchdog: rtc: New driver for ST's LPC IP Lee Jones
` (4 preceding siblings ...)
2015-01-22 11:56 ` [PATCH v2 5/9] watchdog: bindings: Provide ST bindings for ST's LPC Watchdog device Lee Jones
@ 2015-01-22 11:56 ` Lee Jones
2015-01-22 17:10 ` Guenter Roeck
2015-01-22 11:56 ` [PATCH v2 7/9] rtc: bindings: Provide ST bindings for ST's LPC RTC device Lee Jones
` (2 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Lee Jones @ 2015-01-22 11:56 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: David Paris <david.paris@st.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
drivers/watchdog/Kconfig | 13 ++
drivers/watchdog/Makefile | 1 +
drivers/watchdog/st_lpc_wdt.c | 335 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 349 insertions(+)
create mode 100644 drivers/watchdog/st_lpc_wdt.c
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 08f41ad..a3b483c 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -471,6 +471,19 @@ config SIRFSOC_WATCHDOG
Support for CSR SiRFprimaII and SiRFatlasVI watchdog. When
the watchdog triggers the system will be reset.
+config ST_LPC_WATCHDOG
+ tristate "STMicroelectronics LPC Watchdog"
+ depends on ARCH_STI
+ depends on OF
+ select WATCHDOG_CORE
+ select MFD_ST_LPC
+ help
+ Say Y here to include STMicroelectronics Low Power Controller
+ (LPC) based Watchdog timer support.
+
+ To compile this driver as a module, choose M here: the
+ module will be called st_wdt.
+
config TEGRA_WATCHDOG
tristate "Tegra watchdog"
depends on (ARCH_TEGRA || COMPILE_TEST) && HAS_IOMEM
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index c569ec8..31dd6a0 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -59,6 +59,7 @@ obj-$(CONFIG_RETU_WATCHDOG) += retu_wdt.o
obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o
obj-$(CONFIG_MOXART_WDT) += moxart_wdt.o
obj-$(CONFIG_SIRFSOC_WATCHDOG) += sirfsoc_wdt.o
+obj-$(CONFIG_ST_LPC_WATCHDOG) += st_lpc_wdt.o
obj-$(CONFIG_QCOM_WDT) += qcom-wdt.o
obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o
obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
diff --git a/drivers/watchdog/st_lpc_wdt.c b/drivers/watchdog/st_lpc_wdt.c
new file mode 100644
index 0000000..19a7e889
--- /dev/null
+++ b/drivers/watchdog/st_lpc_wdt.c
@@ -0,0 +1,335 @@
+/*
+ * st-wdt.c - ST's LPC Watchdog
+ *
+ * Copyright (C) 2014 STMicroelectronics -- All Rights Reserved
+ *
+ * Author: David Paris <david.paris@st.com> for STMicroelectronics
+ * Lee Jones <lee.jones@linaro.org> for STMicroelectronics
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/watchdog.h>
+
+#include <dt-bindings/mfd/st-lpc.h>
+
+/* Low Power Alarm */
+#define LPC_LPA_LSB_OFF 0x410
+#define LPC_LPA_START_OFF 0x418
+
+/* LPC as WDT */
+#define LPC_WDT_OFF 0x510
+
+static struct watchdog_device st_wdog_dev;
+
+struct st_wdog_syscfg {
+ struct regmap *regmap;
+ unsigned int reset_type_reg;
+ unsigned int reset_type_mask;
+ unsigned int enable_reg;
+ unsigned int enable_mask;
+};
+
+struct st_wdog {
+ void __iomem *base;
+ struct device *dev;
+ struct st_wdog_syscfg *syscfg;
+ struct clk *clk;
+ unsigned long clkrate;
+ bool warm_reset;
+};
+
+static struct st_wdog_syscfg stid127_syscfg = {
+ .reset_type_reg = 0x004,
+ .reset_type_mask = BIT(2),
+ .enable_reg = 0x000,
+ .enable_mask = BIT(2),
+};
+
+static struct st_wdog_syscfg stih415_syscfg = {
+ .reset_type_reg = 0x0B8,
+ .reset_type_mask = BIT(6),
+ .enable_reg = 0x0B4,
+ .enable_mask = BIT(7),
+};
+
+static struct st_wdog_syscfg stih416_syscfg = {
+ .reset_type_reg = 0x88C,
+ .reset_type_mask = BIT(6),
+ .enable_reg = 0x888,
+ .enable_mask = BIT(7),
+};
+
+static struct st_wdog_syscfg stih407_syscfg = {
+ .enable_reg = 0x204,
+ .enable_mask = BIT(19),
+};
+
+static struct of_device_id st_wdog_match[] = {
+ {
+ .compatible = "st,stih407-lpc",
+ .data = &stih407_syscfg,
+ },
+ {
+ .compatible = "st,stih416-lpc",
+ .data = &stih416_syscfg,
+ },
+ {
+ .compatible = "st,stih415-lpc",
+ .data = &stih415_syscfg,
+ },
+ {
+ .compatible = "st,stid127-lpc",
+ .data = &stid127_syscfg,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, st_wdog_match);
+
+static void st_wdog_setup(struct st_wdog *st_wdog, bool enable)
+{
+ /* Type of watchdog reset - 0: Cold 1: Warm */
+ if (st_wdog->syscfg->reset_type_reg)
+ regmap_update_bits(st_wdog->syscfg->regmap,
+ st_wdog->syscfg->reset_type_reg,
+ st_wdog->syscfg->reset_type_mask,
+ st_wdog->warm_reset);
+
+ /* Mask/unmask watchdog reset */
+ regmap_update_bits(st_wdog->syscfg->regmap,
+ st_wdog->syscfg->enable_reg,
+ st_wdog->syscfg->enable_mask,
+ enable ? 0 : st_wdog->syscfg->enable_mask);
+}
+
+static void st_wdog_load_timer(struct st_wdog *st_wdog, unsigned int timeout)
+{
+ unsigned long clkrate = st_wdog->clkrate;
+
+ writel_relaxed(timeout * clkrate, st_wdog->base + LPC_LPA_LSB_OFF);
+ writel_relaxed(1, st_wdog->base + LPC_LPA_START_OFF);
+}
+
+static int st_wdog_start(struct watchdog_device *wdd)
+{
+ struct st_wdog *st_wdog = watchdog_get_drvdata(wdd);
+
+ writel_relaxed(1, st_wdog->base + LPC_WDT_OFF);
+
+ return 0;
+}
+
+static int st_wdog_stop(struct watchdog_device *wdd)
+{
+ struct st_wdog *st_wdog = watchdog_get_drvdata(wdd);
+
+ writel_relaxed(0, st_wdog->base + LPC_WDT_OFF);
+
+ return 0;
+}
+
+static int st_wdog_set_timeout(struct watchdog_device *wdd,
+ unsigned int timeout)
+{
+ struct st_wdog *st_wdog = watchdog_get_drvdata(wdd);
+
+ wdd->timeout = timeout;
+ st_wdog_load_timer(st_wdog, timeout);
+
+ return 0;
+}
+
+static int st_wdog_keepalive(struct watchdog_device *wdd)
+{
+ struct st_wdog *st_wdog = watchdog_get_drvdata(wdd);
+
+ st_wdog_load_timer(st_wdog, wdd->timeout);
+
+ return 0;
+}
+
+static const struct watchdog_info st_wdog_info = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+ .identity = "ST LPC WDT",
+};
+
+static const struct watchdog_ops st_wdog_ops = {
+ .owner = THIS_MODULE,
+ .start = st_wdog_start,
+ .stop = st_wdog_stop,
+ .ping = st_wdog_keepalive,
+ .set_timeout = st_wdog_set_timeout,
+};
+
+static struct watchdog_device st_wdog_dev = {
+ .info = &st_wdog_info,
+ .ops = &st_wdog_ops,
+};
+
+static int st_wdog_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ struct device_node *np = pdev->dev.of_node;
+ struct st_wdog *st_wdog;
+ struct regmap *regmap;
+ struct resource *res;
+ struct clk *clk;
+ void __iomem *base;
+ uint32_t mode;
+ int ret;
+
+ ret = of_property_read_u32(np, "st,lpc-mode", &mode);
+ if (ret) {
+ dev_err(&pdev->dev, "An LPC mode must be provided\n");
+ return -EINVAL;
+ }
+
+ /* LPC can either run in RTC or WDT mode */
+ if (mode != ST_LPC_MODE_WDT)
+ return -ENODEV;
+
+ st_wdog = devm_kzalloc(&pdev->dev, sizeof(*st_wdog), GFP_KERNEL);
+ if (!st_wdog)
+ return -ENOMEM;
+
+ match = of_match_device(st_wdog_match, &pdev->dev);
+ if (!match) {
+ dev_err(&pdev->dev, "Couldn't match device\n");
+ return -ENODEV;
+ }
+ st_wdog->syscfg = (struct st_wdog_syscfg *)match->data;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base)) {
+ dev_err(&pdev->dev, "Failed to ioremap base\n");
+ return PTR_ERR(base);
+ }
+
+ regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+ if (IS_ERR(regmap)) {
+ dev_err(&pdev->dev, "No syscfg phandle specified\n");
+ return PTR_ERR(regmap);
+ }
+
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "Unable to request clock\n");
+ return PTR_ERR(clk);
+ }
+
+ st_wdog->dev = &pdev->dev;
+ st_wdog->base = base;
+ st_wdog->clk = clk;
+ st_wdog->syscfg->regmap = regmap;
+ st_wdog->warm_reset = of_property_read_bool(np, "st,warm_reset");
+ st_wdog->clkrate = clk_get_rate(st_wdog->clk);
+
+ if (!st_wdog->clkrate) {
+ dev_err(&pdev->dev, "Unable to fetch clock rate\n");
+ return -EINVAL;
+ }
+ st_wdog_dev.max_timeout = 0xFFFFFFFF / st_wdog->clkrate;
+
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to enable clock\n");
+ return ret;
+ }
+
+ watchdog_set_drvdata(&st_wdog_dev, st_wdog);
+ watchdog_set_nowayout(&st_wdog_dev, WATCHDOG_NOWAYOUT);
+
+ /* Init Watchdog timeout with value in DT */
+ ret = watchdog_init_timeout(&st_wdog_dev, 0, &pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to initialise watchdog timeout\n");
+ clk_disable_unprepare(clk);
+ return ret;
+ }
+
+ ret = watchdog_register_device(&st_wdog_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to register watchdog\n");
+ clk_disable_unprepare(clk);
+ return ret;
+ }
+
+ st_wdog_setup(st_wdog, true);
+
+ dev_info(&pdev->dev, "LPC Watchdog driver registered, reset type is %s",
+ st_wdog->warm_reset ? "warm" : "cold");
+
+ return ret;
+}
+
+static int st_wdog_remove(struct platform_device *pdev)
+{
+ struct st_wdog *st_wdog = watchdog_get_drvdata(&st_wdog_dev);
+
+ st_wdog_setup(st_wdog, false);
+ watchdog_unregister_device(&st_wdog_dev);
+ clk_disable_unprepare(st_wdog->clk);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int st_wdog_suspend(struct device *dev)
+{
+ struct st_wdog *st_wdog = watchdog_get_drvdata(&st_wdog_dev);
+
+ if (watchdog_active(&st_wdog_dev))
+ st_wdog_stop(&st_wdog_dev);
+
+ st_wdog_setup(st_wdog, false);
+
+ return 0;
+}
+
+static int st_wdog_resume(struct device *dev)
+{
+ struct st_wdog *st_wdog = watchdog_get_drvdata(&st_wdog_dev);
+
+ st_wdog_setup(st_wdog, true);
+
+ if (watchdog_active(&st_wdog_dev)) {
+ st_wdog_load_timer(st_wdog, st_wdog_dev.timeout);
+ st_wdog_start(&st_wdog_dev);
+ }
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(st_wdog_pm_ops,
+ st_wdog_suspend,
+ st_wdog_resume);
+
+static struct platform_driver st_wdog_driver = {
+ .driver = {
+ .name = "st-lpc-wdt",
+ .pm = &st_wdog_pm_ops,
+ .of_match_table = st_wdog_match,
+ },
+ .probe = st_wdog_probe,
+ .remove = st_wdog_remove,
+};
+module_platform_driver(st_wdog_driver);
+
+MODULE_AUTHOR("David Paris <david.paris@st.com>");
+MODULE_DESCRIPTION("ST LPC Watchdog Driver");
+MODULE_LICENSE("GPL v2");
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 6/9] watchdog: st_wdt: Add new driver for ST's LPC Watchdog
2015-01-22 11:56 ` [PATCH v2 6/9] watchdog: st_wdt: Add new driver for ST's LPC Watchdog Lee Jones
@ 2015-01-22 17:10 ` Guenter Roeck
2015-01-22 17:21 ` Lee Jones
0 siblings, 1 reply; 16+ messages in thread
From: Guenter Roeck @ 2015-01-22 17:10 UTC (permalink / raw)
To: linux-arm-kernel
On 01/22/2015 03:56 AM, Lee Jones wrote:
> Signed-off-by: David Paris <david.paris@st.com>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> ---
> drivers/watchdog/Kconfig | 13 ++
> drivers/watchdog/Makefile | 1 +
> drivers/watchdog/st_lpc_wdt.c | 335 ++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 349 insertions(+)
> create mode 100644 drivers/watchdog/st_lpc_wdt.c
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 08f41ad..a3b483c 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -471,6 +471,19 @@ config SIRFSOC_WATCHDOG
> Support for CSR SiRFprimaII and SiRFatlasVI watchdog. When
> the watchdog triggers the system will be reset.
>
> +config ST_LPC_WATCHDOG
> + tristate "STMicroelectronics LPC Watchdog"
> + depends on ARCH_STI
> + depends on OF
> + select WATCHDOG_CORE
> + select MFD_ST_LPC
> + help
> + Say Y here to include STMicroelectronics Low Power Controller
> + (LPC) based Watchdog timer support.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called st_wdt.
> +
> config TEGRA_WATCHDOG
> tristate "Tegra watchdog"
> depends on (ARCH_TEGRA || COMPILE_TEST) && HAS_IOMEM
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index c569ec8..31dd6a0 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -59,6 +59,7 @@ obj-$(CONFIG_RETU_WATCHDOG) += retu_wdt.o
> obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o
> obj-$(CONFIG_MOXART_WDT) += moxart_wdt.o
> obj-$(CONFIG_SIRFSOC_WATCHDOG) += sirfsoc_wdt.o
> +obj-$(CONFIG_ST_LPC_WATCHDOG) += st_lpc_wdt.o
> obj-$(CONFIG_QCOM_WDT) += qcom-wdt.o
> obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o
> obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
> diff --git a/drivers/watchdog/st_lpc_wdt.c b/drivers/watchdog/st_lpc_wdt.c
> new file mode 100644
> index 0000000..19a7e889
> --- /dev/null
> +++ b/drivers/watchdog/st_lpc_wdt.c
> @@ -0,0 +1,335 @@
> +/*
> + * st-wdt.c - ST's LPC Watchdog
> + *
> + * Copyright (C) 2014 STMicroelectronics -- All Rights Reserved
> + *
> + * Author: David Paris <david.paris@st.com> for STMicroelectronics
> + * Lee Jones <lee.jones@linaro.org> for STMicroelectronics
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public Licence
> + * as published by the Free Software Foundation; either version
> + * 2 of the Licence, or (at your option) any later version.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/watchdog.h>
> +
> +#include <dt-bindings/mfd/st-lpc.h>
> +
> +/* Low Power Alarm */
> +#define LPC_LPA_LSB_OFF 0x410
> +#define LPC_LPA_START_OFF 0x418
> +
> +/* LPC as WDT */
> +#define LPC_WDT_OFF 0x510
> +
> +static struct watchdog_device st_wdog_dev;
> +
> +struct st_wdog_syscfg {
> + struct regmap *regmap;
Hi David & Lee,
Why did you add the regmap pointer to this structure and not to st_wdog ?
It is not a configuration value, after all, and it is always dereferenced
through wt_wdog->syscfg. So all it does is to make the code more complicated.
Am I missing something ?
> + unsigned int reset_type_reg;
> + unsigned int reset_type_mask;
> + unsigned int enable_reg;
> + unsigned int enable_mask;
> +};
> +
> +struct st_wdog {
> + void __iomem *base;
> + struct device *dev;
> + struct st_wdog_syscfg *syscfg;
> + struct clk *clk;
> + unsigned long clkrate;
> + bool warm_reset;
> +};
> +
> +static struct st_wdog_syscfg stid127_syscfg = {
> + .reset_type_reg = 0x004,
> + .reset_type_mask = BIT(2),
> + .enable_reg = 0x000,
> + .enable_mask = BIT(2),
> +};
> +
> +static struct st_wdog_syscfg stih415_syscfg = {
> + .reset_type_reg = 0x0B8,
> + .reset_type_mask = BIT(6),
> + .enable_reg = 0x0B4,
> + .enable_mask = BIT(7),
> +};
> +
> +static struct st_wdog_syscfg stih416_syscfg = {
> + .reset_type_reg = 0x88C,
> + .reset_type_mask = BIT(6),
> + .enable_reg = 0x888,
> + .enable_mask = BIT(7),
> +};
> +
> +static struct st_wdog_syscfg stih407_syscfg = {
> + .enable_reg = 0x204,
> + .enable_mask = BIT(19),
> +};
> +
> +static struct of_device_id st_wdog_match[] = {
> + {
> + .compatible = "st,stih407-lpc",
> + .data = &stih407_syscfg,
> + },
> + {
> + .compatible = "st,stih416-lpc",
> + .data = &stih416_syscfg,
> + },
> + {
> + .compatible = "st,stih415-lpc",
> + .data = &stih415_syscfg,
> + },
> + {
> + .compatible = "st,stid127-lpc",
> + .data = &stid127_syscfg,
> + },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, st_wdog_match);
> +
> +static void st_wdog_setup(struct st_wdog *st_wdog, bool enable)
> +{
> + /* Type of watchdog reset - 0: Cold 1: Warm */
> + if (st_wdog->syscfg->reset_type_reg)
> + regmap_update_bits(st_wdog->syscfg->regmap,
> + st_wdog->syscfg->reset_type_reg,
> + st_wdog->syscfg->reset_type_mask,
> + st_wdog->warm_reset);
> +
> + /* Mask/unmask watchdog reset */
> + regmap_update_bits(st_wdog->syscfg->regmap,
> + st_wdog->syscfg->enable_reg,
> + st_wdog->syscfg->enable_mask,
> + enable ? 0 : st_wdog->syscfg->enable_mask);
> +}
> +
> +static void st_wdog_load_timer(struct st_wdog *st_wdog, unsigned int timeout)
> +{
> + unsigned long clkrate = st_wdog->clkrate;
> +
> + writel_relaxed(timeout * clkrate, st_wdog->base + LPC_LPA_LSB_OFF);
> + writel_relaxed(1, st_wdog->base + LPC_LPA_START_OFF);
> +}
> +
> +static int st_wdog_start(struct watchdog_device *wdd)
> +{
> + struct st_wdog *st_wdog = watchdog_get_drvdata(wdd);
> +
> + writel_relaxed(1, st_wdog->base + LPC_WDT_OFF);
> +
> + return 0;
> +}
> +
> +static int st_wdog_stop(struct watchdog_device *wdd)
> +{
> + struct st_wdog *st_wdog = watchdog_get_drvdata(wdd);
> +
> + writel_relaxed(0, st_wdog->base + LPC_WDT_OFF);
> +
> + return 0;
> +}
> +
> +static int st_wdog_set_timeout(struct watchdog_device *wdd,
> + unsigned int timeout)
> +{
> + struct st_wdog *st_wdog = watchdog_get_drvdata(wdd);
> +
> + wdd->timeout = timeout;
> + st_wdog_load_timer(st_wdog, timeout);
> +
> + return 0;
> +}
> +
> +static int st_wdog_keepalive(struct watchdog_device *wdd)
> +{
> + struct st_wdog *st_wdog = watchdog_get_drvdata(wdd);
> +
> + st_wdog_load_timer(st_wdog, wdd->timeout);
> +
> + return 0;
> +}
> +
> +static const struct watchdog_info st_wdog_info = {
> + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
> + .identity = "ST LPC WDT",
> +};
> +
> +static const struct watchdog_ops st_wdog_ops = {
> + .owner = THIS_MODULE,
> + .start = st_wdog_start,
> + .stop = st_wdog_stop,
> + .ping = st_wdog_keepalive,
> + .set_timeout = st_wdog_set_timeout,
> +};
> +
> +static struct watchdog_device st_wdog_dev = {
> + .info = &st_wdog_info,
> + .ops = &st_wdog_ops,
> +};
> +
> +static int st_wdog_probe(struct platform_device *pdev)
> +{
> + const struct of_device_id *match;
> + struct device_node *np = pdev->dev.of_node;
> + struct st_wdog *st_wdog;
> + struct regmap *regmap;
> + struct resource *res;
> + struct clk *clk;
> + void __iomem *base;
> + uint32_t mode;
> + int ret;
> +
> + ret = of_property_read_u32(np, "st,lpc-mode", &mode);
> + if (ret) {
> + dev_err(&pdev->dev, "An LPC mode must be provided\n");
> + return -EINVAL;
> + }
> +
> + /* LPC can either run in RTC or WDT mode */
> + if (mode != ST_LPC_MODE_WDT)
> + return -ENODEV;
> +
> + st_wdog = devm_kzalloc(&pdev->dev, sizeof(*st_wdog), GFP_KERNEL);
> + if (!st_wdog)
> + return -ENOMEM;
> +
> + match = of_match_device(st_wdog_match, &pdev->dev);
> + if (!match) {
> + dev_err(&pdev->dev, "Couldn't match device\n");
> + return -ENODEV;
> + }
> + st_wdog->syscfg = (struct st_wdog_syscfg *)match->data;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + base = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(base)) {
> + dev_err(&pdev->dev, "Failed to ioremap base\n");
devm_ioremap_resource already displays an error message, do this one is unnecessary.
> + return PTR_ERR(base);
> + }
> +
> + regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
> + if (IS_ERR(regmap)) {
> + dev_err(&pdev->dev, "No syscfg phandle specified\n");
> + return PTR_ERR(regmap);
> + }
> +
> + clk = devm_clk_get(&pdev->dev, NULL);
> + if (IS_ERR(clk)) {
> + dev_err(&pdev->dev, "Unable to request clock\n");
> + return PTR_ERR(clk);
> + }
> +
> + st_wdog->dev = &pdev->dev;
> + st_wdog->base = base;
> + st_wdog->clk = clk;
> + st_wdog->syscfg->regmap = regmap;
> + st_wdog->warm_reset = of_property_read_bool(np, "st,warm_reset");
> + st_wdog->clkrate = clk_get_rate(st_wdog->clk);
> +
> + if (!st_wdog->clkrate) {
> + dev_err(&pdev->dev, "Unable to fetch clock rate\n");
> + return -EINVAL;
> + }
> + st_wdog_dev.max_timeout = 0xFFFFFFFF / st_wdog->clkrate;
> +
> + ret = clk_prepare_enable(clk);
> + if (ret) {
> + dev_err(&pdev->dev, "Unable to enable clock\n");
> + return ret;
> + }
> +
> + watchdog_set_drvdata(&st_wdog_dev, st_wdog);
> + watchdog_set_nowayout(&st_wdog_dev, WATCHDOG_NOWAYOUT);
> +
> + /* Init Watchdog timeout with value in DT */
> + ret = watchdog_init_timeout(&st_wdog_dev, 0, &pdev->dev);
> + if (ret) {
> + dev_err(&pdev->dev, "Unable to initialise watchdog timeout\n");
> + clk_disable_unprepare(clk);
> + return ret;
> + }
> +
> + ret = watchdog_register_device(&st_wdog_dev);
> + if (ret) {
> + dev_err(&pdev->dev, "Unable to register watchdog\n");
> + clk_disable_unprepare(clk);
> + return ret;
> + }
> +
> + st_wdog_setup(st_wdog, true);
> +
> + dev_info(&pdev->dev, "LPC Watchdog driver registered, reset type is %s",
> + st_wdog->warm_reset ? "warm" : "cold");
> +
> + return ret;
> +}
> +
> +static int st_wdog_remove(struct platform_device *pdev)
> +{
> + struct st_wdog *st_wdog = watchdog_get_drvdata(&st_wdog_dev);
> +
> + st_wdog_setup(st_wdog, false);
> + watchdog_unregister_device(&st_wdog_dev);
> + clk_disable_unprepare(st_wdog->clk);
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int st_wdog_suspend(struct device *dev)
> +{
> + struct st_wdog *st_wdog = watchdog_get_drvdata(&st_wdog_dev);
> +
> + if (watchdog_active(&st_wdog_dev))
> + st_wdog_stop(&st_wdog_dev);
> +
> + st_wdog_setup(st_wdog, false);
> +
> + return 0;
> +}
> +
> +static int st_wdog_resume(struct device *dev)
> +{
> + struct st_wdog *st_wdog = watchdog_get_drvdata(&st_wdog_dev);
> +
> + st_wdog_setup(st_wdog, true);
> +
> + if (watchdog_active(&st_wdog_dev)) {
> + st_wdog_load_timer(st_wdog, st_wdog_dev.timeout);
> + st_wdog_start(&st_wdog_dev);
> + }
> +
> + return 0;
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(st_wdog_pm_ops,
> + st_wdog_suspend,
> + st_wdog_resume);
> +
> +static struct platform_driver st_wdog_driver = {
> + .driver = {
> + .name = "st-lpc-wdt",
> + .pm = &st_wdog_pm_ops,
> + .of_match_table = st_wdog_match,
> + },
> + .probe = st_wdog_probe,
> + .remove = st_wdog_remove,
> +};
> +module_platform_driver(st_wdog_driver);
> +
> +MODULE_AUTHOR("David Paris <david.paris@st.com>");
> +MODULE_DESCRIPTION("ST LPC Watchdog Driver");
> +MODULE_LICENSE("GPL v2");
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 6/9] watchdog: st_wdt: Add new driver for ST's LPC Watchdog
2015-01-22 17:10 ` Guenter Roeck
@ 2015-01-22 17:21 ` Lee Jones
2015-01-22 19:31 ` Guenter Roeck
0 siblings, 1 reply; 16+ messages in thread
From: Lee Jones @ 2015-01-22 17:21 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, 22 Jan 2015, Guenter Roeck wrote:
> On 01/22/2015 03:56 AM, Lee Jones wrote:
> >Signed-off-by: David Paris <david.paris@st.com>
> >Signed-off-by: Lee Jones <lee.jones@linaro.org>
> >---
> > drivers/watchdog/Kconfig | 13 ++
> > drivers/watchdog/Makefile | 1 +
> > drivers/watchdog/st_lpc_wdt.c | 335 ++++++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 349 insertions(+)
> > create mode 100644 drivers/watchdog/st_lpc_wdt.c
[...]
> >+struct st_wdog_syscfg {
> >+ struct regmap *regmap;
>
> Hi David & Lee,
>
> Why did you add the regmap pointer to this structure and not to st_wdog ?
> It is not a configuration value, after all, and it is always dereferenced
> through wt_wdog->syscfg. So all it does is to make the code more complicated.
>
> Am I missing something ?
I guess it was just to group it all together, as it will all be used
at the same time:
regmap_update_bits(st_wdog->syscfg->regmap,
st_wdog->syscfg->reset_type_reg,
st_wdog->syscfg->reset_type_mask,
st_wdog->warm_reset);
It really doesn't matter to me either way.
> >+ unsigned int reset_type_reg;
> >+ unsigned int reset_type_mask;
> >+ unsigned int enable_reg;
> >+ unsigned int enable_mask;
> >+};
> >+
> >+struct st_wdog {
> >+ void __iomem *base;
> >+ struct device *dev;
> >+ struct st_wdog_syscfg *syscfg;
> >+ struct clk *clk;
> >+ unsigned long clkrate;
> >+ bool warm_reset;
> >+};
[...]
> >+static int st_wdog_probe(struct platform_device *pdev)
> >+{
> >+ const struct of_device_id *match;
> >+ struct device_node *np = pdev->dev.of_node;
> >+ struct st_wdog *st_wdog;
> >+ struct regmap *regmap;
> >+ struct resource *res;
> >+ struct clk *clk;
> >+ void __iomem *base;
> >+ uint32_t mode;
> >+ int ret;
> >+
> >+ ret = of_property_read_u32(np, "st,lpc-mode", &mode);
> >+ if (ret) {
> >+ dev_err(&pdev->dev, "An LPC mode must be provided\n");
> >+ return -EINVAL;
> >+ }
> >+
> >+ /* LPC can either run in RTC or WDT mode */
> >+ if (mode != ST_LPC_MODE_WDT)
> >+ return -ENODEV;
> >+
> >+ st_wdog = devm_kzalloc(&pdev->dev, sizeof(*st_wdog), GFP_KERNEL);
> >+ if (!st_wdog)
> >+ return -ENOMEM;
> >+
> >+ match = of_match_device(st_wdog_match, &pdev->dev);
> >+ if (!match) {
> >+ dev_err(&pdev->dev, "Couldn't match device\n");
> >+ return -ENODEV;
> >+ }
> >+ st_wdog->syscfg = (struct st_wdog_syscfg *)match->data;
> >+
> >+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >+ base = devm_ioremap_resource(&pdev->dev, res);
> >+ if (IS_ERR(base)) {
> >+ dev_err(&pdev->dev, "Failed to ioremap base\n");
>
> devm_ioremap_resource already displays an error message, do this one is unnecessary.
You're right. Will fix.
[...]
--
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] 16+ messages in thread
* [PATCH v2 6/9] watchdog: st_wdt: Add new driver for ST's LPC Watchdog
2015-01-22 17:21 ` Lee Jones
@ 2015-01-22 19:31 ` Guenter Roeck
0 siblings, 0 replies; 16+ messages in thread
From: Guenter Roeck @ 2015-01-22 19:31 UTC (permalink / raw)
To: linux-arm-kernel
On 01/22/2015 09:21 AM, Lee Jones wrote:
> On Thu, 22 Jan 2015, Guenter Roeck wrote:
>
>> On 01/22/2015 03:56 AM, Lee Jones wrote:
>>> Signed-off-by: David Paris <david.paris@st.com>
>>> Signed-off-by: Lee Jones <lee.jones@linaro.org>
>>> ---
>>> drivers/watchdog/Kconfig | 13 ++
>>> drivers/watchdog/Makefile | 1 +
>>> drivers/watchdog/st_lpc_wdt.c | 335 ++++++++++++++++++++++++++++++++++++++++++
>>> 3 files changed, 349 insertions(+)
>>> create mode 100644 drivers/watchdog/st_lpc_wdt.c
>
> [...]
>
>>> +struct st_wdog_syscfg {
>>> + struct regmap *regmap;
>>
>> Hi David & Lee,
>>
>> Why did you add the regmap pointer to this structure and not to st_wdog ?
>> It is not a configuration value, after all, and it is always dereferenced
>> through wt_wdog->syscfg. So all it does is to make the code more complicated.
>>
>> Am I missing something ?
>
> I guess it was just to group it all together, as it will all be used
> at the same time:
>
> regmap_update_bits(st_wdog->syscfg->regmap,
> st_wdog->syscfg->reset_type_reg,
> st_wdog->syscfg->reset_type_mask,
> st_wdog->warm_reset);
>
> It really doesn't matter to me either way.
>
Having it in syscfg means it is stored in the static configuration data instead
of the allocated data, which is at least conceptually wrong. So I think it should
be in st_wdog.
Thanks,
Guenter
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 7/9] rtc: bindings: Provide ST bindings for ST's LPC RTC device
2015-01-22 11:55 [PATCH v2 0/9] mfd: watchdog: rtc: New driver for ST's LPC IP Lee Jones
` (5 preceding siblings ...)
2015-01-22 11:56 ` [PATCH v2 6/9] watchdog: st_wdt: Add new driver for ST's LPC Watchdog Lee Jones
@ 2015-01-22 11:56 ` Lee Jones
2015-01-22 11:56 ` [PATCH v2 8/9] rtc: st: add new driver for ST's LPC RTC Lee Jones
2015-01-22 11:56 ` [PATCH v2 9/9] MAINTAINERS: Add Watchdog and RTC files to STI's maintainer entry Lee Jones
8 siblings, 0 replies; 16+ messages in thread
From: Lee Jones @ 2015-01-22 11:56 UTC (permalink / raw)
To: linux-arm-kernel
On current ST platforms the LPC controls a number of functions including
Watchdog and Real Time Clock. This patch provides the bindings used to
configure LPC in RTC mode.
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
.../devicetree/bindings/rtc/rtc-st-lpc.txt | 25 ++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 Documentation/devicetree/bindings/rtc/rtc-st-lpc.txt
diff --git a/Documentation/devicetree/bindings/rtc/rtc-st-lpc.txt b/Documentation/devicetree/bindings/rtc/rtc-st-lpc.txt
new file mode 100644
index 0000000..aaf9855
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-st-lpc.txt
@@ -0,0 +1,25 @@
+STMicroelectronics Low Power Controller (LPC) - RTC
+===================================================
+
+LPC currently supports Watchdog OR Real Time Clock functionality.
+
+[See: ../watchdog/st_lpc_wdt.txt for Watchdog options]
+
+Required properties
+
+- compatible : Must be one of: "st,stih407-lpc" "st,stih416-lpc"
+ "st,stih415-lpc" "st,stid127-lpc"
+- reg : LPC registers base address + size
+- interrupts : LPC interrupt line number and associated flags
+- clocks : Clock used by LPC device (See: ../clock/clock-bindings.txt)
+- st,lpc-mode : The LPC can run either one of two modes ST_LPC_MODE_RTC [0] or
+ ST_LPC_MODE_WDT [1]. One (and only one) mode must be
+ selected.
+
+Example:
+ lpc at fde05000 {
+ compatible = "st,stih416-lpc-watchdog";
+ reg = <0xfde05000 0x1000>;
+ clocks = <&clk_s_d3_flexgen CLK_LPC_0>;
+ st,lpc-mode = <ST_LPC_MODE_RTC>;
+ };
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 8/9] rtc: st: add new driver for ST's LPC RTC
2015-01-22 11:55 [PATCH v2 0/9] mfd: watchdog: rtc: New driver for ST's LPC IP Lee Jones
` (6 preceding siblings ...)
2015-01-22 11:56 ` [PATCH v2 7/9] rtc: bindings: Provide ST bindings for ST's LPC RTC device Lee Jones
@ 2015-01-22 11:56 ` Lee Jones
2015-01-22 11:56 ` [PATCH v2 9/9] MAINTAINERS: Add Watchdog and RTC files to STI's maintainer entry Lee Jones
8 siblings, 0 replies; 16+ messages in thread
From: Lee Jones @ 2015-01-22 11:56 UTC (permalink / raw)
To: linux-arm-kernel
ST's Low Power Controller (LPC) controls two devices; watchdog and RTC.
Only one of the devices can be used at any one time. This is enforced
by the correlating MFD driver. This portion of the driver-set controls
the Real Time Clock.
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
drivers/rtc/Kconfig | 12 ++
drivers/rtc/Makefile | 1 +
drivers/rtc/rtc-st-lpc.c | 354 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 367 insertions(+)
create mode 100644 drivers/rtc/rtc-st-lpc.c
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index f15cddf..ca509e8 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1417,6 +1417,18 @@ config RTC_DRV_SIRFSOC
Say "yes" here to support the real time clock on SiRF SOC chips.
This driver can also be built as a module called rtc-sirfsoc.
+config RTC_DRV_ST_LPC
+ tristate "STMicroelectronics LPC RTC"
+ depends on ARCH_STI
+ depends on OF
+ select MFD_ST_LPC
+ help
+ Say Y here to include STMicroelectronics Low Power Controller
+ (LPC) based RTC support.
+
+ To compile this driver as a module, choose M here: the
+ module will be called rtc-st-lpc.
+
config RTC_DRV_MOXART
tristate "MOXA ART RTC"
depends on ARCH_MOXART || COMPILE_TEST
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index c8ef3e1..6dbb7d9 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -149,4 +149,5 @@ obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o
obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o
+obj-$(CONFIG_RTC_DRV_ST_LPC) += rtc-st-lpc.o
obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o
diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c
new file mode 100644
index 0000000..f1344ac
--- /dev/null
+++ b/drivers/rtc/rtc-st-lpc.c
@@ -0,0 +1,354 @@
+/*
+ * rtc-st-lpc.c - ST's LPC RTC, powered by the Low Power Timer
+ *
+ * Copyright (C) 2014 STMicroelectronics Limited
+ *
+ * Author: David Paris <david.paris@st.com> for STMicroelectronics
+ * Lee Jones <lee.jones@linaro.org> for STMicroelectronics
+ *
+ * Based on the original driver written by Stuart Menefy.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+
+#include <dt-bindings/mfd/st-lpc.h>
+
+/* Low Power Timer */
+#define LPC_LPT_LSB_OFF 0x400
+#define LPC_LPT_MSB_OFF 0x404
+#define LPC_LPT_START_OFF 0x408
+
+/* Low Power Alarm */
+#define LPC_LPA_LSB_OFF 0x410
+#define LPC_LPA_MSB_OFF 0x414
+#define LPC_LPA_START_OFF 0x418
+
+/* LPC as WDT */
+#define LPC_WDT_OFF 0x510
+#define LPC_WDT_FLAG_OFF 0x514
+
+struct st_rtc {
+ struct rtc_device *rtc_dev;
+ struct rtc_wkalrm alarm;
+ struct resource *res;
+ struct clk *clk;
+ unsigned long clkrate;
+ void __iomem *ioaddr;
+ bool irq_enabled:1;
+ spinlock_t lock;
+ short irq;
+};
+
+static void st_rtc_set_hw_alarm(struct st_rtc *rtc,
+ unsigned long msb, unsigned long lsb)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtc->lock, flags);
+
+ writel(1, rtc->ioaddr + LPC_WDT_OFF);
+
+ writel(msb, rtc->ioaddr + LPC_LPA_MSB_OFF);
+ writel(lsb, rtc->ioaddr + LPC_LPA_LSB_OFF);
+ writel(1, rtc->ioaddr + LPC_LPA_START_OFF);
+
+ writel(0, rtc->ioaddr + LPC_WDT_OFF);
+
+ spin_unlock_irqrestore(&rtc->lock, flags);
+}
+
+static irqreturn_t st_rtc_handler(int this_irq, void *data)
+{
+ struct st_rtc *rtc = (struct st_rtc *)data;
+
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_AF);
+
+ return IRQ_HANDLED;
+}
+
+static int st_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct st_rtc *rtc = dev_get_drvdata(dev);
+ unsigned long lpt_lsb, lpt_msb;
+ unsigned long long lpt;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtc->lock, flags);
+
+ do {
+ lpt_msb = readl(rtc->ioaddr + LPC_LPT_MSB_OFF);
+ lpt_lsb = readl(rtc->ioaddr + LPC_LPT_LSB_OFF);
+ } while (readl(rtc->ioaddr + LPC_LPT_MSB_OFF) != lpt_msb);
+
+ spin_unlock_irqrestore(&rtc->lock, flags);
+
+ lpt = ((unsigned long long)lpt_msb << 32) | lpt_lsb;
+ do_div(lpt, rtc->clkrate);
+ rtc_time_to_tm(lpt, tm);
+
+ return 0;
+}
+
+static int st_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct st_rtc *rtc = dev_get_drvdata(dev);
+ unsigned long long lpt;
+ unsigned long secs, flags;
+ int ret;
+
+ ret = rtc_tm_to_time(tm, &secs);
+ if (ret)
+ return ret;
+
+ lpt = (unsigned long long)secs * rtc->clkrate;
+
+ spin_lock_irqsave(&rtc->lock, flags);
+
+ writel(lpt >> 32, rtc->ioaddr + LPC_LPT_MSB_OFF);
+ writel(lpt, rtc->ioaddr + LPC_LPT_LSB_OFF);
+ writel(1, rtc->ioaddr + LPC_LPT_START_OFF);
+
+ spin_unlock_irqrestore(&rtc->lock, flags);
+
+ return 0;
+}
+
+static int st_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+ struct st_rtc *rtc = dev_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtc->lock, flags);
+
+ memcpy(wkalrm, &rtc->alarm, sizeof(struct rtc_wkalrm));
+
+ spin_unlock_irqrestore(&rtc->lock, flags);
+
+ return 0;
+}
+
+static int st_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct st_rtc *rtc = dev_get_drvdata(dev);
+
+ if (enabled && !rtc->irq_enabled) {
+ enable_irq(rtc->irq);
+ rtc->irq_enabled = true;
+ } else if (!enabled && rtc->irq_enabled) {
+ disable_irq(rtc->irq);
+ rtc->irq_enabled = false;
+ }
+
+ return 0;
+}
+
+static int st_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+ struct st_rtc *rtc = dev_get_drvdata(dev);
+ struct rtc_time now;
+ unsigned long now_secs;
+ unsigned long alarm_secs;
+ unsigned long long lpa;
+
+ st_rtc_read_time(dev, &now);
+ rtc_tm_to_time(&now, &now_secs);
+ rtc_tm_to_time(&t->time, &alarm_secs);
+
+ /* Invalid alarm time */
+ if (now_secs > alarm_secs)
+ return -EINVAL;
+
+ memcpy(&rtc->alarm, t, sizeof(struct rtc_wkalrm));
+
+ /* Now many secs to fire */
+ alarm_secs -= now_secs;
+ lpa = (unsigned long long)alarm_secs * rtc->clkrate;
+
+ st_rtc_set_hw_alarm(rtc, lpa >> 32, lpa);
+ st_rtc_alarm_irq_enable(dev, t->enabled);
+
+ return 0;
+}
+
+static struct rtc_class_ops st_rtc_ops = {
+ .read_time = st_rtc_read_time,
+ .set_time = st_rtc_set_time,
+ .read_alarm = st_rtc_read_alarm,
+ .set_alarm = st_rtc_set_alarm,
+ .alarm_irq_enable = st_rtc_alarm_irq_enable,
+};
+
+static int st_rtc_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct st_rtc *rtc;
+ struct resource *res;
+ struct rtc_time tm_check;
+ uint32_t mode;
+ int ret = 0;
+
+ ret = of_property_read_u32(np, "st,lpc-mode", &mode);
+ if (ret) {
+ dev_err(&pdev->dev, "An LPC mode must be provided\n");
+ return -EINVAL;
+ }
+
+ /* LPC can either run in RTC or WDT mode */
+ if (mode != ST_LPC_MODE_RTC)
+ return -ENODEV;
+
+ rtc = devm_kzalloc(&pdev->dev, sizeof(struct st_rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ spin_lock_init(&rtc->lock);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ rtc->ioaddr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(rtc->ioaddr))
+ return PTR_ERR(rtc->ioaddr);
+
+ rtc->irq = irq_of_parse_and_map(np, 0);
+ if (!rtc->irq) {
+ dev_err(&pdev->dev, "IRQ missing or invalid\n");
+ return -EINVAL;
+ }
+
+ ret = devm_request_irq(&pdev->dev, rtc->irq, st_rtc_handler, 0,
+ pdev->name, rtc);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq %i\n", rtc->irq);
+ return ret;
+ }
+
+ enable_irq_wake(rtc->irq);
+ disable_irq(rtc->irq);
+
+ rtc->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(rtc->clk)) {
+ dev_err(&pdev->dev, "Unable to request clock\n");
+ return PTR_ERR(rtc->clk);
+ }
+
+ clk_prepare_enable(rtc->clk);
+
+ rtc->clkrate = clk_get_rate(rtc->clk);
+ if (!rtc->clkrate) {
+ dev_err(&pdev->dev, "Unable to fetch clock rate\n");
+ return -EINVAL;
+ }
+
+ device_set_wakeup_capable(&pdev->dev, 1);
+
+ platform_set_drvdata(pdev, rtc);
+
+ /*
+ * The RTC-LPC is able to manage date.year > 2038
+ * but currently the kernel can not manage this date!
+ * If the RTC-LPC has a date.year > 2038 then
+ * it's set to the epoch "Jan 1st 2000"
+ */
+ st_rtc_read_time(&pdev->dev, &tm_check);
+
+ if (tm_check.tm_year >= (2038 - 1900)) {
+ memset(&tm_check, 0, sizeof(tm_check));
+ tm_check.tm_year = 100;
+ tm_check.tm_mday = 1;
+ st_rtc_set_time(&pdev->dev, &tm_check);
+ }
+
+ rtc->rtc_dev = rtc_device_register("st-lpc-rtc", &pdev->dev,
+ &st_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc->rtc_dev)) {
+ clk_disable_unprepare(rtc->clk);
+ return PTR_ERR(rtc->rtc_dev);
+ }
+
+ return 0;
+}
+
+static int st_rtc_remove(struct platform_device *pdev)
+{
+ struct st_rtc *rtc = platform_get_drvdata(pdev);
+
+ if (likely(rtc->rtc_dev))
+ rtc_device_unregister(rtc->rtc_dev);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int st_rtc_suspend(struct device *dev)
+{
+ struct st_rtc *rtc = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ return 0;
+
+ writel(1, rtc->ioaddr + LPC_WDT_OFF);
+ writel(0, rtc->ioaddr + LPC_LPA_START_OFF);
+ writel(0, rtc->ioaddr + LPC_WDT_OFF);
+
+ return 0;
+}
+
+static int st_rtc_resume(struct device *dev)
+{
+ struct st_rtc *rtc = dev_get_drvdata(dev);
+
+ rtc_alarm_irq_enable(rtc->rtc_dev, 0);
+
+ /*
+ * clean 'rtc->alarm' to allow a new
+ * .set_alarm to the upper RTC layer
+ */
+ memset(&rtc->alarm, 0, sizeof(struct rtc_wkalrm));
+
+ writel(0, rtc->ioaddr + LPC_LPA_MSB_OFF);
+ writel(0, rtc->ioaddr + LPC_LPA_LSB_OFF);
+ writel(1, rtc->ioaddr + LPC_WDT_OFF);
+ writel(1, rtc->ioaddr + LPC_LPA_START_OFF);
+ writel(0, rtc->ioaddr + LPC_WDT_OFF);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(st_rtc_pm_ops, st_rtc_suspend, st_rtc_resume);
+
+static struct of_device_id st_rtc_match[] = {
+ { .compatible = "st,stih407-lpc" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, st_wdog_match);
+
+static struct platform_driver st_rtc_platform_driver = {
+ .driver = {
+ .name = "st-lpc-rtc",
+ .pm = &st_rtc_pm_ops,
+ .of_match_table = st_rtc_match,
+ },
+ .probe = st_rtc_probe,
+ .remove = st_rtc_remove,
+};
+
+module_platform_driver(st_rtc_platform_driver);
+
+MODULE_DESCRIPTION("STMicroelectronics LPC RTC driver");
+MODULE_AUTHOR("David Paris <david.paris@st.com>");
+MODULE_LICENSE("GPLv2");
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 9/9] MAINTAINERS: Add Watchdog and RTC files to STI's maintainer entry
2015-01-22 11:55 [PATCH v2 0/9] mfd: watchdog: rtc: New driver for ST's LPC IP Lee Jones
` (7 preceding siblings ...)
2015-01-22 11:56 ` [PATCH v2 8/9] rtc: st: add new driver for ST's LPC RTC Lee Jones
@ 2015-01-22 11:56 ` Lee Jones
8 siblings, 0 replies; 16+ messages in thread
From: Lee Jones @ 2015-01-22 11:56 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
MAINTAINERS | 2 ++
1 file changed, 2 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index ddb9ac8..7060aa6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1439,10 +1439,12 @@ F: drivers/phy/phy-stih407-usb.c
F: drivers/phy/phy-stih41x-usb.c
F: drivers/pinctrl/pinctrl-st.c
F: drivers/reset/sti/
+F: drivers/rtc/rtc-st-lpc.c
F: drivers/tty/serial/st-asc.c
F: drivers/usb/dwc3/dwc3-st.c
F: drivers/usb/host/ehci-st.c
F: drivers/usb/host/ohci-st.c
+F: drivers/watchdog/st_lpc_wdt.c
F: drivers/ata/ahci_st.c
ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread