diff mbox series

[2/7] soc: renesas: rzn1-sysc: Export a function to enable/disable the RTC

Message ID 20220405184716.1578385-3-miquel.raynal@bootlin.com
State Changes Requested
Headers show
Series RZN1 RTC support | expand

Commit Message

Miquel Raynal April 5, 2022, 6:47 p.m. UTC
There are two RTC registers located within the system controller.

Like with the dmamux register, let's add a new helper to enable/disable
the power, reset and clock of the RTC.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/clk/renesas/r9a06g032-clocks.c        | 49 +++++++++++++++++++
 include/linux/soc/renesas/r9a06g032-sysctrl.h |  2 +
 2 files changed, 51 insertions(+)

Comments

Thomas Petazzoni April 6, 2022, 7 a.m. UTC | #1
Hello Miquèl,

On Tue,  5 Apr 2022 20:47:11 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> +	spin_lock_irqsave(&sysctrl_priv->lock, flags);

Taking a lock here...

> +
> +	if (enable) {
> +		val = readl(sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> +		val &= ~R9A06G032_SYSCTRL_PWRCTRL_RTC_RST;
> +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> +		val |= R9A06G032_SYSCTRL_PWRCTRL_RTC_CLKEN;
> +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> +		val |= R9A06G032_SYSCTRL_PWRCTRL_RTC_RSTN_FW;
> +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> +		val &= ~R9A06G032_SYSCTRL_PWRCTRL_RTC_IDLE_REQ;
> +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> +		val = readl(sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRSTAT_RTC);
> +		if (val & R9A06G032_SYSCTRL_PWRSTAT_RTC_IDLE)
> +			return -EIO;

And forgetting to release it here in the error case.

Thomas
Miquel Raynal April 6, 2022, 7:43 a.m. UTC | #2
Hi Thomas,

thomas.petazzoni@bootlin.com wrote on Wed, 6 Apr 2022 09:00:04 +0200:

> Hello Miquèl,
> 
> On Tue,  5 Apr 2022 20:47:11 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > +	spin_lock_irqsave(&sysctrl_priv->lock, flags);  
> 
> Taking a lock here...
> 
> > +
> > +	if (enable) {
> > +		val = readl(sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> > +		val &= ~R9A06G032_SYSCTRL_PWRCTRL_RTC_RST;
> > +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> > +		val |= R9A06G032_SYSCTRL_PWRCTRL_RTC_CLKEN;
> > +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> > +		val |= R9A06G032_SYSCTRL_PWRCTRL_RTC_RSTN_FW;
> > +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> > +		val &= ~R9A06G032_SYSCTRL_PWRCTRL_RTC_IDLE_REQ;
> > +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> > +		val = readl(sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRSTAT_RTC);
> > +		if (val & R9A06G032_SYSCTRL_PWRSTAT_RTC_IDLE)
> > +			return -EIO;  
> 
> And forgetting to release it here in the error case.

Right, I'll fix it.

Thanks!
Miquèl
Alexandre Belloni April 6, 2022, 8:32 a.m. UTC | #3
On 05/04/2022 20:47:11+0200, Miquel Raynal wrote:
> There are two RTC registers located within the system controller.
> 
> Like with the dmamux register, let's add a new helper to enable/disable
> the power, reset and clock of the RTC.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/clk/renesas/r9a06g032-clocks.c        | 49 +++++++++++++++++++
>  include/linux/soc/renesas/r9a06g032-sysctrl.h |  2 +
>  2 files changed, 51 insertions(+)
> 
> diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c
> index 1df56d7ab3e1..7e61db39a43b 100644
> --- a/drivers/clk/renesas/r9a06g032-clocks.c
> +++ b/drivers/clk/renesas/r9a06g032-clocks.c
> @@ -26,6 +26,13 @@
>  #include <dt-bindings/clock/r9a06g032-sysctrl.h>
>  
>  #define R9A06G032_SYSCTRL_DMAMUX 0xA0
> +#define R9A06G032_SYSCTRL_PWRCTRL_RTC 0x140
> +#define   R9A06G032_SYSCTRL_PWRCTRL_RTC_CLKEN BIT(0)
> +#define   R9A06G032_SYSCTRL_PWRCTRL_RTC_RST BIT(1)
> +#define   R9A06G032_SYSCTRL_PWRCTRL_RTC_IDLE_REQ BIT(2)
> +#define   R9A06G032_SYSCTRL_PWRCTRL_RTC_RSTN_FW BIT(3)
> +#define R9A06G032_SYSCTRL_PWRSTAT_RTC 0x144
> +#define   R9A06G032_SYSCTRL_PWRSTAT_RTC_IDLE BIT(1)
>  
>  struct r9a06g032_gate {
>  	u16 gate, reset, ready, midle,
> @@ -343,6 +350,48 @@ int r9a06g032_sysctrl_set_dmamux(u32 mask, u32 val)
>  }
>  EXPORT_SYMBOL_GPL(r9a06g032_sysctrl_set_dmamux);
>  
> +/* Exported helper to enable/disable the RTC */
> +int r9a06g032_sysctrl_enable_rtc(bool enable)
> +{
> +	unsigned long flags;
> +	u32 val;
> +
> +	if (!sysctrl_priv)
> +		return -EPROBE_DEFER;
> +
> +	spin_lock_irqsave(&sysctrl_priv->lock, flags);
> +
> +	if (enable) {
> +		val = readl(sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> +		val &= ~R9A06G032_SYSCTRL_PWRCTRL_RTC_RST;
> +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> +		val |= R9A06G032_SYSCTRL_PWRCTRL_RTC_CLKEN;
> +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> +		val |= R9A06G032_SYSCTRL_PWRCTRL_RTC_RSTN_FW;
> +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> +		val &= ~R9A06G032_SYSCTRL_PWRCTRL_RTC_IDLE_REQ;
> +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> +		val = readl(sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRSTAT_RTC);
> +		if (val & R9A06G032_SYSCTRL_PWRSTAT_RTC_IDLE)
> +			return -EIO;
> +	} else {
> +		val = readl(sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> +		val |= R9A06G032_SYSCTRL_PWRCTRL_RTC_IDLE_REQ;
> +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> +		val &= ~R9A06G032_SYSCTRL_PWRCTRL_RTC_RSTN_FW;
> +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> +		val &= ~R9A06G032_SYSCTRL_PWRCTRL_RTC_CLKEN;
> +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> +		val |= R9A06G032_SYSCTRL_PWRCTRL_RTC_RST;
> +		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
> +	}
> +
> +	spin_unlock_irqrestore(&sysctrl_priv->lock, flags);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(r9a06g032_sysctrl_enable_rtc);
> +
>  /* register/bit pairs are encoded as an uint16_t */
>  static void
>  clk_rdesc_set(struct r9a06g032_priv *clocks,
> diff --git a/include/linux/soc/renesas/r9a06g032-sysctrl.h b/include/linux/soc/renesas/r9a06g032-sysctrl.h
> index 066dfb15cbdd..914c8789149c 100644
> --- a/include/linux/soc/renesas/r9a06g032-sysctrl.h
> +++ b/include/linux/soc/renesas/r9a06g032-sysctrl.h
> @@ -4,8 +4,10 @@
>  
>  #ifdef CONFIG_CLK_R9A06G032
>  int r9a06g032_sysctrl_set_dmamux(u32 mask, u32 val);
> +int r9a06g032_sysctrl_enable_rtc(bool enable);
>  #else
>  static inline int r9a06g032_sysctrl_set_dmamux(u32 mask, u32 val) { return -ENODEV; }
> +static inline int r9a06g032_sysctrl_enable_rtc(bool enable) { return -ENODEV; }

Couldn't that be handled using the reset subsystem to avoid leaking a
random API in the RTC driver? (and that would remove the build
dependency)

>  #endif
>  
>  #endif /* __LINUX_SOC_RENESAS_R9A06G032_SYSCTRL_H__ */
> -- 
> 2.27.0
>
diff mbox series

Patch

diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c
index 1df56d7ab3e1..7e61db39a43b 100644
--- a/drivers/clk/renesas/r9a06g032-clocks.c
+++ b/drivers/clk/renesas/r9a06g032-clocks.c
@@ -26,6 +26,13 @@ 
 #include <dt-bindings/clock/r9a06g032-sysctrl.h>
 
 #define R9A06G032_SYSCTRL_DMAMUX 0xA0
+#define R9A06G032_SYSCTRL_PWRCTRL_RTC 0x140
+#define   R9A06G032_SYSCTRL_PWRCTRL_RTC_CLKEN BIT(0)
+#define   R9A06G032_SYSCTRL_PWRCTRL_RTC_RST BIT(1)
+#define   R9A06G032_SYSCTRL_PWRCTRL_RTC_IDLE_REQ BIT(2)
+#define   R9A06G032_SYSCTRL_PWRCTRL_RTC_RSTN_FW BIT(3)
+#define R9A06G032_SYSCTRL_PWRSTAT_RTC 0x144
+#define   R9A06G032_SYSCTRL_PWRSTAT_RTC_IDLE BIT(1)
 
 struct r9a06g032_gate {
 	u16 gate, reset, ready, midle,
@@ -343,6 +350,48 @@  int r9a06g032_sysctrl_set_dmamux(u32 mask, u32 val)
 }
 EXPORT_SYMBOL_GPL(r9a06g032_sysctrl_set_dmamux);
 
+/* Exported helper to enable/disable the RTC */
+int r9a06g032_sysctrl_enable_rtc(bool enable)
+{
+	unsigned long flags;
+	u32 val;
+
+	if (!sysctrl_priv)
+		return -EPROBE_DEFER;
+
+	spin_lock_irqsave(&sysctrl_priv->lock, flags);
+
+	if (enable) {
+		val = readl(sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
+		val &= ~R9A06G032_SYSCTRL_PWRCTRL_RTC_RST;
+		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
+		val |= R9A06G032_SYSCTRL_PWRCTRL_RTC_CLKEN;
+		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
+		val |= R9A06G032_SYSCTRL_PWRCTRL_RTC_RSTN_FW;
+		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
+		val &= ~R9A06G032_SYSCTRL_PWRCTRL_RTC_IDLE_REQ;
+		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
+		val = readl(sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRSTAT_RTC);
+		if (val & R9A06G032_SYSCTRL_PWRSTAT_RTC_IDLE)
+			return -EIO;
+	} else {
+		val = readl(sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
+		val |= R9A06G032_SYSCTRL_PWRCTRL_RTC_IDLE_REQ;
+		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
+		val &= ~R9A06G032_SYSCTRL_PWRCTRL_RTC_RSTN_FW;
+		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
+		val &= ~R9A06G032_SYSCTRL_PWRCTRL_RTC_CLKEN;
+		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
+		val |= R9A06G032_SYSCTRL_PWRCTRL_RTC_RST;
+		writel(val, sysctrl_priv->reg + R9A06G032_SYSCTRL_PWRCTRL_RTC);
+	}
+
+	spin_unlock_irqrestore(&sysctrl_priv->lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(r9a06g032_sysctrl_enable_rtc);
+
 /* register/bit pairs are encoded as an uint16_t */
 static void
 clk_rdesc_set(struct r9a06g032_priv *clocks,
diff --git a/include/linux/soc/renesas/r9a06g032-sysctrl.h b/include/linux/soc/renesas/r9a06g032-sysctrl.h
index 066dfb15cbdd..914c8789149c 100644
--- a/include/linux/soc/renesas/r9a06g032-sysctrl.h
+++ b/include/linux/soc/renesas/r9a06g032-sysctrl.h
@@ -4,8 +4,10 @@ 
 
 #ifdef CONFIG_CLK_R9A06G032
 int r9a06g032_sysctrl_set_dmamux(u32 mask, u32 val);
+int r9a06g032_sysctrl_enable_rtc(bool enable);
 #else
 static inline int r9a06g032_sysctrl_set_dmamux(u32 mask, u32 val) { return -ENODEV; }
+static inline int r9a06g032_sysctrl_enable_rtc(bool enable) { return -ENODEV; }
 #endif
 
 #endif /* __LINUX_SOC_RENESAS_R9A06G032_SYSCTRL_H__ */