diff options
author | Joshua Clayton <stillcompiling@gmail.com> | 2016-02-05 15:41:12 -0500 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2016-03-14 12:08:16 -0400 |
commit | 5495a4159f7413f0367e8c9727ba9facd40ade7f (patch) | |
tree | 5bfdec7f3b6982a2c29c89762e8a20a50e579918 | |
parent | b3967067c273359c7462f4be9a887c3d1a515f49 (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.txt | 6 | ||||
-rw-r--r-- | drivers/rtc/rtc-sysfs.c | 35 |
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. |
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 | IOCTL INTERFACE | 167 | IOCTL 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 | } |
219 | static DEVICE_ATTR_RW(wakealarm); | 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 | static struct attribute *rtc_attrs[] = { | 249 | static 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 | } |