diff options
-rw-r--r-- | drivers/acpi/glue.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 7b6c9ff9bebe..99500871e3fe 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -241,3 +241,92 @@ static int __init init_acpi_device_notify(void) | |||
241 | } | 241 | } |
242 | 242 | ||
243 | arch_initcall(init_acpi_device_notify); | 243 | arch_initcall(init_acpi_device_notify); |
244 | |||
245 | |||
246 | #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) | ||
247 | |||
248 | /* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find | ||
249 | * its device node and pass extra config data. This helps its driver use | ||
250 | * capabilities that the now-obsolete mc146818 didn't have, and informs it | ||
251 | * that this board's RTC is wakeup-capable (per ACPI spec). | ||
252 | */ | ||
253 | #include <linux/mc146818rtc.h> | ||
254 | |||
255 | static struct cmos_rtc_board_info rtc_info; | ||
256 | |||
257 | |||
258 | #ifdef CONFIG_PNPACPI | ||
259 | |||
260 | /* PNP devices are registered in a subsys_initcall(); | ||
261 | * ACPI specifies the PNP IDs to use. | ||
262 | */ | ||
263 | #include <linux/pnp.h> | ||
264 | |||
265 | static int __init pnp_match(struct device *dev, void *data) | ||
266 | { | ||
267 | static const char *ids[] = { "PNP0b00", "PNP0b01", "PNP0b02", }; | ||
268 | struct pnp_dev *pnp = to_pnp_dev(dev); | ||
269 | int i; | ||
270 | |||
271 | for (i = 0; i < ARRAY_SIZE(ids); i++) { | ||
272 | if (compare_pnp_id(pnp->id, ids[i]) != 0) | ||
273 | return 1; | ||
274 | } | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static struct device *__init get_rtc_dev(void) | ||
279 | { | ||
280 | return bus_find_device(&pnp_bus_type, NULL, NULL, pnp_match); | ||
281 | } | ||
282 | |||
283 | #else | ||
284 | |||
285 | /* We expect non-PNPACPI platforms to register an RTC device, usually | ||
286 | * at or near arch_initcall(). That also helps for example PCs that | ||
287 | * aren't configured with ACPI (where this code wouldn't run, but the | ||
288 | * RTC would still be available). The device name matches the driver; | ||
289 | * that's how the platform bus works. | ||
290 | */ | ||
291 | #include <linux/platform_device.h> | ||
292 | |||
293 | static int __init platform_match(struct device *dev, void *data) | ||
294 | { | ||
295 | struct platform_device *pdev; | ||
296 | |||
297 | pdev = container_of(dev, struct platform_device, dev); | ||
298 | return strcmp(pdev->name, "rtc_cmos") == 0; | ||
299 | } | ||
300 | |||
301 | static struct device *__init get_rtc_dev(void) | ||
302 | { | ||
303 | return bus_find_device(&platform_bus_type, NULL, NULL, platform_match); | ||
304 | } | ||
305 | |||
306 | #endif | ||
307 | |||
308 | static int __init acpi_rtc_init(void) | ||
309 | { | ||
310 | struct device *dev = get_rtc_dev(); | ||
311 | |||
312 | if (dev) { | ||
313 | rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm; | ||
314 | rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm; | ||
315 | rtc_info.rtc_century = acpi_gbl_FADT.century; | ||
316 | |||
317 | /* NOTE: acpi_gbl_FADT->rtcs4 is NOT currently useful */ | ||
318 | |||
319 | dev->platform_data = &rtc_info; | ||
320 | |||
321 | /* RTC always wakes from S1/S2/S3, and often S4/STD */ | ||
322 | device_init_wakeup(dev, 1); | ||
323 | |||
324 | put_device(dev); | ||
325 | } else | ||
326 | pr_debug("ACPI: RTC unavailable?\n"); | ||
327 | return 0; | ||
328 | } | ||
329 | /* do this between RTC subsys_initcall() and rtc_cmos driver_initcall() */ | ||
330 | fs_initcall(acpi_rtc_init); | ||
331 | |||
332 | #endif | ||