mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	ACPI: Add CMOS RTC Operation Region handler support
On HP Folio 13-2000, the BIOS defines a CMOS RTC Operation Region and the EC's _REG methord accesses that region. Thus an appropriate address space handler must be registered for that region before the EC driver is loaded. Introduce a mechanism for adding CMOS RTC address space handlers. Register an ACPI scan handler for CMOS RTC devices such that, when a device of that kind is detected during an ACPI namespace scan, a common CMOS RTC operation region address space handler will be installed for it. References: https://bugzilla.kernel.org/show_bug.cgi?id=54621 Reported-and-tested-by: Stefan Nagy <public@stefan-nagy.at> Signed-off-by: Lan Tianyu <tianyu.lan@intel.com> Cc: 3.9+ <stable@vger.kernel.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
		
							parent
							
								
									358b4b35c8
								
							
						
					
					
						commit
						2fa97feb44
					
				
					 4 changed files with 99 additions and 0 deletions
				
			
		|  | @ -43,6 +43,7 @@ acpi-y				+= acpi_platform.o | |||
| acpi-y				+= power.o | ||||
| acpi-y				+= event.o | ||||
| acpi-y				+= sysfs.o | ||||
| acpi-$(CONFIG_X86)		+= acpi_cmos_rtc.o | ||||
| acpi-$(CONFIG_DEBUG_FS)		+= debugfs.o | ||||
| acpi-$(CONFIG_ACPI_NUMA)	+= numa.o | ||||
| acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o | ||||
|  |  | |||
							
								
								
									
										92
									
								
								drivers/acpi/acpi_cmos_rtc.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								drivers/acpi/acpi_cmos_rtc.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,92 @@ | |||
| /*
 | ||||
|  * ACPI support for CMOS RTC Address Space access | ||||
|  * | ||||
|  * Copyright (C) 2013, Intel Corporation | ||||
|  * Authors: Lan Tianyu <tianyu.lan@intel.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License version 2 as | ||||
|  * published by the Free Software Foundation. | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/acpi.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/err.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/module.h> | ||||
| #include <asm-generic/rtc.h> | ||||
| 
 | ||||
| #include "internal.h" | ||||
| 
 | ||||
| #define PREFIX "ACPI: " | ||||
| 
 | ||||
| ACPI_MODULE_NAME("cmos rtc"); | ||||
| 
 | ||||
| static const struct acpi_device_id acpi_cmos_rtc_ids[] = { | ||||
| 	{ "PNP0B00" }, | ||||
| 	{ "PNP0B01" }, | ||||
| 	{ "PNP0B02" }, | ||||
| 	{} | ||||
| }; | ||||
| 
 | ||||
| static acpi_status | ||||
| acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address, | ||||
| 		      u32 bits, u64 *value64, | ||||
| 		      void *handler_context, void *region_context) | ||||
| { | ||||
| 	int i; | ||||
| 	u8 *value = (u8 *)&value64; | ||||
| 
 | ||||
| 	if (address > 0xff || !value64) | ||||
| 		return AE_BAD_PARAMETER; | ||||
| 
 | ||||
| 	if (function != ACPI_WRITE && function != ACPI_READ) | ||||
| 		return AE_BAD_PARAMETER; | ||||
| 
 | ||||
| 	spin_lock_irq(&rtc_lock); | ||||
| 
 | ||||
| 	for (i = 0; i < DIV_ROUND_UP(bits, 8); ++i, ++address, ++value) | ||||
| 		if (function == ACPI_READ) | ||||
| 			*value = CMOS_READ(address); | ||||
| 		else | ||||
| 			CMOS_WRITE(*value, address); | ||||
| 
 | ||||
| 	spin_unlock_irq(&rtc_lock); | ||||
| 
 | ||||
| 	return AE_OK; | ||||
| } | ||||
| 
 | ||||
| static int acpi_install_cmos_rtc_space_handler(struct acpi_device *adev, | ||||
| 		const struct acpi_device_id *id) | ||||
| { | ||||
| 	acpi_status status; | ||||
| 
 | ||||
| 	status = acpi_install_address_space_handler(adev->handle, | ||||
| 			ACPI_ADR_SPACE_CMOS, | ||||
| 			&acpi_cmos_rtc_space_handler, | ||||
| 			NULL, NULL); | ||||
| 	if (ACPI_FAILURE(status)) { | ||||
| 		pr_err(PREFIX "Error installing CMOS-RTC region handler\n"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void acpi_remove_cmos_rtc_space_handler(struct acpi_device *adev) | ||||
| { | ||||
| 	if (ACPI_FAILURE(acpi_remove_address_space_handler(adev->handle, | ||||
| 			ACPI_ADR_SPACE_CMOS, &acpi_cmos_rtc_space_handler))) | ||||
| 		pr_err(PREFIX "Error removing CMOS-RTC region handler\n"); | ||||
| } | ||||
| 
 | ||||
| static struct acpi_scan_handler cmos_rtc_handler = { | ||||
| 	.ids = acpi_cmos_rtc_ids, | ||||
| 	.attach = acpi_install_cmos_rtc_space_handler, | ||||
| 	.detach = acpi_remove_cmos_rtc_space_handler, | ||||
| }; | ||||
| 
 | ||||
| void __init acpi_cmos_rtc_init(void) | ||||
| { | ||||
| 	acpi_scan_add_handler(&cmos_rtc_handler); | ||||
| } | ||||
|  | @ -45,6 +45,11 @@ void acpi_memory_hotplug_init(void); | |||
| #else | ||||
| static inline void acpi_memory_hotplug_init(void) {} | ||||
| #endif | ||||
| #ifdef CONFIG_X86 | ||||
| void acpi_cmos_rtc_init(void); | ||||
| #else | ||||
| static inline void acpi_cmos_rtc_init(void) {} | ||||
| #endif | ||||
| 
 | ||||
| void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug, | ||||
| 				    const char *name); | ||||
|  |  | |||
|  | @ -2040,6 +2040,7 @@ int __init acpi_scan_init(void) | |||
| 	acpi_pci_link_init(); | ||||
| 	acpi_platform_init(); | ||||
| 	acpi_lpss_init(); | ||||
| 	acpi_cmos_rtc_init(); | ||||
| 	acpi_container_init(); | ||||
| 	acpi_memory_hotplug_init(); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Lan Tianyu
						Lan Tianyu