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.
