Skip to content

Commit d070602

Browse files
committed
Merge branch 'acpi-cmos-rtc'
Merge updates related to the CMOS RTC driver and x86/ACPI CMOS RTC support for 7.1-rc1: - Add ACPI support to the platform device interface in the CMOS RTC driver, make the ACPI core device enumeration code create a platform device for the CMOS RTC, and drop CMOS RTC PNP device support (Rafael Wysocki) - Consolidate the x86-specific CMOS RTC handling with the ACPI TAD driver and clean up the CMOS RTC ACPI address space handler (Rafael Wysocki) - Enable ACPI alarm in the CMOS RTC driver if advertised in ACPI FADT and allow that driver to work without a dedicated IRQ if the ACPI alarm is used (Rafael Wysocki) * acpi-cmos-rtc: rtc: cmos: Do not require IRQ if ACPI alarm is used rtc: cmos: Enable ACPI alarm if advertised in ACPI FADT ACPI: TAD/x86: cmos_rtc: Consolidate address space handler setup rtc: cmos: Drop PNP device support x86: rtc: Drop PNP device check ACPI: PNP: Drop CMOS RTC PNP device support ACPI: x86/rtc-cmos: Use platform device for driver binding ACPI: x86: cmos_rtc: Create a CMOS RTC platform device ACPI: x86: cmos_rtc: Improve coordination with ACPI TAD driver ACPI: x86: cmos_rtc: Clean up address space handler driver
2 parents bfb0315 + b48ee1f commit d070602

7 files changed

Lines changed: 99 additions & 219 deletions

File tree

arch/x86/kernel/rtc.c

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
/*
33
* RTC related functions
44
*/
5+
#include <linux/acpi.h>
56
#include <linux/platform_device.h>
67
#include <linux/mc146818rtc.h>
78
#include <linux/export.h>
8-
#include <linux/pnp.h>
99

1010
#include <asm/vsyscall.h>
1111
#include <asm/x86_init.h>
@@ -133,25 +133,14 @@ static struct platform_device rtc_device = {
133133

134134
static __init int add_rtc_cmos(void)
135135
{
136-
#ifdef CONFIG_PNP
137-
static const char * const ids[] __initconst =
138-
{ "PNP0b00", "PNP0b01", "PNP0b02", };
139-
struct pnp_dev *dev;
140-
int i;
141-
142-
pnp_for_each_dev(dev) {
143-
for (i = 0; i < ARRAY_SIZE(ids); i++) {
144-
if (compare_pnp_id(dev->id, ids[i]) != 0)
145-
return 0;
146-
}
147-
}
148-
#endif
136+
if (cmos_rtc_platform_device_present)
137+
return 0;
138+
149139
if (!x86_platform.legacy.rtc)
150140
return -ENODEV;
151141

152142
platform_device_register(&rtc_device);
153-
dev_info(&rtc_device.dev,
154-
"registered platform RTC device (no PNP device found)\n");
143+
dev_info(&rtc_device.dev, "registered fallback platform RTC device\n");
155144

156145
return 0;
157146
}

drivers/acpi/acpi_pnp.c

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,6 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = {
125125
{"PNP0401"}, /* ECP Printer Port */
126126
/* apple-gmux */
127127
{"APP000B"},
128-
/* rtc_cmos */
129-
{"PNP0b00"},
130-
{"PNP0b01"},
131-
{"PNP0b02"},
132128
/* c6xdigio */
133129
{"PNP0400"}, /* Standard LPT Printer Port */
134130
{"PNP0401"}, /* ECP Printer Port */
@@ -355,25 +351,9 @@ static struct acpi_scan_handler acpi_pnp_handler = {
355351
.attach = acpi_pnp_attach,
356352
};
357353

358-
/*
359-
* For CMOS RTC devices, the PNP ACPI scan handler does not work, because
360-
* there is a CMOS RTC ACPI scan handler installed already, so we need to
361-
* check those devices and enumerate them to the PNP bus directly.
362-
*/
363-
static int is_cmos_rtc_device(struct acpi_device *adev)
364-
{
365-
static const struct acpi_device_id ids[] = {
366-
{ "PNP0B00" },
367-
{ "PNP0B01" },
368-
{ "PNP0B02" },
369-
{""},
370-
};
371-
return !acpi_match_device_ids(adev, ids);
372-
}
373-
374354
bool acpi_is_pnp_device(struct acpi_device *adev)
375355
{
376-
return adev->handler == &acpi_pnp_handler || is_cmos_rtc_device(adev);
356+
return adev->handler == &acpi_pnp_handler;
377357
}
378358
EXPORT_SYMBOL_GPL(acpi_is_pnp_device);
379359

drivers/acpi/acpi_tad.c

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,6 @@ static int acpi_tad_disable_timer(struct device *dev, u32 timer_id)
563563
static void acpi_tad_remove(struct platform_device *pdev)
564564
{
565565
struct device *dev = &pdev->dev;
566-
acpi_handle handle = ACPI_HANDLE(dev);
567566
struct acpi_tad_driver_data *dd = dev_get_drvdata(dev);
568567

569568
device_init_wakeup(dev, false);
@@ -587,7 +586,6 @@ static void acpi_tad_remove(struct platform_device *pdev)
587586

588587
pm_runtime_suspend(dev);
589588
pm_runtime_disable(dev);
590-
acpi_remove_cmos_rtc_space_handler(handle);
591589
}
592590

593591
static int acpi_tad_probe(struct platform_device *pdev)
@@ -599,39 +597,29 @@ static int acpi_tad_probe(struct platform_device *pdev)
599597
unsigned long long caps;
600598
int ret;
601599

602-
ret = acpi_install_cmos_rtc_space_handler(handle);
603-
if (ret < 0) {
604-
dev_info(dev, "Unable to install space handler\n");
605-
return -ENODEV;
606-
}
607600
/*
608601
* Initialization failure messages are mostly about firmware issues, so
609602
* print them at the "info" level.
610603
*/
611604
status = acpi_evaluate_integer(handle, "_GCP", NULL, &caps);
612605
if (ACPI_FAILURE(status)) {
613606
dev_info(dev, "Unable to get capabilities\n");
614-
ret = -ENODEV;
615-
goto remove_handler;
607+
return -ENODEV;
616608
}
617609

618610
if (!(caps & ACPI_TAD_AC_WAKE)) {
619611
dev_info(dev, "Unsupported capabilities\n");
620-
ret = -ENODEV;
621-
goto remove_handler;
612+
return -ENODEV;
622613
}
623614

624615
if (!acpi_has_method(handle, "_PRW")) {
625616
dev_info(dev, "Missing _PRW\n");
626-
ret = -ENODEV;
627-
goto remove_handler;
617+
return -ENODEV;
628618
}
629619

630620
dd = devm_kzalloc(dev, sizeof(*dd), GFP_KERNEL);
631-
if (!dd) {
632-
ret = -ENOMEM;
633-
goto remove_handler;
634-
}
621+
if (!dd)
622+
return -ENOMEM;
635623

636624
dd->capabilities = caps;
637625
dev_set_drvdata(dev, dd);
@@ -673,11 +661,6 @@ static int acpi_tad_probe(struct platform_device *pdev)
673661

674662
fail:
675663
acpi_tad_remove(pdev);
676-
/* Don't fallthrough because cmos rtc space handler is removed in acpi_tad_remove() */
677-
return ret;
678-
679-
remove_handler:
680-
acpi_remove_cmos_rtc_space_handler(handle);
681664
return ret;
682665
}
683666

drivers/acpi/x86/cmos_rtc.c

Lines changed: 47 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,78 +18,86 @@
1818
#include "../internal.h"
1919

2020
static const struct acpi_device_id acpi_cmos_rtc_ids[] = {
21-
{ "PNP0B00" },
22-
{ "PNP0B01" },
23-
{ "PNP0B02" },
24-
{}
21+
{ "ACPI000E", 1 }, /* ACPI Time and Alarm Device (TAD) */
22+
ACPI_CMOS_RTC_IDS
2523
};
2624

27-
static acpi_status
28-
acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address,
29-
u32 bits, u64 *value64,
30-
void *handler_context, void *region_context)
25+
bool cmos_rtc_platform_device_present;
26+
27+
static acpi_status acpi_cmos_rtc_space_handler(u32 function,
28+
acpi_physical_address address,
29+
u32 bits, u64 *value64,
30+
void *handler_context,
31+
void *region_context)
3132
{
32-
int i;
33+
unsigned int i, bytes = DIV_ROUND_UP(bits, 8);
3334
u8 *value = (u8 *)value64;
3435

3536
if (address > 0xff || !value64)
3637
return AE_BAD_PARAMETER;
3738

38-
if (function != ACPI_WRITE && function != ACPI_READ)
39-
return AE_BAD_PARAMETER;
39+
guard(spinlock_irq)(&rtc_lock);
40+
41+
if (function == ACPI_WRITE) {
42+
for (i = 0; i < bytes; i++, address++, value++)
43+
CMOS_WRITE(*value, address);
4044

41-
spin_lock_irq(&rtc_lock);
45+
return AE_OK;
46+
}
4247

43-
for (i = 0; i < DIV_ROUND_UP(bits, 8); ++i, ++address, ++value)
44-
if (function == ACPI_READ)
48+
if (function == ACPI_READ) {
49+
for (i = 0; i < bytes; i++, address++, value++)
4550
*value = CMOS_READ(address);
46-
else
47-
CMOS_WRITE(*value, address);
4851

49-
spin_unlock_irq(&rtc_lock);
52+
return AE_OK;
53+
}
5054

51-
return AE_OK;
55+
return AE_BAD_PARAMETER;
5256
}
5357

54-
int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
58+
static int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
5559
{
60+
static bool cmos_rtc_space_handler_present __read_mostly;
5661
acpi_status status;
5762

63+
if (cmos_rtc_space_handler_present)
64+
return 0;
65+
5866
status = acpi_install_address_space_handler(handle,
59-
ACPI_ADR_SPACE_CMOS,
60-
&acpi_cmos_rtc_space_handler,
61-
NULL, NULL);
67+
ACPI_ADR_SPACE_CMOS,
68+
acpi_cmos_rtc_space_handler,
69+
NULL, NULL);
6270
if (ACPI_FAILURE(status)) {
63-
pr_err("Error installing CMOS-RTC region handler\n");
71+
pr_err("Failed to install CMOS-RTC address space handler\n");
6472
return -ENODEV;
6573
}
6674

75+
cmos_rtc_space_handler_present = true;
76+
6777
return 1;
6878
}
69-
EXPORT_SYMBOL_GPL(acpi_install_cmos_rtc_space_handler);
7079

71-
void acpi_remove_cmos_rtc_space_handler(acpi_handle handle)
80+
static int acpi_cmos_rtc_attach(struct acpi_device *adev,
81+
const struct acpi_device_id *id)
7282
{
73-
if (ACPI_FAILURE(acpi_remove_address_space_handler(handle,
74-
ACPI_ADR_SPACE_CMOS, &acpi_cmos_rtc_space_handler)))
75-
pr_err("Error removing CMOS-RTC region handler\n");
76-
}
77-
EXPORT_SYMBOL_GPL(acpi_remove_cmos_rtc_space_handler);
83+
int ret;
7884

79-
static int acpi_cmos_rtc_attach_handler(struct acpi_device *adev, const struct acpi_device_id *id)
80-
{
81-
return acpi_install_cmos_rtc_space_handler(adev->handle);
82-
}
85+
ret = acpi_install_cmos_rtc_space_handler(adev->handle);
86+
if (ret < 0)
87+
return ret;
8388

84-
static void acpi_cmos_rtc_detach_handler(struct acpi_device *adev)
85-
{
86-
acpi_remove_cmos_rtc_space_handler(adev->handle);
89+
if (IS_ERR_OR_NULL(acpi_create_platform_device(adev, NULL))) {
90+
pr_err("Failed to create a platform device for %s\n", (char *)id->id);
91+
return 0;
92+
} else if (!id->driver_data) {
93+
cmos_rtc_platform_device_present = true;
94+
}
95+
return 1;
8796
}
8897

8998
static struct acpi_scan_handler cmos_rtc_handler = {
9099
.ids = acpi_cmos_rtc_ids,
91-
.attach = acpi_cmos_rtc_attach_handler,
92-
.detach = acpi_cmos_rtc_detach_handler,
100+
.attach = acpi_cmos_rtc_attach,
93101
};
94102

95103
void __init acpi_cmos_rtc_init(void)

0 commit comments

Comments
 (0)