Commit 596ca52a authored by Zhang Rui's avatar Zhang Rui Committed by Rafael J. Wysocki

ACPI: TAD: Install SystemCMOS address space handler for ACPI000E

Currently, the SystemCMOS address space handler is installed for the
ACPI RTC devices (PNP0B00/PNP0B01/PNP0B02) only. But there are platforms
with SystemCMOS Operetion Region defined under the ACPI Time and Alarm
Device (ACPI000E), which is used by the ACPI pre-defined control methods
like _GRT (Get the Real time) and _SRT (Set the Real time).

When accessing these control methods via the acpi_tad sysfs interface,
missing SystemCMOS address space handler causes errors like below
[  478.255453] ACPI Error: No handler for Region [RTCM] (00000000a8d2dd39) [SystemCMOS] (20230331/evregion-130)
[  478.255458] ACPI Error: Region SystemCMOS (ID=5) has no handler (20230331/exfldio-261)
[  478.255461] Initialized Local Variables for Method [_GRT]:
[  478.255461]   Local1: 00000000f182542c <Obj>           Integer 0000000000000000
[  478.255464] No Arguments are initialized for method [_GRT]
[  478.255465] ACPI Error: Aborting method \_SB.AWAC._GRT due to previous error (AE_NOT_EXIST) (20230331/psparse-529)

Export two APIs for SystemCMOS address space handler from acpi_cmos_rtc
scan handler and install the handler for the ACPI Time and Alarm Device
from the ACPI TAD driver.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=217714Signed-off-by: default avatarZhang Rui <rui.zhang@intel.com>
[ rjw: Subject and changelog edits, whitespace adjustment ]
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 2ccdd1b1
...@@ -51,12 +51,11 @@ acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address, ...@@ -51,12 +51,11 @@ acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address,
return AE_OK; return AE_OK;
} }
static int acpi_install_cmos_rtc_space_handler(struct acpi_device *adev, int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
const struct acpi_device_id *id)
{ {
acpi_status status; acpi_status status;
status = acpi_install_address_space_handler(adev->handle, status = acpi_install_address_space_handler(handle,
ACPI_ADR_SPACE_CMOS, ACPI_ADR_SPACE_CMOS,
&acpi_cmos_rtc_space_handler, &acpi_cmos_rtc_space_handler,
NULL, NULL); NULL, NULL);
...@@ -67,18 +66,30 @@ static int acpi_install_cmos_rtc_space_handler(struct acpi_device *adev, ...@@ -67,18 +66,30 @@ static int acpi_install_cmos_rtc_space_handler(struct acpi_device *adev,
return 1; return 1;
} }
EXPORT_SYMBOL_GPL(acpi_install_cmos_rtc_space_handler);
static void acpi_remove_cmos_rtc_space_handler(struct acpi_device *adev) void acpi_remove_cmos_rtc_space_handler(acpi_handle handle)
{ {
if (ACPI_FAILURE(acpi_remove_address_space_handler(adev->handle, if (ACPI_FAILURE(acpi_remove_address_space_handler(handle,
ACPI_ADR_SPACE_CMOS, &acpi_cmos_rtc_space_handler))) ACPI_ADR_SPACE_CMOS, &acpi_cmos_rtc_space_handler)))
pr_err("Error removing CMOS-RTC region handler\n"); pr_err("Error removing CMOS-RTC region handler\n");
} }
EXPORT_SYMBOL_GPL(acpi_remove_cmos_rtc_space_handler);
static int acpi_cmos_rtc_attach_handler(struct acpi_device *adev, const struct acpi_device_id *id)
{
return acpi_install_cmos_rtc_space_handler(adev->handle);
}
static void acpi_cmos_rtc_detach_handler(struct acpi_device *adev)
{
acpi_remove_cmos_rtc_space_handler(adev->handle);
}
static struct acpi_scan_handler cmos_rtc_handler = { static struct acpi_scan_handler cmos_rtc_handler = {
.ids = acpi_cmos_rtc_ids, .ids = acpi_cmos_rtc_ids,
.attach = acpi_install_cmos_rtc_space_handler, .attach = acpi_cmos_rtc_attach_handler,
.detach = acpi_remove_cmos_rtc_space_handler, .detach = acpi_cmos_rtc_detach_handler,
}; };
void __init acpi_cmos_rtc_init(void) void __init acpi_cmos_rtc_init(void)
......
...@@ -557,6 +557,7 @@ static int acpi_tad_disable_timer(struct device *dev, u32 timer_id) ...@@ -557,6 +557,7 @@ static int acpi_tad_disable_timer(struct device *dev, u32 timer_id)
static int acpi_tad_remove(struct platform_device *pdev) static int acpi_tad_remove(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
acpi_handle handle = ACPI_HANDLE(dev);
struct acpi_tad_driver_data *dd = dev_get_drvdata(dev); struct acpi_tad_driver_data *dd = dev_get_drvdata(dev);
device_init_wakeup(dev, false); device_init_wakeup(dev, false);
...@@ -577,6 +578,7 @@ static int acpi_tad_remove(struct platform_device *pdev) ...@@ -577,6 +578,7 @@ static int acpi_tad_remove(struct platform_device *pdev)
pm_runtime_put_sync(dev); pm_runtime_put_sync(dev);
pm_runtime_disable(dev); pm_runtime_disable(dev);
acpi_remove_cmos_rtc_space_handler(handle);
return 0; return 0;
} }
...@@ -589,6 +591,11 @@ static int acpi_tad_probe(struct platform_device *pdev) ...@@ -589,6 +591,11 @@ static int acpi_tad_probe(struct platform_device *pdev)
unsigned long long caps; unsigned long long caps;
int ret; int ret;
ret = acpi_install_cmos_rtc_space_handler(handle);
if (ret < 0) {
dev_info(dev, "Unable to install space handler\n");
return -ENODEV;
}
/* /*
* Initialization failure messages are mostly about firmware issues, so * Initialization failure messages are mostly about firmware issues, so
* print them at the "info" level. * print them at the "info" level.
...@@ -596,22 +603,27 @@ static int acpi_tad_probe(struct platform_device *pdev) ...@@ -596,22 +603,27 @@ static int acpi_tad_probe(struct platform_device *pdev)
status = acpi_evaluate_integer(handle, "_GCP", NULL, &caps); status = acpi_evaluate_integer(handle, "_GCP", NULL, &caps);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
dev_info(dev, "Unable to get capabilities\n"); dev_info(dev, "Unable to get capabilities\n");
return -ENODEV; ret = -ENODEV;
goto remove_handler;
} }
if (!(caps & ACPI_TAD_AC_WAKE)) { if (!(caps & ACPI_TAD_AC_WAKE)) {
dev_info(dev, "Unsupported capabilities\n"); dev_info(dev, "Unsupported capabilities\n");
return -ENODEV; ret = -ENODEV;
goto remove_handler;
} }
if (!acpi_has_method(handle, "_PRW")) { if (!acpi_has_method(handle, "_PRW")) {
dev_info(dev, "Missing _PRW\n"); dev_info(dev, "Missing _PRW\n");
return -ENODEV; ret = -ENODEV;
goto remove_handler;
} }
dd = devm_kzalloc(dev, sizeof(*dd), GFP_KERNEL); dd = devm_kzalloc(dev, sizeof(*dd), GFP_KERNEL);
if (!dd) if (!dd) {
return -ENOMEM; ret = -ENOMEM;
goto remove_handler;
}
dd->capabilities = caps; dd->capabilities = caps;
dev_set_drvdata(dev, dd); dev_set_drvdata(dev, dd);
...@@ -653,6 +665,11 @@ static int acpi_tad_probe(struct platform_device *pdev) ...@@ -653,6 +665,11 @@ static int acpi_tad_probe(struct platform_device *pdev)
fail: fail:
acpi_tad_remove(pdev); acpi_tad_remove(pdev);
/* Don't fallthrough because cmos rtc space handler is removed in acpi_tad_remove() */
return ret;
remove_handler:
acpi_remove_cmos_rtc_space_handler(handle);
return ret; return ret;
} }
......
...@@ -645,6 +645,8 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev); ...@@ -645,6 +645,8 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev);
#ifdef CONFIG_X86 #ifdef CONFIG_X86
bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status); bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status);
bool acpi_quirk_skip_acpi_ac_and_battery(void); bool acpi_quirk_skip_acpi_ac_and_battery(void);
int acpi_install_cmos_rtc_space_handler(acpi_handle handle);
void acpi_remove_cmos_rtc_space_handler(acpi_handle handle);
#else #else
static inline bool acpi_device_override_status(struct acpi_device *adev, static inline bool acpi_device_override_status(struct acpi_device *adev,
unsigned long long *status) unsigned long long *status)
...@@ -655,6 +657,13 @@ static inline bool acpi_quirk_skip_acpi_ac_and_battery(void) ...@@ -655,6 +657,13 @@ static inline bool acpi_quirk_skip_acpi_ac_and_battery(void)
{ {
return false; return false;
} }
static inline int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
{
return 1;
}
static inline void acpi_remove_cmos_rtc_space_handler(acpi_handle handle)
{
}
#endif #endif
#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment