aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoshua Clayton <stillcompiling@gmail.com>2016-02-05 15:41:12 -0500
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2016-03-14 12:08:16 -0400
commit5495a4159f7413f0367e8c9727ba9facd40ade7f (patch)
tree5bfdec7f3b6982a2c29c89762e8a20a50e579918
parentb3967067c273359c7462f4be9a887c3d1a515f49 (diff)
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>
-rw-r--r--Documentation/rtc.txt6
-rw-r--r--drivers/rtc/rtc-sysfs.c35
2 files changed, 40 insertions, 1 deletions
diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt
index 8446f1ea1410..ddc366026e00 100644
--- a/Documentation/rtc.txt
+++ b/Documentation/rtc.txt
@@ -157,6 +157,12 @@ wakealarm: The time at which the clock will generate a system wakeup
157 the epoch by default, or if there's a leading +, seconds in the 157 the epoch by default, or if there's a leading +, seconds in the
158 future, or if there is a leading +=, seconds ahead of the current 158 future, or if there is a leading +=, seconds ahead of the current
159 alarm. 159 alarm.
160offset: 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
161IOCTL INTERFACE 167IOCTL INTERFACE
162--------------- 168---------------
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index 463e286064ab..63b9fb1318c2 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -218,6 +218,34 @@ wakealarm_store(struct device *dev, struct device_attribute *attr,
218} 218}
219static DEVICE_ATTR_RW(wakealarm); 219static DEVICE_ATTR_RW(wakealarm);
220 220
221static ssize_t
222offset_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
234static ssize_t
235offset_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}
247static DEVICE_ATTR_RW(offset);
248
221static struct attribute *rtc_attrs[] = { 249static struct attribute *rtc_attrs[] = {
222 &dev_attr_name.attr, 250 &dev_attr_name.attr,
223 &dev_attr_date.attr, 251 &dev_attr_date.attr,
@@ -226,6 +254,7 @@ static struct attribute *rtc_attrs[] = {
226 &dev_attr_max_user_freq.attr, 254 &dev_attr_max_user_freq.attr,
227 &dev_attr_hctosys.attr, 255 &dev_attr_hctosys.attr,
228 &dev_attr_wakealarm.attr, 256 &dev_attr_wakealarm.attr,
257 &dev_attr_offset.attr,
229 NULL, 258 NULL,
230}; 259};
231 260
@@ -249,9 +278,13 @@ static umode_t rtc_attr_is_visible(struct kobject *kobj,
249 struct rtc_device *rtc = to_rtc_device(dev); 278 struct rtc_device *rtc = to_rtc_device(dev);
250 umode_t mode = attr->mode; 279 umode_t mode = attr->mode;
251 280
252 if (attr == &dev_attr_wakealarm.attr) 281 if (attr == &dev_attr_wakealarm.attr) {
253 if (!rtc_does_wakealarm(rtc)) 282 if (!rtc_does_wakealarm(rtc))
254 mode = 0; 283 mode = 0;
284 } else if (attr == &dev_attr_offset.attr) {
285 if (!rtc->ops->set_offset)
286 mode = 0;
287 }
255 288
256 return mode; 289 return mode;
257} 290}