summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMyron Stowe <myron.stowe@hp.com>2010-10-21 14:23:59 -0600
committerLen Brown <len.brown@intel.com>2010-10-24 23:26:23 -0400
commit29718521237a1b1607ea05b49243100ea2044337 (patch)
tree69608fa74248415a6055f0b48753cf54b63043b3
parent620242ae8c3d9c0b1a77451744fb2d855d1e7342 (diff)
ACPI: Add interfaces for ioremapping/iounmapping ACPI registers
Add remapping and unmapping interfaces for ACPI registers that are backed by memory mapped I/O (MMIO). These interfaces, along with the MMIO remapping list, enable accesses of such registers from within interrupt context. ACPI Generic Address Structure (GAS) reference (ACPI's fixed/generic hardware registers use the GAS format): ACPI Specification, Revision 4.0, Section 5.2.3.1, "Generic Address Structure". Signed-off-by: Myron Stowe <myron.stowe@hp.com> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/acpi/osl.c38
-rw-r--r--include/linux/acpi.h3
2 files changed, 41 insertions, 0 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index bd72129e35f..fc6c5d21c3e 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -372,6 +372,44 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
__acpi_unmap_table(virt, size);
}
+int acpi_os_map_generic_address(struct acpi_generic_address *addr)
+{
+ void __iomem *virt;
+
+ if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ return 0;
+
+ if (!addr->address || !addr->bit_width)
+ return -EINVAL;
+
+ virt = acpi_os_map_memory(addr->address, addr->bit_width / 8);
+ if (!virt)
+ return -EIO;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_os_map_generic_address);
+
+void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
+{
+ void __iomem *virt;
+ unsigned long flags;
+ acpi_size size = addr->bit_width / 8;
+
+ if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ return;
+
+ if (!addr->address || !addr->bit_width)
+ return;
+
+ spin_lock_irqsave(&acpi_ioremap_lock, flags);
+ virt = acpi_map_vaddr_lookup(addr->address, size);
+ spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+
+ acpi_os_unmap_memory(virt, size);
+}
+EXPORT_SYMBOL_GPL(acpi_os_unmap_generic_address);
+
#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_os_get_physical_address(void *virt, acpi_physical_address * phys)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index c227757feb0..7774e6d8fdd 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -308,6 +308,9 @@ extern acpi_status acpi_pci_osc_control_set(acpi_handle handle,
u32 *mask, u32 req);
extern void acpi_early_init(void);
+int acpi_os_map_generic_address(struct acpi_generic_address *addr);
+void acpi_os_unmap_generic_address(struct acpi_generic_address *addr);
+
#else /* !CONFIG_ACPI */
#define acpi_disabled 1