1 #include <linux/proc_fs.h> 2 #include <linux/seq_file.h> 3 #include <linux/suspend.h> 4 #include <linux/bcd.h> 5 #include <asm/uaccess.h> 6 7 #include <acpi/acpi_bus.h> 8 #include <acpi/acpi_drivers.h> 9 10 #ifdef CONFIG_X86 11 #include <linux/mc146818rtc.h> 12 #endif 13 14 #include "sleep.h" 15 16 #define _COMPONENT ACPI_SYSTEM_COMPONENT 17 18 /* 19 * this file provides support for: 20 * /proc/acpi/alarm 21 * /proc/acpi/wakeup 22 */ 23 24 ACPI_MODULE_NAME("sleep") 25 26 #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || !defined(CONFIG_X86) 27 /* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */ 28 #else 29 #define HAVE_ACPI_LEGACY_ALARM 30 #endif 31 32 #ifdef HAVE_ACPI_LEGACY_ALARM 33 34 static u32 cmos_bcd_read(int offset, int rtc_control); 35 36 static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset) 37 { 38 u32 sec, min, hr; 39 u32 day, mo, yr, cent = 0; 40 u32 today = 0; 41 unsigned char rtc_control = 0; 42 unsigned long flags; 43 44 spin_lock_irqsave(&rtc_lock, flags); 45 46 rtc_control = CMOS_READ(RTC_CONTROL); 47 sec = cmos_bcd_read(RTC_SECONDS_ALARM, rtc_control); 48 min = cmos_bcd_read(RTC_MINUTES_ALARM, rtc_control); 49 hr = cmos_bcd_read(RTC_HOURS_ALARM, rtc_control); 50 51 /* If we ever get an FACP with proper values... */ 52 if (acpi_gbl_FADT.day_alarm) { 53 /* ACPI spec: only low 6 its should be cared */ 54 day = CMOS_READ(acpi_gbl_FADT.day_alarm) & 0x3F; 55 if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) 56 day = bcd2bin(day); 57 } else 58 day = cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control); 59 if (acpi_gbl_FADT.month_alarm) 60 mo = cmos_bcd_read(acpi_gbl_FADT.month_alarm, rtc_control); 61 else { 62 mo = cmos_bcd_read(RTC_MONTH, rtc_control); 63 today = cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control); 64 } 65 if (acpi_gbl_FADT.century) 66 cent = cmos_bcd_read(acpi_gbl_FADT.century, rtc_control); 67 68 yr = cmos_bcd_read(RTC_YEAR, rtc_control); 69 70 spin_unlock_irqrestore(&rtc_lock, flags); 71 72 /* we're trusting the FADT (see above) */ 73 if (!acpi_gbl_FADT.century) 74 /* If we're not trusting the FADT, we should at least make it 75 * right for _this_ century... ehm, what is _this_ century? 76 * 77 * TBD: 78 * ASAP: find piece of code in the kernel, e.g. star tracker driver, 79 * which we can trust to determine the century correctly. Atom 80 * watch driver would be nice, too... 81 * 82 * if that has not happened, change for first release in 2050: 83 * if (yr<50) 84 * yr += 2100; 85 * else 86 * yr += 2000; // current line of code 87 * 88 * if that has not happened either, please do on 2099/12/31:23:59:59 89 * s/2000/2100 90 * 91 */ 92 yr += 2000; 93 else 94 yr += cent * 100; 95 96 /* 97 * Show correct dates for alarms up to a month into the future. 98 * This solves issues for nearly all situations with the common 99 * 30-day alarm clocks in PC hardware. 100 */ 101 if (day < today) { 102 if (mo < 12) { 103 mo += 1; 104 } else { 105 mo = 1; 106 yr += 1; 107 } 108 } 109 110 seq_printf(seq, "%4.4u-", yr); 111 (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo); 112 (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day); 113 (hr > 23) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", hr); 114 (min > 59) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", min); 115 (sec > 59) ? seq_puts(seq, "**\n") : seq_printf(seq, "%2.2u\n", sec); 116 117 return 0; 118 } 119 120 static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file) 121 { 122 return single_open(file, acpi_system_alarm_seq_show, PDE(inode)->data); 123 } 124 125 static int get_date_field(char **p, u32 * value) 126 { 127 char *next = NULL; 128 char *string_end = NULL; 129 int result = -EINVAL; 130 131 /* 132 * Try to find delimeter, only to insert null. The end of the 133 * string won't have one, but is still valid. 134 */ 135 if (*p == NULL) 136 return result; 137 138 next = strpbrk(*p, "- :"); 139 if (next) 140 *next++ = '\0'; 141 142 *value = simple_strtoul(*p, &string_end, 10); 143 144 /* Signal success if we got a good digit */ 145 if (string_end != *p) 146 result = 0; 147 148 if (next) 149 *p = next; 150 else 151 *p = NULL; 152 153 return result; 154 } 155 156 /* Read a possibly BCD register, always return binary */ 157 static u32 cmos_bcd_read(int offset, int rtc_control) 158 { 159 u32 val = CMOS_READ(offset); 160 if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) 161 val = bcd2bin(val); 162 return val; 163 } 164 165 /* Write binary value into possibly BCD register */ 166 static void cmos_bcd_write(u32 val, int offset, int rtc_control) 167 { 168 if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) 169 val = bin2bcd(val); 170 CMOS_WRITE(val, offset); 171 } 172 173 static ssize_t 174 acpi_system_write_alarm(struct file *file, 175 const char __user * buffer, size_t count, loff_t * ppos) 176 { 177 int result = 0; 178 char alarm_string[30] = { '\0' }; 179 char *p = alarm_string; 180 u32 sec, min, hr, day, mo, yr; 181 int adjust = 0; 182 unsigned char rtc_control = 0; 183 184 if (count > sizeof(alarm_string) - 1) 185 return -EINVAL; 186 187 if (copy_from_user(alarm_string, buffer, count)) 188 return -EFAULT; 189 190 alarm_string[count] = '\0'; 191 192 /* check for time adjustment */ 193 if (alarm_string[0] == '+') { 194 p++; 195 adjust = 1; 196 } 197 198 if ((result = get_date_field(&p, &yr))) 199 goto end; 200 if ((result = get_date_field(&p, &mo))) 201 goto end; 202 if ((result = get_date_field(&p, &day))) 203 goto end; 204 if ((result = get_date_field(&p, &hr))) 205 goto end; 206 if ((result = get_date_field(&p, &min))) 207 goto end; 208 if ((result = get_date_field(&p, &sec))) 209 goto end; 210 211 spin_lock_irq(&rtc_lock); 212 213 rtc_control = CMOS_READ(RTC_CONTROL); 214 215 if (adjust) { 216 yr += cmos_bcd_read(RTC_YEAR, rtc_control); 217 mo += cmos_bcd_read(RTC_MONTH, rtc_control); 218 day += cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control); 219 hr += cmos_bcd_read(RTC_HOURS, rtc_control); 220 min += cmos_bcd_read(RTC_MINUTES, rtc_control); 221 sec += cmos_bcd_read(RTC_SECONDS, rtc_control); 222 } 223 224 spin_unlock_irq(&rtc_lock); 225 226 if (sec > 59) { 227 min += sec/60; 228 sec = sec%60; 229 } 230 if (min > 59) { 231 hr += min/60; 232 min = min%60; 233 } 234 if (hr > 23) { 235 day += hr/24; 236 hr = hr%24; 237 } 238 if (day > 31) { 239 mo += day/32; 240 day = day%32; 241 } 242 if (mo > 12) { 243 yr += mo/13; 244 mo = mo%13; 245 } 246 247 spin_lock_irq(&rtc_lock); 248 /* 249 * Disable alarm interrupt before setting alarm timer or else 250 * when ACPI_EVENT_RTC is enabled, a spurious ACPI interrupt occurs 251 */ 252 rtc_control &= ~RTC_AIE; 253 CMOS_WRITE(rtc_control, RTC_CONTROL); 254 CMOS_READ(RTC_INTR_FLAGS); 255 256 /* write the fields the rtc knows about */ 257 cmos_bcd_write(hr, RTC_HOURS_ALARM, rtc_control); 258 cmos_bcd_write(min, RTC_MINUTES_ALARM, rtc_control); 259 cmos_bcd_write(sec, RTC_SECONDS_ALARM, rtc_control); 260 261 /* 262 * If the system supports an enhanced alarm it will have non-zero 263 * offsets into the CMOS RAM here -- which for some reason are pointing 264 * to the RTC area of memory. 265 */ 266 if (acpi_gbl_FADT.day_alarm) 267 cmos_bcd_write(day, acpi_gbl_FADT.day_alarm, rtc_control); 268 if (acpi_gbl_FADT.month_alarm) 269 cmos_bcd_write(mo, acpi_gbl_FADT.month_alarm, rtc_control); 270 if (acpi_gbl_FADT.century) { 271 if (adjust) 272 yr += cmos_bcd_read(acpi_gbl_FADT.century, rtc_control) * 100; 273 cmos_bcd_write(yr / 100, acpi_gbl_FADT.century, rtc_control); 274 } 275 /* enable the rtc alarm interrupt */ 276 rtc_control |= RTC_AIE; 277 CMOS_WRITE(rtc_control, RTC_CONTROL); 278 CMOS_READ(RTC_INTR_FLAGS); 279 280 spin_unlock_irq(&rtc_lock); 281 282 acpi_clear_event(ACPI_EVENT_RTC); 283 acpi_enable_event(ACPI_EVENT_RTC, 0); 284 285 *ppos += count; 286 287 result = 0; 288 end: 289 return result ? result : count; 290 } 291 #endif /* HAVE_ACPI_LEGACY_ALARM */ 292 293 static int 294 acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) 295 { 296 struct list_head *node, *next; 297 298 seq_printf(seq, "Device\tS-state\t Status Sysfs node\n"); 299 300 mutex_lock(&acpi_device_lock); 301 list_for_each_safe(node, next, &acpi_wakeup_device_list) { 302 struct acpi_device *dev = 303 container_of(node, struct acpi_device, wakeup_list); 304 struct device *ldev; 305 306 if (!dev->wakeup.flags.valid) 307 continue; 308 309 ldev = acpi_get_physical_device(dev->handle); 310 seq_printf(seq, "%s\t S%d\t%c%-8s ", 311 dev->pnp.bus_id, 312 (u32) dev->wakeup.sleep_state, 313 dev->wakeup.flags.run_wake ? '*' : ' ', 314 dev->wakeup.state.enabled ? "enabled" : "disabled"); 315 if (ldev) 316 seq_printf(seq, "%s:%s", 317 ldev->bus ? ldev->bus->name : "no-bus", 318 dev_name(ldev)); 319 seq_printf(seq, "\n"); 320 put_device(ldev); 321 322 } 323 mutex_unlock(&acpi_device_lock); 324 return 0; 325 } 326 327 static void physical_device_enable_wakeup(struct acpi_device *adev) 328 { 329 struct device *dev = acpi_get_physical_device(adev->handle); 330 331 if (dev && device_can_wakeup(dev)) 332 device_set_wakeup_enable(dev, adev->wakeup.state.enabled); 333 } 334 335 static ssize_t 336 acpi_system_write_wakeup_device(struct file *file, 337 const char __user * buffer, 338 size_t count, loff_t * ppos) 339 { 340 struct list_head *node, *next; 341 char strbuf[5]; 342 char str[5] = ""; 343 unsigned int len = count; 344 struct acpi_device *found_dev = NULL; 345 346 if (len > 4) 347 len = 4; 348 if (len < 0) 349 return -EFAULT; 350 351 if (copy_from_user(strbuf, buffer, len)) 352 return -EFAULT; 353 strbuf[len] = '\0'; 354 sscanf(strbuf, "%s", str); 355 356 mutex_lock(&acpi_device_lock); 357 list_for_each_safe(node, next, &acpi_wakeup_device_list) { 358 struct acpi_device *dev = 359 container_of(node, struct acpi_device, wakeup_list); 360 if (!dev->wakeup.flags.valid) 361 continue; 362 363 if (!strncmp(dev->pnp.bus_id, str, 4)) { 364 dev->wakeup.state.enabled = 365 dev->wakeup.state.enabled ? 0 : 1; 366 found_dev = dev; 367 break; 368 } 369 } 370 if (found_dev) { 371 physical_device_enable_wakeup(found_dev); 372 list_for_each_safe(node, next, &acpi_wakeup_device_list) { 373 struct acpi_device *dev = container_of(node, 374 struct 375 acpi_device, 376 wakeup_list); 377 378 if ((dev != found_dev) && 379 (dev->wakeup.gpe_number == 380 found_dev->wakeup.gpe_number) 381 && (dev->wakeup.gpe_device == 382 found_dev->wakeup.gpe_device)) { 383 printk(KERN_WARNING 384 "ACPI: '%s' and '%s' have the same GPE, " 385 "can't disable/enable one separately\n", 386 dev->pnp.bus_id, found_dev->pnp.bus_id); 387 dev->wakeup.state.enabled = 388 found_dev->wakeup.state.enabled; 389 physical_device_enable_wakeup(dev); 390 } 391 } 392 } 393 mutex_unlock(&acpi_device_lock); 394 return count; 395 } 396 397 static int 398 acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file) 399 { 400 return single_open(file, acpi_system_wakeup_device_seq_show, 401 PDE(inode)->data); 402 } 403 404 static const struct file_operations acpi_system_wakeup_device_fops = { 405 .owner = THIS_MODULE, 406 .open = acpi_system_wakeup_device_open_fs, 407 .read = seq_read, 408 .write = acpi_system_write_wakeup_device, 409 .llseek = seq_lseek, 410 .release = single_release, 411 }; 412 413 #ifdef HAVE_ACPI_LEGACY_ALARM 414 static const struct file_operations acpi_system_alarm_fops = { 415 .owner = THIS_MODULE, 416 .open = acpi_system_alarm_open_fs, 417 .read = seq_read, 418 .write = acpi_system_write_alarm, 419 .llseek = seq_lseek, 420 .release = single_release, 421 }; 422 423 static u32 rtc_handler(void *context) 424 { 425 acpi_clear_event(ACPI_EVENT_RTC); 426 acpi_disable_event(ACPI_EVENT_RTC, 0); 427 428 return ACPI_INTERRUPT_HANDLED; 429 } 430 #endif /* HAVE_ACPI_LEGACY_ALARM */ 431 432 int __init acpi_sleep_proc_init(void) 433 { 434 #ifdef HAVE_ACPI_LEGACY_ALARM 435 /* 'alarm' [R/W] */ 436 proc_create("alarm", S_IFREG | S_IRUGO | S_IWUSR, 437 acpi_root_dir, &acpi_system_alarm_fops); 438 439 acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); 440 /* 441 * Disable the RTC event after installing RTC handler. 442 * Only when RTC alarm is set will it be enabled. 443 */ 444 acpi_clear_event(ACPI_EVENT_RTC); 445 acpi_disable_event(ACPI_EVENT_RTC, 0); 446 #endif /* HAVE_ACPI_LEGACY_ALARM */ 447 448 /* 'wakeup device' [R/W] */ 449 proc_create("wakeup", S_IFREG | S_IRUGO | S_IWUSR, 450 acpi_root_dir, &acpi_system_wakeup_device_fops); 451 452 return 0; 453 } 454