14e10d12aSDavid Shaohua Li /* 24e10d12aSDavid Shaohua Li * Link physical devices with ACPI devices support 34e10d12aSDavid Shaohua Li * 44e10d12aSDavid Shaohua Li * Copyright (c) 2005 David Shaohua Li <shaohua.li@intel.com> 54e10d12aSDavid Shaohua Li * Copyright (c) 2005 Intel Corp. 64e10d12aSDavid Shaohua Li * 74e10d12aSDavid Shaohua Li * This file is released under the GPLv2. 84e10d12aSDavid Shaohua Li */ 94e10d12aSDavid Shaohua Li #include <linux/init.h> 104e10d12aSDavid Shaohua Li #include <linux/list.h> 114e10d12aSDavid Shaohua Li #include <linux/device.h> 124e10d12aSDavid Shaohua Li #include <linux/rwsem.h> 134e10d12aSDavid Shaohua Li #include <linux/acpi.h> 144e10d12aSDavid Shaohua Li 154e10d12aSDavid Shaohua Li #define ACPI_GLUE_DEBUG 0 164e10d12aSDavid Shaohua Li #if ACPI_GLUE_DEBUG 174e10d12aSDavid Shaohua Li #define DBG(x...) printk(PREFIX x) 184e10d12aSDavid Shaohua Li #else 194ebf83c8SDave Jones #define DBG(x...) do { } while(0) 204e10d12aSDavid Shaohua Li #endif 214e10d12aSDavid Shaohua Li static LIST_HEAD(bus_type_list); 224e10d12aSDavid Shaohua Li static DECLARE_RWSEM(bus_type_sem); 234e10d12aSDavid Shaohua Li 244e10d12aSDavid Shaohua Li int register_acpi_bus_type(struct acpi_bus_type *type) 254e10d12aSDavid Shaohua Li { 264e10d12aSDavid Shaohua Li if (acpi_disabled) 274e10d12aSDavid Shaohua Li return -ENODEV; 284e10d12aSDavid Shaohua Li if (type && type->bus && type->find_device) { 294e10d12aSDavid Shaohua Li down_write(&bus_type_sem); 304e10d12aSDavid Shaohua Li list_add_tail(&type->list, &bus_type_list); 314e10d12aSDavid Shaohua Li up_write(&bus_type_sem); 324be44fcdSLen Brown printk(KERN_INFO PREFIX "bus type %s registered\n", 334be44fcdSLen Brown type->bus->name); 344e10d12aSDavid Shaohua Li return 0; 354e10d12aSDavid Shaohua Li } 364e10d12aSDavid Shaohua Li return -ENODEV; 374e10d12aSDavid Shaohua Li } 384e10d12aSDavid Shaohua Li 394e10d12aSDavid Shaohua Li int unregister_acpi_bus_type(struct acpi_bus_type *type) 404e10d12aSDavid Shaohua Li { 414e10d12aSDavid Shaohua Li if (acpi_disabled) 424e10d12aSDavid Shaohua Li return 0; 434e10d12aSDavid Shaohua Li if (type) { 444e10d12aSDavid Shaohua Li down_write(&bus_type_sem); 454e10d12aSDavid Shaohua Li list_del_init(&type->list); 464e10d12aSDavid Shaohua Li up_write(&bus_type_sem); 474be44fcdSLen Brown printk(KERN_INFO PREFIX "ACPI bus type %s unregistered\n", 484be44fcdSLen Brown type->bus->name); 494e10d12aSDavid Shaohua Li return 0; 504e10d12aSDavid Shaohua Li } 514e10d12aSDavid Shaohua Li return -ENODEV; 524e10d12aSDavid Shaohua Li } 534e10d12aSDavid Shaohua Li 544e10d12aSDavid Shaohua Li static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type) 554e10d12aSDavid Shaohua Li { 564e10d12aSDavid Shaohua Li struct acpi_bus_type *tmp, *ret = NULL; 574e10d12aSDavid Shaohua Li 584e10d12aSDavid Shaohua Li down_read(&bus_type_sem); 594e10d12aSDavid Shaohua Li list_for_each_entry(tmp, &bus_type_list, list) { 604e10d12aSDavid Shaohua Li if (tmp->bus == type) { 614e10d12aSDavid Shaohua Li ret = tmp; 624e10d12aSDavid Shaohua Li break; 634e10d12aSDavid Shaohua Li } 644e10d12aSDavid Shaohua Li } 654e10d12aSDavid Shaohua Li up_read(&bus_type_sem); 664e10d12aSDavid Shaohua Li return ret; 674e10d12aSDavid Shaohua Li } 684e10d12aSDavid Shaohua Li 694e10d12aSDavid Shaohua Li static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle) 704e10d12aSDavid Shaohua Li { 714e10d12aSDavid Shaohua Li struct acpi_bus_type *tmp; 724e10d12aSDavid Shaohua Li int ret = -ENODEV; 734e10d12aSDavid Shaohua Li 744e10d12aSDavid Shaohua Li down_read(&bus_type_sem); 754e10d12aSDavid Shaohua Li list_for_each_entry(tmp, &bus_type_list, list) { 764e10d12aSDavid Shaohua Li if (tmp->find_bridge && !tmp->find_bridge(dev, handle)) { 774e10d12aSDavid Shaohua Li ret = 0; 784e10d12aSDavid Shaohua Li break; 794e10d12aSDavid Shaohua Li } 804e10d12aSDavid Shaohua Li } 814e10d12aSDavid Shaohua Li up_read(&bus_type_sem); 824e10d12aSDavid Shaohua Li return ret; 834e10d12aSDavid Shaohua Li } 844e10d12aSDavid Shaohua Li 854e10d12aSDavid Shaohua Li /* Get device's handler per its address under its parent */ 864e10d12aSDavid Shaohua Li struct acpi_find_child { 874e10d12aSDavid Shaohua Li acpi_handle handle; 884e10d12aSDavid Shaohua Li acpi_integer address; 894e10d12aSDavid Shaohua Li }; 904e10d12aSDavid Shaohua Li 914e10d12aSDavid Shaohua Li static acpi_status 924e10d12aSDavid Shaohua Li do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv) 934e10d12aSDavid Shaohua Li { 944e10d12aSDavid Shaohua Li acpi_status status; 954e10d12aSDavid Shaohua Li struct acpi_device_info *info; 964e10d12aSDavid Shaohua Li struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 9750dd0969SJan Engelhardt struct acpi_find_child *find = context; 984e10d12aSDavid Shaohua Li 994e10d12aSDavid Shaohua Li status = acpi_get_object_info(handle, &buffer); 1004e10d12aSDavid Shaohua Li if (ACPI_SUCCESS(status)) { 1014e10d12aSDavid Shaohua Li info = buffer.pointer; 1024e10d12aSDavid Shaohua Li if (info->address == find->address) 1034e10d12aSDavid Shaohua Li find->handle = handle; 10402438d87SLen Brown kfree(buffer.pointer); 1054e10d12aSDavid Shaohua Li } 1064e10d12aSDavid Shaohua Li return AE_OK; 1074e10d12aSDavid Shaohua Li } 1084e10d12aSDavid Shaohua Li 1094e10d12aSDavid Shaohua Li acpi_handle acpi_get_child(acpi_handle parent, acpi_integer address) 1104e10d12aSDavid Shaohua Li { 1114e10d12aSDavid Shaohua Li struct acpi_find_child find = { NULL, address }; 1124e10d12aSDavid Shaohua Li 1134e10d12aSDavid Shaohua Li if (!parent) 1144e10d12aSDavid Shaohua Li return NULL; 1154e10d12aSDavid Shaohua Li acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1164e10d12aSDavid Shaohua Li 1, do_acpi_find_child, &find, NULL); 1174e10d12aSDavid Shaohua Li return find.handle; 1184e10d12aSDavid Shaohua Li } 1194e10d12aSDavid Shaohua Li 1204e10d12aSDavid Shaohua Li EXPORT_SYMBOL(acpi_get_child); 1214e10d12aSDavid Shaohua Li 1224e10d12aSDavid Shaohua Li /* Link ACPI devices with physical devices */ 1234e10d12aSDavid Shaohua Li static void acpi_glue_data_handler(acpi_handle handle, 1244e10d12aSDavid Shaohua Li u32 function, void *context) 1254e10d12aSDavid Shaohua Li { 1264e10d12aSDavid Shaohua Li /* we provide an empty handler */ 1274e10d12aSDavid Shaohua Li } 1284e10d12aSDavid Shaohua Li 1294e10d12aSDavid Shaohua Li /* Note: a success call will increase reference count by one */ 1304e10d12aSDavid Shaohua Li struct device *acpi_get_physical_device(acpi_handle handle) 1314e10d12aSDavid Shaohua Li { 1324e10d12aSDavid Shaohua Li acpi_status status; 1334e10d12aSDavid Shaohua Li struct device *dev; 1344e10d12aSDavid Shaohua Li 1354e10d12aSDavid Shaohua Li status = acpi_get_data(handle, acpi_glue_data_handler, (void **)&dev); 1364e10d12aSDavid Shaohua Li if (ACPI_SUCCESS(status)) 1374e10d12aSDavid Shaohua Li return get_device(dev); 1384e10d12aSDavid Shaohua Li return NULL; 1394e10d12aSDavid Shaohua Li } 1404e10d12aSDavid Shaohua Li 1414e10d12aSDavid Shaohua Li EXPORT_SYMBOL(acpi_get_physical_device); 1424e10d12aSDavid Shaohua Li 1434e10d12aSDavid Shaohua Li static int acpi_bind_one(struct device *dev, acpi_handle handle) 1444e10d12aSDavid Shaohua Li { 1451071695fSDavid Brownell struct acpi_device *acpi_dev; 1464e10d12aSDavid Shaohua Li acpi_status status; 1474e10d12aSDavid Shaohua Li 148465ae641SBenjamin Herrenschmidt if (dev->archdata.acpi_handle) { 1494e10d12aSDavid Shaohua Li printk(KERN_WARNING PREFIX 150465ae641SBenjamin Herrenschmidt "Drivers changed 'acpi_handle' for %s\n", dev->bus_id); 1514e10d12aSDavid Shaohua Li return -EINVAL; 1524e10d12aSDavid Shaohua Li } 1534e10d12aSDavid Shaohua Li get_device(dev); 1544e10d12aSDavid Shaohua Li status = acpi_attach_data(handle, acpi_glue_data_handler, dev); 1554e10d12aSDavid Shaohua Li if (ACPI_FAILURE(status)) { 1564e10d12aSDavid Shaohua Li put_device(dev); 1574e10d12aSDavid Shaohua Li return -EINVAL; 1584e10d12aSDavid Shaohua Li } 159465ae641SBenjamin Herrenschmidt dev->archdata.acpi_handle = handle; 1604e10d12aSDavid Shaohua Li 1611071695fSDavid Brownell status = acpi_bus_get_device(handle, &acpi_dev); 1621071695fSDavid Brownell if (!ACPI_FAILURE(status)) { 1631071695fSDavid Brownell int ret; 1641071695fSDavid Brownell 1651071695fSDavid Brownell ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj, 1661071695fSDavid Brownell "firmware_node"); 1671071695fSDavid Brownell ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, 1681071695fSDavid Brownell "physical_node"); 169*eb9d0fe4SRafael J. Wysocki if (acpi_dev->wakeup.flags.valid) 170*eb9d0fe4SRafael J. Wysocki device_set_wakeup_capable(dev, true); 1711071695fSDavid Brownell } 1721071695fSDavid Brownell 1734e10d12aSDavid Shaohua Li return 0; 1744e10d12aSDavid Shaohua Li } 1754e10d12aSDavid Shaohua Li 1764e10d12aSDavid Shaohua Li static int acpi_unbind_one(struct device *dev) 1774e10d12aSDavid Shaohua Li { 178465ae641SBenjamin Herrenschmidt if (!dev->archdata.acpi_handle) 1794e10d12aSDavid Shaohua Li return 0; 180465ae641SBenjamin Herrenschmidt if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) { 1811071695fSDavid Brownell struct acpi_device *acpi_dev; 1821071695fSDavid Brownell 1834e10d12aSDavid Shaohua Li /* acpi_get_physical_device increase refcnt by one */ 1844e10d12aSDavid Shaohua Li put_device(dev); 1851071695fSDavid Brownell 1861071695fSDavid Brownell if (!acpi_bus_get_device(dev->archdata.acpi_handle, 1871071695fSDavid Brownell &acpi_dev)) { 1881071695fSDavid Brownell sysfs_remove_link(&dev->kobj, "firmware_node"); 1891071695fSDavid Brownell sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node"); 1901071695fSDavid Brownell } 1911071695fSDavid Brownell 192465ae641SBenjamin Herrenschmidt acpi_detach_data(dev->archdata.acpi_handle, 193465ae641SBenjamin Herrenschmidt acpi_glue_data_handler); 194465ae641SBenjamin Herrenschmidt dev->archdata.acpi_handle = NULL; 1954e10d12aSDavid Shaohua Li /* acpi_bind_one increase refcnt by one */ 1964e10d12aSDavid Shaohua Li put_device(dev); 1974e10d12aSDavid Shaohua Li } else { 1984e10d12aSDavid Shaohua Li printk(KERN_ERR PREFIX 199465ae641SBenjamin Herrenschmidt "Oops, 'acpi_handle' corrupt for %s\n", dev->bus_id); 2004e10d12aSDavid Shaohua Li } 2014e10d12aSDavid Shaohua Li return 0; 2024e10d12aSDavid Shaohua Li } 2034e10d12aSDavid Shaohua Li 2044e10d12aSDavid Shaohua Li static int acpi_platform_notify(struct device *dev) 2054e10d12aSDavid Shaohua Li { 2064e10d12aSDavid Shaohua Li struct acpi_bus_type *type; 2074e10d12aSDavid Shaohua Li acpi_handle handle; 2084e10d12aSDavid Shaohua Li int ret = -EINVAL; 2094e10d12aSDavid Shaohua Li 2104e10d12aSDavid Shaohua Li if (!dev->bus || !dev->parent) { 2114e10d12aSDavid Shaohua Li /* bridge devices genernally haven't bus or parent */ 2124e10d12aSDavid Shaohua Li ret = acpi_find_bridge_device(dev, &handle); 2134e10d12aSDavid Shaohua Li goto end; 2144e10d12aSDavid Shaohua Li } 2154e10d12aSDavid Shaohua Li type = acpi_get_bus_type(dev->bus); 2164e10d12aSDavid Shaohua Li if (!type) { 217ef7b06cdSDavid Shaohua Li DBG("No ACPI bus support for %s\n", dev->bus_id); 2184e10d12aSDavid Shaohua Li ret = -EINVAL; 2194e10d12aSDavid Shaohua Li goto end; 2204e10d12aSDavid Shaohua Li } 2214e10d12aSDavid Shaohua Li if ((ret = type->find_device(dev, &handle)) != 0) 222ef7b06cdSDavid Shaohua Li DBG("Can't get handler for %s\n", dev->bus_id); 2234e10d12aSDavid Shaohua Li end: 2244e10d12aSDavid Shaohua Li if (!ret) 2254e10d12aSDavid Shaohua Li acpi_bind_one(dev, handle); 2264e10d12aSDavid Shaohua Li 2274e10d12aSDavid Shaohua Li #if ACPI_GLUE_DEBUG 2284e10d12aSDavid Shaohua Li if (!ret) { 2294e10d12aSDavid Shaohua Li struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 2304e10d12aSDavid Shaohua Li 231465ae641SBenjamin Herrenschmidt acpi_get_name(dev->archdata.acpi_handle, 232465ae641SBenjamin Herrenschmidt ACPI_FULL_PATHNAME, &buffer); 2334e10d12aSDavid Shaohua Li DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer); 23402438d87SLen Brown kfree(buffer.pointer); 2354e10d12aSDavid Shaohua Li } else 2364e10d12aSDavid Shaohua Li DBG("Device %s -> No ACPI support\n", dev->bus_id); 2374e10d12aSDavid Shaohua Li #endif 2384e10d12aSDavid Shaohua Li 2394e10d12aSDavid Shaohua Li return ret; 2404e10d12aSDavid Shaohua Li } 2414e10d12aSDavid Shaohua Li 2424e10d12aSDavid Shaohua Li static int acpi_platform_notify_remove(struct device *dev) 2434e10d12aSDavid Shaohua Li { 2444e10d12aSDavid Shaohua Li acpi_unbind_one(dev); 2454e10d12aSDavid Shaohua Li return 0; 2464e10d12aSDavid Shaohua Li } 2474e10d12aSDavid Shaohua Li 2484e10d12aSDavid Shaohua Li static int __init init_acpi_device_notify(void) 2494e10d12aSDavid Shaohua Li { 2504e10d12aSDavid Shaohua Li if (acpi_disabled) 2514e10d12aSDavid Shaohua Li return 0; 2524e10d12aSDavid Shaohua Li if (platform_notify || platform_notify_remove) { 2534e10d12aSDavid Shaohua Li printk(KERN_ERR PREFIX "Can't use platform_notify\n"); 2544e10d12aSDavid Shaohua Li return 0; 2554e10d12aSDavid Shaohua Li } 2564e10d12aSDavid Shaohua Li platform_notify = acpi_platform_notify; 2574e10d12aSDavid Shaohua Li platform_notify_remove = acpi_platform_notify_remove; 2584e10d12aSDavid Shaohua Li return 0; 2594e10d12aSDavid Shaohua Li } 2604e10d12aSDavid Shaohua Li 2614e10d12aSDavid Shaohua Li arch_initcall(init_acpi_device_notify); 262a74388e2SDavid Brownell 263a74388e2SDavid Brownell 264a74388e2SDavid Brownell #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) 265a74388e2SDavid Brownell 266f5f72b46SDavid Brownell #ifdef CONFIG_PM 267f5f72b46SDavid Brownell static u32 rtc_handler(void *context) 268f5f72b46SDavid Brownell { 269f5f72b46SDavid Brownell acpi_clear_event(ACPI_EVENT_RTC); 270f5f72b46SDavid Brownell acpi_disable_event(ACPI_EVENT_RTC, 0); 271f5f72b46SDavid Brownell return ACPI_INTERRUPT_HANDLED; 272f5f72b46SDavid Brownell } 273f5f72b46SDavid Brownell 274f5f72b46SDavid Brownell static inline void rtc_wake_setup(void) 275f5f72b46SDavid Brownell { 276f5f72b46SDavid Brownell acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); 277f5f72b46SDavid Brownell } 278f5f72b46SDavid Brownell 279f5f72b46SDavid Brownell static void rtc_wake_on(struct device *dev) 280f5f72b46SDavid Brownell { 281f5f72b46SDavid Brownell acpi_clear_event(ACPI_EVENT_RTC); 282f5f72b46SDavid Brownell acpi_enable_event(ACPI_EVENT_RTC, 0); 283f5f72b46SDavid Brownell } 284f5f72b46SDavid Brownell 285f5f72b46SDavid Brownell static void rtc_wake_off(struct device *dev) 286f5f72b46SDavid Brownell { 287f5f72b46SDavid Brownell acpi_disable_event(ACPI_EVENT_RTC, 0); 288f5f72b46SDavid Brownell } 289f5f72b46SDavid Brownell #else 290f5f72b46SDavid Brownell #define rtc_wake_setup() do{}while(0) 291f5f72b46SDavid Brownell #define rtc_wake_on NULL 292f5f72b46SDavid Brownell #define rtc_wake_off NULL 293f5f72b46SDavid Brownell #endif 294f5f72b46SDavid Brownell 295a74388e2SDavid Brownell /* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find 296a74388e2SDavid Brownell * its device node and pass extra config data. This helps its driver use 297a74388e2SDavid Brownell * capabilities that the now-obsolete mc146818 didn't have, and informs it 298a74388e2SDavid Brownell * that this board's RTC is wakeup-capable (per ACPI spec). 299a74388e2SDavid Brownell */ 300a74388e2SDavid Brownell #include <linux/mc146818rtc.h> 301a74388e2SDavid Brownell 302a74388e2SDavid Brownell static struct cmos_rtc_board_info rtc_info; 303a74388e2SDavid Brownell 304a74388e2SDavid Brownell 305a74388e2SDavid Brownell /* PNP devices are registered in a subsys_initcall(); 306a74388e2SDavid Brownell * ACPI specifies the PNP IDs to use. 307a74388e2SDavid Brownell */ 308a74388e2SDavid Brownell #include <linux/pnp.h> 309a74388e2SDavid Brownell 310a74388e2SDavid Brownell static int __init pnp_match(struct device *dev, void *data) 311a74388e2SDavid Brownell { 312a74388e2SDavid Brownell static const char *ids[] = { "PNP0b00", "PNP0b01", "PNP0b02", }; 313a74388e2SDavid Brownell struct pnp_dev *pnp = to_pnp_dev(dev); 314a74388e2SDavid Brownell int i; 315a74388e2SDavid Brownell 316a74388e2SDavid Brownell for (i = 0; i < ARRAY_SIZE(ids); i++) { 317a74388e2SDavid Brownell if (compare_pnp_id(pnp->id, ids[i]) != 0) 318a74388e2SDavid Brownell return 1; 319a74388e2SDavid Brownell } 320a74388e2SDavid Brownell return 0; 321a74388e2SDavid Brownell } 322a74388e2SDavid Brownell 323a74388e2SDavid Brownell static struct device *__init get_rtc_dev(void) 324a74388e2SDavid Brownell { 325a74388e2SDavid Brownell return bus_find_device(&pnp_bus_type, NULL, NULL, pnp_match); 326a74388e2SDavid Brownell } 327a74388e2SDavid Brownell 328a74388e2SDavid Brownell static int __init acpi_rtc_init(void) 329a74388e2SDavid Brownell { 330a74388e2SDavid Brownell struct device *dev = get_rtc_dev(); 331a74388e2SDavid Brownell 332a74388e2SDavid Brownell if (dev) { 333f5f72b46SDavid Brownell rtc_wake_setup(); 334f5f72b46SDavid Brownell rtc_info.wake_on = rtc_wake_on; 335f5f72b46SDavid Brownell rtc_info.wake_off = rtc_wake_off; 336f5f72b46SDavid Brownell 33719bfe37cSDavid Brownell /* workaround bug in some ACPI tables */ 33819bfe37cSDavid Brownell if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) { 33919bfe37cSDavid Brownell DBG("bogus FADT month_alarm\n"); 34019bfe37cSDavid Brownell acpi_gbl_FADT.month_alarm = 0; 34119bfe37cSDavid Brownell } 34219bfe37cSDavid Brownell 343a74388e2SDavid Brownell rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm; 344a74388e2SDavid Brownell rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm; 345a74388e2SDavid Brownell rtc_info.rtc_century = acpi_gbl_FADT.century; 346a74388e2SDavid Brownell 347f5f72b46SDavid Brownell /* NOTE: S4_RTC_WAKE is NOT currently useful to Linux */ 348f5f72b46SDavid Brownell if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE) 34919bfe37cSDavid Brownell printk(PREFIX "RTC can wake from S4\n"); 35019bfe37cSDavid Brownell 351a74388e2SDavid Brownell 352a74388e2SDavid Brownell dev->platform_data = &rtc_info; 353a74388e2SDavid Brownell 354a74388e2SDavid Brownell /* RTC always wakes from S1/S2/S3, and often S4/STD */ 355a74388e2SDavid Brownell device_init_wakeup(dev, 1); 356a74388e2SDavid Brownell 357a74388e2SDavid Brownell put_device(dev); 358a74388e2SDavid Brownell } else 35919bfe37cSDavid Brownell DBG("RTC unavailable?\n"); 360a74388e2SDavid Brownell return 0; 361a74388e2SDavid Brownell } 362a74388e2SDavid Brownell /* do this between RTC subsys_initcall() and rtc_cmos driver_initcall() */ 363a74388e2SDavid Brownell fs_initcall(acpi_rtc_init); 364a74388e2SDavid Brownell 365a74388e2SDavid Brownell #endif 366