Hello Kortmann

I am trying to use internal RTC of with Allwinner H3 for Orangepi board. 
I need to know how to change the clock source of the intrnal RTC at boot 
time (using armbian with 3.4.113) and the code you mentioned below how to 
use in the driver part.
Thanks.
Mahesh 



On Wednesday, July 27, 2016 at 8:45:12 PM UTC+5:30, Onno Kortmann wrote:
>
> This adds a sysfs 'clock_source' attribute which can be used to query 
> and set the clock source of the RTC, either 'internal' or 'external'. 
>
> Important note: Probing the pins of the 32kHz crystal with a scope will 
> not reliably tell you whether the (usually) more accurate external is 
> selected! On a 'Cubietech Cubietruck' board, the author saw a stable 
> 32768Hz signal on the crystal, even though the internal oscillator was 
> selected and the clock wildly drifting. 
>
> Using adjtimex might help to figure out which oscillator is selected: 
>
> ~# echo internal > /sys/devices/.../1c20d00.rtc/clock_source 
> ~# adjtimex -n -c=3 
>                                       --- current ---   -- suggested -- 
> cmos time     system-cmos  error_ppm   tick      freq    tick      freq 
> 1469627826      31.224561 
> 1469627835      31.858098    63353.6  10000         0 
> 1469627844      32.490782    63268.4  10000         0    9367   2069425 
> ~# echo external > /sys/devices/.../1c20d00.rtc/clock_source 
> ~# adjtimex -n -c=3 
>                                       --- current ---   -- suggested -- 
> cmos time     system-cmos  error_ppm   tick      freq    tick      freq 
> 1469627851      32.883407 
> 1469627861      32.883380       -2.7  10000         0 
> 1469627871      32.883352       -2.8  10000         0   10000    185937 
>
> Signed-off-by: Onno Kortmann <[email protected] <javascript:>> 
> --- 
>  drivers/rtc/rtc-sunxi.c | 54 
> +++++++++++++++++++++++++++++++++++++++++++++++++ 
>  1 file changed, 54 insertions(+) 
>
> diff --git a/drivers/rtc/rtc-sunxi.c b/drivers/rtc/rtc-sunxi.c 
> index abada60..3fcf571 100644 
> --- a/drivers/rtc/rtc-sunxi.c 
> +++ b/drivers/rtc/rtc-sunxi.c 
> @@ -36,6 +36,8 @@ 
>  #define SUNXI_LOSC_CTRL                                0x0000 
>  #define SUNXI_LOSC_CTRL_RTC_HMS_ACC                BIT(8) 
>  #define SUNXI_LOSC_CTRL_RTC_YMD_ACC                BIT(7) 
> +#define SUNXI_LOSC_OSC32K_SRC_SEL                 BIT(0) 
> +#define SUNXI_LOSC_KEY_VALUE                        0x16aa0000 
>   
>  #define SUNXI_RTC_YMD                                0x0004 
>   
> @@ -432,6 +434,50 @@ static const struct of_device_id sunxi_rtc_dt_ids[] = 
> { 
>  }; 
>  MODULE_DEVICE_TABLE(of, sunxi_rtc_dt_ids); 
>   
> +/* As per page 126 of the A20 manual, the lowest bit in LOSC_CTRL_REG 
> controls 
> + * the 32.768KHz clock source to use for the RTC. Using the clock_source 
> sysfs 
> + * attribute, the clock can be selected between external (accurate 32kHz 
> + * crystal) and internal (seems to be an inaccurate RC oscillator) mode. 
>  It 
> + * appears that this bit is non-volatile and will be kept in the RTC when 
> the 
> + * system is powered off. 
> + */ 
> +static ssize_t sunxi_rtc_show_clock_source(struct device *dev, 
> +                                        struct device_attribute *attr, 
> +                                        char *buf) 
> +{ 
> +        struct sunxi_rtc_dev *chip = dev_get_drvdata(dev); 
> +        u32 val = readl(chip->base + SUNXI_LOSC_CTRL); 
> +        if (val & SUNXI_LOSC_OSC32K_SRC_SEL) 
> +                return sprintf(buf, "external\n"); 
> +        else 
> +                return sprintf(buf, "internal\n"); 
> +} 
> + 
> +static ssize_t sunxi_rtc_store_clock_source(struct device *dev, 
> +                                        struct device_attribute *attr, 
> +                                        const char *buf, size_t count) { 
> +        struct sunxi_rtc_dev *chip = dev_get_drvdata(dev); 
> +        u32 val = readl(chip->base + SUNXI_LOSC_CTRL); 
> + 
> +        if (strncmp(buf, "external", 8) == 0) 
> +                val|=SUNXI_LOSC_OSC32K_SRC_SEL; 
> +        else if (strncmp(buf, "internal", 8) == 0) 
> +                val&=~SUNXI_LOSC_OSC32K_SRC_SEL; 
> +        else 
> +                return -EINVAL; 
> + 
> +        /* Writing this bit requires setting the upper 16 bit to 0x16aa 
> (key 
> +         * value). */ 
> +        val |= SUNXI_LOSC_KEY_VALUE; 
> + 
> +        writel(val, chip->base + SUNXI_LOSC_CTRL); 
> +        return count; 
> +} 
> + 
> +static DEVICE_ATTR(clock_source, S_IRUGO | S_IWUSR, 
> +                sunxi_rtc_show_clock_source, 
> +                sunxi_rtc_store_clock_source); 
> + 
>  static int sunxi_rtc_probe(struct platform_device *pdev) 
>  { 
>          struct sunxi_rtc_dev *chip; 
> @@ -490,6 +536,13 @@ static int sunxi_rtc_probe(struct platform_device 
> *pdev) 
>   
>          dev_info(&pdev->dev, "RTC enabled\n"); 
>   
> +        ret = device_create_file(&pdev->dev, &dev_attr_clock_source); 
> +        if (ret) { 
> +                dev_err(&pdev->dev, "Unable to create sysfs entry: %s\n", 
> +                        dev_attr_clock_source.attr.name); 
> +                return ret; 
> +        } 
> + 
>          return 0; 
>  } 
>   
> @@ -499,6 +552,7 @@ static int sunxi_rtc_remove(struct platform_device 
> *pdev) 
>   
>          rtc_device_unregister(chip->rtc); 
>   
> +        device_remove_file(&pdev->dev, &dev_attr_clock_source); 
>          return 0; 
>  } 
>   
> -- 
> 2.2.0.34.gb8f29bf 
>
>

-- 
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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to