linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/9] rtc: stmp3xxx: DT bindings and wakealarm
@ 2013-03-04 14:05 Steffen Trumtrar
  2013-03-04 14:05 ` [PATCH 1/9] MXS/i.MX28: add the possibility to define the used crystals via device tree Steffen Trumtrar
                   ` (8 more replies)
  0 siblings, 9 replies; 18+ messages in thread
From: Steffen Trumtrar @ 2013-03-04 14:05 UTC (permalink / raw)
  To: linux-arm-kernel

Hi!

This series touches multiple things in the stmp3xxx RTC:
        - DT bindings and selection for the crystal
        - add sysfs entry for persistent regs 1-5
        - check the copy controller on all writes/reads

Sorry for the multiple topics. If need be, I can split this up in multiple
series, but the series is in itself a little interdependent.

The series is based on v3.9-rc1.

Regards,
Steffen


Juergen Beisert (5):
  MXS/i.MX28: add the possibility to define the used crystals via
    device tree
  MXS/i.MX28: add the possibility to define the external RTC crystal
  MXS/i.MX28: prepare different clocking of the built-in RTC
  MXS/i.MX28: there is more than one way to clock the RTC
  MXS/i.MX28: enable RTC to wakeup the system

Steffen Trumtrar (4):
  rtc: stmp3xxx: add sysfs entries for persistent regs
  rtc: stmp3xxx: Re-enable active alarm
  rtc: stmp3xxx: Check copy controller state
  rtc: stmp3xxx: Replace wait_time function

 arch/arm/boot/dts/imx28.dtsi |   19 +++
 drivers/clk/mxs/clk-imx28.c  |   20 ++-
 drivers/rtc/rtc-stmp3xxx.c   |  275 +++++++++++++++++++++++++++++++++++++++---
 3 files changed, 297 insertions(+), 17 deletions(-)

-- 
1.7.10.4

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

* [PATCH 1/9] MXS/i.MX28: add the possibility to define the used crystals via device tree
  2013-03-04 14:05 [PATCH 0/9] rtc: stmp3xxx: DT bindings and wakealarm Steffen Trumtrar
@ 2013-03-04 14:05 ` Steffen Trumtrar
  2013-03-07  6:17   ` Shawn Guo
  2013-03-04 14:05 ` [PATCH 2/9] MXS/i.MX28: add the possibility to define the external RTC crystal Steffen Trumtrar
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Steffen Trumtrar @ 2013-03-04 14:05 UTC (permalink / raw)
  To: linux-arm-kernel

From: Juergen Beisert <jbe@pengutronix.de>

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 arch/arm/boot/dts/imx28.dtsi |   11 +++++++++++
 drivers/clk/mxs/clk-imx28.c  |   16 +++++++++++++++-
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 7ba4966..958bd10 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -37,6 +37,17 @@
 		};
 	};
 
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc24m: system_oscillator {
+			compatible = "fsl,mxs-system", "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <24000000>;
+		};
+	};
+
 	apb at 80000000 {
 		compatible = "simple-bus";
 		#address-cells = <1>;
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index 76ce6c6..01048b5 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -158,7 +158,21 @@ int __init mx28_clocks_init(void)
 
 	clk_misc_init();
 
-	clks[ref_xtal] = mxs_clk_fixed("ref_xtal", 24000000);
+	/* retrieve the crystal's frequencies from device tree */
+	for_each_compatible_node(np, NULL, "fixed-clock") {
+		u32 rate;
+
+		if (of_property_read_u32(np, "clock-frequency", &rate))
+			continue;
+
+		if (of_device_is_compatible(np, "fsl,mxs-system"))
+			clks[ref_xtal] = mxs_clk_fixed("ref_xtal", rate);
+	}
+
+	/* if not set, guess their frequency */
+	if (clks[ref_xtal] == NULL)
+		clks[ref_xtal] = mxs_clk_fixed("ref_xtal", 24000000);
+
 	clks[pll0] = mxs_clk_pll("pll0", "ref_xtal", PLL0CTRL0, 17, 480000000);
 	clks[pll1] = mxs_clk_pll("pll1", "ref_xtal", PLL1CTRL0, 17, 480000000);
 	clks[pll2] = mxs_clk_pll("pll2", "ref_xtal", PLL2CTRL0, 23, 50000000);
-- 
1.7.10.4

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

* [PATCH 2/9] MXS/i.MX28: add the possibility to define the external RTC crystal
  2013-03-04 14:05 [PATCH 0/9] rtc: stmp3xxx: DT bindings and wakealarm Steffen Trumtrar
  2013-03-04 14:05 ` [PATCH 1/9] MXS/i.MX28: add the possibility to define the used crystals via device tree Steffen Trumtrar
@ 2013-03-04 14:05 ` Steffen Trumtrar
  2013-03-07  6:33   ` Shawn Guo
  2013-03-04 14:05 ` [PATCH 3/9] MXS/i.MX28: prepare different clocking of the built-in RTC Steffen Trumtrar
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Steffen Trumtrar @ 2013-03-04 14:05 UTC (permalink / raw)
  To: linux-arm-kernel

From: Juergen Beisert <jbe@pengutronix.de>

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
---
 arch/arm/boot/dts/imx28.dtsi |    6 ++++++
 drivers/clk/mxs/clk-imx28.c  |    4 +++-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 958bd10..dcd0844 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -41,6 +41,12 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
+		osc32k: rtc_oscillator {
+			compatible = "fsl,mxs-rtc", "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+
 		osc24m: system_oscillator {
 			compatible = "fsl,mxs-system", "fixed-clock";
 			#clock-cells = <0>;
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index 01048b5..a910d72 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -141,7 +141,7 @@ enum imx28_clk {
 	clk32k_div, rtc, lradc, spdif_div, clk32k, pwm, uart, ssp0,
 	ssp1, ssp2, ssp3, gpmi, spdif, emi, saif0, saif1, lcdif, etm,
 	fec, can0, can1, usb0, usb1, usb0_phy, usb1_phy, enet_out,
-	clk_max
+	rtc_32k, clk_max
 };
 
 static struct clk *clks[clk_max];
@@ -167,6 +167,8 @@ int __init mx28_clocks_init(void)
 
 		if (of_device_is_compatible(np, "fsl,mxs-system"))
 			clks[ref_xtal] = mxs_clk_fixed("ref_xtal", rate);
+		else if (of_device_is_compatible(np, "fsl,mxs-rtc"))
+			clks[rtc_32k] = mxs_clk_fixed("rtc32k", rate);
 	}
 
 	/* if not set, guess their frequency */
-- 
1.7.10.4

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

* [PATCH 3/9] MXS/i.MX28: prepare different clocking of the built-in RTC
  2013-03-04 14:05 [PATCH 0/9] rtc: stmp3xxx: DT bindings and wakealarm Steffen Trumtrar
  2013-03-04 14:05 ` [PATCH 1/9] MXS/i.MX28: add the possibility to define the used crystals via device tree Steffen Trumtrar
  2013-03-04 14:05 ` [PATCH 2/9] MXS/i.MX28: add the possibility to define the external RTC crystal Steffen Trumtrar
@ 2013-03-04 14:05 ` Steffen Trumtrar
  2013-03-07  6:40   ` Shawn Guo
  2013-03-04 14:05 ` [PATCH 4/9] MXS/i.MX28: there is more than one way to clock the RTC Steffen Trumtrar
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Steffen Trumtrar @ 2013-03-04 14:05 UTC (permalink / raw)
  To: linux-arm-kernel

From: Juergen Beisert <jbe@pengutronix.de>

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
---
 drivers/rtc/rtc-stmp3xxx.c |    8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index 98f0d3c..7311292 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -53,18 +53,26 @@
 #define STMP3XXX_RTC_PERSISTENT0		0x60
 #define STMP3XXX_RTC_PERSISTENT0_SET		0x64
 #define STMP3XXX_RTC_PERSISTENT0_CLR		0x68
+#define STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE	(1 << 0)
 #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN	0x00000002
 #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN	0x00000004
+#define STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP (1 << 4)
+#define STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP (1 << 5)
+#define STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ	(1 << 6)
+
 #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE	0x00000080
 
 #define STMP3XXX_RTC_PERSISTENT1		0x70
 /* missing bitmask in headers */
 #define STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER	0x80000000
 
+enum clock_source { MXS_UNKNOWN, MXS_OSC_24M, MXS_OSC_32K, MXS_OSC_32K768 };
+
 struct stmp3xxx_rtc_data {
 	struct rtc_device *rtc;
 	void __iomem *io;
 	int irq_alarm;
+	enum clock_source clk_src;
 };
 
 #if IS_ENABLED(CONFIG_STMP3XXX_RTC_WATCHDOG)
-- 
1.7.10.4

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

* [PATCH 4/9] MXS/i.MX28: there is more than one way to clock the RTC
  2013-03-04 14:05 [PATCH 0/9] rtc: stmp3xxx: DT bindings and wakealarm Steffen Trumtrar
                   ` (2 preceding siblings ...)
  2013-03-04 14:05 ` [PATCH 3/9] MXS/i.MX28: prepare different clocking of the built-in RTC Steffen Trumtrar
@ 2013-03-04 14:05 ` Steffen Trumtrar
  2013-03-07  6:48   ` Shawn Guo
  2013-03-04 14:05 ` [PATCH 5/9] MXS/i.MX28: enable RTC to wakeup the system Steffen Trumtrar
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Steffen Trumtrar @ 2013-03-04 14:05 UTC (permalink / raw)
  To: linux-arm-kernel

From: Juergen Beisert <jbe@pengutronix.de>

Reflect the possibilities via device tree and configure the RTC correctly

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 arch/arm/boot/dts/imx28.dtsi |    2 ++
 drivers/rtc/rtc-stmp3xxx.c   |   76 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+)

diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index dcd0844..d89af79 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -818,6 +818,8 @@
 				compatible = "fsl,imx28-rtc", "fsl,stmp3xxx-rtc";
 				reg = <0x80056000 0x2000>;
 				interrupts = <29>;
+				clocks = <&clks 65>, <&clks 40> ;
+				clock-names = "32k", "24m";
 			};
 
 			i2c0: i2c at 80058000 {
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index 7311292..fb4b823 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/init.h>
+#include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/rtc.h>
@@ -176,11 +177,55 @@ static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id)
 	return IRQ_NONE;
 }
 
+/*
+ * To keep the energy consumption low, keep only
+ * the really used oscillator running when the power is down
+ */
+static void stmp3xxx_alarm_keep_oscillator(const struct stmp3xxx_rtc_data *rtc_data)
+{
+	switch (rtc_data->clk_src) {
+	case MXS_OSC_24M:
+		/* keep the 24 MHz oscillator running even in power down */
+		writel(STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ | /* 24 MHz / 750 */
+			STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP,
+			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
+		writel(STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
+			STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE,
+			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+		break;
+	case MXS_OSC_32K:
+		/* keep the 32 kHz oscillator running even in power down */
+		writel(STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ | /* 32 kHz */
+			STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
+			STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE,
+			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
+		writel(STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP,
+			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+		break;
+	case MXS_OSC_32K768:
+		/* keep the 32 kHz oscillator running even in power down */
+		writel(STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
+			STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE,
+			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
+		writel(STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ | /* 32.768 kHz */
+			STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP,
+			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+		break;
+	case MXS_UNKNOWN:
+	default:
+		break;
+	}
+}
+
 static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 
+	stmp3xxx_alarm_keep_oscillator(rtc_data);
+
 	if (enabled) {
+		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, /* to be able to sleep */
+			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
 		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
 				STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
 				rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
@@ -248,6 +293,8 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 {
 	struct stmp3xxx_rtc_data *rtc_data;
 	struct resource *r;
+	struct clk *clk;
+	unsigned long rate;
 	int err;
 
 	rtc_data = kzalloc(sizeof *rtc_data, GFP_KERNEL);
@@ -280,6 +327,35 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, rtc_data);
 
 	mxs_reset_block(rtc_data->io);
+
+	/*
+	 * configure the RTC to provide the correct time
+	 */
+	clk = clk_get(&pdev->dev, "32k");
+	if (IS_ERR(clk)) {
+		/* just a fall back */
+		dev_warn(&pdev->dev, "RTC's input clock undefined\n");
+		rtc_data->clk_src = MXS_OSC_24M;
+	} else {
+		rate = clk_get_rate(clk);
+		if (rate == 0) {
+			/* no dedicated external crystal */
+			rtc_data->clk_src = MXS_OSC_24M;
+			dev_info(&pdev->dev, "Using 24 MHz as RTC's clock\n");
+		} else if (rate == 32000) {
+			rtc_data->clk_src = MXS_OSC_32K;
+			dev_info(&pdev->dev, "Using 32.0 kHz as RTC's clock\n");
+		} else if (rate == 32768) {
+			rtc_data->clk_src = MXS_OSC_32K768;
+			dev_info(&pdev->dev, "Using 32.768 kHz as RTC's clock\n");
+		} else
+			dev_warn(&pdev->dev,
+				"Cannot init the RTC's clock source\n");
+	}
+
+	/* basically configure the RTC's input clock */
+	stmp3xxx_alarm_keep_oscillator(rtc_data);
+
 	writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
 			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
 			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
-- 
1.7.10.4

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

* [PATCH 5/9] MXS/i.MX28: enable RTC to wakeup the system
  2013-03-04 14:05 [PATCH 0/9] rtc: stmp3xxx: DT bindings and wakealarm Steffen Trumtrar
                   ` (3 preceding siblings ...)
  2013-03-04 14:05 ` [PATCH 4/9] MXS/i.MX28: there is more than one way to clock the RTC Steffen Trumtrar
@ 2013-03-04 14:05 ` Steffen Trumtrar
  2013-03-04 14:05 ` [PATCH 6/9] rtc: stmp3xxx: add sysfs entries for persistent regs Steffen Trumtrar
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Steffen Trumtrar @ 2013-03-04 14:05 UTC (permalink / raw)
  To: linux-arm-kernel

From: Juergen Beisert <jbe@pengutronix.de>

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
---
 drivers/rtc/rtc-stmp3xxx.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index fb4b823..936b0ca 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -365,6 +365,9 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 			STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
 			rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
 
+	/* this RTC can wake up the system */
+	device_init_wakeup(&pdev->dev, true);
+
 	rtc_data->rtc = rtc_device_register(pdev->name, &pdev->dev,
 				&stmp3xxx_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc_data->rtc)) {
-- 
1.7.10.4

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

* [PATCH 6/9] rtc: stmp3xxx: add sysfs entries for persistent regs
  2013-03-04 14:05 [PATCH 0/9] rtc: stmp3xxx: DT bindings and wakealarm Steffen Trumtrar
                   ` (4 preceding siblings ...)
  2013-03-04 14:05 ` [PATCH 5/9] MXS/i.MX28: enable RTC to wakeup the system Steffen Trumtrar
@ 2013-03-04 14:05 ` Steffen Trumtrar
  2013-03-04 15:14   ` Grant Likely
  2013-03-04 14:05 ` [PATCH 7/9] rtc: stmp3xxx: Re-enable active alarm Steffen Trumtrar
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Steffen Trumtrar @ 2013-03-04 14:05 UTC (permalink / raw)
  To: linux-arm-kernel

The persistent registers 1-5 are completely software defined. To have access
from userspace, export them via sysfs.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/rtc/rtc-stmp3xxx.c |   69 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index 936b0ca..16b45c8 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -67,6 +67,8 @@
 /* missing bitmask in headers */
 #define STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER	0x80000000
 
+#define STMP3XXX_RTC_PERSISTENT_LEN		(0xC0 - STMP3XXX_RTC_PERSISTENT1)
+
 enum clock_source { MXS_UNKNOWN, MXS_OSC_24M, MXS_OSC_32K, MXS_OSC_32K768 };
 
 struct stmp3xxx_rtc_data {
@@ -74,6 +76,9 @@ struct stmp3xxx_rtc_data {
 	void __iomem *io;
 	int irq_alarm;
 	enum clock_source clk_src;
+#if IS_ENABLED(CONFIG_RTC_INTF_SYSFS)
+	struct bin_attribute *persist;
+#endif
 };
 
 #if IS_ENABLED(CONFIG_STMP3XXX_RTC_WATCHDOG)
@@ -262,6 +267,42 @@ static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 	return 0;
 }
 
+#if IS_ENABLED(CONFIG_RTC_INTF_SYSFS)
+static ssize_t stmp3xxx_rtc_persist_read(struct file *filep,
+					 struct kobject *kobj,
+					 struct bin_attribute *bin_attr,
+					 char *buf, loff_t off, size_t size)
+{
+	struct rtc_device *rtc = container_of(kobj, struct rtc_device,
+					      dev.kobj);
+	struct device *dev = rtc->dev.parent;
+	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
+	ssize_t count;
+
+	for (count = 0; size; size--, off++, count++)
+		*buf++ = readl(rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + off);
+
+	return count;
+}
+
+static ssize_t stmp3xxx_rtc_persist_write(struct file *filep,
+					  struct kobject *kobj,
+					  struct bin_attribute *bin_attr,
+					  char *buf, loff_t off, size_t size)
+{
+	struct rtc_device *rtc = container_of(kobj, struct rtc_device,
+					      dev.kobj);
+	struct device *dev = rtc->dev.parent;
+	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
+	ssize_t count;
+
+	for (count = 0; size; size--, off++, count++)
+		writel(*buf++, rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + off);
+
+	return count;
+}
+#endif
+
 static struct rtc_class_ops stmp3xxx_rtc_ops = {
 	.alarm_irq_enable =
 			  stmp3xxx_alarm_irq_enable,
@@ -278,6 +319,11 @@ static int stmp3xxx_rtc_remove(struct platform_device *pdev)
 	if (!rtc_data)
 		return 0;
 
+#if IS_ENABLED(CONFIG_RTC_INTF_SYSFS)
+	sysfs_remove_bin_file(&pdev->dev.kobj, rtc_data->persist);
+	kfree(rtc_data->persist);
+#endif
+
 	writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
 			rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
 	free_irq(rtc_data->irq_alarm, &pdev->dev);
@@ -384,8 +430,31 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 	}
 
 	stmp3xxx_wdt_register(pdev);
+
+#if IS_ENABLED(CONFIG_RTC_INTF_SYSFS)
+	rtc_data->persist = kzalloc(sizeof(struct bin_attribute), GFP_KERNEL);
+	if (!rtc_data->persist) {
+		err = -ENOMEM;
+		goto out_persist;
+	}
+
+	rtc_data->persist->attr.name = "persistent";
+	rtc_data->persist->attr.mode = S_IRUGO | S_IWUSR;
+	sysfs_bin_attr_init(rtc_data->persist);
+	rtc_data->persist->read = stmp3xxx_rtc_persist_read;
+	rtc_data->persist->write = stmp3xxx_rtc_persist_write;
+	rtc_data->persist->size = STMP3XXX_RTC_PERSISTENT_LEN;
+	err = sysfs_create_bin_file(&rtc_data->rtc->dev.kobj,
+				rtc_data->persist);
+	if (err) {
+		kfree(rtc_data->persist);
+		goto out_persist;
+	}
+#endif
+
 	return 0;
 
+out_persist:
 out_irq_alarm:
 	rtc_device_unregister(rtc_data->rtc);
 out_remap:
-- 
1.7.10.4

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

* [PATCH 7/9] rtc: stmp3xxx: Re-enable active alarm
  2013-03-04 14:05 [PATCH 0/9] rtc: stmp3xxx: DT bindings and wakealarm Steffen Trumtrar
                   ` (5 preceding siblings ...)
  2013-03-04 14:05 ` [PATCH 6/9] rtc: stmp3xxx: add sysfs entries for persistent regs Steffen Trumtrar
@ 2013-03-04 14:05 ` Steffen Trumtrar
  2013-03-04 14:05 ` [PATCH 8/9] rtc: stmp3xxx: Check copy controller state Steffen Trumtrar
  2013-03-04 14:05 ` [PATCH 9/9] rtc: stmp3xxx: Replace wait_time function Steffen Trumtrar
  8 siblings, 0 replies; 18+ messages in thread
From: Steffen Trumtrar @ 2013-03-04 14:05 UTC (permalink / raw)
  To: linux-arm-kernel

If an alarm is set and the system rebooted, the alarm does not get re-enabled,
although it may still be valid (i.e. in the future).

The sysfs representation of wakealarms prevents overwriting active alarms. One
needs to instead write a 0 first and then the new value. Therefore an alarm is
considered active if
	wakealarm != 0 && wakealarm > now

To preserve this information over a reboot, the alarm needs to be re-written
on startup, if it is still valid. This leads to all flags being reactivated
and interrupts reenabled.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/rtc/rtc-stmp3xxx.c |   26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index 16b45c8..f31ac76 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -242,27 +242,39 @@ static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
 				rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
 		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
 				rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+		writel(0, rtc_data->io + STMP3XXX_RTC_ALARM);
 	}
 	return 0;
 }
 
-static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
+	unsigned long t;
 	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 
-	rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_ALARM), &alm->time);
+	rtc_tm_to_time(&alm->time, &t);
+	writel(t, rtc_data->io + STMP3XXX_RTC_ALARM);
+
+	stmp3xxx_alarm_irq_enable(dev, alm->enabled);
+
 	return 0;
 }
 
-static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
-	unsigned long t;
 	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
+	struct rtc_time now;
+	u32 alarm = readl(rtc_data->io + STMP3XXX_RTC_ALARM);
 
-	rtc_tm_to_time(&alm->time, &t);
-	writel(t, rtc_data->io + STMP3XXX_RTC_ALARM);
+	rtc_time_to_tm(alarm, &alm->time);
 
-	stmp3xxx_alarm_irq_enable(dev, alm->enabled);
+	stmp3xxx_rtc_gettime(dev, &now);
+	if (rtc_tm_to_ktime(now).tv64 < rtc_tm_to_ktime(alm->time).tv64) {
+		alm->enabled = 1;
+		stmp3xxx_rtc_set_alarm(dev, alm);
+	} else {
+		alm->enabled = 0;
+	}
 
 	return 0;
 }
-- 
1.7.10.4

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

* [PATCH 8/9] rtc: stmp3xxx: Check copy controller state
  2013-03-04 14:05 [PATCH 0/9] rtc: stmp3xxx: DT bindings and wakealarm Steffen Trumtrar
                   ` (6 preceding siblings ...)
  2013-03-04 14:05 ` [PATCH 7/9] rtc: stmp3xxx: Re-enable active alarm Steffen Trumtrar
@ 2013-03-04 14:05 ` Steffen Trumtrar
  2013-03-04 14:05 ` [PATCH 9/9] rtc: stmp3xxx: Replace wait_time function Steffen Trumtrar
  8 siblings, 0 replies; 18+ messages in thread
From: Steffen Trumtrar @ 2013-03-04 14:05 UTC (permalink / raw)
  To: linux-arm-kernel

The stmp3xxx has a copy controller that needs some time to copy the
analog side to the digital shadow registers. This has implications for
a correct reset behaviour.

The datasheet states that one should not reset the rtc if NEW_REGS != 0 or
a possible loss of data is to be expected.
Accordingly, one should not access the registers while STALE_REGS != 0.

If an alarm is written to the shadow registers, the copy controller does not
persist the values to the analog in every case. This is no problem in the
running kernel, but leads to lost values in case of a reboot.
Always check if the rtc is in a clean state, before writing or continueing.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/rtc/rtc-stmp3xxx.c |   89 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index f31ac76..be4fd78 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -43,8 +43,18 @@
 
 #define STMP3XXX_RTC_STAT			0x10
 #define STMP3XXX_RTC_STAT_STALE_SHIFT		16
+#define STMP3XXX_RTC_STAT_NEW_SHIFT		8
 #define STMP3XXX_RTC_STAT_RTC_PRESENT		0x80000000
 
+#define STMP3XXX_RTC_STAT_PERS0_MASK		(1 << 0)
+#define STMP3XXX_RTC_STAT_PERS1_MASK		(1 << 1)
+#define STMP3XXX_RTC_STAT_PERS2_MASK		(1 << 2)
+#define STMP3XXX_RTC_STAT_PERS3_MASK		(1 << 3)
+#define STMP3XXX_RTC_STAT_PERS4_MASK		(1 << 4)
+#define STMP3XXX_RTC_STAT_PERS5_MASK		(1 << 5)
+#define STMP3XXX_RTC_STAT_ALARM_MASK		(1 << 6)
+#define STMP3XXX_RTC_STAT_SEC_MASK		(1 << 7)
+
 #define STMP3XXX_RTC_SECONDS			0x30
 
 #define STMP3XXX_RTC_ALARM			0x40
@@ -135,6 +145,33 @@ static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev)
 }
 #endif /* CONFIG_STMP3XXX_RTC_WATCHDOG */
 
+static inline void stmp3xxx_wait_copy_ctrl(const struct stmp3xxx_rtc_data *rtc_data,
+					   const unsigned int shift,
+					   unsigned int mask)
+{
+	/*
+	 * totally random number, as the datasheet is very unclear
+	 * about the timings
+	 */
+	int timeout = 0x8000;
+
+	while ((readl(rtc_data->io + STMP3XXX_RTC_STAT) &
+			(mask << shift)) && --timeout)
+		cpu_relax();
+
+	if (unlikely(!timeout))
+		if (&rtc_data->rtc->dev)
+			dev_warn(&rtc_data->rtc->dev,
+				"possible data loss of shadow registers\n");
+		else
+			/*
+			 * When this function is called for the mxs_reset in
+			 * the probe function, rtc->dev is not yet set
+			 * FIXME: find a better/correct way to do this
+			 */
+			pr_warn("possible data loss of rtc shadow registers\n");
+}
+
 static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)
 {
 	/*
@@ -188,6 +225,9 @@ static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id)
  */
 static void stmp3xxx_alarm_keep_oscillator(const struct stmp3xxx_rtc_data *rtc_data)
 {
+	stmp3xxx_wait_copy_ctrl(rtc_data, STMP3XXX_RTC_STAT_STALE_SHIFT,
+				STMP3XXX_RTC_STAT_PERS0_MASK);
+
 	switch (rtc_data->clk_src) {
 	case MXS_OSC_24M:
 		/* keep the 24 MHz oscillator running even in power down */
@@ -220,6 +260,9 @@ static void stmp3xxx_alarm_keep_oscillator(const struct stmp3xxx_rtc_data *rtc_d
 	default:
 		break;
 	}
+
+	stmp3xxx_wait_copy_ctrl(rtc_data, STMP3XXX_RTC_STAT_NEW_SHIFT,
+				STMP3XXX_RTC_STAT_PERS0_MASK);
 }
 
 static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
@@ -228,6 +271,10 @@ static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
 
 	stmp3xxx_alarm_keep_oscillator(rtc_data);
 
+	stmp3xxx_wait_copy_ctrl(rtc_data, STMP3XXX_RTC_STAT_STALE_SHIFT,
+				STMP3XXX_RTC_STAT_PERS0_MASK |
+				STMP3XXX_RTC_STAT_ALARM_MASK);
+
 	if (enabled) {
 		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, /* to be able to sleep */
 			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
@@ -244,6 +291,10 @@ static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
 				rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
 		writel(0, rtc_data->io + STMP3XXX_RTC_ALARM);
 	}
+	stmp3xxx_wait_copy_ctrl(rtc_data, STMP3XXX_RTC_STAT_NEW_SHIFT,
+				STMP3XXX_RTC_STAT_PERS0_MASK |
+				STMP3XXX_RTC_STAT_ALARM_MASK);
+
 	return 0;
 }
 
@@ -253,10 +304,16 @@ static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 
 	rtc_tm_to_time(&alm->time, &t);
+
+	stmp3xxx_wait_copy_ctrl(rtc_data, STMP3XXX_RTC_STAT_STALE_SHIFT,
+				STMP3XXX_RTC_STAT_ALARM_MASK);
+
 	writel(t, rtc_data->io + STMP3XXX_RTC_ALARM);
 
-	stmp3xxx_alarm_irq_enable(dev, alm->enabled);
+	stmp3xxx_wait_copy_ctrl(rtc_data, STMP3XXX_RTC_STAT_NEW_SHIFT,
+				STMP3XXX_RTC_STAT_ALARM_MASK);
 
+	stmp3xxx_alarm_irq_enable(dev, alm->enabled);
 	return 0;
 }
 
@@ -291,6 +348,13 @@ static ssize_t stmp3xxx_rtc_persist_read(struct file *filep,
 	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 	ssize_t count;
 
+	stmp3xxx_wait_copy_ctrl(rtc_data, STMP3XXX_RTC_STAT_STALE_SHIFT,
+				STMP3XXX_RTC_STAT_PERS1_MASK |
+				STMP3XXX_RTC_STAT_PERS2_MASK |
+				STMP3XXX_RTC_STAT_PERS3_MASK |
+				STMP3XXX_RTC_STAT_PERS4_MASK |
+				STMP3XXX_RTC_STAT_PERS5_MASK);
+
 	for (count = 0; size; size--, off++, count++)
 		*buf++ = readl(rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + off);
 
@@ -311,6 +375,13 @@ static ssize_t stmp3xxx_rtc_persist_write(struct file *filep,
 	for (count = 0; size; size--, off++, count++)
 		writel(*buf++, rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + off);
 
+	stmp3xxx_wait_copy_ctrl(rtc_data, STMP3XXX_RTC_STAT_NEW_SHIFT,
+				STMP3XXX_RTC_STAT_PERS1_MASK |
+				STMP3XXX_RTC_STAT_PERS2_MASK |
+				STMP3XXX_RTC_STAT_PERS3_MASK |
+				STMP3XXX_RTC_STAT_PERS4_MASK |
+				STMP3XXX_RTC_STAT_PERS5_MASK);
+
 	return count;
 }
 #endif
@@ -384,7 +455,23 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, rtc_data);
 
+	stmp3xxx_wait_copy_ctrl(rtc_data, STMP3XXX_RTC_STAT_NEW_SHIFT,
+				STMP3XXX_RTC_STAT_PERS1_MASK |
+				STMP3XXX_RTC_STAT_PERS2_MASK |
+				STMP3XXX_RTC_STAT_PERS3_MASK |
+				STMP3XXX_RTC_STAT_PERS4_MASK |
+				STMP3XXX_RTC_STAT_PERS5_MASK |
+				STMP3XXX_RTC_STAT_ALARM_MASK |
+				STMP3XXX_RTC_STAT_SEC_MASK);
 	mxs_reset_block(rtc_data->io);
+	stmp3xxx_wait_copy_ctrl(rtc_data, STMP3XXX_RTC_STAT_STALE_SHIFT,
+				STMP3XXX_RTC_STAT_PERS1_MASK |
+				STMP3XXX_RTC_STAT_PERS2_MASK |
+				STMP3XXX_RTC_STAT_PERS3_MASK |
+				STMP3XXX_RTC_STAT_PERS4_MASK |
+				STMP3XXX_RTC_STAT_PERS5_MASK |
+				STMP3XXX_RTC_STAT_ALARM_MASK |
+				STMP3XXX_RTC_STAT_SEC_MASK);
 
 	/*
 	 * configure the RTC to provide the correct time
-- 
1.7.10.4

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

* [PATCH 9/9] rtc: stmp3xxx: Replace wait_time function
  2013-03-04 14:05 [PATCH 0/9] rtc: stmp3xxx: DT bindings and wakealarm Steffen Trumtrar
                   ` (7 preceding siblings ...)
  2013-03-04 14:05 ` [PATCH 8/9] rtc: stmp3xxx: Check copy controller state Steffen Trumtrar
@ 2013-03-04 14:05 ` Steffen Trumtrar
  8 siblings, 0 replies; 18+ messages in thread
From: Steffen Trumtrar @ 2013-03-04 14:05 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the wait_time function with the more generic wait_copy_ctrl function.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/rtc/rtc-stmp3xxx.c |   18 ++++--------------
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index be4fd78..35a92cd 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -172,24 +172,13 @@ static inline void stmp3xxx_wait_copy_ctrl(const struct stmp3xxx_rtc_data *rtc_d
 			pr_warn("possible data loss of rtc shadow registers\n");
 }
 
-static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)
-{
-	/*
-	 * The datasheet doesn't say which way round the
-	 * NEW_REGS/STALE_REGS bitfields go. In fact it's 0x1=P0,
-	 * 0x2=P1, .., 0x20=P5, 0x40=ALARM, 0x80=SECONDS
-	 */
-	while (readl(rtc_data->io + STMP3XXX_RTC_STAT) &
-			(0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT))
-		cpu_relax();
-}
-
 /* Time read/write */
 static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
 {
 	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 
-	stmp3xxx_wait_time(rtc_data);
+	stmp3xxx_wait_copy_ctrl(rtc_data, STMP3XXX_RTC_STAT_STALE_SHIFT,
+				STMP3XXX_RTC_STAT_SEC_MASK);
 	rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_SECONDS), rtc_tm);
 	return 0;
 }
@@ -199,7 +188,8 @@ static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t)
 	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 
 	writel(t, rtc_data->io + STMP3XXX_RTC_SECONDS);
-	stmp3xxx_wait_time(rtc_data);
+	stmp3xxx_wait_copy_ctrl(rtc_data, STMP3XXX_RTC_STAT_NEW_SHIFT,
+				STMP3XXX_RTC_STAT_SEC_MASK);
 	return 0;
 }
 
-- 
1.7.10.4

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

* [PATCH 6/9] rtc: stmp3xxx: add sysfs entries for persistent regs
  2013-03-04 14:05 ` [PATCH 6/9] rtc: stmp3xxx: add sysfs entries for persistent regs Steffen Trumtrar
@ 2013-03-04 15:14   ` Grant Likely
  2013-03-05  8:02     ` Steffen Trumtrar
  0 siblings, 1 reply; 18+ messages in thread
From: Grant Likely @ 2013-03-04 15:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 4, 2013 at 10:05 PM, Steffen Trumtrar
<s.trumtrar@pengutronix.de> wrote:
> The persistent registers 1-5 are completely software defined. To have access
> from userspace, export them via sysfs.
>
> Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>

Hi Steffen,

A few comments on this. First and foremost, any additions to the
kernel sysfs interface must be accompanied with documentation in
Documentation/ABI/. Second, adding attributes to an existing device
that has already been registered is almost guaranteed to be wrong. The
attributes need to be added all at the same time so they are available
immediately when the new device uevent is issued by the kernel.

Instead, the correct thing to do is add an attribute_group to the
child device before the device gets registered. See the 'attributes'
section of Documentation/driver-model/device.txt to see how to do
this.

(I also see that the rtc core code is doing the wrong thing here also.
rtc_sysfs_add_device(), rtc_sysfs_add_device() should also be replaced
with an attribute group so that the sysfs files get added
automatically; but that is outside the scope of this patch)

g.

> ---
>  drivers/rtc/rtc-stmp3xxx.c |   69 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 69 insertions(+)
>
> diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
> index 936b0ca..16b45c8 100644
> --- a/drivers/rtc/rtc-stmp3xxx.c
> +++ b/drivers/rtc/rtc-stmp3xxx.c
> @@ -67,6 +67,8 @@
>  /* missing bitmask in headers */
>  #define STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER 0x80000000
>
> +#define STMP3XXX_RTC_PERSISTENT_LEN            (0xC0 - STMP3XXX_RTC_PERSISTENT1)
> +
>  enum clock_source { MXS_UNKNOWN, MXS_OSC_24M, MXS_OSC_32K, MXS_OSC_32K768 };
>
>  struct stmp3xxx_rtc_data {
> @@ -74,6 +76,9 @@ struct stmp3xxx_rtc_data {
>         void __iomem *io;
>         int irq_alarm;
>         enum clock_source clk_src;
> +#if IS_ENABLED(CONFIG_RTC_INTF_SYSFS)
> +       struct bin_attribute *persist;
> +#endif
>  };
>
>  #if IS_ENABLED(CONFIG_STMP3XXX_RTC_WATCHDOG)
> @@ -262,6 +267,42 @@ static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
>         return 0;
>  }
>
> +#if IS_ENABLED(CONFIG_RTC_INTF_SYSFS)
> +static ssize_t stmp3xxx_rtc_persist_read(struct file *filep,
> +                                        struct kobject *kobj,
> +                                        struct bin_attribute *bin_attr,
> +                                        char *buf, loff_t off, size_t size)
> +{
> +       struct rtc_device *rtc = container_of(kobj, struct rtc_device,
> +                                             dev.kobj);
> +       struct device *dev = rtc->dev.parent;
> +       struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
> +       ssize_t count;
> +
> +       for (count = 0; size; size--, off++, count++)
> +               *buf++ = readl(rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + off);
> +
> +       return count;
> +}
> +
> +static ssize_t stmp3xxx_rtc_persist_write(struct file *filep,
> +                                         struct kobject *kobj,
> +                                         struct bin_attribute *bin_attr,
> +                                         char *buf, loff_t off, size_t size)
> +{
> +       struct rtc_device *rtc = container_of(kobj, struct rtc_device,
> +                                             dev.kobj);
> +       struct device *dev = rtc->dev.parent;
> +       struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
> +       ssize_t count;
> +
> +       for (count = 0; size; size--, off++, count++)
> +               writel(*buf++, rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + off);
> +
> +       return count;
> +}
> +#endif
> +
>  static struct rtc_class_ops stmp3xxx_rtc_ops = {
>         .alarm_irq_enable =
>                           stmp3xxx_alarm_irq_enable,
> @@ -278,6 +319,11 @@ static int stmp3xxx_rtc_remove(struct platform_device *pdev)
>         if (!rtc_data)
>                 return 0;
>
> +#if IS_ENABLED(CONFIG_RTC_INTF_SYSFS)
> +       sysfs_remove_bin_file(&pdev->dev.kobj, rtc_data->persist);
> +       kfree(rtc_data->persist);
> +#endif
> +
>         writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
>                         rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
>         free_irq(rtc_data->irq_alarm, &pdev->dev);
> @@ -384,8 +430,31 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
>         }
>
>         stmp3xxx_wdt_register(pdev);
> +
> +#if IS_ENABLED(CONFIG_RTC_INTF_SYSFS)
> +       rtc_data->persist = kzalloc(sizeof(struct bin_attribute), GFP_KERNEL);
> +       if (!rtc_data->persist) {
> +               err = -ENOMEM;
> +               goto out_persist;
> +       }
> +
> +       rtc_data->persist->attr.name = "persistent";
> +       rtc_data->persist->attr.mode = S_IRUGO | S_IWUSR;
> +       sysfs_bin_attr_init(rtc_data->persist);
> +       rtc_data->persist->read = stmp3xxx_rtc_persist_read;
> +       rtc_data->persist->write = stmp3xxx_rtc_persist_write;
> +       rtc_data->persist->size = STMP3XXX_RTC_PERSISTENT_LEN;
> +       err = sysfs_create_bin_file(&rtc_data->rtc->dev.kobj,
> +                               rtc_data->persist);
> +       if (err) {
> +               kfree(rtc_data->persist);
> +               goto out_persist;
> +       }
> +#endif
> +
>         return 0;
>
> +out_persist:
>  out_irq_alarm:
>         rtc_device_unregister(rtc_data->rtc);
>  out_remap:
> --
> 1.7.10.4
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss



--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

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

* [PATCH 6/9] rtc: stmp3xxx: add sysfs entries for persistent regs
  2013-03-04 15:14   ` Grant Likely
@ 2013-03-05  8:02     ` Steffen Trumtrar
  2013-03-06 13:27       ` Steffen Trumtrar
  0 siblings, 1 reply; 18+ messages in thread
From: Steffen Trumtrar @ 2013-03-05  8:02 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Grant!

On Mon, Mar 04, 2013 at 11:14:54PM +0800, Grant Likely wrote:
> On Mon, Mar 4, 2013 at 10:05 PM, Steffen Trumtrar
> <s.trumtrar@pengutronix.de> wrote:
> > The persistent registers 1-5 are completely software defined. To have access
> > from userspace, export them via sysfs.
> >
> > Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
> 
> Hi Steffen,
> 
> A few comments on this. First and foremost, any additions to the
> kernel sysfs interface must be accompanied with documentation in
> Documentation/ABI/. Second, adding attributes to an existing device

Okay. I forgot that and will add it in the next version.

> that has already been registered is almost guaranteed to be wrong. The
> attributes need to be added all at the same time so they are available
> immediately when the new device uevent is issued by the kernel.
> 
> Instead, the correct thing to do is add an attribute_group to the
> child device before the device gets registered. See the 'attributes'
> section of Documentation/driver-model/device.txt to see how to do
> this.
> 
> (I also see that the rtc core code is doing the wrong thing here also.
> rtc_sysfs_add_device(), rtc_sysfs_add_device() should also be replaced
> with an attribute group so that the sysfs files get added
> automatically; but that is outside the scope of this patch)
> 

Hm, I modeled it after other rtcs and the rtc_sysfs. Seems that I have to
rework this.

Thanks,
Steffen

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* [PATCH 6/9] rtc: stmp3xxx: add sysfs entries for persistent regs
  2013-03-05  8:02     ` Steffen Trumtrar
@ 2013-03-06 13:27       ` Steffen Trumtrar
  0 siblings, 0 replies; 18+ messages in thread
From: Steffen Trumtrar @ 2013-03-06 13:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Mar 05, 2013 at 09:02:52AM +0100, Steffen Trumtrar wrote:
> Hi Grant!
> 
> On Mon, Mar 04, 2013 at 11:14:54PM +0800, Grant Likely wrote:
> > On Mon, Mar 4, 2013 at 10:05 PM, Steffen Trumtrar
> > <s.trumtrar@pengutronix.de> wrote:
> > > The persistent registers 1-5 are completely software defined. To have access
> > > from userspace, export them via sysfs.
> > >
> > > Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
> > 
> > Hi Steffen,
> > 
> > A few comments on this. First and foremost, any additions to the
> > kernel sysfs interface must be accompanied with documentation in
> > Documentation/ABI/. Second, adding attributes to an existing device
> 
> Okay. I forgot that and will add it in the next version.
> 
> > that has already been registered is almost guaranteed to be wrong. The
> > attributes need to be added all at the same time so they are available
> > immediately when the new device uevent is issued by the kernel.
> > 
> > Instead, the correct thing to do is add an attribute_group to the
> > child device before the device gets registered. See the 'attributes'
> > section of Documentation/driver-model/device.txt to see how to do
> > this.
> > 
> > (I also see that the rtc core code is doing the wrong thing here also.
> > rtc_sysfs_add_device(), rtc_sysfs_add_device() should also be replaced
> > with an attribute group so that the sysfs files get added
> > automatically; but that is outside the scope of this patch)
> > 
> 
> Hm, I modeled it after other rtcs and the rtc_sysfs. Seems that I have to
> rework this.

Okay. Wait. I looked at it again. What I want to do is adding the persistent
registers as a binary-attribute. Basically having nvram like other rtcs.
Is that even possible with attribute group? Would I add the attr inside the
bin_attribute to the group then?
Or is it wrong to add these regs as binary?

Thanks,
Steffen

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* [PATCH 1/9] MXS/i.MX28: add the possibility to define the used crystals via device tree
  2013-03-04 14:05 ` [PATCH 1/9] MXS/i.MX28: add the possibility to define the used crystals via device tree Steffen Trumtrar
@ 2013-03-07  6:17   ` Shawn Guo
  0 siblings, 0 replies; 18+ messages in thread
From: Shawn Guo @ 2013-03-07  6:17 UTC (permalink / raw)
  To: linux-arm-kernel

For patches that you intend to go via mxs tree, please prefix it with
something like "ARM: mxs: ...".

On Mon, Mar 04, 2013 at 03:05:40PM +0100, Steffen Trumtrar wrote:
> From: Juergen Beisert <jbe@pengutronix.de>
> 
Please do something with commit log.

> Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
> Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
> ---
>  arch/arm/boot/dts/imx28.dtsi |   11 +++++++++++
>  drivers/clk/mxs/clk-imx28.c  |   16 +++++++++++++++-
>  2 files changed, 26 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> index 7ba4966..958bd10 100644
> --- a/arch/arm/boot/dts/imx28.dtsi
> +++ b/arch/arm/boot/dts/imx28.dtsi
> @@ -37,6 +37,17 @@
>  		};
>  	};
>  
> +	clocks {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		osc24m: system_oscillator {
> +			compatible = "fsl,mxs-system", "fixed-clock";
> +			#clock-cells = <0>;
> +			clock-frequency = <24000000>;
> +		};
> +	};
> +
>  	apb at 80000000 {
>  		compatible = "simple-bus";
>  		#address-cells = <1>;
> diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
> index 76ce6c6..01048b5 100644
> --- a/drivers/clk/mxs/clk-imx28.c
> +++ b/drivers/clk/mxs/clk-imx28.c
> @@ -158,7 +158,21 @@ int __init mx28_clocks_init(void)
>  
>  	clk_misc_init();
>  
> -	clks[ref_xtal] = mxs_clk_fixed("ref_xtal", 24000000);
> +	/* retrieve the crystal's frequencies from device tree */
> +	for_each_compatible_node(np, NULL, "fixed-clock") {
> +		u32 rate;
> +
> +		if (of_property_read_u32(np, "clock-frequency", &rate))
> +			continue;
> +
> +		if (of_device_is_compatible(np, "fsl,mxs-system"))
> +			clks[ref_xtal] = mxs_clk_fixed("ref_xtal", rate);
> +	}
> +
> +	/* if not set, guess their frequency */
> +	if (clks[ref_xtal] == NULL)
> +		clks[ref_xtal] = mxs_clk_fixed("ref_xtal", 24000000);
> +

I think ref_xtal has to be 24 MHz, no?

Shawn

>  	clks[pll0] = mxs_clk_pll("pll0", "ref_xtal", PLL0CTRL0, 17, 480000000);
>  	clks[pll1] = mxs_clk_pll("pll1", "ref_xtal", PLL1CTRL0, 17, 480000000);
>  	clks[pll2] = mxs_clk_pll("pll2", "ref_xtal", PLL2CTRL0, 23, 50000000);
> -- 
> 1.7.10.4
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 2/9] MXS/i.MX28: add the possibility to define the external RTC crystal
  2013-03-04 14:05 ` [PATCH 2/9] MXS/i.MX28: add the possibility to define the external RTC crystal Steffen Trumtrar
@ 2013-03-07  6:33   ` Shawn Guo
  0 siblings, 0 replies; 18+ messages in thread
From: Shawn Guo @ 2013-03-07  6:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 04, 2013 at 03:05:41PM +0100, Steffen Trumtrar wrote:
> From: Juergen Beisert <jbe@pengutronix.de>
> 
> Signed-off-by: Juergen Beisert <jbe@pengutronix.de>

You should have your SoB added here.

> ---
>  arch/arm/boot/dts/imx28.dtsi |    6 ++++++
>  drivers/clk/mxs/clk-imx28.c  |    4 +++-
>  2 files changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> index 958bd10..dcd0844 100644
> --- a/arch/arm/boot/dts/imx28.dtsi
> +++ b/arch/arm/boot/dts/imx28.dtsi
> @@ -41,6 +41,12 @@
>  		#address-cells = <1>;
>  		#size-cells = <0>;
>  
> +		osc32k: rtc_oscillator {

Please use "-" than "_" in node name.

> +			compatible = "fsl,mxs-rtc", "fixed-clock";

I would suggest drop "fsl,mxs-rtc" here, and ...

> +			#clock-cells = <0>;
> +			clock-frequency = <0>;
> +		};
> +
>  		osc24m: system_oscillator {
>  			compatible = "fsl,mxs-system", "fixed-clock";
>  			#clock-cells = <0>;
> diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
> index 01048b5..a910d72 100644
> --- a/drivers/clk/mxs/clk-imx28.c
> +++ b/drivers/clk/mxs/clk-imx28.c
> @@ -141,7 +141,7 @@ enum imx28_clk {
>  	clk32k_div, rtc, lradc, spdif_div, clk32k, pwm, uart, ssp0,
>  	ssp1, ssp2, ssp3, gpmi, spdif, emi, saif0, saif1, lcdif, etm,
>  	fec, can0, can1, usb0, usb1, usb0_phy, usb1_phy, enet_out,
> -	clk_max
> +	rtc_32k, clk_max

Number it in binding doc.

>  };
>  
>  static struct clk *clks[clk_max];
> @@ -167,6 +167,8 @@ int __init mx28_clocks_init(void)
>  
>  		if (of_device_is_compatible(np, "fsl,mxs-system"))
>  			clks[ref_xtal] = mxs_clk_fixed("ref_xtal", rate);
> +		else if (of_device_is_compatible(np, "fsl,mxs-rtc"))

... use node name to match, so that we can save a custom compatible.

Shawn

> +			clks[rtc_32k] = mxs_clk_fixed("rtc32k", rate);
>  	}
>  
>  	/* if not set, guess their frequency */
> -- 
> 1.7.10.4
> 

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

* [PATCH 3/9] MXS/i.MX28: prepare different clocking of the built-in RTC
  2013-03-04 14:05 ` [PATCH 3/9] MXS/i.MX28: prepare different clocking of the built-in RTC Steffen Trumtrar
@ 2013-03-07  6:40   ` Shawn Guo
  0 siblings, 0 replies; 18+ messages in thread
From: Shawn Guo @ 2013-03-07  6:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 04, 2013 at 03:05:42PM +0100, Steffen Trumtrar wrote:
> From: Juergen Beisert <jbe@pengutronix.de>
> 
> Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
> ---
>  drivers/rtc/rtc-stmp3xxx.c |    8 ++++++++
>  1 file changed, 8 insertions(+)

So this is a rtc patch, and should be prefixed with "rtc: stmp3xxx: "
like patches #6~9.

And IMO, all the changes in this patch can just be added together with
the codes that use them.  IOW, it can be merged into patch #4.

> 
> diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
> index 98f0d3c..7311292 100644
> --- a/drivers/rtc/rtc-stmp3xxx.c
> +++ b/drivers/rtc/rtc-stmp3xxx.c
> @@ -53,18 +53,26 @@
>  #define STMP3XXX_RTC_PERSISTENT0		0x60
>  #define STMP3XXX_RTC_PERSISTENT0_SET		0x64
>  #define STMP3XXX_RTC_PERSISTENT0_CLR		0x68
> +#define STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE	(1 << 0)
>  #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN	0x00000002
>  #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN	0x00000004
> +#define STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP (1 << 4)
> +#define STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP (1 << 5)
> +#define STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ	(1 << 6)
> +
>  #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE	0x00000080
>  
>  #define STMP3XXX_RTC_PERSISTENT1		0x70
>  /* missing bitmask in headers */
>  #define STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER	0x80000000
>  
> +enum clock_source { MXS_UNKNOWN, MXS_OSC_24M, MXS_OSC_32K, MXS_OSC_32K768 };
> +
We generic write it like

enum clock_source {
        MXS_UNKNOWN,
        MXS_OSC_24M,
        MXS_OSC_32K,
        MXS_OSC_32K768
};

Shawn

>  struct stmp3xxx_rtc_data {
>  	struct rtc_device *rtc;
>  	void __iomem *io;
>  	int irq_alarm;
> +	enum clock_source clk_src;
>  };
>  
>  #if IS_ENABLED(CONFIG_STMP3XXX_RTC_WATCHDOG)
> -- 
> 1.7.10.4
> 

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

* [PATCH 4/9] MXS/i.MX28: there is more than one way to clock the RTC
  2013-03-04 14:05 ` [PATCH 4/9] MXS/i.MX28: there is more than one way to clock the RTC Steffen Trumtrar
@ 2013-03-07  6:48   ` Shawn Guo
  2013-03-07  8:19     ` Steffen Trumtrar
  0 siblings, 1 reply; 18+ messages in thread
From: Shawn Guo @ 2013-03-07  6:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 04, 2013 at 03:05:43PM +0100, Steffen Trumtrar wrote:
> From: Juergen Beisert <jbe@pengutronix.de>
> 
> Reflect the possibilities via device tree and configure the RTC correctly
> 
> Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
> Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
> ---
>  arch/arm/boot/dts/imx28.dtsi |    2 ++
>  drivers/rtc/rtc-stmp3xxx.c   |   76 ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 78 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> index dcd0844..d89af79 100644
> --- a/arch/arm/boot/dts/imx28.dtsi
> +++ b/arch/arm/boot/dts/imx28.dtsi
> @@ -818,6 +818,8 @@
>  				compatible = "fsl,imx28-rtc", "fsl,stmp3xxx-rtc";
>  				reg = <0x80056000 0x2000>;
>  				interrupts = <29>;
> +				clocks = <&clks 65>, <&clks 40> ;
> +				clock-names = "32k", "24m";

The changes should be in some mxs/arch patch.

>  			};
>  
>  			i2c0: i2c at 80058000 {
> diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
> index 7311292..fb4b823 100644
> --- a/drivers/rtc/rtc-stmp3xxx.c
> +++ b/drivers/rtc/rtc-stmp3xxx.c
> @@ -21,6 +21,7 @@
>  #include <linux/module.h>
>  #include <linux/io.h>
>  #include <linux/init.h>
> +#include <linux/clk.h>
>  #include <linux/platform_device.h>
>  #include <linux/interrupt.h>
>  #include <linux/rtc.h>
> @@ -176,11 +177,55 @@ static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id)
>  	return IRQ_NONE;
>  }
>  
> +/*
> + * To keep the energy consumption low, keep only
> + * the really used oscillator running when the power is down
> + */
> +static void stmp3xxx_alarm_keep_oscillator(const struct stmp3xxx_rtc_data *rtc_data)
> +{
> +	switch (rtc_data->clk_src) {
> +	case MXS_OSC_24M:
> +		/* keep the 24 MHz oscillator running even in power down */
> +		writel(STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ | /* 24 MHz / 750 */
> +			STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP,
> +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
> +		writel(STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
> +			STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE,
> +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
> +		break;
> +	case MXS_OSC_32K:
> +		/* keep the 32 kHz oscillator running even in power down */
> +		writel(STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ | /* 32 kHz */
> +			STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
> +			STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE,
> +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
> +		writel(STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP,
> +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
> +		break;
> +	case MXS_OSC_32K768:
> +		/* keep the 32 kHz oscillator running even in power down */
> +		writel(STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
> +			STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE,
> +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
> +		writel(STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ | /* 32.768 kHz */
> +			STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP,
> +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
> +		break;
> +	case MXS_UNKNOWN:
> +	default:
> +		break;
> +	}
> +}
> +
>  static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
>  {
>  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
>  
> +	stmp3xxx_alarm_keep_oscillator(rtc_data);
> +
>  	if (enabled) {
> +		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, /* to be able to sleep */
> +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
>  		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
>  				STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
>  				rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
> @@ -248,6 +293,8 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
>  {
>  	struct stmp3xxx_rtc_data *rtc_data;
>  	struct resource *r;
> +	struct clk *clk;
> +	unsigned long rate;
>  	int err;
>  
>  	rtc_data = kzalloc(sizeof *rtc_data, GFP_KERNEL);
> @@ -280,6 +327,35 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
>  	platform_set_drvdata(pdev, rtc_data);
>  
>  	mxs_reset_block(rtc_data->io);
> +
> +	/*
> +	 * configure the RTC to provide the correct time
> +	 */
> +	clk = clk_get(&pdev->dev, "32k");

devm_clk_get

Shawn

> +	if (IS_ERR(clk)) {
> +		/* just a fall back */
> +		dev_warn(&pdev->dev, "RTC's input clock undefined\n");
> +		rtc_data->clk_src = MXS_OSC_24M;
> +	} else {
> +		rate = clk_get_rate(clk);
> +		if (rate == 0) {
> +			/* no dedicated external crystal */
> +			rtc_data->clk_src = MXS_OSC_24M;
> +			dev_info(&pdev->dev, "Using 24 MHz as RTC's clock\n");
> +		} else if (rate == 32000) {
> +			rtc_data->clk_src = MXS_OSC_32K;
> +			dev_info(&pdev->dev, "Using 32.0 kHz as RTC's clock\n");
> +		} else if (rate == 32768) {
> +			rtc_data->clk_src = MXS_OSC_32K768;
> +			dev_info(&pdev->dev, "Using 32.768 kHz as RTC's clock\n");
> +		} else
> +			dev_warn(&pdev->dev,
> +				"Cannot init the RTC's clock source\n");
> +	}
> +
> +	/* basically configure the RTC's input clock */
> +	stmp3xxx_alarm_keep_oscillator(rtc_data);
> +
>  	writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
>  			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
>  			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
> -- 
> 1.7.10.4
> 

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

* [PATCH 4/9] MXS/i.MX28: there is more than one way to clock the RTC
  2013-03-07  6:48   ` Shawn Guo
@ 2013-03-07  8:19     ` Steffen Trumtrar
  0 siblings, 0 replies; 18+ messages in thread
From: Steffen Trumtrar @ 2013-03-07  8:19 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Shawn!

On Thu, Mar 07, 2013 at 02:48:26PM +0800, Shawn Guo wrote:
> On Mon, Mar 04, 2013 at 03:05:43PM +0100, Steffen Trumtrar wrote:
> > From: Juergen Beisert <jbe@pengutronix.de>
> > 
> > Reflect the possibilities via device tree and configure the RTC correctly
> > 
> > Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
> > Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
> > ---
> >  arch/arm/boot/dts/imx28.dtsi |    2 ++
> >  drivers/rtc/rtc-stmp3xxx.c   |   76 ++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 78 insertions(+)
> > 
> > diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> > index dcd0844..d89af79 100644
> > --- a/arch/arm/boot/dts/imx28.dtsi
> > +++ b/arch/arm/boot/dts/imx28.dtsi
> > @@ -818,6 +818,8 @@
> >  				compatible = "fsl,imx28-rtc", "fsl,stmp3xxx-rtc";
> >  				reg = <0x80056000 0x2000>;
> >  				interrupts = <29>;
> > +				clocks = <&clks 65>, <&clks 40> ;
> > +				clock-names = "32k", "24m";
> 
> The changes should be in some mxs/arch patch.
> 
> >  			};
> >  
> >  			i2c0: i2c at 80058000 {
> > diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
> > index 7311292..fb4b823 100644
> > --- a/drivers/rtc/rtc-stmp3xxx.c
> > +++ b/drivers/rtc/rtc-stmp3xxx.c
> > @@ -21,6 +21,7 @@
> >  #include <linux/module.h>
> >  #include <linux/io.h>
> >  #include <linux/init.h>
> > +#include <linux/clk.h>
> >  #include <linux/platform_device.h>
> >  #include <linux/interrupt.h>
> >  #include <linux/rtc.h>
> > @@ -176,11 +177,55 @@ static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id)
> >  	return IRQ_NONE;
> >  }
> >  
> > +/*
> > + * To keep the energy consumption low, keep only
> > + * the really used oscillator running when the power is down
> > + */
> > +static void stmp3xxx_alarm_keep_oscillator(const struct stmp3xxx_rtc_data *rtc_data)
> > +{
> > +	switch (rtc_data->clk_src) {
> > +	case MXS_OSC_24M:
> > +		/* keep the 24 MHz oscillator running even in power down */
> > +		writel(STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ | /* 24 MHz / 750 */
> > +			STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP,
> > +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
> > +		writel(STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
> > +			STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE,
> > +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
> > +		break;
> > +	case MXS_OSC_32K:
> > +		/* keep the 32 kHz oscillator running even in power down */
> > +		writel(STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ | /* 32 kHz */
> > +			STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
> > +			STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE,
> > +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
> > +		writel(STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP,
> > +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
> > +		break;
> > +	case MXS_OSC_32K768:
> > +		/* keep the 32 kHz oscillator running even in power down */
> > +		writel(STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
> > +			STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE,
> > +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
> > +		writel(STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ | /* 32.768 kHz */
> > +			STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP,
> > +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
> > +		break;
> > +	case MXS_UNKNOWN:
> > +	default:
> > +		break;
> > +	}
> > +}
> > +
> >  static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
> >  {
> >  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
> >  
> > +	stmp3xxx_alarm_keep_oscillator(rtc_data);
> > +
> >  	if (enabled) {
> > +		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, /* to be able to sleep */
> > +			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
> >  		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
> >  				STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
> >  				rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
> > @@ -248,6 +293,8 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
> >  {
> >  	struct stmp3xxx_rtc_data *rtc_data;
> >  	struct resource *r;
> > +	struct clk *clk;
> > +	unsigned long rate;
> >  	int err;
> >  
> >  	rtc_data = kzalloc(sizeof *rtc_data, GFP_KERNEL);
> > @@ -280,6 +327,35 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
> >  	platform_set_drvdata(pdev, rtc_data);
> >  
> >  	mxs_reset_block(rtc_data->io);
> > +
> > +	/*
> > +	 * configure the RTC to provide the correct time
> > +	 */
> > +	clk = clk_get(&pdev->dev, "32k");
> 
> devm_clk_get
> 
> Shawn
> 
> > +	if (IS_ERR(clk)) {
> > +		/* just a fall back */
> > +		dev_warn(&pdev->dev, "RTC's input clock undefined\n");
> > +		rtc_data->clk_src = MXS_OSC_24M;
> > +	} else {
> > +		rate = clk_get_rate(clk);
> > +		if (rate == 0) {
> > +			/* no dedicated external crystal */
> > +			rtc_data->clk_src = MXS_OSC_24M;
> > +			dev_info(&pdev->dev, "Using 24 MHz as RTC's clock\n");
> > +		} else if (rate == 32000) {
> > +			rtc_data->clk_src = MXS_OSC_32K;
> > +			dev_info(&pdev->dev, "Using 32.0 kHz as RTC's clock\n");
> > +		} else if (rate == 32768) {
> > +			rtc_data->clk_src = MXS_OSC_32K768;
> > +			dev_info(&pdev->dev, "Using 32.768 kHz as RTC's clock\n");
> > +		} else
> > +			dev_warn(&pdev->dev,
> > +				"Cannot init the RTC's clock source\n");
> > +	}
> > +
> > +	/* basically configure the RTC's input clock */
> > +	stmp3xxx_alarm_keep_oscillator(rtc_data);
> > +
> >  	writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
> >  			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
> >  			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
> > -- 
> > 1.7.10.4
> > 
> 
> 

I can agree to all your comments to this patch and the others in this series
and will take care of all of them.

Thanks,
Steffen

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

end of thread, other threads:[~2013-03-07  8:19 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-04 14:05 [PATCH 0/9] rtc: stmp3xxx: DT bindings and wakealarm Steffen Trumtrar
2013-03-04 14:05 ` [PATCH 1/9] MXS/i.MX28: add the possibility to define the used crystals via device tree Steffen Trumtrar
2013-03-07  6:17   ` Shawn Guo
2013-03-04 14:05 ` [PATCH 2/9] MXS/i.MX28: add the possibility to define the external RTC crystal Steffen Trumtrar
2013-03-07  6:33   ` Shawn Guo
2013-03-04 14:05 ` [PATCH 3/9] MXS/i.MX28: prepare different clocking of the built-in RTC Steffen Trumtrar
2013-03-07  6:40   ` Shawn Guo
2013-03-04 14:05 ` [PATCH 4/9] MXS/i.MX28: there is more than one way to clock the RTC Steffen Trumtrar
2013-03-07  6:48   ` Shawn Guo
2013-03-07  8:19     ` Steffen Trumtrar
2013-03-04 14:05 ` [PATCH 5/9] MXS/i.MX28: enable RTC to wakeup the system Steffen Trumtrar
2013-03-04 14:05 ` [PATCH 6/9] rtc: stmp3xxx: add sysfs entries for persistent regs Steffen Trumtrar
2013-03-04 15:14   ` Grant Likely
2013-03-05  8:02     ` Steffen Trumtrar
2013-03-06 13:27       ` Steffen Trumtrar
2013-03-04 14:05 ` [PATCH 7/9] rtc: stmp3xxx: Re-enable active alarm Steffen Trumtrar
2013-03-04 14:05 ` [PATCH 8/9] rtc: stmp3xxx: Check copy controller state Steffen Trumtrar
2013-03-04 14:05 ` [PATCH 9/9] rtc: stmp3xxx: Replace wait_time function Steffen Trumtrar

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