[PATCH] ACPI: add a dummy ACPI RTC driver to handle BIOS's accesses to registers delcared in OperationRegion.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is to fix acpica returns an error and terminate AML execution as
soon as BIOS tries to access ACPI's RTC registers.

BugLink: http://launchpad.net/bugs/1065066

Signed-off-by: Alex Hung <alex.hung@xxxxxxxxxxxxx>
---
 drivers/acpi/Kconfig    |    9 +++
 drivers/acpi/Makefile   |    1 +
 drivers/acpi/acpi_rtc.c |  140 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 150 insertions(+)
 create mode 100644 drivers/acpi/acpi_rtc.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 38c5078..fb90397 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -181,6 +181,15 @@ config ACPI_DOCK
 	  This driver supports ACPI-controlled docking stations and removable
 	  drive bays such as the IBM Ultrabay and the Dell Module Bay.
 
+config ACPI_RTC
+	tristate "RTC"
+	default m
+	help
+	  This driver supports an ACPI RTC device. It enables BIOS to read and
+	  to write ACPI RTC registers declared in an OperationRegion with
+	  RegionSpace as SYSTEMCMOS. This is required if BIOS needs to access
+	  RTC registers during run-time such as a number of HP laptops.
+
 config ACPI_I2C
 	def_tristate I2C
 	depends on I2C
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 2a4502b..383c62b 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS)	+= ec_sys.o
 obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
 obj-$(CONFIG_ACPI_BGRT)		+= bgrt.o
 obj-$(CONFIG_ACPI_I2C)		+= acpi_i2c.o
+obj-$(CONFIG_ACPI_RTC)          += acpi_rtc.o
 
 # processor has its own "processor." module_param namespace
 processor-y			:= processor_driver.o processor_throttling.o
diff --git a/drivers/acpi/acpi_rtc.c b/drivers/acpi/acpi_rtc.c
new file mode 100644
index 0000000..0ddcfc8
--- /dev/null
+++ b/drivers/acpi/acpi_rtc.c
@@ -0,0 +1,140 @@
+/*
+ *  acpi_rtc - ACPI RTC Driver
+ *
+ *  Copyright (C) 2013 Alex Hung <alex.hung@xxxxxxxxxxxxx>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <linux/miscdevice.h>
+
+#define pr_fmt(fmt) "acpi_rtc: " fmt
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("acpi*:PNP0B00:*");
+
+static const struct acpi_device_id rtc_device_ids[] = {
+	{"PNP0B00", 0},
+	{"", 0},
+};
+
+static acpi_status acpi_acpi_handle_locate_callback(acpi_handle handle,
+			u32 level, void *context, void **return_value)
+{
+	struct acpi_device *dev = context;
+	dev->handle = handle;
+
+	return AE_CTRL_TERMINATE;
+}
+
+static acpi_status
+acpi_rtc_space_handler(u32 function, acpi_physical_address address,
+		      u32 bits, u64 *value64,
+		      void *handler_context, void *region_context)
+{
+	return AE_OK;
+}
+
+static int rtc_install_handlers(struct acpi_device *rtc_dev)
+{
+	acpi_status status;
+	status = acpi_install_address_space_handler(rtc_dev->handle,
+						    ACPI_ADR_SPACE_CMOS,
+						    &acpi_rtc_space_handler,
+						    NULL, rtc_dev);
+	if (ACPI_FAILURE(status)) {
+		pr_info("Fail to install ACPI RTC handler\n");
+		return AE_ERROR;
+	}
+
+	return 0;
+}
+
+static int acpi_rtc_add(struct acpi_device *device)
+{
+	int ret;
+	acpi_status status;
+	acpi_handle rtc_dev;
+
+	status = acpi_get_devices(rtc_device_ids[0].id,
+				  acpi_acpi_handle_locate_callback,
+				  &rtc_dev, &rtc_dev);
+	if (!ACPI_SUCCESS(status))
+		return AE_NOT_FOUND;
+
+	ret = rtc_install_handlers((struct acpi_device *) &rtc_dev);
+
+	return ret;
+}
+
+static int acpi_rtc_remove(struct acpi_device *device, int type)
+{
+	acpi_status status;
+	status = acpi_remove_address_space_handler(device->handle,
+						   ACPI_ADR_SPACE_CMOS,
+						   &acpi_rtc_space_handler);
+	if (!ACPI_SUCCESS(status))
+		return AE_ERROR;
+
+	return AE_OK;
+}
+
+static struct acpi_driver acpi_rtc_driver = {
+	.name = "rtc",
+	.class = "ACPI_RTC_CLASS",
+	.ids = rtc_device_ids,
+	.ops = {
+		.add = acpi_rtc_add,
+		.remove = acpi_rtc_remove,
+		},
+};
+
+static int __init rtc_init(void)
+{
+	int err;
+
+	pr_info("Initializing ACPI RTC module\n");
+	err = acpi_bus_register_driver(&acpi_rtc_driver);
+	if (err) {
+		pr_err("Unable to register acpi driver.\n");
+		goto error_acpi_register;
+	}
+
+	return 0;
+
+error_acpi_register:
+
+	return err;
+}
+
+static void __exit rtc_exit(void)
+{
+	pr_info("Exiting ACPI RTC module\n");
+	acpi_bus_unregister_driver(&acpi_rtc_driver);
+}
+
+module_init(rtc_init);
+module_exit(rtc_exit);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux