diff mbox series

[2/3] rtc: sun6i: Add support for H6 RTC

Message ID 20190412120730.473-3-megous@megous.com
State Changes Requested
Headers show
Series Add basic support for RTC on Allwinner H6 SoC | expand

Commit Message

Ondřej Jirman April 12, 2019, 12:07 p.m. UTC
From: Ondrej Jirman <megous@megous.com>

RTC on H6 is mostly the same as on H5 and H3. It has slight differences
mostly in features that are not yet supported by this driver.

Some differences are already stated in the comments in existing code.
One other difference is that H6 has extra bit in LOSC_CTRL_REG, called
EXT_LOSC_EN to enable/disable external low speed crystal oscillator.

It also has bit EXT_LOSC_STA in LOSC_AUTO_SWT_STA_REG, to check whether
external low speed oscillator is working correctly.

This patch adds support for enabling LOSC when necessary:

- during reparenting
- when probing the clock

H6 also has capacbility to automatically reparent RTC clock from
external crystal oscillator, to internal RC oscillator, if external
oscillator fails. This is enabled by default. Disable it during
probe.

Signed-off-by: Ondrej Jirman <megous@megous.com>
---
 drivers/rtc/rtc-sun6i.c | 40 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 38 insertions(+), 2 deletions(-)

Comments

Chen-Yu Tsai Aug. 5, 2019, 10:16 a.m. UTC | #1
On Fri, Apr 12, 2019 at 8:07 PM megous via linux-sunxi
<linux-sunxi@googlegroups.com> wrote:
>
> From: Ondrej Jirman <megous@megous.com>
>
> RTC on H6 is mostly the same as on H5 and H3. It has slight differences
> mostly in features that are not yet supported by this driver.
>
> Some differences are already stated in the comments in existing code.
> One other difference is that H6 has extra bit in LOSC_CTRL_REG, called
> EXT_LOSC_EN to enable/disable external low speed crystal oscillator.
>
> It also has bit EXT_LOSC_STA in LOSC_AUTO_SWT_STA_REG, to check whether
> external low speed oscillator is working correctly.
>
> This patch adds support for enabling LOSC when necessary:
>
> - during reparenting
> - when probing the clock
>
> H6 also has capacbility to automatically reparent RTC clock from
> external crystal oscillator, to internal RC oscillator, if external
> oscillator fails. This is enabled by default. Disable it during
> probe.
>
> Signed-off-by: Ondrej Jirman <megous@megous.com>
> ---
>  drivers/rtc/rtc-sun6i.c | 40 ++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 38 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
> index 11f56de52179..7375a530c565 100644
> --- a/drivers/rtc/rtc-sun6i.c
> +++ b/drivers/rtc/rtc-sun6i.c
> @@ -41,9 +41,11 @@
>  /* Control register */
>  #define SUN6I_LOSC_CTRL                                0x0000
>  #define SUN6I_LOSC_CTRL_KEY                    (0x16aa << 16)
> +#define SUN6I_LOSC_CTRL_AUTO_SWT_BYPASS                BIT(15)

Manual says bit 14? Or is this different from LOSC_AUTO_SWT_EN?

The rest looks ok.

ChenYu
Ondřej Jirman Aug. 5, 2019, 10:20 a.m. UTC | #2
On Mon, Aug 05, 2019 at 06:16:14PM +0800, Chen-Yu Tsai wrote:
> On Fri, Apr 12, 2019 at 8:07 PM megous via linux-sunxi
> <linux-sunxi@googlegroups.com> wrote:
> >
> > From: Ondrej Jirman <megous@megous.com>
> >
> > RTC on H6 is mostly the same as on H5 and H3. It has slight differences
> > mostly in features that are not yet supported by this driver.
> >
> > Some differences are already stated in the comments in existing code.
> > One other difference is that H6 has extra bit in LOSC_CTRL_REG, called
> > EXT_LOSC_EN to enable/disable external low speed crystal oscillator.
> >
> > It also has bit EXT_LOSC_STA in LOSC_AUTO_SWT_STA_REG, to check whether
> > external low speed oscillator is working correctly.
> >
> > This patch adds support for enabling LOSC when necessary:
> >
> > - during reparenting
> > - when probing the clock
> >
> > H6 also has capacbility to automatically reparent RTC clock from
> > external crystal oscillator, to internal RC oscillator, if external
> > oscillator fails. This is enabled by default. Disable it during
> > probe.
> >
> > Signed-off-by: Ondrej Jirman <megous@megous.com>
> > ---
> >  drivers/rtc/rtc-sun6i.c | 40 ++++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 38 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
> > index 11f56de52179..7375a530c565 100644
> > --- a/drivers/rtc/rtc-sun6i.c
> > +++ b/drivers/rtc/rtc-sun6i.c
> > @@ -41,9 +41,11 @@
> >  /* Control register */
> >  #define SUN6I_LOSC_CTRL                                0x0000
> >  #define SUN6I_LOSC_CTRL_KEY                    (0x16aa << 16)
> > +#define SUN6I_LOSC_CTRL_AUTO_SWT_BYPASS                BIT(15)
> 
> Manual says bit 14? Or is this different from LOSC_AUTO_SWT_EN?
> 
> The rest looks ok.

Yes, see H6 BSP:

drivers/rtc/rtc-sunxi.h

 20 #define REG_CLK32K_AUTO_SWT_EN                  BIT(14)
 21 #define REG_CLK32K_AUTO_SWT_BYPASS              BIT(15)

regards,
	Ondrej

> ChenYu
Ondřej Jirman Aug. 5, 2019, 10:45 a.m. UTC | #3
On Mon, Aug 05, 2019 at 06:16:14PM +0800, Chen-Yu Tsai wrote:
> On Fri, Apr 12, 2019 at 8:07 PM megous via linux-sunxi
> <linux-sunxi@googlegroups.com> wrote:
> >
> > From: Ondrej Jirman <megous@megous.com>
> >
> > RTC on H6 is mostly the same as on H5 and H3. It has slight differences
> > mostly in features that are not yet supported by this driver.
> >
> > Some differences are already stated in the comments in existing code.
> > One other difference is that H6 has extra bit in LOSC_CTRL_REG, called
> > EXT_LOSC_EN to enable/disable external low speed crystal oscillator.
> >
> > It also has bit EXT_LOSC_STA in LOSC_AUTO_SWT_STA_REG, to check whether
> > external low speed oscillator is working correctly.
> >
> > This patch adds support for enabling LOSC when necessary:
> >
> > - during reparenting
> > - when probing the clock
> >
> > H6 also has capacbility to automatically reparent RTC clock from
> > external crystal oscillator, to internal RC oscillator, if external
> > oscillator fails. This is enabled by default. Disable it during
> > probe.
> >
> > Signed-off-by: Ondrej Jirman <megous@megous.com>
> > ---
> >  drivers/rtc/rtc-sun6i.c | 40 ++++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 38 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
> > index 11f56de52179..7375a530c565 100644
> > --- a/drivers/rtc/rtc-sun6i.c
> > +++ b/drivers/rtc/rtc-sun6i.c
> > @@ -41,9 +41,11 @@
> >  /* Control register */
> >  #define SUN6I_LOSC_CTRL                                0x0000
> >  #define SUN6I_LOSC_CTRL_KEY                    (0x16aa << 16)
> > +#define SUN6I_LOSC_CTRL_AUTO_SWT_BYPASS                BIT(15)
> 
> Manual says bit 14? Or is this different from LOSC_AUTO_SWT_EN?
> 
> The rest looks ok.

To give you more information. This is a new thing in H6 BSP, compared
to BSPs for previous SoCs (H5/H3).

 20 #define REG_CLK32K_AUTO_SWT_EN                  BIT(14)
 21 #define REG_CLK32K_AUTO_SWT_BYPASS              BIT(15)

Init sequence changed in H6 BSP to:

646         /*
647          * Step1: select RTC clock source
648          */
649         tmp_data = readl(chip->base + SUNXI_LOSC_CTRL);
650         tmp_data &= (~REG_CLK32K_AUTO_SWT_EN);
651
652         /* Disable auto switch function */
653         tmp_data |= REG_CLK32K_AUTO_SWT_BYPASS;
654         writel(tmp_data, chip->base + SUNXI_LOSC_CTRL);
655
656         tmp_data = readl(chip->base + SUNXI_LOSC_CTRL);
657         tmp_data |= (RTC_SOURCE_EXTERNAL | REG_LOSCCTRL_MAGIC);
658         writel(tmp_data, chip->base + SUNXI_LOSC_CTRL);
659
660         /* We need to set GSM after change clock source */
661         udelay(10);
662         tmp_data = readl(chip->base + SUNXI_LOSC_CTRL);
663         tmp_data |= (EXT_LOSC_GSM | REG_LOSCCTRL_MAGIC);
664         writel(tmp_data, chip->base + SUNXI_LOSC_CTRL);
665

For older BSPs, the init sequence looked like this:

482         /*
483          * Step1: select RTC clock source
484          */
485         tmp_data = sunxi_rtc_read(SUNXI_LOSC_CTRL_REG);
486         tmp_data &= (~REG_CLK32K_AUTO_SWT_EN);
487         tmp_data |= (RTC_SOURCE_EXTERNAL | REG_LOSCCTRL_MAGIC);
488         tmp_data |= (EXT_LOSC_GSM);
489         sunxi_rtc_write(tmp_data, SUNXI_LOSC_CTRL_REG);
490

EXT_LOSC_GSM has values 4 values from low to high, and I guess it configures
gain for the oscillator's amplifier in the feedback loop of the circuit.

So the new code, for some reason changed from single write to sequence
of individual writes/config steps:

1) disable auto-switch and enable auto-switch bypass
2) select RTC clock source (to LOSC)
  (wait)
3) configure gain on the LOSC

regards,
	o.

> ChenYu
Chen-Yu Tsai Aug. 5, 2019, 10:54 a.m. UTC | #4
On Mon, Aug 5, 2019 at 6:45 PM Ondřej Jirman <megous@megous.com> wrote:
>
> On Mon, Aug 05, 2019 at 06:16:14PM +0800, Chen-Yu Tsai wrote:
> > On Fri, Apr 12, 2019 at 8:07 PM megous via linux-sunxi
> > <linux-sunxi@googlegroups.com> wrote:
> > >
> > > From: Ondrej Jirman <megous@megous.com>
> > >
> > > RTC on H6 is mostly the same as on H5 and H3. It has slight differences
> > > mostly in features that are not yet supported by this driver.
> > >
> > > Some differences are already stated in the comments in existing code.
> > > One other difference is that H6 has extra bit in LOSC_CTRL_REG, called
> > > EXT_LOSC_EN to enable/disable external low speed crystal oscillator.
> > >
> > > It also has bit EXT_LOSC_STA in LOSC_AUTO_SWT_STA_REG, to check whether
> > > external low speed oscillator is working correctly.
> > >
> > > This patch adds support for enabling LOSC when necessary:
> > >
> > > - during reparenting
> > > - when probing the clock
> > >
> > > H6 also has capacbility to automatically reparent RTC clock from
> > > external crystal oscillator, to internal RC oscillator, if external
> > > oscillator fails. This is enabled by default. Disable it during
> > > probe.
> > >
> > > Signed-off-by: Ondrej Jirman <megous@megous.com>
> > > ---
> > >  drivers/rtc/rtc-sun6i.c | 40 ++++++++++++++++++++++++++++++++++++++--
> > >  1 file changed, 38 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
> > > index 11f56de52179..7375a530c565 100644
> > > --- a/drivers/rtc/rtc-sun6i.c
> > > +++ b/drivers/rtc/rtc-sun6i.c
> > > @@ -41,9 +41,11 @@
> > >  /* Control register */
> > >  #define SUN6I_LOSC_CTRL                                0x0000
> > >  #define SUN6I_LOSC_CTRL_KEY                    (0x16aa << 16)
> > > +#define SUN6I_LOSC_CTRL_AUTO_SWT_BYPASS                BIT(15)
> >
> > Manual says bit 14? Or is this different from LOSC_AUTO_SWT_EN?
> >
> > The rest looks ok.
>
> To give you more information. This is a new thing in H6 BSP, compared
> to BSPs for previous SoCs (H5/H3).
>
>  20 #define REG_CLK32K_AUTO_SWT_EN                  BIT(14)
>  21 #define REG_CLK32K_AUTO_SWT_BYPASS              BIT(15)
>
> Init sequence changed in H6 BSP to:
>
> 646         /*
> 647          * Step1: select RTC clock source
> 648          */
> 649         tmp_data = readl(chip->base + SUNXI_LOSC_CTRL);
> 650         tmp_data &= (~REG_CLK32K_AUTO_SWT_EN);
> 651
> 652         /* Disable auto switch function */
> 653         tmp_data |= REG_CLK32K_AUTO_SWT_BYPASS;
> 654         writel(tmp_data, chip->base + SUNXI_LOSC_CTRL);
> 655
> 656         tmp_data = readl(chip->base + SUNXI_LOSC_CTRL);
> 657         tmp_data |= (RTC_SOURCE_EXTERNAL | REG_LOSCCTRL_MAGIC);
> 658         writel(tmp_data, chip->base + SUNXI_LOSC_CTRL);
> 659
> 660         /* We need to set GSM after change clock source */
> 661         udelay(10);
> 662         tmp_data = readl(chip->base + SUNXI_LOSC_CTRL);
> 663         tmp_data |= (EXT_LOSC_GSM | REG_LOSCCTRL_MAGIC);
> 664         writel(tmp_data, chip->base + SUNXI_LOSC_CTRL);
> 665

I don't have this in my H6 BSPs. One is H6 Lichee v1.1 downloaded from Pine64.
The link was from linux-sunxi wiki's H6 page.

The other is a 4.9 kernel tree, which I believe is from Allwinner's github:

    https://github.com/Allwinner-Homlet/H6-BSP4.9-linux

> For older BSPs, the init sequence looked like this:
>
> 482         /*
> 483          * Step1: select RTC clock source
> 484          */
> 485         tmp_data = sunxi_rtc_read(SUNXI_LOSC_CTRL_REG);
> 486         tmp_data &= (~REG_CLK32K_AUTO_SWT_EN);
> 487         tmp_data |= (RTC_SOURCE_EXTERNAL | REG_LOSCCTRL_MAGIC);
> 488         tmp_data |= (EXT_LOSC_GSM);
> 489         sunxi_rtc_write(tmp_data, SUNXI_LOSC_CTRL_REG);
> 490
>
> EXT_LOSC_GSM has values 4 values from low to high, and I guess it configures
> gain for the oscillator's amplifier in the feedback loop of the circuit.
>
> So the new code, for some reason changed from single write to sequence
> of individual writes/config steps:
>
> 1) disable auto-switch and enable auto-switch bypass
> 2) select RTC clock source (to LOSC)
>   (wait)

Maybe it's possible to glitch if these two are combined?

> 3) configure gain on the LOSC
>
> regards,
>         o.
>
> > ChenYu
>
> --
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe@googlegroups.com.
> To view this discussion on the web, visit https://groups.google.com/d/msgid/linux-sunxi/20190805104529.z3mex3m2tss7lzlr%40core.my.home.
Ondřej Jirman Aug. 5, 2019, 11:10 a.m. UTC | #5
On Mon, Aug 05, 2019 at 06:54:17PM +0800, Chen-Yu Tsai wrote:
> On Mon, Aug 5, 2019 at 6:45 PM Ondřej Jirman <megous@megous.com> wrote:
> >
> > On Mon, Aug 05, 2019 at 06:16:14PM +0800, Chen-Yu Tsai wrote:
> > > On Fri, Apr 12, 2019 at 8:07 PM megous via linux-sunxi
> > > <linux-sunxi@googlegroups.com> wrote:
> > > >
> > > > From: Ondrej Jirman <megous@megous.com>
> > > >
> > > > RTC on H6 is mostly the same as on H5 and H3. It has slight differences
> > > > mostly in features that are not yet supported by this driver.
> > > >
> > > > Some differences are already stated in the comments in existing code.
> > > > One other difference is that H6 has extra bit in LOSC_CTRL_REG, called
> > > > EXT_LOSC_EN to enable/disable external low speed crystal oscillator.
> > > >
> > > > It also has bit EXT_LOSC_STA in LOSC_AUTO_SWT_STA_REG, to check whether
> > > > external low speed oscillator is working correctly.
> > > >
> > > > This patch adds support for enabling LOSC when necessary:
> > > >
> > > > - during reparenting
> > > > - when probing the clock
> > > >
> > > > H6 also has capacbility to automatically reparent RTC clock from
> > > > external crystal oscillator, to internal RC oscillator, if external
> > > > oscillator fails. This is enabled by default. Disable it during
> > > > probe.
> > > >
> > > > Signed-off-by: Ondrej Jirman <megous@megous.com>
> > > > ---
> > > >  drivers/rtc/rtc-sun6i.c | 40 ++++++++++++++++++++++++++++++++++++++--
> > > >  1 file changed, 38 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
> > > > index 11f56de52179..7375a530c565 100644
> > > > --- a/drivers/rtc/rtc-sun6i.c
> > > > +++ b/drivers/rtc/rtc-sun6i.c
> > > > @@ -41,9 +41,11 @@
> > > >  /* Control register */
> > > >  #define SUN6I_LOSC_CTRL                                0x0000
> > > >  #define SUN6I_LOSC_CTRL_KEY                    (0x16aa << 16)
> > > > +#define SUN6I_LOSC_CTRL_AUTO_SWT_BYPASS                BIT(15)
> > >
> > > Manual says bit 14? Or is this different from LOSC_AUTO_SWT_EN?
> > >
> > > The rest looks ok.
> >
> > To give you more information. This is a new thing in H6 BSP, compared
> > to BSPs for previous SoCs (H5/H3).
> >
> >  20 #define REG_CLK32K_AUTO_SWT_EN                  BIT(14)
> >  21 #define REG_CLK32K_AUTO_SWT_BYPASS              BIT(15)
> >
> > Init sequence changed in H6 BSP to:
> >
> > 646         /*
> > 647          * Step1: select RTC clock source
> > 648          */
> > 649         tmp_data = readl(chip->base + SUNXI_LOSC_CTRL);
> > 650         tmp_data &= (~REG_CLK32K_AUTO_SWT_EN);
> > 651
> > 652         /* Disable auto switch function */
> > 653         tmp_data |= REG_CLK32K_AUTO_SWT_BYPASS;
> > 654         writel(tmp_data, chip->base + SUNXI_LOSC_CTRL);
> > 655
> > 656         tmp_data = readl(chip->base + SUNXI_LOSC_CTRL);
> > 657         tmp_data |= (RTC_SOURCE_EXTERNAL | REG_LOSCCTRL_MAGIC);
> > 658         writel(tmp_data, chip->base + SUNXI_LOSC_CTRL);
> > 659
> > 660         /* We need to set GSM after change clock source */
> > 661         udelay(10);
> > 662         tmp_data = readl(chip->base + SUNXI_LOSC_CTRL);
> > 663         tmp_data |= (EXT_LOSC_GSM | REG_LOSCCTRL_MAGIC);
> > 664         writel(tmp_data, chip->base + SUNXI_LOSC_CTRL);
> > 665
> 
> I don't have this in my H6 BSPs. One is H6 Lichee v1.1 downloaded from Pine64.
> The link was from linux-sunxi wiki's H6 page.
> 
> The other is a 4.9 kernel tree, which I believe is from Allwinner's github:
> 
>     https://github.com/Allwinner-Homlet/H6-BSP4.9-linux

Interesting. :) I have the BSP I was using saved here:

https://megous.com/git/linux/tree/drivers/rtc/rtc-sunxi.c?h=h6-4.9-bsp#n649

It's based of 4.9.119

https://megous.com/git/linux/log/?h=h6-4.9-bsp

I don't remember where I found it. But I imported it fairly recently, and
the code you pointed to looks like an older version that I can found in some
beta H6 BSP, that I imported way earlier and is based on 4.9.56:

https://megous.com/git/linux/tree/drivers/rtc/rtc-sunxi.c?h=linux-h6
https://megous.com/git/linux/log/?h=linux-h6

Hmm, archeology. :)

> > For older BSPs, the init sequence looked like this:
> >
> > 482         /*
> > 483          * Step1: select RTC clock source
> > 484          */
> > 485         tmp_data = sunxi_rtc_read(SUNXI_LOSC_CTRL_REG);
> > 486         tmp_data &= (~REG_CLK32K_AUTO_SWT_EN);
> > 487         tmp_data |= (RTC_SOURCE_EXTERNAL | REG_LOSCCTRL_MAGIC);
> > 488         tmp_data |= (EXT_LOSC_GSM);
> > 489         sunxi_rtc_write(tmp_data, SUNXI_LOSC_CTRL_REG);
> > 490
> >
> > EXT_LOSC_GSM has values 4 values from low to high, and I guess it configures
> > gain for the oscillator's amplifier in the feedback loop of the circuit.
> >
> > So the new code, for some reason changed from single write to sequence
> > of individual writes/config steps:
> >
> > 1) disable auto-switch and enable auto-switch bypass
> > 2) select RTC clock source (to LOSC)
> >   (wait)
> 
> Maybe it's possible to glitch if these two are combined?

That's what I thought too. Or the programmer thought so, and was just
programming defensively, and there's no real problem in the practice.

But that specific delay() seems like someone trying to solve a real issue. Of
course there's no knowing if it was on H6 or on some other SoC.

regards,
	o.

> 
> > 3) configure gain on the LOSC
> >
> > regards,
> >         o.
> >
> > > ChenYu
> >
> > --
> > You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> > To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe@googlegroups.com.
> > To view this discussion on the web, visit https://groups.google.com/d/msgid/linux-sunxi/20190805104529.z3mex3m2tss7lzlr%40core.my.home.
Chen-Yu Tsai Aug. 5, 2019, 11:21 a.m. UTC | #6
On Mon, Aug 5, 2019 at 7:10 PM Ondřej Jirman <megous@megous.com> wrote:
>
> On Mon, Aug 05, 2019 at 06:54:17PM +0800, Chen-Yu Tsai wrote:
> > On Mon, Aug 5, 2019 at 6:45 PM Ondřej Jirman <megous@megous.com> wrote:
> > >
> > > On Mon, Aug 05, 2019 at 06:16:14PM +0800, Chen-Yu Tsai wrote:
> > > > On Fri, Apr 12, 2019 at 8:07 PM megous via linux-sunxi
> > > > <linux-sunxi@googlegroups.com> wrote:
> > > > >
> > > > > From: Ondrej Jirman <megous@megous.com>
> > > > >
> > > > > RTC on H6 is mostly the same as on H5 and H3. It has slight differences
> > > > > mostly in features that are not yet supported by this driver.
> > > > >
> > > > > Some differences are already stated in the comments in existing code.
> > > > > One other difference is that H6 has extra bit in LOSC_CTRL_REG, called
> > > > > EXT_LOSC_EN to enable/disable external low speed crystal oscillator.
> > > > >
> > > > > It also has bit EXT_LOSC_STA in LOSC_AUTO_SWT_STA_REG, to check whether
> > > > > external low speed oscillator is working correctly.
> > > > >
> > > > > This patch adds support for enabling LOSC when necessary:
> > > > >
> > > > > - during reparenting
> > > > > - when probing the clock
> > > > >
> > > > > H6 also has capacbility to automatically reparent RTC clock from
> > > > > external crystal oscillator, to internal RC oscillator, if external
> > > > > oscillator fails. This is enabled by default. Disable it during
> > > > > probe.
> > > > >
> > > > > Signed-off-by: Ondrej Jirman <megous@megous.com>
> > > > > ---
> > > > >  drivers/rtc/rtc-sun6i.c | 40 ++++++++++++++++++++++++++++++++++++++--
> > > > >  1 file changed, 38 insertions(+), 2 deletions(-)
> > > > >
> > > > > diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
> > > > > index 11f56de52179..7375a530c565 100644
> > > > > --- a/drivers/rtc/rtc-sun6i.c
> > > > > +++ b/drivers/rtc/rtc-sun6i.c
> > > > > @@ -41,9 +41,11 @@
> > > > >  /* Control register */
> > > > >  #define SUN6I_LOSC_CTRL                                0x0000
> > > > >  #define SUN6I_LOSC_CTRL_KEY                    (0x16aa << 16)
> > > > > +#define SUN6I_LOSC_CTRL_AUTO_SWT_BYPASS                BIT(15)
> > > >
> > > > Manual says bit 14? Or is this different from LOSC_AUTO_SWT_EN?
> > > >
> > > > The rest looks ok.
> > >
> > > To give you more information. This is a new thing in H6 BSP, compared
> > > to BSPs for previous SoCs (H5/H3).
> > >
> > >  20 #define REG_CLK32K_AUTO_SWT_EN                  BIT(14)
> > >  21 #define REG_CLK32K_AUTO_SWT_BYPASS              BIT(15)
> > >
> > > Init sequence changed in H6 BSP to:
> > >
> > > 646         /*
> > > 647          * Step1: select RTC clock source
> > > 648          */
> > > 649         tmp_data = readl(chip->base + SUNXI_LOSC_CTRL);
> > > 650         tmp_data &= (~REG_CLK32K_AUTO_SWT_EN);
> > > 651
> > > 652         /* Disable auto switch function */
> > > 653         tmp_data |= REG_CLK32K_AUTO_SWT_BYPASS;
> > > 654         writel(tmp_data, chip->base + SUNXI_LOSC_CTRL);
> > > 655
> > > 656         tmp_data = readl(chip->base + SUNXI_LOSC_CTRL);
> > > 657         tmp_data |= (RTC_SOURCE_EXTERNAL | REG_LOSCCTRL_MAGIC);
> > > 658         writel(tmp_data, chip->base + SUNXI_LOSC_CTRL);
> > > 659
> > > 660         /* We need to set GSM after change clock source */
> > > 661         udelay(10);
> > > 662         tmp_data = readl(chip->base + SUNXI_LOSC_CTRL);
> > > 663         tmp_data |= (EXT_LOSC_GSM | REG_LOSCCTRL_MAGIC);
> > > 664         writel(tmp_data, chip->base + SUNXI_LOSC_CTRL);
> > > 665
> >
> > I don't have this in my H6 BSPs. One is H6 Lichee v1.1 downloaded from Pine64.
> > The link was from linux-sunxi wiki's H6 page.
> >
> > The other is a 4.9 kernel tree, which I believe is from Allwinner's github:
> >
> >     https://github.com/Allwinner-Homlet/H6-BSP4.9-linux
>
> Interesting. :) I have the BSP I was using saved here:
>
> https://megous.com/git/linux/tree/drivers/rtc/rtc-sunxi.c?h=h6-4.9-bsp#n649
>
> It's based of 4.9.119
>
> https://megous.com/git/linux/log/?h=h6-4.9-bsp
>
> I don't remember where I found it. But I imported it fairly recently, and
> the code you pointed to looks like an older version that I can found in some
> beta H6 BSP, that I imported way earlier and is based on 4.9.56:
>
> https://megous.com/git/linux/tree/drivers/rtc/rtc-sunxi.c?h=linux-h6
> https://megous.com/git/linux/log/?h=linux-h6
>
> Hmm, archeology. :)

That's good enough for me. I suppose if we do have any more doubts we could
ask them directly.


Reviewed-by: Chen-Yu Tsai <wens@csie.org>

> > > For older BSPs, the init sequence looked like this:
> > >
> > > 482         /*
> > > 483          * Step1: select RTC clock source
> > > 484          */
> > > 485         tmp_data = sunxi_rtc_read(SUNXI_LOSC_CTRL_REG);
> > > 486         tmp_data &= (~REG_CLK32K_AUTO_SWT_EN);
> > > 487         tmp_data |= (RTC_SOURCE_EXTERNAL | REG_LOSCCTRL_MAGIC);
> > > 488         tmp_data |= (EXT_LOSC_GSM);
> > > 489         sunxi_rtc_write(tmp_data, SUNXI_LOSC_CTRL_REG);
> > > 490
> > >
> > > EXT_LOSC_GSM has values 4 values from low to high, and I guess it configures
> > > gain for the oscillator's amplifier in the feedback loop of the circuit.
> > >
> > > So the new code, for some reason changed from single write to sequence
> > > of individual writes/config steps:
> > >
> > > 1) disable auto-switch and enable auto-switch bypass
> > > 2) select RTC clock source (to LOSC)
> > >   (wait)
> >
> > Maybe it's possible to glitch if these two are combined?
>
> That's what I thought too. Or the programmer thought so, and was just
> programming defensively, and there's no real problem in the practice.
>
> But that specific delay() seems like someone trying to solve a real issue. Of
> course there's no knowing if it was on H6 or on some other SoC.

It's probably for the clock waveform to stabilize. Why they do it _after_
switching to the clock is weird though.

> regards,
>         o.
>
> >
> > > 3) configure gain on the LOSC
> > >
> > > regards,
> > >         o.
> > >
> > > > ChenYu
> > >
> > > --
> > > You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> > > To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe@googlegroups.com.
> > > To view this discussion on the web, visit https://groups.google.com/d/msgid/linux-sunxi/20190805104529.z3mex3m2tss7lzlr%40core.my.home.
>
> --
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe@googlegroups.com.
> To view this discussion on the web, visit https://groups.google.com/d/msgid/linux-sunxi/20190805111037.76vmanzcurffpbdf%40core.my.home.
Clément Péron Aug. 5, 2019, 12:16 p.m. UTC | #7
Hi,

On Mon, 5 Aug 2019 at 13:10, Ondřej Jirman <megous@megous.com> wrote:
>
> On Mon, Aug 05, 2019 at 06:54:17PM +0800, Chen-Yu Tsai wrote:
> > On Mon, Aug 5, 2019 at 6:45 PM Ondřej Jirman <megous@megous.com> wrote:
> > >
[snip]
>
> Interesting. :) I have the BSP I was using saved here:
>
> https://megous.com/git/linux/tree/drivers/rtc/rtc-sunxi.c?h=h6-4.9-bsp#n649
>
> It's based of 4.9.119
>
> https://megous.com/git/linux/log/?h=h6-4.9-bsp
>
> I don't remember where I found it. But I imported it fairly recently, and
> the code you pointed to looks like an older version that I can found in some
> beta H6 BSP, that I imported way earlier and is based on 4.9.56:

The last recent that I know is from OrangePi H6 but it's based on 4.9.118.

https://github.com/orangepi-xunlong/OrangePiH6_Linux4_9

Regards,
Clément

>
> https://megous.com/git/linux/tree/drivers/rtc/rtc-sunxi.c?h=linux-h6
> https://megous.com/git/linux/log/?h=linux-h6
>
> Hmm, archeology. :)
>
> > > For older BSPs, the init sequence looked like this:
> > >
> > > 482         /*
> > > 483          * Step1: select RTC clock source
> > > 484          */
> > > 485         tmp_data = sunxi_rtc_read(SUNXI_LOSC_CTRL_REG);
> > > 486         tmp_data &= (~REG_CLK32K_AUTO_SWT_EN);
> > > 487         tmp_data |= (RTC_SOURCE_EXTERNAL | REG_LOSCCTRL_MAGIC);
> > > 488         tmp_data |= (EXT_LOSC_GSM);
> > > 489         sunxi_rtc_write(tmp_data, SUNXI_LOSC_CTRL_REG);
> > > 490
> > >
> > > EXT_LOSC_GSM has values 4 values from low to high, and I guess it configures
> > > gain for the oscillator's amplifier in the feedback loop of the circuit.
> > >
> > > So the new code, for some reason changed from single write to sequence
> > > of individual writes/config steps:
> > >
> > > 1) disable auto-switch and enable auto-switch bypass
> > > 2) select RTC clock source (to LOSC)
> > >   (wait)
> >
> > Maybe it's possible to glitch if these two are combined?
>
> That's what I thought too. Or the programmer thought so, and was just
> programming defensively, and there's no real problem in the practice.
>
> But that specific delay() seems like someone trying to solve a real issue. Of
> course there's no knowing if it was on H6 or on some other SoC.
>
> regards,
>         o.
>
> >
> > > 3) configure gain on the LOSC
> > >
> > > regards,
> > >         o.
> > >
> > > > ChenYu
> > >
> > > --
> > > You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> > > To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe@googlegroups.com.
> > > To view this discussion on the web, visit https://groups.google.com/d/msgid/linux-sunxi/20190805104529.z3mex3m2tss7lzlr%40core.my.home.
>
> --
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe@googlegroups.com.
> To view this discussion on the web, visit https://groups.google.com/d/msgid/linux-sunxi/20190805111037.76vmanzcurffpbdf%40core.my.home.
diff mbox series

Patch

diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index 11f56de52179..7375a530c565 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -41,9 +41,11 @@ 
 /* Control register */
 #define SUN6I_LOSC_CTRL				0x0000
 #define SUN6I_LOSC_CTRL_KEY			(0x16aa << 16)
+#define SUN6I_LOSC_CTRL_AUTO_SWT_BYPASS		BIT(15)
 #define SUN6I_LOSC_CTRL_ALM_DHMS_ACC		BIT(9)
 #define SUN6I_LOSC_CTRL_RTC_HMS_ACC		BIT(8)
 #define SUN6I_LOSC_CTRL_RTC_YMD_ACC		BIT(7)
+#define SUN6I_LOSC_CTRL_EXT_LOSC_EN		BIT(4)
 #define SUN6I_LOSC_CTRL_EXT_OSC			BIT(0)
 #define SUN6I_LOSC_CTRL_ACC_MASK		GENMASK(9, 7)
 
@@ -137,6 +139,8 @@  struct sun6i_rtc_clk_data {
 	unsigned int has_prescaler : 1;
 	unsigned int has_out_clk : 1;
 	unsigned int export_iosc : 1;
+	unsigned int has_losc_en : 1;
+	unsigned int has_auto_swt : 1;
 };
 
 struct sun6i_rtc_dev {
@@ -199,6 +203,10 @@  static int sun6i_rtc_osc_set_parent(struct clk_hw *hw, u8 index)
 	val &= ~SUN6I_LOSC_CTRL_EXT_OSC;
 	val |= SUN6I_LOSC_CTRL_KEY;
 	val |= index ? SUN6I_LOSC_CTRL_EXT_OSC : 0;
+	if (rtc->data->has_losc_en) {
+		val &= ~SUN6I_LOSC_CTRL_EXT_LOSC_EN;
+		val |= index ? SUN6I_LOSC_CTRL_EXT_LOSC_EN : 0;
+	}
 	writel(val, rtc->base + SUN6I_LOSC_CTRL);
 	spin_unlock_irqrestore(&rtc->lock, flags);
 
@@ -224,6 +232,7 @@  static void __init sun6i_rtc_clk_init(struct device_node *node,
 	const char *iosc_name = "rtc-int-osc";
 	const char *clkout_name = "osc32k-out";
 	const char *parents[2];
+	u32 reg;
 
 	rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
 	if (!rtc)
@@ -244,9 +253,18 @@  static void __init sun6i_rtc_clk_init(struct device_node *node,
 		goto err;
 	}
 
+	reg = SUN6I_LOSC_CTRL_KEY;
+	if (rtc->data->has_auto_swt) {
+		/* Bypass auto-switch to int osc, on ext losc failure */
+		reg |= SUN6I_LOSC_CTRL_AUTO_SWT_BYPASS;
+		writel(reg, rtc->base + SUN6I_LOSC_CTRL);
+	}
+
 	/* Switch to the external, more precise, oscillator */
-	writel(SUN6I_LOSC_CTRL_KEY | SUN6I_LOSC_CTRL_EXT_OSC,
-	       rtc->base + SUN6I_LOSC_CTRL);
+	reg |= SUN6I_LOSC_CTRL_EXT_OSC;
+	if (rtc->data->has_losc_en)
+		reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN;
+	writel(reg, rtc->base + SUN6I_LOSC_CTRL);
 
 	/* Yes, I know, this is ugly. */
 	sun6i_rtc = rtc;
@@ -354,6 +372,23 @@  CLK_OF_DECLARE_DRIVER(sun8i_h3_rtc_clk, "allwinner,sun8i-h3-rtc",
 CLK_OF_DECLARE_DRIVER(sun50i_h5_rtc_clk, "allwinner,sun50i-h5-rtc",
 		      sun8i_h3_rtc_clk_init);
 
+static const struct sun6i_rtc_clk_data sun50i_h6_rtc_data = {
+	.rc_osc_rate = 16000000,
+	.fixed_prescaler = 32,
+	.has_prescaler = 1,
+	.has_out_clk = 1,
+	.export_iosc = 1,
+	.has_losc_en = 1,
+	.has_auto_swt = 1,
+};
+
+static void __init sun50i_h6_rtc_clk_init(struct device_node *node)
+{
+	sun6i_rtc_clk_init(node, &sun50i_h6_rtc_data);
+}
+CLK_OF_DECLARE_DRIVER(sun50i_h6_rtc_clk, "allwinner,sun50i-h6-rtc",
+		      sun50i_h6_rtc_clk_init);
+
 static const struct sun6i_rtc_clk_data sun8i_v3_rtc_data = {
 	.rc_osc_rate = 32000,
 	.has_out_clk = 1,
@@ -683,6 +718,7 @@  static const struct of_device_id sun6i_rtc_dt_ids[] = {
 	{ .compatible = "allwinner,sun8i-h3-rtc" },
 	{ .compatible = "allwinner,sun8i-v3-rtc" },
 	{ .compatible = "allwinner,sun50i-h5-rtc" },
+	{ .compatible = "allwinner,sun50i-h6-rtc" },
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids);