#if ACPI_GLUE_DEBUG
#define DBG(x...) printk(PREFIX x)
#else
-#define DBG(x...)
+#define DBG(x...) do { } while(0)
#endif
static LIST_HEAD(bus_type_list);
static DECLARE_RWSEM(bus_type_sem);
return -ENODEV;
}
-EXPORT_SYMBOL(register_acpi_bus_type);
-
int unregister_acpi_bus_type(struct acpi_bus_type *type)
{
if (acpi_disabled)
return -ENODEV;
}
-EXPORT_SYMBOL(unregister_acpi_bus_type);
-
static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
{
struct acpi_bus_type *tmp, *ret = NULL;
static int acpi_bind_one(struct device *dev, acpi_handle handle)
{
+ struct acpi_device *acpi_dev;
acpi_status status;
if (dev->archdata.acpi_handle) {
}
dev->archdata.acpi_handle = handle;
+ status = acpi_bus_get_device(handle, &acpi_dev);
+ if (!ACPI_FAILURE(status)) {
+ int ret;
+
+ ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
+ "firmware_node");
+ ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
+ "physical_node");
+ if (acpi_dev->wakeup.flags.valid)
+ device_set_wakeup_capable(dev, true);
+ }
+
return 0;
}
if (!dev->archdata.acpi_handle)
return 0;
if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) {
+ struct acpi_device *acpi_dev;
+
/* acpi_get_physical_device increase refcnt by one */
put_device(dev);
+
+ if (!acpi_bus_get_device(dev->archdata.acpi_handle,
+ &acpi_dev)) {
+ sysfs_remove_link(&dev->kobj, "firmware_node");
+ sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node");
+ }
+
acpi_detach_data(dev->archdata.acpi_handle,
acpi_glue_data_handler);
dev->archdata.acpi_handle = NULL;
#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
+#ifdef CONFIG_PM
+static u32 rtc_handler(void *context)
+{
+ acpi_clear_event(ACPI_EVENT_RTC);
+ acpi_disable_event(ACPI_EVENT_RTC, 0);
+ return ACPI_INTERRUPT_HANDLED;
+}
+
+static inline void rtc_wake_setup(void)
+{
+ acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
+}
+
+static void rtc_wake_on(struct device *dev)
+{
+ acpi_clear_event(ACPI_EVENT_RTC);
+ acpi_enable_event(ACPI_EVENT_RTC, 0);
+}
+
+static void rtc_wake_off(struct device *dev)
+{
+ acpi_disable_event(ACPI_EVENT_RTC, 0);
+}
+#else
+#define rtc_wake_setup() do{}while(0)
+#define rtc_wake_on NULL
+#define rtc_wake_off NULL
+#endif
+
/* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find
* its device node and pass extra config data. This helps its driver use
* capabilities that the now-obsolete mc146818 didn't have, and informs it
struct device *dev = get_rtc_dev();
if (dev) {
+ rtc_wake_setup();
+ rtc_info.wake_on = rtc_wake_on;
+ rtc_info.wake_off = rtc_wake_off;
+
+ /* workaround bug in some ACPI tables */
+ if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) {
+ DBG("bogus FADT month_alarm\n");
+ acpi_gbl_FADT.month_alarm = 0;
+ }
+
rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm;
rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm;
rtc_info.rtc_century = acpi_gbl_FADT.century;
- /* NOTE: acpi_gbl_FADT->rtcs4 is NOT currently useful */
+ /* NOTE: S4_RTC_WAKE is NOT currently useful to Linux */
+ if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE)
+ printk(PREFIX "RTC can wake from S4\n");
+
dev->platform_data = &rtc_info;
put_device(dev);
} else
- pr_debug("ACPI: RTC unavailable?\n");
+ DBG("RTC unavailable?\n");
return 0;
}
/* do this between RTC subsys_initcall() and rtc_cmos driver_initcall() */