| From cebbert@redhat.com Tue Nov 4 14:31:31 2008 |
| From: Bjorn Helgaas <bjorn.helgaas@hp.com> |
| Date: Sun, 26 Oct 2008 18:57:33 -0400 |
| Subject: x86: register a platform RTC device if PNP doesn't describe it |
| To: stable@kernel.org |
| Cc: David Brownell <dbrownell@users.sourceforge.net>, Bjorn Helgaas <bjorn.helgaas@hp.com> |
| Message-ID: <20081026185733.6ad3746f@redhat.com> |
| |
| From: Bjorn Helgaas <bjorn.helgaas@hp.com> |
| |
| commit 758a7f7bb86b520aadc484f23da85e547b3bf3d8 upstream |
| |
| x86: register a platform RTC device if PNP doesn't describe it |
| |
| Most if not all x86 platforms have an RTC device, but sometimes the RTC |
| is not exposed as a PNP0b00/PNP0b01/PNP0b02 device in PNPBIOS or ACPI: |
| |
| http://bugzilla.kernel.org/show_bug.cgi?id=11580 |
| https://bugzilla.redhat.com/show_bug.cgi?id=451188 |
| |
| It's best if we can discover the RTC via PNP because then we know |
| which flavor of device it is, where it lives, and which IRQ it uses. |
| |
| But if we can't, we should register a platform device using the |
| compiled-in RTC_PORT/RTC_IRQ resource assumptions. |
| |
| Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> |
| Acked-by: Rafael J. Wysocki <rjw@sisk.pl> |
| Acked-by: David Brownell <dbrownell@users.sourceforge.net> |
| Reported-by: Rik Theys <rik.theys@esat.kuleuven.be> |
| Reported-by: shr_msn@yahoo.com.tw |
| Cc: Chuck Ebbert <cebbert@redhat.com> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| arch/x86/kernel/rtc.c | 22 ++++++++++++++++++---- |
| 1 file changed, 18 insertions(+), 4 deletions(-) |
| |
| --- a/arch/x86/kernel/rtc.c |
| +++ b/arch/x86/kernel/rtc.c |
| @@ -223,11 +223,25 @@ static struct platform_device rtc_device |
| static __init int add_rtc_cmos(void) |
| { |
| #ifdef CONFIG_PNP |
| - if (!pnp_platform_devices) |
| - platform_device_register(&rtc_device); |
| -#else |
| + static const char *ids[] __initconst = |
| + { "PNP0b00", "PNP0b01", "PNP0b02", }; |
| + struct pnp_dev *dev; |
| + struct pnp_id *id; |
| + int i; |
| + |
| + pnp_for_each_dev(dev) { |
| + for (id = dev->id; id; id = id->next) { |
| + for (i = 0; i < ARRAY_SIZE(ids); i++) { |
| + if (compare_pnp_id(id, ids[i]) != 0) |
| + return 0; |
| + } |
| + } |
| + } |
| +#endif |
| + |
| platform_device_register(&rtc_device); |
| -#endif /* CONFIG_PNP */ |
| + dev_info(&rtc_device.dev, |
| + "registered platform RTC device (no PNP device found)\n"); |
| return 0; |
| } |
| device_initcall(add_rtc_cmos); |