Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rtc: implement a sysfs interface for clock offset

clock offset may be set and read in decimal parts per billion
attribute is /sys/class/rtc/rtcN/offset
The attribute is only visible for rtcs that have set_offset implemented.

Signed-off-by: Joshua Clayton <stillcompiling@gmail.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>

authored by

Joshua Clayton and committed by
Alexandre Belloni
5495a415 b3967067

+40 -1
+6
Documentation/rtc.txt
··· 157 157 the epoch by default, or if there's a leading +, seconds in the 158 158 future, or if there is a leading +=, seconds ahead of the current 159 159 alarm. 160 + offset: The amount which the rtc clock has been adjusted in firmware. 161 + Visible only if the driver supports clock offset adjustment. 162 + The unit is parts per billion, i.e. The number of clock ticks 163 + which are added to or removed from the rtc's base clock per 164 + billion ticks. A positive value makes a day pass more slowly, 165 + longer, and a negative value makes a day pass more quickly. 160 166 161 167 IOCTL INTERFACE 162 168 ---------------
+34 -1
drivers/rtc/rtc-sysfs.c
··· 218 218 } 219 219 static DEVICE_ATTR_RW(wakealarm); 220 220 221 + static ssize_t 222 + offset_show(struct device *dev, struct device_attribute *attr, char *buf) 223 + { 224 + ssize_t retval; 225 + long offset; 226 + 227 + retval = rtc_read_offset(to_rtc_device(dev), &offset); 228 + if (retval == 0) 229 + retval = sprintf(buf, "%ld\n", offset); 230 + 231 + return retval; 232 + } 233 + 234 + static ssize_t 235 + offset_store(struct device *dev, struct device_attribute *attr, 236 + const char *buf, size_t n) 237 + { 238 + ssize_t retval; 239 + long offset; 240 + 241 + retval = kstrtol(buf, 10, &offset); 242 + if (retval == 0) 243 + retval = rtc_set_offset(to_rtc_device(dev), offset); 244 + 245 + return (retval < 0) ? retval : n; 246 + } 247 + static DEVICE_ATTR_RW(offset); 248 + 221 249 static struct attribute *rtc_attrs[] = { 222 250 &dev_attr_name.attr, 223 251 &dev_attr_date.attr, ··· 254 226 &dev_attr_max_user_freq.attr, 255 227 &dev_attr_hctosys.attr, 256 228 &dev_attr_wakealarm.attr, 229 + &dev_attr_offset.attr, 257 230 NULL, 258 231 }; 259 232 ··· 278 249 struct rtc_device *rtc = to_rtc_device(dev); 279 250 umode_t mode = attr->mode; 280 251 281 - if (attr == &dev_attr_wakealarm.attr) 252 + if (attr == &dev_attr_wakealarm.attr) { 282 253 if (!rtc_does_wakealarm(rtc)) 283 254 mode = 0; 255 + } else if (attr == &dev_attr_offset.attr) { 256 + if (!rtc->ops->set_offset) 257 + mode = 0; 258 + } 284 259 285 260 return mode; 286 261 }