diff mbox

[4/5] rtc: at91sam9: retain slow clock and check its rate

Message ID 1409733934-14465-5-git-send-email-boris.brezillon@free-electrons.com
State Superseded
Headers show

Commit Message

Boris Brezillon Sept. 3, 2014, 8:45 a.m. UTC
The RTT block is using the slow clock and expect it to run at 32KHz.
Now that we moved to the CCF it's better to retain the clk reference so
that the CCF can't disable the slow clock considering it is unused.

Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
---
 drivers/rtc/rtc-at91sam9.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

Comments

Alexandre Belloni Sept. 8, 2014, 5:33 p.m. UTC | #1
On 03/09/2014 at 10:45:33 +0200, Boris Brezillon wrote :
> The RTT block is using the slow clock and expect it to run at 32KHz.
> Now that we moved to the CCF it's better to retain the clk reference so
> that the CCF can't disable the slow clock considering it is unused.
> 
> Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
> ---
>  drivers/rtc/rtc-at91sam9.c | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 
> diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
> index 57014b7..5c5093b 100644
> --- a/drivers/rtc/rtc-at91sam9.c
> +++ b/drivers/rtc/rtc-at91sam9.c
> @@ -21,6 +21,7 @@
>  #include <linux/slab.h>
>  #include <linux/platform_data/atmel.h>
>  #include <linux/io.h>
> +#include <linux/clk.h>
>  
>  /*
>   * This driver uses two configurable hardware resources that live in the
> @@ -74,6 +75,7 @@ struct sam9_rtc {
>  	u32			imr;
>  	void __iomem		*gpbr;
>  	int 			irq;
> +	struct clk		*sclk;
>  };
>  
>  #define rtt_readl(rtc, field) \
> @@ -373,6 +375,25 @@ static int at91_rtc_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> +	/* Retain slow clk if it is specified in the DT.
> +	 * Do not complain if slow clk is missing, but check its rate
> +	 * if it is available.
> +	 */
> +	rtc->sclk = devm_clk_get(&pdev->dev, NULL);
> +	if (!IS_ERR(rtc->sclk)) {
> +		if (clk_get_rate(rtc->sclk) != AT91_SLOW_CLOCK) {

I would not bother doing that check but use the value for MR instead of
AT91_SLOW_CLOCK (see my previous mail).

> +			dev_err(&pdev->dev,
> +				"Invalid slow clock rate (expecting %lu got %lu)",
> +				(unsigned long)AT91_SLOW_CLOCK,
> +				clk_get_rate(rtc->sclk));
> +			return -EINVAL;
> +		}
> +
> +		ret = clk_prepare_enable(rtc->sclk);
> +		if (ret)
> +			return ret;
> +	}
> +
>  	/* NOTE:  sam9260 rev A silicon has a ROM bug which resets the
>  	 * RTT on at least some reboots.  If you have that chip, you must
>  	 * initialize the time from some external source like a GPS, wall
> @@ -397,6 +418,9 @@ static int at91_rtc_remove(struct platform_device *pdev)
>  	/* disable all interrupts */
>  	rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
>  
> +	if (!IS_ERR(rtc->sclk))
> +		clk_disable_unprepare(rtc->sclk);
> +
>  	return 0;
>  }
>  
> -- 
> 1.9.1
>
Boris Brezillon Sept. 8, 2014, 7:22 p.m. UTC | #2
On Mon, 8 Sep 2014 19:33:38 +0200
Alexandre Belloni <alexandre.belloni@free-electrons.com> wrote:

> On 03/09/2014 at 10:45:33 +0200, Boris Brezillon wrote :
> > The RTT block is using the slow clock and expect it to run at 32KHz.
> > Now that we moved to the CCF it's better to retain the clk reference so
> > that the CCF can't disable the slow clock considering it is unused.
> > 
> > Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
> > ---
> >  drivers/rtc/rtc-at91sam9.c | 24 ++++++++++++++++++++++++
> >  1 file changed, 24 insertions(+)
> > 
> > diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
> > index 57014b7..5c5093b 100644
> > --- a/drivers/rtc/rtc-at91sam9.c
> > +++ b/drivers/rtc/rtc-at91sam9.c
> > @@ -21,6 +21,7 @@
> >  #include <linux/slab.h>
> >  #include <linux/platform_data/atmel.h>
> >  #include <linux/io.h>
> > +#include <linux/clk.h>
> >  
> >  /*
> >   * This driver uses two configurable hardware resources that live in the
> > @@ -74,6 +75,7 @@ struct sam9_rtc {
> >  	u32			imr;
> >  	void __iomem		*gpbr;
> >  	int 			irq;
> > +	struct clk		*sclk;
> >  };
> >  
> >  #define rtt_readl(rtc, field) \
> > @@ -373,6 +375,25 @@ static int at91_rtc_probe(struct platform_device *pdev)
> >  		return ret;
> >  	}
> >  
> > +	/* Retain slow clk if it is specified in the DT.
> > +	 * Do not complain if slow clk is missing, but check its rate
> > +	 * if it is available.
> > +	 */
> > +	rtc->sclk = devm_clk_get(&pdev->dev, NULL);
> > +	if (!IS_ERR(rtc->sclk)) {
> > +		if (clk_get_rate(rtc->sclk) != AT91_SLOW_CLOCK) {
> 
> I would not bother doing that check but use the value for MR instead of
> AT91_SLOW_CLOCK (see my previous mail).

Unfortunately, we can't get rid of this macro without modifying the
clk_lookup table in several arch/arm/mach-at91/<soc-name>.c files in
order to handle non DT/CCF cases (which will remain until all non DT
boards are moved to DT).
But I agree that this should be removed as soon as possible (AFAIR, all
SoCs have already been moved to the CCF).
How about adding a TODO comment ?

> 
> > +			dev_err(&pdev->dev,
> > +				"Invalid slow clock rate (expecting %lu got %lu)",
> > +				(unsigned long)AT91_SLOW_CLOCK,
> > +				clk_get_rate(rtc->sclk));
> > +			return -EINVAL;
> > +		}
> > +
> > +		ret = clk_prepare_enable(rtc->sclk);
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> >  	/* NOTE:  sam9260 rev A silicon has a ROM bug which resets the
> >  	 * RTT on at least some reboots.  If you have that chip, you must
> >  	 * initialize the time from some external source like a GPS, wall
> > @@ -397,6 +418,9 @@ static int at91_rtc_remove(struct platform_device *pdev)
> >  	/* disable all interrupts */
> >  	rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
> >  
> > +	if (!IS_ERR(rtc->sclk))
> > +		clk_disable_unprepare(rtc->sclk);
> > +
> >  	return 0;
> >  }
> >  
> > -- 
> > 1.9.1
> > 
>
Boris Brezillon Sept. 8, 2014, 7:37 p.m. UTC | #3
On Mon, 8 Sep 2014 21:22:18 +0200
Boris BREZILLON <boris.brezillon@free-electrons.com> wrote:

> On Mon, 8 Sep 2014 19:33:38 +0200
> Alexandre Belloni <alexandre.belloni@free-electrons.com> wrote:
> 
> > On 03/09/2014 at 10:45:33 +0200, Boris Brezillon wrote :
> > > The RTT block is using the slow clock and expect it to run at 32KHz.
> > > Now that we moved to the CCF it's better to retain the clk reference so
> > > that the CCF can't disable the slow clock considering it is unused.
> > > 
> > > Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
> > > ---
> > >  drivers/rtc/rtc-at91sam9.c | 24 ++++++++++++++++++++++++
> > >  1 file changed, 24 insertions(+)
> > > 
> > > diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
> > > index 57014b7..5c5093b 100644
> > > --- a/drivers/rtc/rtc-at91sam9.c
> > > +++ b/drivers/rtc/rtc-at91sam9.c
> > > @@ -21,6 +21,7 @@
> > >  #include <linux/slab.h>
> > >  #include <linux/platform_data/atmel.h>
> > >  #include <linux/io.h>
> > > +#include <linux/clk.h>
> > >  
> > >  /*
> > >   * This driver uses two configurable hardware resources that live in the
> > > @@ -74,6 +75,7 @@ struct sam9_rtc {
> > >  	u32			imr;
> > >  	void __iomem		*gpbr;
> > >  	int 			irq;
> > > +	struct clk		*sclk;
> > >  };
> > >  
> > >  #define rtt_readl(rtc, field) \
> > > @@ -373,6 +375,25 @@ static int at91_rtc_probe(struct platform_device *pdev)
> > >  		return ret;
> > >  	}
> > >  
> > > +	/* Retain slow clk if it is specified in the DT.
> > > +	 * Do not complain if slow clk is missing, but check its rate
> > > +	 * if it is available.
> > > +	 */
> > > +	rtc->sclk = devm_clk_get(&pdev->dev, NULL);
> > > +	if (!IS_ERR(rtc->sclk)) {
> > > +		if (clk_get_rate(rtc->sclk) != AT91_SLOW_CLOCK) {
> > 
> > I would not bother doing that check but use the value for MR instead of
> > AT91_SLOW_CLOCK (see my previous mail).
> 
> Unfortunately, we can't get rid of this macro without modifying the
> clk_lookup table in several arch/arm/mach-at91/<soc-name>.c files in
> order to handle non DT/CCF cases (which will remain until all non DT
> boards are moved to DT).

After taking a closer look at what should be modified, I think it's
worth it: there's only 5 impacted files (at91sam9260.c, at91sam9261.c,
at91sam9263.c, at91sam9rl.c and at91sam9g45.c) and adding a clk_lookup
entry is pretty easy.

Moreover we'll end up with a clean driver and won't have to bother
about cleaning it up when dropping non DT boards support.
Nicolas Ferre Sept. 9, 2014, 8:36 a.m. UTC | #4
On 08/09/2014 21:37, Boris BREZILLON :
> On Mon, 8 Sep 2014 21:22:18 +0200
> Boris BREZILLON <boris.brezillon@free-electrons.com> wrote:
> 
>> On Mon, 8 Sep 2014 19:33:38 +0200
>> Alexandre Belloni <alexandre.belloni@free-electrons.com> wrote:
>>
>>> On 03/09/2014 at 10:45:33 +0200, Boris Brezillon wrote :
>>>> The RTT block is using the slow clock and expect it to run at 32KHz.
>>>> Now that we moved to the CCF it's better to retain the clk reference so
>>>> that the CCF can't disable the slow clock considering it is unused.
>>>>
>>>> Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
>>>> ---
>>>>  drivers/rtc/rtc-at91sam9.c | 24 ++++++++++++++++++++++++
>>>>  1 file changed, 24 insertions(+)
>>>>
>>>> diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
>>>> index 57014b7..5c5093b 100644
>>>> --- a/drivers/rtc/rtc-at91sam9.c
>>>> +++ b/drivers/rtc/rtc-at91sam9.c
>>>> @@ -21,6 +21,7 @@
>>>>  #include <linux/slab.h>
>>>>  #include <linux/platform_data/atmel.h>
>>>>  #include <linux/io.h>
>>>> +#include <linux/clk.h>
>>>>  
>>>>  /*
>>>>   * This driver uses two configurable hardware resources that live in the
>>>> @@ -74,6 +75,7 @@ struct sam9_rtc {
>>>>  	u32			imr;
>>>>  	void __iomem		*gpbr;
>>>>  	int 			irq;
>>>> +	struct clk		*sclk;
>>>>  };
>>>>  
>>>>  #define rtt_readl(rtc, field) \
>>>> @@ -373,6 +375,25 @@ static int at91_rtc_probe(struct platform_device *pdev)
>>>>  		return ret;
>>>>  	}
>>>>  
>>>> +	/* Retain slow clk if it is specified in the DT.
>>>> +	 * Do not complain if slow clk is missing, but check its rate
>>>> +	 * if it is available.
>>>> +	 */
>>>> +	rtc->sclk = devm_clk_get(&pdev->dev, NULL);
>>>> +	if (!IS_ERR(rtc->sclk)) {
>>>> +		if (clk_get_rate(rtc->sclk) != AT91_SLOW_CLOCK) {
>>>
>>> I would not bother doing that check but use the value for MR instead of
>>> AT91_SLOW_CLOCK (see my previous mail).
>>
>> Unfortunately, we can't get rid of this macro without modifying the
>> clk_lookup table in several arch/arm/mach-at91/<soc-name>.c files in
>> order to handle non DT/CCF cases (which will remain until all non DT
>> boards are moved to DT).
> 
> After taking a closer look at what should be modified, I think it's
> worth it: there's only 5 impacted files (at91sam9260.c, at91sam9261.c,
> at91sam9263.c, at91sam9rl.c and at91sam9g45.c) and adding a clk_lookup
> entry is pretty easy.
> 
> Moreover we'll end up with a clean driver and won't have to bother
> about cleaning it up when dropping non DT boards support.

I vote for this => +1 ;-)

Bye,
diff mbox

Patch

diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 57014b7..5c5093b 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -21,6 +21,7 @@ 
 #include <linux/slab.h>
 #include <linux/platform_data/atmel.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 
 /*
  * This driver uses two configurable hardware resources that live in the
@@ -74,6 +75,7 @@  struct sam9_rtc {
 	u32			imr;
 	void __iomem		*gpbr;
 	int 			irq;
+	struct clk		*sclk;
 };
 
 #define rtt_readl(rtc, field) \
@@ -373,6 +375,25 @@  static int at91_rtc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	/* Retain slow clk if it is specified in the DT.
+	 * Do not complain if slow clk is missing, but check its rate
+	 * if it is available.
+	 */
+	rtc->sclk = devm_clk_get(&pdev->dev, NULL);
+	if (!IS_ERR(rtc->sclk)) {
+		if (clk_get_rate(rtc->sclk) != AT91_SLOW_CLOCK) {
+			dev_err(&pdev->dev,
+				"Invalid slow clock rate (expecting %lu got %lu)",
+				(unsigned long)AT91_SLOW_CLOCK,
+				clk_get_rate(rtc->sclk));
+			return -EINVAL;
+		}
+
+		ret = clk_prepare_enable(rtc->sclk);
+		if (ret)
+			return ret;
+	}
+
 	/* NOTE:  sam9260 rev A silicon has a ROM bug which resets the
 	 * RTT on at least some reboots.  If you have that chip, you must
 	 * initialize the time from some external source like a GPS, wall
@@ -397,6 +418,9 @@  static int at91_rtc_remove(struct platform_device *pdev)
 	/* disable all interrupts */
 	rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
 
+	if (!IS_ERR(rtc->sclk))
+		clk_disable_unprepare(rtc->sclk);
+
 	return 0;
 }