1c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo/* 2c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo * RTC subsystem, sysfs interface 3c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo * 4c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo * Copyright (C) 2005 Tower Technologies 5c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo * Author: Alessandro Zummo <a.zummo@towertech.it> 6c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo * 7c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo * This program is free software; you can redistribute it and/or modify 8c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo * it under the terms of the GNU General Public License version 2 as 9c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo * published by the Free Software Foundation. 10c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo*/ 11c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 12c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo#include <linux/module.h> 13c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo#include <linux/rtc.h> 14c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 15ab6a2d70d18edc7a716ef3127b9e13382faec98cDavid Brownell#include "rtc-core.h" 16ab6a2d70d18edc7a716ef3127b9e13382faec98cDavid Brownell 17ab6a2d70d18edc7a716ef3127b9e13382faec98cDavid Brownell 18c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo/* device attributes */ 19c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 208a0bdfd7a05f5bb0486fbe7146a2cf775957e95eDavid Brownell/* 218a0bdfd7a05f5bb0486fbe7146a2cf775957e95eDavid Brownell * NOTE: RTC times displayed in sysfs use the RTC's timezone. That's 228a0bdfd7a05f5bb0486fbe7146a2cf775957e95eDavid Brownell * ideally UTC. However, PCs that also boot to MS-Windows normally use 238a0bdfd7a05f5bb0486fbe7146a2cf775957e95eDavid Brownell * the local time and change to match daylight savings time. That affects 248a0bdfd7a05f5bb0486fbe7146a2cf775957e95eDavid Brownell * attributes including date, time, since_epoch, and wakealarm. 258a0bdfd7a05f5bb0486fbe7146a2cf775957e95eDavid Brownell */ 268a0bdfd7a05f5bb0486fbe7146a2cf775957e95eDavid Brownell 27cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownellstatic ssize_t 28cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownellrtc_sysfs_show_name(struct device *dev, struct device_attribute *attr, 29cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownell char *buf) 30c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo{ 31c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo return sprintf(buf, "%s\n", to_rtc_device(dev)->name); 32c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo} 33c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 34cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownellstatic ssize_t 35cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownellrtc_sysfs_show_date(struct device *dev, struct device_attribute *attr, 36cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownell char *buf) 37c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo{ 38c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo ssize_t retval; 39c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo struct rtc_time tm; 40c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 41ab6a2d70d18edc7a716ef3127b9e13382faec98cDavid Brownell retval = rtc_read_time(to_rtc_device(dev), &tm); 42c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo if (retval == 0) { 43c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo retval = sprintf(buf, "%04d-%02d-%02d\n", 44c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); 45c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo } 46c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 47c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo return retval; 48c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo} 49c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 50cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownellstatic ssize_t 51cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownellrtc_sysfs_show_time(struct device *dev, struct device_attribute *attr, 52cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownell char *buf) 53c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo{ 54c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo ssize_t retval; 55c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo struct rtc_time tm; 56c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 57ab6a2d70d18edc7a716ef3127b9e13382faec98cDavid Brownell retval = rtc_read_time(to_rtc_device(dev), &tm); 58c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo if (retval == 0) { 59c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo retval = sprintf(buf, "%02d:%02d:%02d\n", 60c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo tm.tm_hour, tm.tm_min, tm.tm_sec); 61c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo } 62c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 63c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo return retval; 64c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo} 65c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 66cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownellstatic ssize_t 67cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownellrtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr, 68cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownell char *buf) 69c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo{ 70c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo ssize_t retval; 71c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo struct rtc_time tm; 72c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 73ab6a2d70d18edc7a716ef3127b9e13382faec98cDavid Brownell retval = rtc_read_time(to_rtc_device(dev), &tm); 74c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo if (retval == 0) { 75c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo unsigned long time; 76c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo rtc_tm_to_time(&tm, &time); 77c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo retval = sprintf(buf, "%lu\n", time); 78c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo } 79c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 80c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo return retval; 81c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo} 82c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 8306c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzbanstatic ssize_t 8406c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzbanrtc_sysfs_show_max_user_freq(struct device *dev, struct device_attribute *attr, 8506c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban char *buf) 8606c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban{ 8706c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban return sprintf(buf, "%d\n", to_rtc_device(dev)->max_user_freq); 8806c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban} 8906c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban 9006c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzbanstatic ssize_t 9106c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzbanrtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr, 9206c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban const char *buf, size_t n) 9306c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban{ 9406c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban struct rtc_device *rtc = to_rtc_device(dev); 9506c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban unsigned long val = simple_strtoul(buf, NULL, 0); 9606c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban 9706c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban if (val >= 4096 || val == 0) 9806c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban return -EINVAL; 9906c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban 10006c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban rtc->max_user_freq = (int)val; 10106c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban 10206c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban return n; 10306c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban} 10406c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban 105d8c1acb1664d17dd995e34507533321e986d9215Matthew Garrettstatic ssize_t 106d8c1acb1664d17dd995e34507533321e986d9215Matthew Garrettrtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr, 107d8c1acb1664d17dd995e34507533321e986d9215Matthew Garrett char *buf) 108d8c1acb1664d17dd995e34507533321e986d9215Matthew Garrett{ 109d8c1acb1664d17dd995e34507533321e986d9215Matthew Garrett#ifdef CONFIG_RTC_HCTOSYS_DEVICE 110d0ab4a4d5094e5d17b103dc5073529a04f00a469Uwe Kleine-König if (rtc_hctosys_ret == 0 && 111d0ab4a4d5094e5d17b103dc5073529a04f00a469Uwe Kleine-König strcmp(dev_name(&to_rtc_device(dev)->dev), 112d0ab4a4d5094e5d17b103dc5073529a04f00a469Uwe Kleine-König CONFIG_RTC_HCTOSYS_DEVICE) == 0) 113d8c1acb1664d17dd995e34507533321e986d9215Matthew Garrett return sprintf(buf, "1\n"); 114d8c1acb1664d17dd995e34507533321e986d9215Matthew Garrett else 115d8c1acb1664d17dd995e34507533321e986d9215Matthew Garrett#endif 116d8c1acb1664d17dd995e34507533321e986d9215Matthew Garrett return sprintf(buf, "0\n"); 117d8c1acb1664d17dd995e34507533321e986d9215Matthew Garrett} 118d8c1acb1664d17dd995e34507533321e986d9215Matthew Garrett 119cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownellstatic struct device_attribute rtc_attrs[] = { 120446ecbd925dc580c9972049c926c17aa8d967fe4David Brownell __ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL), 121446ecbd925dc580c9972049c926c17aa8d967fe4David Brownell __ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL), 122446ecbd925dc580c9972049c926c17aa8d967fe4David Brownell __ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL), 123446ecbd925dc580c9972049c926c17aa8d967fe4David Brownell __ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL), 12406c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban __ATTR(max_user_freq, S_IRUGO | S_IWUSR, rtc_sysfs_show_max_user_freq, 12506c65eb45578c52d1bc69d044239646d4c90e7eaBryan Kadzban rtc_sysfs_set_max_user_freq), 126d8c1acb1664d17dd995e34507533321e986d9215Matthew Garrett __ATTR(hctosys, S_IRUGO, rtc_sysfs_show_hctosys, NULL), 127446ecbd925dc580c9972049c926c17aa8d967fe4David Brownell { }, 128c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo}; 129c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 1303925a5ce44330767f7f0de5c58c6a797009f0f75David Brownellstatic ssize_t 131cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownellrtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr, 132cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownell char *buf) 1333925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell{ 1343925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell ssize_t retval; 1353925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell unsigned long alarm; 1363925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell struct rtc_wkalrm alm; 1373925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell 1388a0bdfd7a05f5bb0486fbe7146a2cf775957e95eDavid Brownell /* Don't show disabled alarms. For uniformity, RTC alarms are 1398a0bdfd7a05f5bb0486fbe7146a2cf775957e95eDavid Brownell * conceptually one-shot, even though some common RTCs (on PCs) 1408a0bdfd7a05f5bb0486fbe7146a2cf775957e95eDavid Brownell * don't actually work that way. 1413925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell * 1428a0bdfd7a05f5bb0486fbe7146a2cf775957e95eDavid Brownell * NOTE: RTC implementations where the alarm doesn't match an 1438a0bdfd7a05f5bb0486fbe7146a2cf775957e95eDavid Brownell * exact YYYY-MM-DD HH:MM[:SS] date *must* disable their RTC 1448a0bdfd7a05f5bb0486fbe7146a2cf775957e95eDavid Brownell * alarms after they trigger, to ensure one-shot semantics. 1453925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell */ 146ab6a2d70d18edc7a716ef3127b9e13382faec98cDavid Brownell retval = rtc_read_alarm(to_rtc_device(dev), &alm); 1473925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell if (retval == 0 && alm.enabled) { 1483925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell rtc_tm_to_time(&alm.time, &alarm); 1493925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell retval = sprintf(buf, "%lu\n", alarm); 1503925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell } 1513925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell 1523925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell return retval; 1533925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell} 1543925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell 1553925a5ce44330767f7f0de5c58c6a797009f0f75David Brownellstatic ssize_t 156cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownellrtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr, 157cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownell const char *buf, size_t n) 1583925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell{ 1593925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell ssize_t retval; 1603925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell unsigned long now, alarm; 1613925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell struct rtc_wkalrm alm; 162ab6a2d70d18edc7a716ef3127b9e13382faec98cDavid Brownell struct rtc_device *rtc = to_rtc_device(dev); 163c116bc2ae516e9949d645bc75b1ee294ff15db23Zhao Yakui char *buf_ptr; 164c116bc2ae516e9949d645bc75b1ee294ff15db23Zhao Yakui int adjust = 0; 1653925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell 1663925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell /* Only request alarms that trigger in the future. Disable them 1673925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell * by writing another time, e.g. 0 meaning Jan 1 1970 UTC. 1683925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell */ 169ab6a2d70d18edc7a716ef3127b9e13382faec98cDavid Brownell retval = rtc_read_time(rtc, &alm.time); 1703925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell if (retval < 0) 1713925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell return retval; 1723925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell rtc_tm_to_time(&alm.time, &now); 1733925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell 174c116bc2ae516e9949d645bc75b1ee294ff15db23Zhao Yakui buf_ptr = (char *)buf; 175c116bc2ae516e9949d645bc75b1ee294ff15db23Zhao Yakui if (*buf_ptr == '+') { 176c116bc2ae516e9949d645bc75b1ee294ff15db23Zhao Yakui buf_ptr++; 177c116bc2ae516e9949d645bc75b1ee294ff15db23Zhao Yakui adjust = 1; 178c116bc2ae516e9949d645bc75b1ee294ff15db23Zhao Yakui } 179c116bc2ae516e9949d645bc75b1ee294ff15db23Zhao Yakui alarm = simple_strtoul(buf_ptr, NULL, 0); 180c116bc2ae516e9949d645bc75b1ee294ff15db23Zhao Yakui if (adjust) { 181c116bc2ae516e9949d645bc75b1ee294ff15db23Zhao Yakui alarm += now; 182c116bc2ae516e9949d645bc75b1ee294ff15db23Zhao Yakui } 1833925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell if (alarm > now) { 1843925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell /* Avoid accidentally clobbering active alarms; we can't 1853925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell * entirely prevent that here, without even the minimal 1863925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell * locking from the /dev/rtcN api. 1873925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell */ 188ab6a2d70d18edc7a716ef3127b9e13382faec98cDavid Brownell retval = rtc_read_alarm(rtc, &alm); 1893925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell if (retval < 0) 1903925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell return retval; 1913925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell if (alm.enabled) 1923925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell return -EBUSY; 1933925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell 1943925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell alm.enabled = 1; 1953925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell } else { 1963925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell alm.enabled = 0; 1973925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell 1983925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell /* Provide a valid future alarm time. Linux isn't EFI, 1993925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell * this time won't be ignored when disabling the alarm. 2003925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell */ 2013925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell alarm = now + 300; 2023925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell } 2033925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell rtc_time_to_tm(alarm, &alm.time); 2043925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell 205ab6a2d70d18edc7a716ef3127b9e13382faec98cDavid Brownell retval = rtc_set_alarm(rtc, &alm); 2063925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell return (retval < 0) ? retval : n; 2073925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell} 208cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownellstatic DEVICE_ATTR(wakealarm, S_IRUGO | S_IWUSR, 2093925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell rtc_sysfs_show_wakealarm, rtc_sysfs_set_wakealarm); 2103925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell 2113925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell 2123925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell/* The reason to trigger an alarm with no process watching it (via sysfs) 2133925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell * is its side effect: waking from a system state like suspend-to-RAM or 2143925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell * suspend-to-disk. So: no attribute unless that side effect is possible. 2153925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell * (Userspace may disable that mechanism later.) 2163925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell */ 217446ecbd925dc580c9972049c926c17aa8d967fe4David Brownellstatic inline int rtc_does_wakealarm(struct rtc_device *rtc) 2183925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell{ 219cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownell if (!device_can_wakeup(rtc->dev.parent)) 2203925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell return 0; 2213925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell return rtc->ops->set_alarm != NULL; 2223925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell} 2233925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell 2243925a5ce44330767f7f0de5c58c6a797009f0f75David Brownell 225446ecbd925dc580c9972049c926c17aa8d967fe4David Brownellvoid rtc_sysfs_add_device(struct rtc_device *rtc) 226c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo{ 227c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo int err; 228c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 229446ecbd925dc580c9972049c926c17aa8d967fe4David Brownell /* not all RTCs support both alarms and wakeup */ 230446ecbd925dc580c9972049c926c17aa8d967fe4David Brownell if (!rtc_does_wakealarm(rtc)) 231446ecbd925dc580c9972049c926c17aa8d967fe4David Brownell return; 232c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 233cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownell err = device_create_file(&rtc->dev, &dev_attr_wakealarm); 234c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo if (err) 235898eb71cb17644964c5895fb190e79e3d0c49679Joe Perches dev_err(rtc->dev.parent, 236898eb71cb17644964c5895fb190e79e3d0c49679Joe Perches "failed to create alarm attribute, %d\n", err); 237c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo} 238c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 239446ecbd925dc580c9972049c926c17aa8d967fe4David Brownellvoid rtc_sysfs_del_device(struct rtc_device *rtc) 240c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo{ 241446ecbd925dc580c9972049c926c17aa8d967fe4David Brownell /* REVISIT did we add it successfully? */ 242446ecbd925dc580c9972049c926c17aa8d967fe4David Brownell if (rtc_does_wakealarm(rtc)) 243cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownell device_remove_file(&rtc->dev, &dev_attr_wakealarm); 244c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo} 245c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo 246446ecbd925dc580c9972049c926c17aa8d967fe4David Brownellvoid __init rtc_sysfs_init(struct class *rtc_class) 247c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo{ 248cd9662094edf4173e87f0452e57e4eacc228f8ffDavid Brownell rtc_class->dev_attrs = rtc_attrs; 249c5c3e19225217536d90515c494e55e642a21e4faAlessandro Zummo} 250