at v2.6.13 518 lines 12 kB view raw
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#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP 17#define ACPI_SYSTEM_FILE_SLEEP "sleep" 18#endif 19 20#define ACPI_SYSTEM_FILE_ALARM "alarm" 21#define ACPI_SYSTEM_FILE_WAKEUP_DEVICE "wakeup" 22 23#define _COMPONENT ACPI_SYSTEM_COMPONENT 24ACPI_MODULE_NAME ("sleep") 25 26#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP 27 28static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset) 29{ 30 int i; 31 32 ACPI_FUNCTION_TRACE("acpi_system_sleep_seq_show"); 33 34 for (i = 0; i <= ACPI_STATE_S5; i++) { 35 if (sleep_states[i]) { 36 seq_printf(seq,"S%d ", i); 37 if (i == ACPI_STATE_S4 && acpi_gbl_FACS->S4bios_f) 38 seq_printf(seq, "S4bios "); 39 } 40 } 41 42 seq_puts(seq, "\n"); 43 44 return 0; 45} 46 47static int acpi_system_sleep_open_fs(struct inode *inode, struct file *file) 48{ 49 return single_open(file, acpi_system_sleep_seq_show, PDE(inode)->data); 50} 51 52static ssize_t 53acpi_system_write_sleep ( 54 struct file *file, 55 const char __user *buffer, 56 size_t count, 57 loff_t *ppos) 58{ 59 char str[12]; 60 u32 state = 0; 61 int error = 0; 62 63 if (count > sizeof(str) - 1) 64 goto Done; 65 memset(str,0,sizeof(str)); 66 if (copy_from_user(str, buffer, count)) 67 return -EFAULT; 68 69 /* Check for S4 bios request */ 70 if (!strcmp(str,"4b")) { 71 error = acpi_suspend(4); 72 goto Done; 73 } 74 state = simple_strtoul(str, NULL, 0); 75#ifdef CONFIG_SOFTWARE_SUSPEND 76 if (state == 4) { 77 error = software_suspend(); 78 goto Done; 79 } 80#endif 81 error = acpi_suspend(state); 82 Done: 83 return error ? error : count; 84} 85#endif /* CONFIG_ACPI_SLEEP_PROC_SLEEP */ 86 87static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset) 88{ 89 u32 sec, min, hr; 90 u32 day, mo, yr; 91 unsigned char rtc_control = 0; 92 unsigned long flags; 93 94 ACPI_FUNCTION_TRACE("acpi_system_alarm_seq_show"); 95 96 spin_lock_irqsave(&rtc_lock, flags); 97 98 sec = CMOS_READ(RTC_SECONDS_ALARM); 99 min = CMOS_READ(RTC_MINUTES_ALARM); 100 hr = CMOS_READ(RTC_HOURS_ALARM); 101 rtc_control = CMOS_READ(RTC_CONTROL); 102 103 /* If we ever get an FACP with proper values... */ 104 if (acpi_gbl_FADT->day_alrm) 105 /* ACPI spec: only low 6 its should be cared */ 106 day = CMOS_READ(acpi_gbl_FADT->day_alrm) & 0x3F; 107 else 108 day = CMOS_READ(RTC_DAY_OF_MONTH); 109 if (acpi_gbl_FADT->mon_alrm) 110 mo = CMOS_READ(acpi_gbl_FADT->mon_alrm); 111 else 112 mo = CMOS_READ(RTC_MONTH); 113 if (acpi_gbl_FADT->century) 114 yr = CMOS_READ(acpi_gbl_FADT->century) * 100 + CMOS_READ(RTC_YEAR); 115 else 116 yr = CMOS_READ(RTC_YEAR); 117 118 spin_unlock_irqrestore(&rtc_lock, flags); 119 120 if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { 121 BCD_TO_BIN(sec); 122 BCD_TO_BIN(min); 123 BCD_TO_BIN(hr); 124 BCD_TO_BIN(day); 125 BCD_TO_BIN(mo); 126 BCD_TO_BIN(yr); 127 } 128 129 /* we're trusting the FADT (see above)*/ 130 if (!acpi_gbl_FADT->century) 131 /* If we're not trusting the FADT, we should at least make it 132 * right for _this_ century... ehm, what is _this_ century? 133 * 134 * TBD: 135 * ASAP: find piece of code in the kernel, e.g. star tracker driver, 136 * which we can trust to determine the century correctly. Atom 137 * watch driver would be nice, too... 138 * 139 * if that has not happened, change for first release in 2050: 140 * if (yr<50) 141 * yr += 2100; 142 * else 143 * yr += 2000; // current line of code 144 * 145 * if that has not happened either, please do on 2099/12/31:23:59:59 146 * s/2000/2100 147 * 148 */ 149 yr += 2000; 150 151 seq_printf(seq,"%4.4u-", yr); 152 (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo); 153 (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day); 154 (hr > 23) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", hr); 155 (min > 59) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", min); 156 (sec > 59) ? seq_puts(seq, "**\n") : seq_printf(seq, "%2.2u\n", sec); 157 158 return 0; 159} 160 161static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file) 162{ 163 return single_open(file, acpi_system_alarm_seq_show, PDE(inode)->data); 164} 165 166 167static int 168get_date_field ( 169 char **p, 170 u32 *value) 171{ 172 char *next = NULL; 173 char *string_end = NULL; 174 int result = -EINVAL; 175 176 /* 177 * Try to find delimeter, only to insert null. The end of the 178 * string won't have one, but is still valid. 179 */ 180 next = strpbrk(*p, "- :"); 181 if (next) 182 *next++ = '\0'; 183 184 *value = simple_strtoul(*p, &string_end, 10); 185 186 /* Signal success if we got a good digit */ 187 if (string_end != *p) 188 result = 0; 189 190 if (next) 191 *p = next; 192 193 return result; 194} 195 196 197static ssize_t 198acpi_system_write_alarm ( 199 struct file *file, 200 const char __user *buffer, 201 size_t count, 202 loff_t *ppos) 203{ 204 int result = 0; 205 char alarm_string[30] = {'\0'}; 206 char *p = alarm_string; 207 u32 sec, min, hr, day, mo, yr; 208 int adjust = 0; 209 unsigned char rtc_control = 0; 210 211 ACPI_FUNCTION_TRACE("acpi_system_write_alarm"); 212 213 if (count > sizeof(alarm_string) - 1) 214 return_VALUE(-EINVAL); 215 216 if (copy_from_user(alarm_string, buffer, count)) 217 return_VALUE(-EFAULT); 218 219 alarm_string[count] = '\0'; 220 221 /* check for time adjustment */ 222 if (alarm_string[0] == '+') { 223 p++; 224 adjust = 1; 225 } 226 227 if ((result = get_date_field(&p, &yr))) 228 goto end; 229 if ((result = get_date_field(&p, &mo))) 230 goto end; 231 if ((result = get_date_field(&p, &day))) 232 goto end; 233 if ((result = get_date_field(&p, &hr))) 234 goto end; 235 if ((result = get_date_field(&p, &min))) 236 goto end; 237 if ((result = get_date_field(&p, &sec))) 238 goto end; 239 240 if (sec > 59) { 241 min += 1; 242 sec -= 60; 243 } 244 if (min > 59) { 245 hr += 1; 246 min -= 60; 247 } 248 if (hr > 23) { 249 day += 1; 250 hr -= 24; 251 } 252 if (day > 31) { 253 mo += 1; 254 day -= 31; 255 } 256 if (mo > 12) { 257 yr += 1; 258 mo -= 12; 259 } 260 261 spin_lock_irq(&rtc_lock); 262 263 rtc_control = CMOS_READ(RTC_CONTROL); 264 if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { 265 BIN_TO_BCD(yr); 266 BIN_TO_BCD(mo); 267 BIN_TO_BCD(day); 268 BIN_TO_BCD(hr); 269 BIN_TO_BCD(min); 270 BIN_TO_BCD(sec); 271 } 272 273 if (adjust) { 274 yr += CMOS_READ(RTC_YEAR); 275 mo += CMOS_READ(RTC_MONTH); 276 day += CMOS_READ(RTC_DAY_OF_MONTH); 277 hr += CMOS_READ(RTC_HOURS); 278 min += CMOS_READ(RTC_MINUTES); 279 sec += CMOS_READ(RTC_SECONDS); 280 } 281 282 spin_unlock_irq(&rtc_lock); 283 284 if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { 285 BCD_TO_BIN(yr); 286 BCD_TO_BIN(mo); 287 BCD_TO_BIN(day); 288 BCD_TO_BIN(hr); 289 BCD_TO_BIN(min); 290 BCD_TO_BIN(sec); 291 } 292 293 if (sec > 59) { 294 min++; 295 sec -= 60; 296 } 297 if (min > 59) { 298 hr++; 299 min -= 60; 300 } 301 if (hr > 23) { 302 day++; 303 hr -= 24; 304 } 305 if (day > 31) { 306 mo++; 307 day -= 31; 308 } 309 if (mo > 12) { 310 yr++; 311 mo -= 12; 312 } 313 if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { 314 BIN_TO_BCD(yr); 315 BIN_TO_BCD(mo); 316 BIN_TO_BCD(day); 317 BIN_TO_BCD(hr); 318 BIN_TO_BCD(min); 319 BIN_TO_BCD(sec); 320 } 321 322 spin_lock_irq(&rtc_lock); 323 /* 324 * Disable alarm interrupt before setting alarm timer or else 325 * when ACPI_EVENT_RTC is enabled, a spurious ACPI interrupt occurs 326 */ 327 rtc_control &= ~RTC_AIE; 328 CMOS_WRITE(rtc_control, RTC_CONTROL); 329 CMOS_READ(RTC_INTR_FLAGS); 330 331 /* write the fields the rtc knows about */ 332 CMOS_WRITE(hr, RTC_HOURS_ALARM); 333 CMOS_WRITE(min, RTC_MINUTES_ALARM); 334 CMOS_WRITE(sec, RTC_SECONDS_ALARM); 335 336 /* 337 * If the system supports an enhanced alarm it will have non-zero 338 * offsets into the CMOS RAM here -- which for some reason are pointing 339 * to the RTC area of memory. 340 */ 341 if (acpi_gbl_FADT->day_alrm) 342 CMOS_WRITE(day, acpi_gbl_FADT->day_alrm); 343 if (acpi_gbl_FADT->mon_alrm) 344 CMOS_WRITE(mo, acpi_gbl_FADT->mon_alrm); 345 if (acpi_gbl_FADT->century) 346 CMOS_WRITE(yr/100, acpi_gbl_FADT->century); 347 /* enable the rtc alarm interrupt */ 348 rtc_control |= RTC_AIE; 349 CMOS_WRITE(rtc_control, RTC_CONTROL); 350 CMOS_READ(RTC_INTR_FLAGS); 351 352 spin_unlock_irq(&rtc_lock); 353 354 acpi_clear_event(ACPI_EVENT_RTC); 355 acpi_enable_event(ACPI_EVENT_RTC, 0); 356 357 *ppos += count; 358 359 result = 0; 360end: 361 return_VALUE(result ? result : count); 362} 363 364extern struct list_head acpi_wakeup_device_list; 365extern spinlock_t acpi_device_lock; 366 367static int 368acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) 369{ 370 struct list_head * node, * next; 371 372 seq_printf(seq, "Device Sleep state Status\n"); 373 374 spin_lock(&acpi_device_lock); 375 list_for_each_safe(node, next, &acpi_wakeup_device_list) { 376 struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list); 377 378 if (!dev->wakeup.flags.valid) 379 continue; 380 spin_unlock(&acpi_device_lock); 381 if (dev->wakeup.flags.run_wake) 382 seq_printf(seq, "%4s %4d %8s\n", 383 dev->pnp.bus_id, (u32) dev->wakeup.sleep_state, 384 dev->wakeup.state.enabled ? "*enabled" : "*disabled"); 385 else 386 seq_printf(seq, "%4s %4d %8s\n", 387 dev->pnp.bus_id, (u32) dev->wakeup.sleep_state, 388 dev->wakeup.state.enabled ? "enabled" : "disabled"); 389 spin_lock(&acpi_device_lock); 390 } 391 spin_unlock(&acpi_device_lock); 392 return 0; 393} 394 395static ssize_t 396acpi_system_write_wakeup_device ( 397 struct file *file, 398 const char __user *buffer, 399 size_t count, 400 loff_t *ppos) 401{ 402 struct list_head * node, * next; 403 char strbuf[5]; 404 char str[5] = ""; 405 int len = count; 406 struct acpi_device *found_dev = NULL; 407 408 if (len > 4) len = 4; 409 410 if (copy_from_user(strbuf, buffer, len)) 411 return -EFAULT; 412 strbuf[len] = '\0'; 413 sscanf(strbuf, "%s", str); 414 415 spin_lock(&acpi_device_lock); 416 list_for_each_safe(node, next, &acpi_wakeup_device_list) { 417 struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list); 418 if (!dev->wakeup.flags.valid) 419 continue; 420 421 if (!strncmp(dev->pnp.bus_id, str, 4)) { 422 dev->wakeup.state.enabled = dev->wakeup.state.enabled ? 0:1; 423 found_dev = dev; 424 break; 425 } 426 } 427 if (found_dev) { 428 list_for_each_safe(node, next, &acpi_wakeup_device_list) { 429 struct acpi_device * dev = container_of(node, 430 struct acpi_device, wakeup_list); 431 432 if ((dev != found_dev) && 433 (dev->wakeup.gpe_number == found_dev->wakeup.gpe_number) && 434 (dev->wakeup.gpe_device == found_dev->wakeup.gpe_device)) { 435 printk(KERN_WARNING "ACPI: '%s' and '%s' have the same GPE, " 436 "can't disable/enable one seperately\n", 437 dev->pnp.bus_id, found_dev->pnp.bus_id); 438 dev->wakeup.state.enabled = found_dev->wakeup.state.enabled; 439 } 440 } 441 } 442 spin_unlock(&acpi_device_lock); 443 return count; 444} 445 446static int 447acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file) 448{ 449 return single_open(file, acpi_system_wakeup_device_seq_show, PDE(inode)->data); 450} 451 452static struct file_operations acpi_system_wakeup_device_fops = { 453 .open = acpi_system_wakeup_device_open_fs, 454 .read = seq_read, 455 .write = acpi_system_write_wakeup_device, 456 .llseek = seq_lseek, 457 .release = single_release, 458}; 459 460#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP 461static struct file_operations acpi_system_sleep_fops = { 462 .open = acpi_system_sleep_open_fs, 463 .read = seq_read, 464 .write = acpi_system_write_sleep, 465 .llseek = seq_lseek, 466 .release = single_release, 467}; 468#endif /* CONFIG_ACPI_SLEEP_PROC_SLEEP */ 469 470static struct file_operations acpi_system_alarm_fops = { 471 .open = acpi_system_alarm_open_fs, 472 .read = seq_read, 473 .write = acpi_system_write_alarm, 474 .llseek = seq_lseek, 475 .release = single_release, 476}; 477 478 479static u32 rtc_handler(void * context) 480{ 481 acpi_clear_event(ACPI_EVENT_RTC); 482 acpi_disable_event(ACPI_EVENT_RTC, 0); 483 484 return ACPI_INTERRUPT_HANDLED; 485} 486 487static int acpi_sleep_proc_init(void) 488{ 489 struct proc_dir_entry *entry = NULL; 490 491 if (acpi_disabled) 492 return 0; 493 494#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP 495 /* 'sleep' [R/W]*/ 496 entry = create_proc_entry(ACPI_SYSTEM_FILE_SLEEP, 497 S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir); 498 if (entry) 499 entry->proc_fops = &acpi_system_sleep_fops; 500#endif 501 502 /* 'alarm' [R/W] */ 503 entry = create_proc_entry(ACPI_SYSTEM_FILE_ALARM, 504 S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir); 505 if (entry) 506 entry->proc_fops = &acpi_system_alarm_fops; 507 508 /* 'wakeup device' [R/W]*/ 509 entry = create_proc_entry(ACPI_SYSTEM_FILE_WAKEUP_DEVICE, 510 S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir); 511 if (entry) 512 entry->proc_fops = &acpi_system_wakeup_device_fops; 513 514 acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); 515 return 0; 516} 517 518late_initcall(acpi_sleep_proc_init);