diff options
-rw-r--r-- | arch/ia64/include/asm/device.h | 3 | ||||
-rw-r--r-- | arch/ia64/kernel/acpi.c | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/device.h | 3 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 6 | ||||
-rw-r--r-- | drivers/acpi/Kconfig | 6 | ||||
-rw-r--r-- | drivers/acpi/Makefile | 3 | ||||
-rw-r--r-- | drivers/acpi/acpi_i2c.c | 103 | ||||
-rw-r--r-- | drivers/acpi/acpi_platform.c | 104 | ||||
-rw-r--r-- | drivers/acpi/glue.c | 56 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 7 | ||||
-rw-r--r-- | drivers/acpi/pci_irq.c | 5 | ||||
-rw-r--r-- | drivers/acpi/resource.c | 526 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 58 | ||||
-rw-r--r-- | drivers/base/platform.c | 26 | ||||
-rw-r--r-- | drivers/i2c/i2c-core.c | 6 | ||||
-rw-r--r-- | drivers/mmc/host/Kconfig | 12 | ||||
-rw-r--r-- | drivers/mmc/host/Makefile | 1 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-acpi.c | 304 | ||||
-rw-r--r-- | drivers/pnp/base.h | 2 | ||||
-rw-r--r-- | drivers/pnp/pnpacpi/core.c | 4 | ||||
-rw-r--r-- | drivers/pnp/pnpacpi/rsparser.c | 296 | ||||
-rw-r--r-- | drivers/pnp/resource.c | 16 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 2 | ||||
-rw-r--r-- | include/linux/acpi.h | 48 | ||||
-rw-r--r-- | include/linux/device.h | 18 | ||||
-rw-r--r-- | include/linux/i2c.h | 9 | ||||
-rw-r--r-- | include/linux/platform_device.h | 1 |
27 files changed, 1326 insertions, 301 deletions
diff --git a/arch/ia64/include/asm/device.h b/arch/ia64/include/asm/device.h index d05e78f6db94..f69c32ffbe6a 100644 --- a/arch/ia64/include/asm/device.h +++ b/arch/ia64/include/asm/device.h | |||
@@ -7,9 +7,6 @@ | |||
7 | #define _ASM_IA64_DEVICE_H | 7 | #define _ASM_IA64_DEVICE_H |
8 | 8 | ||
9 | struct dev_archdata { | 9 | struct dev_archdata { |
10 | #ifdef CONFIG_ACPI | ||
11 | void *acpi_handle; | ||
12 | #endif | ||
13 | #ifdef CONFIG_INTEL_IOMMU | 10 | #ifdef CONFIG_INTEL_IOMMU |
14 | void *iommu; /* hook for IOMMU specific extension */ | 11 | void *iommu; /* hook for IOMMU specific extension */ |
15 | #endif | 12 | #endif |
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 440578850ae5..e9682f5be343 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c | |||
@@ -633,6 +633,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int triggering, int polarity) | |||
633 | ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : | 633 | ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : |
634 | IOSAPIC_LEVEL); | 634 | IOSAPIC_LEVEL); |
635 | } | 635 | } |
636 | EXPORT_SYMBOL_GPL(acpi_register_gsi); | ||
636 | 637 | ||
637 | void acpi_unregister_gsi(u32 gsi) | 638 | void acpi_unregister_gsi(u32 gsi) |
638 | { | 639 | { |
@@ -644,6 +645,7 @@ void acpi_unregister_gsi(u32 gsi) | |||
644 | 645 | ||
645 | iosapic_unregister_intr(gsi); | 646 | iosapic_unregister_intr(gsi); |
646 | } | 647 | } |
648 | EXPORT_SYMBOL_GPL(acpi_unregister_gsi); | ||
647 | 649 | ||
648 | static int __init acpi_parse_fadt(struct acpi_table_header *table) | 650 | static int __init acpi_parse_fadt(struct acpi_table_header *table) |
649 | { | 651 | { |
diff --git a/arch/x86/include/asm/device.h b/arch/x86/include/asm/device.h index 93e1c55f14ab..03dd72957d2f 100644 --- a/arch/x86/include/asm/device.h +++ b/arch/x86/include/asm/device.h | |||
@@ -2,9 +2,6 @@ | |||
2 | #define _ASM_X86_DEVICE_H | 2 | #define _ASM_X86_DEVICE_H |
3 | 3 | ||
4 | struct dev_archdata { | 4 | struct dev_archdata { |
5 | #ifdef CONFIG_ACPI | ||
6 | void *acpi_handle; | ||
7 | #endif | ||
8 | #ifdef CONFIG_X86_DEV_DMA_OPS | 5 | #ifdef CONFIG_X86_DEV_DMA_OPS |
9 | struct dma_map_ops *dma_ops; | 6 | struct dma_map_ops *dma_ops; |
10 | #endif | 7 | #endif |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index e651f7a589ac..e48cafcf92ae 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -574,6 +574,12 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) | |||
574 | 574 | ||
575 | return irq; | 575 | return irq; |
576 | } | 576 | } |
577 | EXPORT_SYMBOL_GPL(acpi_register_gsi); | ||
578 | |||
579 | void acpi_unregister_gsi(u32 gsi) | ||
580 | { | ||
581 | } | ||
582 | EXPORT_SYMBOL_GPL(acpi_unregister_gsi); | ||
577 | 583 | ||
578 | void __init acpi_set_irq_model_pic(void) | 584 | void __init acpi_set_irq_model_pic(void) |
579 | { | 585 | { |
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 119d58db8342..0300bf612946 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -181,6 +181,12 @@ config ACPI_DOCK | |||
181 | This driver supports ACPI-controlled docking stations and removable | 181 | This driver supports ACPI-controlled docking stations and removable |
182 | drive bays such as the IBM Ultrabay and the Dell Module Bay. | 182 | drive bays such as the IBM Ultrabay and the Dell Module Bay. |
183 | 183 | ||
184 | config ACPI_I2C | ||
185 | def_tristate I2C | ||
186 | depends on I2C | ||
187 | help | ||
188 | ACPI I2C enumeration support. | ||
189 | |||
184 | config ACPI_PROCESSOR | 190 | config ACPI_PROCESSOR |
185 | tristate "Processor" | 191 | tristate "Processor" |
186 | select THERMAL | 192 | select THERMAL |
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index a2711fae62d8..2a4502becd13 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
@@ -33,10 +33,12 @@ acpi-$(CONFIG_ACPI_SLEEP) += proc.o | |||
33 | # | 33 | # |
34 | acpi-y += bus.o glue.o | 34 | acpi-y += bus.o glue.o |
35 | acpi-y += scan.o | 35 | acpi-y += scan.o |
36 | acpi-y += resource.o | ||
36 | acpi-y += processor_core.o | 37 | acpi-y += processor_core.o |
37 | acpi-y += ec.o | 38 | acpi-y += ec.o |
38 | acpi-$(CONFIG_ACPI_DOCK) += dock.o | 39 | acpi-$(CONFIG_ACPI_DOCK) += dock.o |
39 | acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o | 40 | acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o |
41 | acpi-y += acpi_platform.o | ||
40 | acpi-y += power.o | 42 | acpi-y += power.o |
41 | acpi-y += event.o | 43 | acpi-y += event.o |
42 | acpi-y += sysfs.o | 44 | acpi-y += sysfs.o |
@@ -68,6 +70,7 @@ obj-$(CONFIG_ACPI_HED) += hed.o | |||
68 | obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o | 70 | obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o |
69 | obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o | 71 | obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o |
70 | obj-$(CONFIG_ACPI_BGRT) += bgrt.o | 72 | obj-$(CONFIG_ACPI_BGRT) += bgrt.o |
73 | obj-$(CONFIG_ACPI_I2C) += acpi_i2c.o | ||
71 | 74 | ||
72 | # processor has its own "processor." module_param namespace | 75 | # processor has its own "processor." module_param namespace |
73 | processor-y := processor_driver.o processor_throttling.o | 76 | processor-y := processor_driver.o processor_throttling.o |
diff --git a/drivers/acpi/acpi_i2c.c b/drivers/acpi/acpi_i2c.c new file mode 100644 index 000000000000..82045e3f5cac --- /dev/null +++ b/drivers/acpi/acpi_i2c.c | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | * ACPI I2C enumeration support | ||
3 | * | ||
4 | * Copyright (C) 2012, Intel Corporation | ||
5 | * Author: Mika Westerberg <mika.westerberg@linux.intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/acpi.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/export.h> | ||
15 | #include <linux/i2c.h> | ||
16 | #include <linux/ioport.h> | ||
17 | |||
18 | ACPI_MODULE_NAME("i2c"); | ||
19 | |||
20 | static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) | ||
21 | { | ||
22 | struct i2c_board_info *info = data; | ||
23 | |||
24 | if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { | ||
25 | struct acpi_resource_i2c_serialbus *sb; | ||
26 | |||
27 | sb = &ares->data.i2c_serial_bus; | ||
28 | if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { | ||
29 | info->addr = sb->slave_address; | ||
30 | if (sb->access_mode == ACPI_I2C_10BIT_MODE) | ||
31 | info->flags |= I2C_CLIENT_TEN; | ||
32 | } | ||
33 | } else if (info->irq < 0) { | ||
34 | struct resource r; | ||
35 | |||
36 | if (acpi_dev_resource_interrupt(ares, 0, &r)) | ||
37 | info->irq = r.start; | ||
38 | } | ||
39 | |||
40 | /* Tell the ACPI core to skip this resource */ | ||
41 | return 1; | ||
42 | } | ||
43 | |||
44 | static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, | ||
45 | void *data, void **return_value) | ||
46 | { | ||
47 | struct i2c_adapter *adapter = data; | ||
48 | struct list_head resource_list; | ||
49 | struct i2c_board_info info; | ||
50 | struct acpi_device *adev; | ||
51 | int ret; | ||
52 | |||
53 | if (acpi_bus_get_device(handle, &adev)) | ||
54 | return AE_OK; | ||
55 | if (acpi_bus_get_status(adev) || !adev->status.present) | ||
56 | return AE_OK; | ||
57 | |||
58 | memset(&info, 0, sizeof(info)); | ||
59 | info.acpi_node.handle = handle; | ||
60 | info.irq = -1; | ||
61 | |||
62 | INIT_LIST_HEAD(&resource_list); | ||
63 | ret = acpi_dev_get_resources(adev, &resource_list, | ||
64 | acpi_i2c_add_resource, &info); | ||
65 | acpi_dev_free_resource_list(&resource_list); | ||
66 | |||
67 | if (ret < 0 || !info.addr) | ||
68 | return AE_OK; | ||
69 | |||
70 | strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); | ||
71 | if (!i2c_new_device(adapter, &info)) { | ||
72 | dev_err(&adapter->dev, | ||
73 | "failed to add I2C device %s from ACPI\n", | ||
74 | dev_name(&adev->dev)); | ||
75 | } | ||
76 | |||
77 | return AE_OK; | ||
78 | } | ||
79 | |||
80 | /** | ||
81 | * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter | ||
82 | * @adapter: pointer to adapter | ||
83 | * | ||
84 | * Enumerate all I2C slave devices behind this adapter by walking the ACPI | ||
85 | * namespace. When a device is found it will be added to the Linux device | ||
86 | * model and bound to the corresponding ACPI handle. | ||
87 | */ | ||
88 | void acpi_i2c_register_devices(struct i2c_adapter *adapter) | ||
89 | { | ||
90 | acpi_handle handle; | ||
91 | acpi_status status; | ||
92 | |||
93 | handle = ACPI_HANDLE(&adapter->dev); | ||
94 | if (!handle) | ||
95 | return; | ||
96 | |||
97 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, | ||
98 | acpi_i2c_add_device, NULL, | ||
99 | adapter, NULL); | ||
100 | if (ACPI_FAILURE(status)) | ||
101 | dev_warn(&adapter->dev, "failed to enumerate I2C slaves\n"); | ||
102 | } | ||
103 | EXPORT_SYMBOL_GPL(acpi_i2c_register_devices); | ||
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c new file mode 100644 index 000000000000..db129b9f52cb --- /dev/null +++ b/drivers/acpi/acpi_platform.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * ACPI support for platform bus type. | ||
3 | * | ||
4 | * Copyright (C) 2012, Intel Corporation | ||
5 | * Authors: Mika Westerberg <mika.westerberg@linux.intel.com> | ||
6 | * Mathias Nyman <mathias.nyman@linux.intel.com> | ||
7 | * Rafael J. Wysocki <rafael.j.wysocki@intel.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/acpi.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | |||
20 | #include "internal.h" | ||
21 | |||
22 | ACPI_MODULE_NAME("platform"); | ||
23 | |||
24 | /** | ||
25 | * acpi_create_platform_device - Create platform device for ACPI device node | ||
26 | * @adev: ACPI device node to create a platform device for. | ||
27 | * | ||
28 | * Check if the given @adev can be represented as a platform device and, if | ||
29 | * that's the case, create and register a platform device, populate its common | ||
30 | * resources and returns a pointer to it. Otherwise, return %NULL. | ||
31 | * | ||
32 | * The platform device's name will be taken from the @adev's _HID and _UID. | ||
33 | */ | ||
34 | struct platform_device *acpi_create_platform_device(struct acpi_device *adev) | ||
35 | { | ||
36 | struct platform_device *pdev = NULL; | ||
37 | struct acpi_device *acpi_parent; | ||
38 | struct platform_device_info pdevinfo; | ||
39 | struct resource_list_entry *rentry; | ||
40 | struct list_head resource_list; | ||
41 | struct resource *resources; | ||
42 | int count; | ||
43 | |||
44 | /* If the ACPI node already has a physical device attached, skip it. */ | ||
45 | if (adev->physical_node_count) | ||
46 | return NULL; | ||
47 | |||
48 | INIT_LIST_HEAD(&resource_list); | ||
49 | count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL); | ||
50 | if (count <= 0) | ||
51 | return NULL; | ||
52 | |||
53 | resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL); | ||
54 | if (!resources) { | ||
55 | dev_err(&adev->dev, "No memory for resources\n"); | ||
56 | acpi_dev_free_resource_list(&resource_list); | ||
57 | return NULL; | ||
58 | } | ||
59 | count = 0; | ||
60 | list_for_each_entry(rentry, &resource_list, node) | ||
61 | resources[count++] = rentry->res; | ||
62 | |||
63 | acpi_dev_free_resource_list(&resource_list); | ||
64 | |||
65 | memset(&pdevinfo, 0, sizeof(pdevinfo)); | ||
66 | /* | ||
67 | * If the ACPI node has a parent and that parent has a physical device | ||
68 | * attached to it, that physical device should be the parent of the | ||
69 | * platform device we are about to create. | ||
70 | */ | ||
71 | pdevinfo.parent = NULL; | ||
72 | acpi_parent = adev->parent; | ||
73 | if (acpi_parent) { | ||
74 | struct acpi_device_physical_node *entry; | ||
75 | struct list_head *list; | ||
76 | |||
77 | mutex_lock(&acpi_parent->physical_node_lock); | ||
78 | list = &acpi_parent->physical_node_list; | ||
79 | if (!list_empty(list)) { | ||
80 | entry = list_first_entry(list, | ||
81 | struct acpi_device_physical_node, | ||
82 | node); | ||
83 | pdevinfo.parent = entry->dev; | ||
84 | } | ||
85 | mutex_unlock(&acpi_parent->physical_node_lock); | ||
86 | } | ||
87 | pdevinfo.name = dev_name(&adev->dev); | ||
88 | pdevinfo.id = -1; | ||
89 | pdevinfo.res = resources; | ||
90 | pdevinfo.num_res = count; | ||
91 | pdevinfo.acpi_node.handle = adev->handle; | ||
92 | pdev = platform_device_register_full(&pdevinfo); | ||
93 | if (IS_ERR(pdev)) { | ||
94 | dev_err(&adev->dev, "platform device creation failed: %ld\n", | ||
95 | PTR_ERR(pdev)); | ||
96 | pdev = NULL; | ||
97 | } else { | ||
98 | dev_dbg(&adev->dev, "created platform device %s\n", | ||
99 | dev_name(&pdev->dev)); | ||
100 | } | ||
101 | |||
102 | kfree(resources); | ||
103 | return pdev; | ||
104 | } | ||
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 08373086cd7e..01551840d236 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -130,46 +130,59 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) | |||
130 | { | 130 | { |
131 | struct acpi_device *acpi_dev; | 131 | struct acpi_device *acpi_dev; |
132 | acpi_status status; | 132 | acpi_status status; |
133 | struct acpi_device_physical_node *physical_node; | 133 | struct acpi_device_physical_node *physical_node, *pn; |
134 | char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2]; | 134 | char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2]; |
135 | int retval = -EINVAL; | 135 | int retval = -EINVAL; |
136 | 136 | ||
137 | if (dev->archdata.acpi_handle) { | 137 | if (ACPI_HANDLE(dev)) { |
138 | dev_warn(dev, "Drivers changed 'acpi_handle'\n"); | 138 | if (handle) { |
139 | return -EINVAL; | 139 | dev_warn(dev, "ACPI handle is already set\n"); |
140 | return -EINVAL; | ||
141 | } else { | ||
142 | handle = ACPI_HANDLE(dev); | ||
143 | } | ||
140 | } | 144 | } |
145 | if (!handle) | ||
146 | return -EINVAL; | ||
141 | 147 | ||
142 | get_device(dev); | 148 | get_device(dev); |
143 | status = acpi_bus_get_device(handle, &acpi_dev); | 149 | status = acpi_bus_get_device(handle, &acpi_dev); |
144 | if (ACPI_FAILURE(status)) | 150 | if (ACPI_FAILURE(status)) |
145 | goto err; | 151 | goto err; |
146 | 152 | ||
147 | physical_node = kzalloc(sizeof(struct acpi_device_physical_node), | 153 | physical_node = kzalloc(sizeof(*physical_node), GFP_KERNEL); |
148 | GFP_KERNEL); | ||
149 | if (!physical_node) { | 154 | if (!physical_node) { |
150 | retval = -ENOMEM; | 155 | retval = -ENOMEM; |
151 | goto err; | 156 | goto err; |
152 | } | 157 | } |
153 | 158 | ||
154 | mutex_lock(&acpi_dev->physical_node_lock); | 159 | mutex_lock(&acpi_dev->physical_node_lock); |
160 | |||
161 | /* Sanity check. */ | ||
162 | list_for_each_entry(pn, &acpi_dev->physical_node_list, node) | ||
163 | if (pn->dev == dev) { | ||
164 | dev_warn(dev, "Already associated with ACPI node\n"); | ||
165 | goto err_free; | ||
166 | } | ||
167 | |||
155 | /* allocate physical node id according to physical_node_id_bitmap */ | 168 | /* allocate physical node id according to physical_node_id_bitmap */ |
156 | physical_node->node_id = | 169 | physical_node->node_id = |
157 | find_first_zero_bit(acpi_dev->physical_node_id_bitmap, | 170 | find_first_zero_bit(acpi_dev->physical_node_id_bitmap, |
158 | ACPI_MAX_PHYSICAL_NODE); | 171 | ACPI_MAX_PHYSICAL_NODE); |
159 | if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) { | 172 | if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) { |
160 | retval = -ENOSPC; | 173 | retval = -ENOSPC; |
161 | mutex_unlock(&acpi_dev->physical_node_lock); | 174 | goto err_free; |
162 | kfree(physical_node); | ||
163 | goto err; | ||
164 | } | 175 | } |
165 | 176 | ||
166 | set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap); | 177 | set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap); |
167 | physical_node->dev = dev; | 178 | physical_node->dev = dev; |
168 | list_add_tail(&physical_node->node, &acpi_dev->physical_node_list); | 179 | list_add_tail(&physical_node->node, &acpi_dev->physical_node_list); |
169 | acpi_dev->physical_node_count++; | 180 | acpi_dev->physical_node_count++; |
181 | |||
170 | mutex_unlock(&acpi_dev->physical_node_lock); | 182 | mutex_unlock(&acpi_dev->physical_node_lock); |
171 | 183 | ||
172 | dev->archdata.acpi_handle = handle; | 184 | if (!ACPI_HANDLE(dev)) |
185 | ACPI_HANDLE_SET(dev, acpi_dev->handle); | ||
173 | 186 | ||
174 | if (!physical_node->node_id) | 187 | if (!physical_node->node_id) |
175 | strcpy(physical_node_name, PHYSICAL_NODE_STRING); | 188 | strcpy(physical_node_name, PHYSICAL_NODE_STRING); |
@@ -187,8 +200,14 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) | |||
187 | return 0; | 200 | return 0; |
188 | 201 | ||
189 | err: | 202 | err: |
203 | ACPI_HANDLE_SET(dev, NULL); | ||
190 | put_device(dev); | 204 | put_device(dev); |
191 | return retval; | 205 | return retval; |
206 | |||
207 | err_free: | ||
208 | mutex_unlock(&acpi_dev->physical_node_lock); | ||
209 | kfree(physical_node); | ||
210 | goto err; | ||
192 | } | 211 | } |
193 | 212 | ||
194 | static int acpi_unbind_one(struct device *dev) | 213 | static int acpi_unbind_one(struct device *dev) |
@@ -198,11 +217,10 @@ static int acpi_unbind_one(struct device *dev) | |||
198 | acpi_status status; | 217 | acpi_status status; |
199 | struct list_head *node, *next; | 218 | struct list_head *node, *next; |
200 | 219 | ||
201 | if (!dev->archdata.acpi_handle) | 220 | if (!ACPI_HANDLE(dev)) |
202 | return 0; | 221 | return 0; |
203 | 222 | ||
204 | status = acpi_bus_get_device(dev->archdata.acpi_handle, | 223 | status = acpi_bus_get_device(ACPI_HANDLE(dev), &acpi_dev); |
205 | &acpi_dev); | ||
206 | if (ACPI_FAILURE(status)) | 224 | if (ACPI_FAILURE(status)) |
207 | goto err; | 225 | goto err; |
208 | 226 | ||
@@ -228,7 +246,7 @@ static int acpi_unbind_one(struct device *dev) | |||
228 | 246 | ||
229 | sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name); | 247 | sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name); |
230 | sysfs_remove_link(&dev->kobj, "firmware_node"); | 248 | sysfs_remove_link(&dev->kobj, "firmware_node"); |
231 | dev->archdata.acpi_handle = NULL; | 249 | ACPI_HANDLE_SET(dev, NULL); |
232 | /* acpi_bind_one increase refcnt by one */ | 250 | /* acpi_bind_one increase refcnt by one */ |
233 | put_device(dev); | 251 | put_device(dev); |
234 | kfree(entry); | 252 | kfree(entry); |
@@ -248,6 +266,10 @@ static int acpi_platform_notify(struct device *dev) | |||
248 | acpi_handle handle; | 266 | acpi_handle handle; |
249 | int ret = -EINVAL; | 267 | int ret = -EINVAL; |
250 | 268 | ||
269 | ret = acpi_bind_one(dev, NULL); | ||
270 | if (!ret) | ||
271 | goto out; | ||
272 | |||
251 | if (!dev->bus || !dev->parent) { | 273 | if (!dev->bus || !dev->parent) { |
252 | /* bridge devices genernally haven't bus or parent */ | 274 | /* bridge devices genernally haven't bus or parent */ |
253 | ret = acpi_find_bridge_device(dev, &handle); | 275 | ret = acpi_find_bridge_device(dev, &handle); |
@@ -261,16 +283,16 @@ static int acpi_platform_notify(struct device *dev) | |||
261 | } | 283 | } |
262 | if ((ret = type->find_device(dev, &handle)) != 0) | 284 | if ((ret = type->find_device(dev, &handle)) != 0) |
263 | DBG("Can't get handler for %s\n", dev_name(dev)); | 285 | DBG("Can't get handler for %s\n", dev_name(dev)); |
264 | end: | 286 | end: |
265 | if (!ret) | 287 | if (!ret) |
266 | acpi_bind_one(dev, handle); | 288 | acpi_bind_one(dev, handle); |
267 | 289 | ||
290 | out: | ||
268 | #if ACPI_GLUE_DEBUG | 291 | #if ACPI_GLUE_DEBUG |
269 | if (!ret) { | 292 | if (!ret) { |
270 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 293 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
271 | 294 | ||
272 | acpi_get_name(dev->archdata.acpi_handle, | 295 | acpi_get_name(dev->acpi_handle, ACPI_FULL_PATHNAME, &buffer); |
273 | ACPI_FULL_PATHNAME, &buffer); | ||
274 | DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer); | 296 | DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer); |
275 | kfree(buffer.pointer); | 297 | kfree(buffer.pointer); |
276 | } else | 298 | } else |
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index ca75b9ce0489..57d41f6e1441 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -93,4 +93,11 @@ static inline int suspend_nvs_save(void) { return 0; } | |||
93 | static inline void suspend_nvs_restore(void) {} | 93 | static inline void suspend_nvs_restore(void) {} |
94 | #endif | 94 | #endif |
95 | 95 | ||
96 | /*-------------------------------------------------------------------------- | ||
97 | Platform bus support | ||
98 | -------------------------------------------------------------------------- */ | ||
99 | struct platform_device; | ||
100 | |||
101 | struct platform_device *acpi_create_platform_device(struct acpi_device *adev); | ||
102 | |||
96 | #endif /* _ACPI_INTERNAL_H_ */ | 103 | #endif /* _ACPI_INTERNAL_H_ */ |
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 0eefa12e648c..1be25a590dce 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
@@ -495,11 +495,6 @@ int acpi_pci_irq_enable(struct pci_dev *dev) | |||
495 | return 0; | 495 | return 0; |
496 | } | 496 | } |
497 | 497 | ||
498 | /* FIXME: implement x86/x86_64 version */ | ||
499 | void __attribute__ ((weak)) acpi_unregister_gsi(u32 i) | ||
500 | { | ||
501 | } | ||
502 | |||
503 | void acpi_pci_irq_disable(struct pci_dev *dev) | 498 | void acpi_pci_irq_disable(struct pci_dev *dev) |
504 | { | 499 | { |
505 | struct acpi_prt_entry *entry; | 500 | struct acpi_prt_entry *entry; |
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c new file mode 100644 index 000000000000..a3868f6c222a --- /dev/null +++ b/drivers/acpi/resource.c | |||
@@ -0,0 +1,526 @@ | |||
1 | /* | ||
2 | * drivers/acpi/resource.c - ACPI device resources interpretation. | ||
3 | * | ||
4 | * Copyright (C) 2012, Intel Corp. | ||
5 | * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> | ||
6 | * | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as published | ||
11 | * by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
21 | * | ||
22 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
23 | */ | ||
24 | |||
25 | #include <linux/acpi.h> | ||
26 | #include <linux/device.h> | ||
27 | #include <linux/export.h> | ||
28 | #include <linux/ioport.h> | ||
29 | #include <linux/slab.h> | ||
30 | |||
31 | #ifdef CONFIG_X86 | ||
32 | #define valid_IRQ(i) (((i) != 0) && ((i) != 2)) | ||
33 | #else | ||
34 | #define valid_IRQ(i) (true) | ||
35 | #endif | ||
36 | |||
37 | static unsigned long acpi_dev_memresource_flags(u64 len, u8 write_protect, | ||
38 | bool window) | ||
39 | { | ||
40 | unsigned long flags = IORESOURCE_MEM; | ||
41 | |||
42 | if (len == 0) | ||
43 | flags |= IORESOURCE_DISABLED; | ||
44 | |||
45 | if (write_protect == ACPI_READ_WRITE_MEMORY) | ||
46 | flags |= IORESOURCE_MEM_WRITEABLE; | ||
47 | |||
48 | if (window) | ||
49 | flags |= IORESOURCE_WINDOW; | ||
50 | |||
51 | return flags; | ||
52 | } | ||
53 | |||
54 | static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len, | ||
55 | u8 write_protect) | ||
56 | { | ||
57 | res->start = start; | ||
58 | res->end = start + len - 1; | ||
59 | res->flags = acpi_dev_memresource_flags(len, write_protect, false); | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * acpi_dev_resource_memory - Extract ACPI memory resource information. | ||
64 | * @ares: Input ACPI resource object. | ||
65 | * @res: Output generic resource object. | ||
66 | * | ||
67 | * Check if the given ACPI resource object represents a memory resource and | ||
68 | * if that's the case, use the information in it to populate the generic | ||
69 | * resource object pointed to by @res. | ||
70 | */ | ||
71 | bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) | ||
72 | { | ||
73 | struct acpi_resource_memory24 *memory24; | ||
74 | struct acpi_resource_memory32 *memory32; | ||
75 | struct acpi_resource_fixed_memory32 *fixed_memory32; | ||
76 | |||
77 | switch (ares->type) { | ||
78 | case ACPI_RESOURCE_TYPE_MEMORY24: | ||
79 | memory24 = &ares->data.memory24; | ||
80 | acpi_dev_get_memresource(res, memory24->minimum, | ||
81 | memory24->address_length, | ||
82 | memory24->write_protect); | ||
83 | break; | ||
84 | case ACPI_RESOURCE_TYPE_MEMORY32: | ||
85 | memory32 = &ares->data.memory32; | ||
86 | acpi_dev_get_memresource(res, memory32->minimum, | ||
87 | memory32->address_length, | ||
88 | memory32->write_protect); | ||
89 | break; | ||
90 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: | ||
91 | fixed_memory32 = &ares->data.fixed_memory32; | ||
92 | acpi_dev_get_memresource(res, fixed_memory32->address, | ||
93 | fixed_memory32->address_length, | ||
94 | fixed_memory32->write_protect); | ||
95 | break; | ||
96 | default: | ||
97 | return false; | ||
98 | } | ||
99 | return true; | ||
100 | } | ||
101 | EXPORT_SYMBOL_GPL(acpi_dev_resource_memory); | ||
102 | |||
103 | static unsigned int acpi_dev_ioresource_flags(u64 start, u64 end, u8 io_decode, | ||
104 | bool window) | ||
105 | { | ||
106 | int flags = IORESOURCE_IO; | ||
107 | |||
108 | if (io_decode == ACPI_DECODE_16) | ||
109 | flags |= IORESOURCE_IO_16BIT_ADDR; | ||
110 | |||
111 | if (start > end || end >= 0x10003) | ||
112 | flags |= IORESOURCE_DISABLED; | ||
113 | |||
114 | if (window) | ||
115 | flags |= IORESOURCE_WINDOW; | ||
116 | |||
117 | return flags; | ||
118 | } | ||
119 | |||
120 | static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len, | ||
121 | u8 io_decode) | ||
122 | { | ||
123 | u64 end = start + len - 1; | ||
124 | |||
125 | res->start = start; | ||
126 | res->end = end; | ||
127 | res->flags = acpi_dev_ioresource_flags(start, end, io_decode, false); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * acpi_dev_resource_io - Extract ACPI I/O resource information. | ||
132 | * @ares: Input ACPI resource object. | ||
133 | * @res: Output generic resource object. | ||
134 | * | ||
135 | * Check if the given ACPI resource object represents an I/O resource and | ||
136 | * if that's the case, use the information in it to populate the generic | ||
137 | * resource object pointed to by @res. | ||
138 | */ | ||
139 | bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) | ||
140 | { | ||
141 | struct acpi_resource_io *io; | ||
142 | struct acpi_resource_fixed_io *fixed_io; | ||
143 | |||
144 | switch (ares->type) { | ||
145 | case ACPI_RESOURCE_TYPE_IO: | ||
146 | io = &ares->data.io; | ||
147 | acpi_dev_get_ioresource(res, io->minimum, | ||
148 | io->address_length, | ||
149 | io->io_decode); | ||
150 | break; | ||
151 | case ACPI_RESOURCE_TYPE_FIXED_IO: | ||
152 | fixed_io = &ares->data.fixed_io; | ||
153 | acpi_dev_get_ioresource(res, fixed_io->address, | ||
154 | fixed_io->address_length, | ||
155 | ACPI_DECODE_10); | ||
156 | break; | ||
157 | default: | ||
158 | return false; | ||
159 | } | ||
160 | return true; | ||
161 | } | ||
162 | EXPORT_SYMBOL_GPL(acpi_dev_resource_io); | ||
163 | |||
164 | /** | ||
165 | * acpi_dev_resource_address_space - Extract ACPI address space information. | ||
166 | * @ares: Input ACPI resource object. | ||
167 | * @res: Output generic resource object. | ||
168 | * | ||
169 | * Check if the given ACPI resource object represents an address space resource | ||
170 | * and if that's the case, use the information in it to populate the generic | ||
171 | * resource object pointed to by @res. | ||
172 | */ | ||
173 | bool acpi_dev_resource_address_space(struct acpi_resource *ares, | ||
174 | struct resource *res) | ||
175 | { | ||
176 | acpi_status status; | ||
177 | struct acpi_resource_address64 addr; | ||
178 | bool window; | ||
179 | u64 len; | ||
180 | u8 io_decode; | ||
181 | |||
182 | switch (ares->type) { | ||
183 | case ACPI_RESOURCE_TYPE_ADDRESS16: | ||
184 | case ACPI_RESOURCE_TYPE_ADDRESS32: | ||
185 | case ACPI_RESOURCE_TYPE_ADDRESS64: | ||
186 | break; | ||
187 | default: | ||
188 | return false; | ||
189 | } | ||
190 | |||
191 | status = acpi_resource_to_address64(ares, &addr); | ||
192 | if (ACPI_FAILURE(status)) | ||
193 | return true; | ||
194 | |||
195 | res->start = addr.minimum; | ||
196 | res->end = addr.maximum; | ||
197 | window = addr.producer_consumer == ACPI_PRODUCER; | ||
198 | |||
199 | switch(addr.resource_type) { | ||
200 | case ACPI_MEMORY_RANGE: | ||
201 | len = addr.maximum - addr.minimum + 1; | ||
202 | res->flags = acpi_dev_memresource_flags(len, | ||
203 | addr.info.mem.write_protect, | ||
204 | window); | ||
205 | break; | ||
206 | case ACPI_IO_RANGE: | ||
207 | io_decode = addr.granularity == 0xfff ? | ||
208 | ACPI_DECODE_10 : ACPI_DECODE_16; | ||
209 | res->flags = acpi_dev_ioresource_flags(addr.minimum, | ||
210 | addr.maximum, | ||
211 | io_decode, window); | ||
212 | break; | ||
213 | case ACPI_BUS_NUMBER_RANGE: | ||
214 | res->flags = IORESOURCE_BUS; | ||
215 | break; | ||
216 | default: | ||
217 | res->flags = 0; | ||
218 | } | ||
219 | |||
220 | return true; | ||
221 | } | ||
222 | EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space); | ||
223 | |||
224 | /** | ||
225 | * acpi_dev_resource_ext_address_space - Extract ACPI address space information. | ||
226 | * @ares: Input ACPI resource object. | ||
227 | * @res: Output generic resource object. | ||
228 | * | ||
229 | * Check if the given ACPI resource object represents an extended address space | ||
230 | * resource and if that's the case, use the information in it to populate the | ||
231 | * generic resource object pointed to by @res. | ||
232 | */ | ||
233 | bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, | ||
234 | struct resource *res) | ||
235 | { | ||
236 | struct acpi_resource_extended_address64 *ext_addr; | ||
237 | bool window; | ||
238 | u64 len; | ||
239 | u8 io_decode; | ||
240 | |||
241 | if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64) | ||
242 | return false; | ||
243 | |||
244 | ext_addr = &ares->data.ext_address64; | ||
245 | |||
246 | res->start = ext_addr->minimum; | ||
247 | res->end = ext_addr->maximum; | ||
248 | window = ext_addr->producer_consumer == ACPI_PRODUCER; | ||
249 | |||
250 | switch(ext_addr->resource_type) { | ||
251 | case ACPI_MEMORY_RANGE: | ||
252 | len = ext_addr->maximum - ext_addr->minimum + 1; | ||
253 | res->flags = acpi_dev_memresource_flags(len, | ||
254 | ext_addr->info.mem.write_protect, | ||
255 | window); | ||
256 | break; | ||
257 | case ACPI_IO_RANGE: | ||
258 | io_decode = ext_addr->granularity == 0xfff ? | ||
259 | ACPI_DECODE_10 : ACPI_DECODE_16; | ||
260 | res->flags = acpi_dev_ioresource_flags(ext_addr->minimum, | ||
261 | ext_addr->maximum, | ||
262 | io_decode, window); | ||
263 | break; | ||
264 | case ACPI_BUS_NUMBER_RANGE: | ||
265 | res->flags = IORESOURCE_BUS; | ||
266 | break; | ||
267 | default: | ||
268 | res->flags = 0; | ||
269 | } | ||
270 | |||
271 | return true; | ||
272 | } | ||
273 | EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space); | ||
274 | |||
275 | /** | ||
276 | * acpi_dev_irq_flags - Determine IRQ resource flags. | ||
277 | * @triggering: Triggering type as provided by ACPI. | ||
278 | * @polarity: Interrupt polarity as provided by ACPI. | ||
279 | * @shareable: Whether or not the interrupt is shareable. | ||
280 | */ | ||
281 | unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable) | ||
282 | { | ||
283 | unsigned long flags; | ||
284 | |||
285 | if (triggering == ACPI_LEVEL_SENSITIVE) | ||
286 | flags = polarity == ACPI_ACTIVE_LOW ? | ||
287 | IORESOURCE_IRQ_LOWLEVEL : IORESOURCE_IRQ_HIGHLEVEL; | ||
288 | else | ||
289 | flags = polarity == ACPI_ACTIVE_LOW ? | ||
290 | IORESOURCE_IRQ_LOWEDGE : IORESOURCE_IRQ_HIGHEDGE; | ||
291 | |||
292 | if (shareable == ACPI_SHARED) | ||
293 | flags |= IORESOURCE_IRQ_SHAREABLE; | ||
294 | |||
295 | return flags | IORESOURCE_IRQ; | ||
296 | } | ||
297 | EXPORT_SYMBOL_GPL(acpi_dev_irq_flags); | ||
298 | |||
299 | static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi) | ||
300 | { | ||
301 | res->start = gsi; | ||
302 | res->end = gsi; | ||
303 | res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED; | ||
304 | } | ||
305 | |||
306 | static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, | ||
307 | u8 triggering, u8 polarity, u8 shareable) | ||
308 | { | ||
309 | int irq, p, t; | ||
310 | |||
311 | if (!valid_IRQ(gsi)) { | ||
312 | acpi_dev_irqresource_disabled(res, gsi); | ||
313 | return; | ||
314 | } | ||
315 | |||
316 | /* | ||
317 | * In IO-APIC mode, use overrided attribute. Two reasons: | ||
318 | * 1. BIOS bug in DSDT | ||
319 | * 2. BIOS uses IO-APIC mode Interrupt Source Override | ||
320 | */ | ||
321 | if (!acpi_get_override_irq(gsi, &t, &p)) { | ||
322 | u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; | ||
323 | u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; | ||
324 | |||
325 | if (triggering != trig || polarity != pol) { | ||
326 | pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi, | ||
327 | t ? "edge" : "level", p ? "low" : "high"); | ||
328 | triggering = trig; | ||
329 | polarity = pol; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | res->flags = acpi_dev_irq_flags(triggering, polarity, shareable); | ||
334 | irq = acpi_register_gsi(NULL, gsi, triggering, polarity); | ||
335 | if (irq >= 0) { | ||
336 | res->start = irq; | ||
337 | res->end = irq; | ||
338 | } else { | ||
339 | acpi_dev_irqresource_disabled(res, gsi); | ||
340 | } | ||
341 | } | ||
342 | |||
343 | /** | ||
344 | * acpi_dev_resource_interrupt - Extract ACPI interrupt resource information. | ||
345 | * @ares: Input ACPI resource object. | ||
346 | * @index: Index into the array of GSIs represented by the resource. | ||
347 | * @res: Output generic resource object. | ||
348 | * | ||
349 | * Check if the given ACPI resource object represents an interrupt resource | ||
350 | * and @index does not exceed the resource's interrupt count (true is returned | ||
351 | * in that case regardless of the results of the other checks)). If that's the | ||
352 | * case, register the GSI corresponding to @index from the array of interrupts | ||
353 | * represented by the resource and populate the generic resource object pointed | ||
354 | * to by @res accordingly. If the registration of the GSI is not successful, | ||
355 | * IORESOURCE_DISABLED will be set it that object's flags. | ||
356 | */ | ||
357 | bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, | ||
358 | struct resource *res) | ||
359 | { | ||
360 | struct acpi_resource_irq *irq; | ||
361 | struct acpi_resource_extended_irq *ext_irq; | ||
362 | |||
363 | switch (ares->type) { | ||
364 | case ACPI_RESOURCE_TYPE_IRQ: | ||
365 | /* | ||
366 | * Per spec, only one interrupt per descriptor is allowed in | ||
367 | * _CRS, but some firmware violates this, so parse them all. | ||
368 | */ | ||
369 | irq = &ares->data.irq; | ||
370 | if (index >= irq->interrupt_count) { | ||
371 | acpi_dev_irqresource_disabled(res, 0); | ||
372 | return false; | ||
373 | } | ||
374 | acpi_dev_get_irqresource(res, irq->interrupts[index], | ||
375 | irq->triggering, irq->polarity, | ||
376 | irq->sharable); | ||
377 | break; | ||
378 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | ||
379 | ext_irq = &ares->data.extended_irq; | ||
380 | if (index >= ext_irq->interrupt_count) { | ||
381 | acpi_dev_irqresource_disabled(res, 0); | ||
382 | return false; | ||
383 | } | ||
384 | acpi_dev_get_irqresource(res, ext_irq->interrupts[index], | ||
385 | ext_irq->triggering, ext_irq->polarity, | ||
386 | ext_irq->sharable); | ||
387 | break; | ||
388 | default: | ||
389 | return false; | ||
390 | } | ||
391 | |||
392 | return true; | ||
393 | } | ||
394 | EXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt); | ||
395 | |||
396 | /** | ||
397 | * acpi_dev_free_resource_list - Free resource from %acpi_dev_get_resources(). | ||
398 | * @list: The head of the resource list to free. | ||
399 | */ | ||
400 | void acpi_dev_free_resource_list(struct list_head *list) | ||
401 | { | ||
402 | struct resource_list_entry *rentry, *re; | ||
403 | |||
404 | list_for_each_entry_safe(rentry, re, list, node) { | ||
405 | list_del(&rentry->node); | ||
406 | kfree(rentry); | ||
407 | } | ||
408 | } | ||
409 | EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list); | ||
410 | |||
411 | struct res_proc_context { | ||
412 | struct list_head *list; | ||
413 | int (*preproc)(struct acpi_resource *, void *); | ||
414 | void *preproc_data; | ||
415 | int count; | ||
416 | int error; | ||
417 | }; | ||
418 | |||
419 | static acpi_status acpi_dev_new_resource_entry(struct resource *r, | ||
420 | struct res_proc_context *c) | ||
421 | { | ||
422 | struct resource_list_entry *rentry; | ||
423 | |||
424 | rentry = kmalloc(sizeof(*rentry), GFP_KERNEL); | ||
425 | if (!rentry) { | ||
426 | c->error = -ENOMEM; | ||
427 | return AE_NO_MEMORY; | ||
428 | } | ||
429 | rentry->res = *r; | ||
430 | list_add_tail(&rentry->node, c->list); | ||
431 | c->count++; | ||
432 | return AE_OK; | ||
433 | } | ||
434 | |||
435 | static acpi_status acpi_dev_process_resource(struct acpi_resource *ares, | ||
436 | void *context) | ||
437 | { | ||
438 | struct res_proc_context *c = context; | ||
439 | struct resource r; | ||
440 | int i; | ||
441 | |||
442 | if (c->preproc) { | ||
443 | int ret; | ||
444 | |||
445 | ret = c->preproc(ares, c->preproc_data); | ||
446 | if (ret < 0) { | ||
447 | c->error = ret; | ||
448 | return AE_CTRL_TERMINATE; | ||
449 | } else if (ret > 0) { | ||
450 | return AE_OK; | ||
451 | } | ||
452 | } | ||
453 | |||
454 | memset(&r, 0, sizeof(r)); | ||
455 | |||
456 | if (acpi_dev_resource_memory(ares, &r) | ||
457 | || acpi_dev_resource_io(ares, &r) | ||
458 | || acpi_dev_resource_address_space(ares, &r) | ||
459 | || acpi_dev_resource_ext_address_space(ares, &r)) | ||
460 | return acpi_dev_new_resource_entry(&r, c); | ||
461 | |||
462 | for (i = 0; acpi_dev_resource_interrupt(ares, i, &r); i++) { | ||
463 | acpi_status status; | ||
464 | |||
465 | status = acpi_dev_new_resource_entry(&r, c); | ||
466 | if (ACPI_FAILURE(status)) | ||
467 | return status; | ||
468 | } | ||
469 | |||
470 | return AE_OK; | ||
471 | } | ||
472 | |||
473 | /** | ||
474 | * acpi_dev_get_resources - Get current resources of a device. | ||
475 | * @adev: ACPI device node to get the resources for. | ||
476 | * @list: Head of the resultant list of resources (must be empty). | ||
477 | * @preproc: The caller's preprocessing routine. | ||
478 | * @preproc_data: Pointer passed to the caller's preprocessing routine. | ||
479 | * | ||
480 | * Evaluate the _CRS method for the given device node and process its output by | ||
481 | * (1) executing the @preproc() rountine provided by the caller, passing the | ||
482 | * resource pointer and @preproc_data to it as arguments, for each ACPI resource | ||
483 | * returned and (2) converting all of the returned ACPI resources into struct | ||
484 | * resource objects if possible. If the return value of @preproc() in step (1) | ||
485 | * is different from 0, step (2) is not applied to the given ACPI resource and | ||
486 | * if that value is negative, the whole processing is aborted and that value is | ||
487 | * returned as the final error code. | ||
488 | * | ||
489 | * The resultant struct resource objects are put on the list pointed to by | ||
490 | * @list, that must be empty initially, as members of struct resource_list_entry | ||
491 | * objects. Callers of this routine should use %acpi_dev_free_resource_list() to | ||
492 | * free that list. | ||
493 | * | ||
494 | * The number of resources in the output list is returned on success, an error | ||
495 | * code reflecting the error condition is returned otherwise. | ||
496 | */ | ||
497 | int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list, | ||
498 | int (*preproc)(struct acpi_resource *, void *), | ||
499 | void *preproc_data) | ||
500 | { | ||
501 | struct res_proc_context c; | ||
502 | acpi_handle not_used; | ||
503 | acpi_status status; | ||
504 | |||
505 | if (!adev || !adev->handle || !list_empty(list)) | ||
506 | return -EINVAL; | ||
507 | |||
508 | status = acpi_get_handle(adev->handle, METHOD_NAME__CRS, ¬_used); | ||
509 | if (ACPI_FAILURE(status)) | ||
510 | return 0; | ||
511 | |||
512 | c.list = list; | ||
513 | c.preproc = preproc; | ||
514 | c.preproc_data = preproc_data; | ||
515 | c.count = 0; | ||
516 | c.error = 0; | ||
517 | status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS, | ||
518 | acpi_dev_process_resource, &c); | ||
519 | if (ACPI_FAILURE(status)) { | ||
520 | acpi_dev_free_resource_list(list); | ||
521 | return c.error ? c.error : -EIO; | ||
522 | } | ||
523 | |||
524 | return c.count; | ||
525 | } | ||
526 | EXPORT_SYMBOL_GPL(acpi_dev_get_resources); | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index da1416af0c8b..d59a60736e1c 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -29,6 +29,17 @@ extern struct acpi_device *acpi_root; | |||
29 | 29 | ||
30 | static const char *dummy_hid = "device"; | 30 | static const char *dummy_hid = "device"; |
31 | 31 | ||
32 | /* | ||
33 | * The following ACPI IDs are known to be suitable for representing as | ||
34 | * platform devices. | ||
35 | */ | ||
36 | static const struct acpi_device_id acpi_platform_device_ids[] = { | ||
37 | |||
38 | { "PNP0D40" }, | ||
39 | |||
40 | { } | ||
41 | }; | ||
42 | |||
32 | static LIST_HEAD(acpi_device_list); | 43 | static LIST_HEAD(acpi_device_list); |
33 | static LIST_HEAD(acpi_bus_id_list); | 44 | static LIST_HEAD(acpi_bus_id_list); |
34 | DEFINE_MUTEX(acpi_device_lock); | 45 | DEFINE_MUTEX(acpi_device_lock); |
@@ -340,8 +351,8 @@ static void acpi_device_remove_files(struct acpi_device *dev) | |||
340 | ACPI Bus operations | 351 | ACPI Bus operations |
341 | -------------------------------------------------------------------------- */ | 352 | -------------------------------------------------------------------------- */ |
342 | 353 | ||
343 | int acpi_match_device_ids(struct acpi_device *device, | 354 | static const struct acpi_device_id *__acpi_match_device( |
344 | const struct acpi_device_id *ids) | 355 | struct acpi_device *device, const struct acpi_device_id *ids) |
345 | { | 356 | { |
346 | const struct acpi_device_id *id; | 357 | const struct acpi_device_id *id; |
347 | struct acpi_hardware_id *hwid; | 358 | struct acpi_hardware_id *hwid; |
@@ -351,14 +362,44 @@ int acpi_match_device_ids(struct acpi_device *device, | |||
351 | * driver for it. | 362 | * driver for it. |
352 | */ | 363 | */ |
353 | if (!device->status.present) | 364 | if (!device->status.present) |
354 | return -ENODEV; | 365 | return NULL; |
355 | 366 | ||
356 | for (id = ids; id->id[0]; id++) | 367 | for (id = ids; id->id[0]; id++) |
357 | list_for_each_entry(hwid, &device->pnp.ids, list) | 368 | list_for_each_entry(hwid, &device->pnp.ids, list) |
358 | if (!strcmp((char *) id->id, hwid->id)) | 369 | if (!strcmp((char *) id->id, hwid->id)) |
359 | return 0; | 370 | return id; |
371 | |||
372 | return NULL; | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * acpi_match_device - Match a struct device against a given list of ACPI IDs | ||
377 | * @ids: Array of struct acpi_device_id object to match against. | ||
378 | * @dev: The device structure to match. | ||
379 | * | ||
380 | * Check if @dev has a valid ACPI handle and if there is a struct acpi_device | ||
381 | * object for that handle and use that object to match against a given list of | ||
382 | * device IDs. | ||
383 | * | ||
384 | * Return a pointer to the first matching ID on success or %NULL on failure. | ||
385 | */ | ||
386 | const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids, | ||
387 | const struct device *dev) | ||
388 | { | ||
389 | struct acpi_device *adev; | ||
390 | |||
391 | if (!ids || !ACPI_HANDLE(dev) | ||
392 | || ACPI_FAILURE(acpi_bus_get_device(ACPI_HANDLE(dev), &adev))) | ||
393 | return NULL; | ||
360 | 394 | ||
361 | return -ENOENT; | 395 | return __acpi_match_device(adev, ids); |
396 | } | ||
397 | EXPORT_SYMBOL_GPL(acpi_match_device); | ||
398 | |||
399 | int acpi_match_device_ids(struct acpi_device *device, | ||
400 | const struct acpi_device_id *ids) | ||
401 | { | ||
402 | return __acpi_match_device(device, ids) ? 0 : -ENOENT; | ||
362 | } | 403 | } |
363 | EXPORT_SYMBOL(acpi_match_device_ids); | 404 | EXPORT_SYMBOL(acpi_match_device_ids); |
364 | 405 | ||
@@ -1490,8 +1531,13 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, | |||
1490 | */ | 1531 | */ |
1491 | device = NULL; | 1532 | device = NULL; |
1492 | acpi_bus_get_device(handle, &device); | 1533 | acpi_bus_get_device(handle, &device); |
1493 | if (ops->acpi_op_add && !device) | 1534 | if (ops->acpi_op_add && !device) { |
1494 | acpi_add_single_object(&device, handle, type, sta, ops); | 1535 | acpi_add_single_object(&device, handle, type, sta, ops); |
1536 | /* Is the device a known good platform device? */ | ||
1537 | if (device | ||
1538 | && !acpi_match_device_ids(device, acpi_platform_device_ids)) | ||
1539 | acpi_create_platform_device(device); | ||
1540 | } | ||
1495 | 1541 | ||
1496 | if (!device) | 1542 | if (!device) |
1497 | return AE_CTRL_DEPTH; | 1543 | return AE_CTRL_DEPTH; |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 72c776f2a1f5..b2ee3bcd5a41 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/pm_runtime.h> | 22 | #include <linux/pm_runtime.h> |
23 | #include <linux/idr.h> | 23 | #include <linux/idr.h> |
24 | #include <linux/acpi.h> | ||
24 | 25 | ||
25 | #include "base.h" | 26 | #include "base.h" |
26 | #include "power/power.h" | 27 | #include "power/power.h" |
@@ -436,6 +437,7 @@ struct platform_device *platform_device_register_full( | |||
436 | goto err_alloc; | 437 | goto err_alloc; |
437 | 438 | ||
438 | pdev->dev.parent = pdevinfo->parent; | 439 | pdev->dev.parent = pdevinfo->parent; |
440 | ACPI_HANDLE_SET(&pdev->dev, pdevinfo->acpi_node.handle); | ||
439 | 441 | ||
440 | if (pdevinfo->dma_mask) { | 442 | if (pdevinfo->dma_mask) { |
441 | /* | 443 | /* |
@@ -466,6 +468,7 @@ struct platform_device *platform_device_register_full( | |||
466 | ret = platform_device_add(pdev); | 468 | ret = platform_device_add(pdev); |
467 | if (ret) { | 469 | if (ret) { |
468 | err: | 470 | err: |
471 | ACPI_HANDLE_SET(&pdev->dev, NULL); | ||
469 | kfree(pdev->dev.dma_mask); | 472 | kfree(pdev->dev.dma_mask); |
470 | 473 | ||
471 | err_alloc: | 474 | err_alloc: |
@@ -481,8 +484,16 @@ static int platform_drv_probe(struct device *_dev) | |||
481 | { | 484 | { |
482 | struct platform_driver *drv = to_platform_driver(_dev->driver); | 485 | struct platform_driver *drv = to_platform_driver(_dev->driver); |
483 | struct platform_device *dev = to_platform_device(_dev); | 486 | struct platform_device *dev = to_platform_device(_dev); |
487 | int ret; | ||
484 | 488 | ||
485 | return drv->probe(dev); | 489 | if (ACPI_HANDLE(_dev)) |
490 | acpi_dev_pm_attach(_dev, true); | ||
491 | |||
492 | ret = drv->probe(dev); | ||
493 | if (ret && ACPI_HANDLE(_dev)) | ||
494 | acpi_dev_pm_detach(_dev, true); | ||
495 | |||
496 | return ret; | ||
486 | } | 497 | } |
487 | 498 | ||
488 | static int platform_drv_probe_fail(struct device *_dev) | 499 | static int platform_drv_probe_fail(struct device *_dev) |
@@ -494,8 +505,13 @@ static int platform_drv_remove(struct device *_dev) | |||
494 | { | 505 | { |
495 | struct platform_driver *drv = to_platform_driver(_dev->driver); | 506 | struct platform_driver *drv = to_platform_driver(_dev->driver); |
496 | struct platform_device *dev = to_platform_device(_dev); | 507 | struct platform_device *dev = to_platform_device(_dev); |
508 | int ret; | ||
509 | |||
510 | ret = drv->remove(dev); | ||
511 | if (ACPI_HANDLE(_dev)) | ||
512 | acpi_dev_pm_detach(_dev, true); | ||
497 | 513 | ||
498 | return drv->remove(dev); | 514 | return ret; |
499 | } | 515 | } |
500 | 516 | ||
501 | static void platform_drv_shutdown(struct device *_dev) | 517 | static void platform_drv_shutdown(struct device *_dev) |
@@ -504,6 +520,8 @@ static void platform_drv_shutdown(struct device *_dev) | |||
504 | struct platform_device *dev = to_platform_device(_dev); | 520 | struct platform_device *dev = to_platform_device(_dev); |
505 | 521 | ||
506 | drv->shutdown(dev); | 522 | drv->shutdown(dev); |
523 | if (ACPI_HANDLE(_dev)) | ||
524 | acpi_dev_pm_detach(_dev, true); | ||
507 | } | 525 | } |
508 | 526 | ||
509 | /** | 527 | /** |
@@ -709,6 +727,10 @@ static int platform_match(struct device *dev, struct device_driver *drv) | |||
709 | if (of_driver_match_device(dev, drv)) | 727 | if (of_driver_match_device(dev, drv)) |
710 | return 1; | 728 | return 1; |
711 | 729 | ||
730 | /* Then try ACPI style match */ | ||
731 | if (acpi_driver_match_device(dev, drv)) | ||
732 | return 1; | ||
733 | |||
712 | /* Then try to match against the id table */ | 734 | /* Then try to match against the id table */ |
713 | if (pdrv->id_table) | 735 | if (pdrv->id_table) |
714 | return platform_match_id(pdrv->id_table, pdev) != NULL; | 736 | return platform_match_id(pdrv->id_table, pdev) != NULL; |
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index a7edf987a339..e388590b44ab 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/irqflags.h> | 39 | #include <linux/irqflags.h> |
40 | #include <linux/rwsem.h> | 40 | #include <linux/rwsem.h> |
41 | #include <linux/pm_runtime.h> | 41 | #include <linux/pm_runtime.h> |
42 | #include <linux/acpi.h> | ||
42 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
43 | 44 | ||
44 | #include "i2c-core.h" | 45 | #include "i2c-core.h" |
@@ -78,6 +79,10 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv) | |||
78 | if (of_driver_match_device(dev, drv)) | 79 | if (of_driver_match_device(dev, drv)) |
79 | return 1; | 80 | return 1; |
80 | 81 | ||
82 | /* Then ACPI style match */ | ||
83 | if (acpi_driver_match_device(dev, drv)) | ||
84 | return 1; | ||
85 | |||
81 | driver = to_i2c_driver(drv); | 86 | driver = to_i2c_driver(drv); |
82 | /* match on an id table if there is one */ | 87 | /* match on an id table if there is one */ |
83 | if (driver->id_table) | 88 | if (driver->id_table) |
@@ -539,6 +544,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) | |||
539 | client->dev.bus = &i2c_bus_type; | 544 | client->dev.bus = &i2c_bus_type; |
540 | client->dev.type = &i2c_client_type; | 545 | client->dev.type = &i2c_client_type; |
541 | client->dev.of_node = info->of_node; | 546 | client->dev.of_node = info->of_node; |
547 | ACPI_HANDLE_SET(&client->dev, info->acpi_node.handle); | ||
542 | 548 | ||
543 | /* For 10-bit clients, add an arbitrary offset to avoid collisions */ | 549 | /* For 10-bit clients, add an arbitrary offset to avoid collisions */ |
544 | dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), | 550 | dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 9bf10e7bbfaf..56eac101c013 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -81,6 +81,18 @@ config MMC_RICOH_MMC | |||
81 | 81 | ||
82 | If unsure, say Y. | 82 | If unsure, say Y. |
83 | 83 | ||
84 | config MMC_SDHCI_ACPI | ||
85 | tristate "SDHCI support for ACPI enumerated SDHCI controllers" | ||
86 | depends on MMC_SDHCI && ACPI | ||
87 | help | ||
88 | This selects support for ACPI enumerated SDHCI controllers, | ||
89 | identified by ACPI Compatibility ID PNP0D40 or specific | ||
90 | ACPI Hardware IDs. | ||
91 | |||
92 | If you have a controller with this interface, say Y or M here. | ||
93 | |||
94 | If unsure, say N. | ||
95 | |||
84 | config MMC_SDHCI_PLTFM | 96 | config MMC_SDHCI_PLTFM |
85 | tristate "SDHCI platform and OF driver helper" | 97 | tristate "SDHCI platform and OF driver helper" |
86 | depends on MMC_SDHCI | 98 | depends on MMC_SDHCI |
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 17ad0a7ba40b..0e4960a107de 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_MMC_MXS) += mxs-mmc.o | |||
9 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o | 9 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o |
10 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o | 10 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o |
11 | obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-data.o | 11 | obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-data.o |
12 | obj-$(CONFIG_MMC_SDHCI_ACPI) += sdhci-acpi.o | ||
12 | obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o | 13 | obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o |
13 | obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o | 14 | obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o |
14 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o | 15 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o |
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c new file mode 100644 index 000000000000..6ac361744d36 --- /dev/null +++ b/drivers/mmc/host/sdhci-acpi.c | |||
@@ -0,0 +1,304 @@ | |||
1 | /* | ||
2 | * Secure Digital Host Controller Interface ACPI driver. | ||
3 | * | ||
4 | * Copyright (c) 2012, Intel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/init.h> | ||
22 | #include <linux/export.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/device.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/ioport.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/dma-mapping.h> | ||
29 | #include <linux/compiler.h> | ||
30 | #include <linux/stddef.h> | ||
31 | #include <linux/bitops.h> | ||
32 | #include <linux/types.h> | ||
33 | #include <linux/err.h> | ||
34 | #include <linux/interrupt.h> | ||
35 | #include <linux/acpi.h> | ||
36 | #include <linux/pm.h> | ||
37 | #include <linux/pm_runtime.h> | ||
38 | |||
39 | #include <linux/mmc/host.h> | ||
40 | #include <linux/mmc/pm.h> | ||
41 | #include <linux/mmc/sdhci.h> | ||
42 | |||
43 | #include "sdhci.h" | ||
44 | |||
45 | enum { | ||
46 | SDHCI_ACPI_SD_CD = BIT(0), | ||
47 | SDHCI_ACPI_RUNTIME_PM = BIT(1), | ||
48 | }; | ||
49 | |||
50 | struct sdhci_acpi_chip { | ||
51 | const struct sdhci_ops *ops; | ||
52 | unsigned int quirks; | ||
53 | unsigned int quirks2; | ||
54 | unsigned long caps; | ||
55 | unsigned int caps2; | ||
56 | mmc_pm_flag_t pm_caps; | ||
57 | }; | ||
58 | |||
59 | struct sdhci_acpi_slot { | ||
60 | const struct sdhci_acpi_chip *chip; | ||
61 | unsigned int quirks; | ||
62 | unsigned int quirks2; | ||
63 | unsigned long caps; | ||
64 | unsigned int caps2; | ||
65 | mmc_pm_flag_t pm_caps; | ||
66 | unsigned int flags; | ||
67 | }; | ||
68 | |||
69 | struct sdhci_acpi_host { | ||
70 | struct sdhci_host *host; | ||
71 | const struct sdhci_acpi_slot *slot; | ||
72 | struct platform_device *pdev; | ||
73 | bool use_runtime_pm; | ||
74 | }; | ||
75 | |||
76 | static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag) | ||
77 | { | ||
78 | return c->slot && (c->slot->flags & flag); | ||
79 | } | ||
80 | |||
81 | static int sdhci_acpi_enable_dma(struct sdhci_host *host) | ||
82 | { | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static const struct sdhci_ops sdhci_acpi_ops_dflt = { | ||
87 | .enable_dma = sdhci_acpi_enable_dma, | ||
88 | }; | ||
89 | |||
90 | static const struct acpi_device_id sdhci_acpi_ids[] = { | ||
91 | { "PNP0D40" }, | ||
92 | { }, | ||
93 | }; | ||
94 | MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids); | ||
95 | |||
96 | static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid) | ||
97 | { | ||
98 | const struct acpi_device_id *id; | ||
99 | |||
100 | for (id = sdhci_acpi_ids; id->id[0]; id++) | ||
101 | if (!strcmp(id->id, hid)) | ||
102 | return (const struct sdhci_acpi_slot *)id->driver_data; | ||
103 | return NULL; | ||
104 | } | ||
105 | |||
106 | static int __devinit sdhci_acpi_probe(struct platform_device *pdev) | ||
107 | { | ||
108 | struct device *dev = &pdev->dev; | ||
109 | acpi_handle handle = ACPI_HANDLE(dev); | ||
110 | struct acpi_device *device; | ||
111 | struct sdhci_acpi_host *c; | ||
112 | struct sdhci_host *host; | ||
113 | struct resource *iomem; | ||
114 | resource_size_t len; | ||
115 | const char *hid; | ||
116 | int err; | ||
117 | |||
118 | if (acpi_bus_get_device(handle, &device)) | ||
119 | return -ENODEV; | ||
120 | |||
121 | if (acpi_bus_get_status(device) || !device->status.present) | ||
122 | return -ENODEV; | ||
123 | |||
124 | hid = acpi_device_hid(device); | ||
125 | |||
126 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
127 | if (!iomem) | ||
128 | return -ENOMEM; | ||
129 | |||
130 | len = resource_size(iomem); | ||
131 | if (len < 0x100) | ||
132 | dev_err(dev, "Invalid iomem size!\n"); | ||
133 | |||
134 | if (!devm_request_mem_region(dev, iomem->start, len, dev_name(dev))) | ||
135 | return -ENOMEM; | ||
136 | |||
137 | host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host)); | ||
138 | if (IS_ERR(host)) | ||
139 | return PTR_ERR(host); | ||
140 | |||
141 | c = sdhci_priv(host); | ||
142 | c->host = host; | ||
143 | c->slot = sdhci_acpi_get_slot(hid); | ||
144 | c->pdev = pdev; | ||
145 | c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM); | ||
146 | |||
147 | platform_set_drvdata(pdev, c); | ||
148 | |||
149 | host->hw_name = "ACPI"; | ||
150 | host->ops = &sdhci_acpi_ops_dflt; | ||
151 | host->irq = platform_get_irq(pdev, 0); | ||
152 | |||
153 | host->ioaddr = devm_ioremap_nocache(dev, iomem->start, | ||
154 | resource_size(iomem)); | ||
155 | if (host->ioaddr == NULL) { | ||
156 | err = -ENOMEM; | ||
157 | goto err_free; | ||
158 | } | ||
159 | |||
160 | if (!dev->dma_mask) { | ||
161 | u64 dma_mask; | ||
162 | |||
163 | if (sdhci_readl(host, SDHCI_CAPABILITIES) & SDHCI_CAN_64BIT) { | ||
164 | /* 64-bit DMA is not supported at present */ | ||
165 | dma_mask = DMA_BIT_MASK(32); | ||
166 | } else { | ||
167 | dma_mask = DMA_BIT_MASK(32); | ||
168 | } | ||
169 | |||
170 | dev->dma_mask = &dev->coherent_dma_mask; | ||
171 | dev->coherent_dma_mask = dma_mask; | ||
172 | } | ||
173 | |||
174 | if (c->slot) { | ||
175 | if (c->slot->chip) { | ||
176 | host->ops = c->slot->chip->ops; | ||
177 | host->quirks |= c->slot->chip->quirks; | ||
178 | host->quirks2 |= c->slot->chip->quirks2; | ||
179 | host->mmc->caps |= c->slot->chip->caps; | ||
180 | host->mmc->caps2 |= c->slot->chip->caps2; | ||
181 | host->mmc->pm_caps |= c->slot->chip->pm_caps; | ||
182 | } | ||
183 | host->quirks |= c->slot->quirks; | ||
184 | host->quirks2 |= c->slot->quirks2; | ||
185 | host->mmc->caps |= c->slot->caps; | ||
186 | host->mmc->caps2 |= c->slot->caps2; | ||
187 | host->mmc->pm_caps |= c->slot->pm_caps; | ||
188 | } | ||
189 | |||
190 | err = sdhci_add_host(host); | ||
191 | if (err) | ||
192 | goto err_free; | ||
193 | |||
194 | if (c->use_runtime_pm) { | ||
195 | pm_suspend_ignore_children(dev, 1); | ||
196 | pm_runtime_set_autosuspend_delay(dev, 50); | ||
197 | pm_runtime_use_autosuspend(dev); | ||
198 | pm_runtime_enable(dev); | ||
199 | } | ||
200 | |||
201 | return 0; | ||
202 | |||
203 | err_free: | ||
204 | platform_set_drvdata(pdev, NULL); | ||
205 | sdhci_free_host(c->host); | ||
206 | return err; | ||
207 | } | ||
208 | |||
209 | static int __devexit sdhci_acpi_remove(struct platform_device *pdev) | ||
210 | { | ||
211 | struct sdhci_acpi_host *c = platform_get_drvdata(pdev); | ||
212 | struct device *dev = &pdev->dev; | ||
213 | int dead; | ||
214 | |||
215 | if (c->use_runtime_pm) { | ||
216 | pm_runtime_get_sync(dev); | ||
217 | pm_runtime_disable(dev); | ||
218 | pm_runtime_put_noidle(dev); | ||
219 | } | ||
220 | |||
221 | dead = (sdhci_readl(c->host, SDHCI_INT_STATUS) == ~0); | ||
222 | sdhci_remove_host(c->host, dead); | ||
223 | platform_set_drvdata(pdev, NULL); | ||
224 | sdhci_free_host(c->host); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | #ifdef CONFIG_PM_SLEEP | ||
230 | |||
231 | static int sdhci_acpi_suspend(struct device *dev) | ||
232 | { | ||
233 | struct sdhci_acpi_host *c = dev_get_drvdata(dev); | ||
234 | |||
235 | return sdhci_suspend_host(c->host); | ||
236 | } | ||
237 | |||
238 | static int sdhci_acpi_resume(struct device *dev) | ||
239 | { | ||
240 | struct sdhci_acpi_host *c = dev_get_drvdata(dev); | ||
241 | |||
242 | return sdhci_resume_host(c->host); | ||
243 | } | ||
244 | |||
245 | #else | ||
246 | |||
247 | #define sdhci_acpi_suspend NULL | ||
248 | #define sdhci_acpi_resume NULL | ||
249 | |||
250 | #endif | ||
251 | |||
252 | #ifdef CONFIG_PM_RUNTIME | ||
253 | |||
254 | static int sdhci_acpi_runtime_suspend(struct device *dev) | ||
255 | { | ||
256 | struct sdhci_acpi_host *c = dev_get_drvdata(dev); | ||
257 | |||
258 | return sdhci_runtime_suspend_host(c->host); | ||
259 | } | ||
260 | |||
261 | static int sdhci_acpi_runtime_resume(struct device *dev) | ||
262 | { | ||
263 | struct sdhci_acpi_host *c = dev_get_drvdata(dev); | ||
264 | |||
265 | return sdhci_runtime_resume_host(c->host); | ||
266 | } | ||
267 | |||
268 | static int sdhci_acpi_runtime_idle(struct device *dev) | ||
269 | { | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | #else | ||
274 | |||
275 | #define sdhci_acpi_runtime_suspend NULL | ||
276 | #define sdhci_acpi_runtime_resume NULL | ||
277 | #define sdhci_acpi_runtime_idle NULL | ||
278 | |||
279 | #endif | ||
280 | |||
281 | static const struct dev_pm_ops sdhci_acpi_pm_ops = { | ||
282 | .suspend = sdhci_acpi_suspend, | ||
283 | .resume = sdhci_acpi_resume, | ||
284 | .runtime_suspend = sdhci_acpi_runtime_suspend, | ||
285 | .runtime_resume = sdhci_acpi_runtime_resume, | ||
286 | .runtime_idle = sdhci_acpi_runtime_idle, | ||
287 | }; | ||
288 | |||
289 | static struct platform_driver sdhci_acpi_driver = { | ||
290 | .driver = { | ||
291 | .name = "sdhci-acpi", | ||
292 | .owner = THIS_MODULE, | ||
293 | .acpi_match_table = sdhci_acpi_ids, | ||
294 | .pm = &sdhci_acpi_pm_ops, | ||
295 | }, | ||
296 | .probe = sdhci_acpi_probe, | ||
297 | .remove = __devexit_p(sdhci_acpi_remove), | ||
298 | }; | ||
299 | |||
300 | module_platform_driver(sdhci_acpi_driver); | ||
301 | |||
302 | MODULE_DESCRIPTION("Secure Digital Host Controller Interface ACPI driver"); | ||
303 | MODULE_AUTHOR("Adrian Hunter"); | ||
304 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index fa4e0a5db3f8..ffd53e3eb92f 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h | |||
@@ -159,6 +159,8 @@ struct pnp_resource { | |||
159 | 159 | ||
160 | void pnp_free_resource(struct pnp_resource *pnp_res); | 160 | void pnp_free_resource(struct pnp_resource *pnp_res); |
161 | 161 | ||
162 | struct pnp_resource *pnp_add_resource(struct pnp_dev *dev, | ||
163 | struct resource *res); | ||
162 | struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, | 164 | struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, |
163 | int flags); | 165 | int flags); |
164 | struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma, | 166 | struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma, |
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 26b5d4b18dd7..653d5637a37c 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c | |||
@@ -242,6 +242,10 @@ static int __init pnpacpi_add_device(struct acpi_device *device) | |||
242 | char *pnpid; | 242 | char *pnpid; |
243 | struct acpi_hardware_id *id; | 243 | struct acpi_hardware_id *id; |
244 | 244 | ||
245 | /* Skip devices that are already bound */ | ||
246 | if (device->physical_node_count) | ||
247 | return 0; | ||
248 | |||
245 | /* | 249 | /* |
246 | * If a PnPacpi device is not present , the device | 250 | * If a PnPacpi device is not present , the device |
247 | * driver should not be loaded. | 251 | * driver should not be loaded. |
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 5be4a392a3ae..b8f4ea7b27fc 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
@@ -28,37 +28,6 @@ | |||
28 | #include "../base.h" | 28 | #include "../base.h" |
29 | #include "pnpacpi.h" | 29 | #include "pnpacpi.h" |
30 | 30 | ||
31 | #ifdef CONFIG_IA64 | ||
32 | #define valid_IRQ(i) (1) | ||
33 | #else | ||
34 | #define valid_IRQ(i) (((i) != 0) && ((i) != 2)) | ||
35 | #endif | ||
36 | |||
37 | /* | ||
38 | * Allocated Resources | ||
39 | */ | ||
40 | static int irq_flags(int triggering, int polarity, int shareable) | ||
41 | { | ||
42 | int flags; | ||
43 | |||
44 | if (triggering == ACPI_LEVEL_SENSITIVE) { | ||
45 | if (polarity == ACPI_ACTIVE_LOW) | ||
46 | flags = IORESOURCE_IRQ_LOWLEVEL; | ||
47 | else | ||
48 | flags = IORESOURCE_IRQ_HIGHLEVEL; | ||
49 | } else { | ||
50 | if (polarity == ACPI_ACTIVE_LOW) | ||
51 | flags = IORESOURCE_IRQ_LOWEDGE; | ||
52 | else | ||
53 | flags = IORESOURCE_IRQ_HIGHEDGE; | ||
54 | } | ||
55 | |||
56 | if (shareable == ACPI_SHARED) | ||
57 | flags |= IORESOURCE_IRQ_SHAREABLE; | ||
58 | |||
59 | return flags; | ||
60 | } | ||
61 | |||
62 | static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering, | 31 | static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering, |
63 | int *polarity, int *shareable) | 32 | int *polarity, int *shareable) |
64 | { | 33 | { |
@@ -94,45 +63,6 @@ static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering, | |||
94 | *shareable = ACPI_EXCLUSIVE; | 63 | *shareable = ACPI_EXCLUSIVE; |
95 | } | 64 | } |
96 | 65 | ||
97 | static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, | ||
98 | u32 gsi, int triggering, | ||
99 | int polarity, int shareable) | ||
100 | { | ||
101 | int irq, flags; | ||
102 | int p, t; | ||
103 | |||
104 | if (!valid_IRQ(gsi)) { | ||
105 | pnp_add_irq_resource(dev, gsi, IORESOURCE_DISABLED); | ||
106 | return; | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * in IO-APIC mode, use overrided attribute. Two reasons: | ||
111 | * 1. BIOS bug in DSDT | ||
112 | * 2. BIOS uses IO-APIC mode Interrupt Source Override | ||
113 | */ | ||
114 | if (!acpi_get_override_irq(gsi, &t, &p)) { | ||
115 | t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; | ||
116 | p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; | ||
117 | |||
118 | if (triggering != t || polarity != p) { | ||
119 | dev_warn(&dev->dev, "IRQ %d override to %s, %s\n", | ||
120 | gsi, t ? "edge":"level", p ? "low":"high"); | ||
121 | triggering = t; | ||
122 | polarity = p; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | flags = irq_flags(triggering, polarity, shareable); | ||
127 | irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity); | ||
128 | if (irq >= 0) | ||
129 | pcibios_penalize_isa_irq(irq, 1); | ||
130 | else | ||
131 | flags |= IORESOURCE_DISABLED; | ||
132 | |||
133 | pnp_add_irq_resource(dev, irq, flags); | ||
134 | } | ||
135 | |||
136 | static int dma_flags(struct pnp_dev *dev, int type, int bus_master, | 66 | static int dma_flags(struct pnp_dev *dev, int type, int bus_master, |
137 | int transfer) | 67 | int transfer) |
138 | { | 68 | { |
@@ -177,21 +107,16 @@ static int dma_flags(struct pnp_dev *dev, int type, int bus_master, | |||
177 | return flags; | 107 | return flags; |
178 | } | 108 | } |
179 | 109 | ||
180 | static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start, | 110 | /* |
181 | u64 len, int io_decode, | 111 | * Allocated Resources |
182 | int window) | 112 | */ |
183 | { | ||
184 | int flags = 0; | ||
185 | u64 end = start + len - 1; | ||
186 | 113 | ||
187 | if (io_decode == ACPI_DECODE_16) | 114 | static void pnpacpi_add_irqresource(struct pnp_dev *dev, struct resource *r) |
188 | flags |= IORESOURCE_IO_16BIT_ADDR; | 115 | { |
189 | if (len == 0 || end >= 0x10003) | 116 | if (!(r->flags & IORESOURCE_DISABLED)) |
190 | flags |= IORESOURCE_DISABLED; | 117 | pcibios_penalize_isa_irq(r->start, 1); |
191 | if (window) | ||
192 | flags |= IORESOURCE_WINDOW; | ||
193 | 118 | ||
194 | pnp_add_io_resource(dev, start, end, flags); | 119 | pnp_add_resource(dev, r); |
195 | } | 120 | } |
196 | 121 | ||
197 | /* | 122 | /* |
@@ -249,130 +174,49 @@ static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev, | |||
249 | } | 174 | } |
250 | } | 175 | } |
251 | 176 | ||
252 | static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev, | ||
253 | u64 start, u64 len, | ||
254 | int write_protect, int window) | ||
255 | { | ||
256 | int flags = 0; | ||
257 | u64 end = start + len - 1; | ||
258 | |||
259 | if (len == 0) | ||
260 | flags |= IORESOURCE_DISABLED; | ||
261 | if (write_protect == ACPI_READ_WRITE_MEMORY) | ||
262 | flags |= IORESOURCE_MEM_WRITEABLE; | ||
263 | if (window) | ||
264 | flags |= IORESOURCE_WINDOW; | ||
265 | |||
266 | pnp_add_mem_resource(dev, start, end, flags); | ||
267 | } | ||
268 | |||
269 | static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev, | ||
270 | u64 start, u64 len) | ||
271 | { | ||
272 | u64 end = start + len - 1; | ||
273 | |||
274 | pnp_add_bus_resource(dev, start, end); | ||
275 | } | ||
276 | |||
277 | static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev, | ||
278 | struct acpi_resource *res) | ||
279 | { | ||
280 | struct acpi_resource_address64 addr, *p = &addr; | ||
281 | acpi_status status; | ||
282 | int window; | ||
283 | u64 len; | ||
284 | |||
285 | status = acpi_resource_to_address64(res, p); | ||
286 | if (!ACPI_SUCCESS(status)) { | ||
287 | dev_warn(&dev->dev, "failed to convert resource type %d\n", | ||
288 | res->type); | ||
289 | return; | ||
290 | } | ||
291 | |||
292 | /* Windows apparently computes length rather than using _LEN */ | ||
293 | len = p->maximum - p->minimum + 1; | ||
294 | window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0; | ||
295 | |||
296 | if (p->resource_type == ACPI_MEMORY_RANGE) | ||
297 | pnpacpi_parse_allocated_memresource(dev, p->minimum, len, | ||
298 | p->info.mem.write_protect, window); | ||
299 | else if (p->resource_type == ACPI_IO_RANGE) | ||
300 | pnpacpi_parse_allocated_ioresource(dev, p->minimum, len, | ||
301 | p->granularity == 0xfff ? ACPI_DECODE_10 : | ||
302 | ACPI_DECODE_16, window); | ||
303 | else if (p->resource_type == ACPI_BUS_NUMBER_RANGE) | ||
304 | pnpacpi_parse_allocated_busresource(dev, p->minimum, len); | ||
305 | } | ||
306 | |||
307 | static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev, | ||
308 | struct acpi_resource *res) | ||
309 | { | ||
310 | struct acpi_resource_extended_address64 *p = &res->data.ext_address64; | ||
311 | int window; | ||
312 | u64 len; | ||
313 | |||
314 | /* Windows apparently computes length rather than using _LEN */ | ||
315 | len = p->maximum - p->minimum + 1; | ||
316 | window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0; | ||
317 | |||
318 | if (p->resource_type == ACPI_MEMORY_RANGE) | ||
319 | pnpacpi_parse_allocated_memresource(dev, p->minimum, len, | ||
320 | p->info.mem.write_protect, window); | ||
321 | else if (p->resource_type == ACPI_IO_RANGE) | ||
322 | pnpacpi_parse_allocated_ioresource(dev, p->minimum, len, | ||
323 | p->granularity == 0xfff ? ACPI_DECODE_10 : | ||
324 | ACPI_DECODE_16, window); | ||
325 | else if (p->resource_type == ACPI_BUS_NUMBER_RANGE) | ||
326 | pnpacpi_parse_allocated_busresource(dev, p->minimum, len); | ||
327 | } | ||
328 | |||
329 | static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | 177 | static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, |
330 | void *data) | 178 | void *data) |
331 | { | 179 | { |
332 | struct pnp_dev *dev = data; | 180 | struct pnp_dev *dev = data; |
333 | struct acpi_resource_irq *irq; | ||
334 | struct acpi_resource_dma *dma; | 181 | struct acpi_resource_dma *dma; |
335 | struct acpi_resource_io *io; | ||
336 | struct acpi_resource_fixed_io *fixed_io; | ||
337 | struct acpi_resource_vendor_typed *vendor_typed; | 182 | struct acpi_resource_vendor_typed *vendor_typed; |
338 | struct acpi_resource_memory24 *memory24; | 183 | struct resource r; |
339 | struct acpi_resource_memory32 *memory32; | ||
340 | struct acpi_resource_fixed_memory32 *fixed_memory32; | ||
341 | struct acpi_resource_extended_irq *extended_irq; | ||
342 | int i, flags; | 184 | int i, flags; |
343 | 185 | ||
344 | switch (res->type) { | 186 | if (acpi_dev_resource_memory(res, &r) |
345 | case ACPI_RESOURCE_TYPE_IRQ: | 187 | || acpi_dev_resource_io(res, &r) |
346 | /* | 188 | || acpi_dev_resource_address_space(res, &r) |
347 | * Per spec, only one interrupt per descriptor is allowed in | 189 | || acpi_dev_resource_ext_address_space(res, &r)) { |
348 | * _CRS, but some firmware violates this, so parse them all. | 190 | pnp_add_resource(dev, &r); |
349 | */ | 191 | return AE_OK; |
350 | irq = &res->data.irq; | 192 | } |
351 | if (irq->interrupt_count == 0) | ||
352 | pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED); | ||
353 | else { | ||
354 | for (i = 0; i < irq->interrupt_count; i++) { | ||
355 | pnpacpi_parse_allocated_irqresource(dev, | ||
356 | irq->interrupts[i], | ||
357 | irq->triggering, | ||
358 | irq->polarity, | ||
359 | irq->sharable); | ||
360 | } | ||
361 | 193 | ||
194 | r.flags = 0; | ||
195 | if (acpi_dev_resource_interrupt(res, 0, &r)) { | ||
196 | pnpacpi_add_irqresource(dev, &r); | ||
197 | for (i = 1; acpi_dev_resource_interrupt(res, i, &r); i++) | ||
198 | pnpacpi_add_irqresource(dev, &r); | ||
199 | |||
200 | if (i > 1) { | ||
362 | /* | 201 | /* |
363 | * The IRQ encoder puts a single interrupt in each | 202 | * The IRQ encoder puts a single interrupt in each |
364 | * descriptor, so if a _CRS descriptor has more than | 203 | * descriptor, so if a _CRS descriptor has more than |
365 | * one interrupt, we won't be able to re-encode it. | 204 | * one interrupt, we won't be able to re-encode it. |
366 | */ | 205 | */ |
367 | if (pnp_can_write(dev) && irq->interrupt_count > 1) { | 206 | if (pnp_can_write(dev)) { |
368 | dev_warn(&dev->dev, "multiple interrupts in " | 207 | dev_warn(&dev->dev, "multiple interrupts in " |
369 | "_CRS descriptor; configuration can't " | 208 | "_CRS descriptor; configuration can't " |
370 | "be changed\n"); | 209 | "be changed\n"); |
371 | dev->capabilities &= ~PNP_WRITE; | 210 | dev->capabilities &= ~PNP_WRITE; |
372 | } | 211 | } |
373 | } | 212 | } |
374 | break; | 213 | return AE_OK; |
214 | } else if (r.flags & IORESOURCE_DISABLED) { | ||
215 | pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED); | ||
216 | return AE_OK; | ||
217 | } | ||
375 | 218 | ||
219 | switch (res->type) { | ||
376 | case ACPI_RESOURCE_TYPE_DMA: | 220 | case ACPI_RESOURCE_TYPE_DMA: |
377 | dma = &res->data.dma; | 221 | dma = &res->data.dma; |
378 | if (dma->channel_count > 0 && dma->channels[0] != (u8) -1) | 222 | if (dma->channel_count > 0 && dma->channels[0] != (u8) -1) |
@@ -383,26 +227,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
383 | pnp_add_dma_resource(dev, dma->channels[0], flags); | 227 | pnp_add_dma_resource(dev, dma->channels[0], flags); |
384 | break; | 228 | break; |
385 | 229 | ||
386 | case ACPI_RESOURCE_TYPE_IO: | ||
387 | io = &res->data.io; | ||
388 | pnpacpi_parse_allocated_ioresource(dev, | ||
389 | io->minimum, | ||
390 | io->address_length, | ||
391 | io->io_decode, 0); | ||
392 | break; | ||
393 | |||
394 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: | 230 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: |
395 | case ACPI_RESOURCE_TYPE_END_DEPENDENT: | 231 | case ACPI_RESOURCE_TYPE_END_DEPENDENT: |
396 | break; | 232 | break; |
397 | 233 | ||
398 | case ACPI_RESOURCE_TYPE_FIXED_IO: | ||
399 | fixed_io = &res->data.fixed_io; | ||
400 | pnpacpi_parse_allocated_ioresource(dev, | ||
401 | fixed_io->address, | ||
402 | fixed_io->address_length, | ||
403 | ACPI_DECODE_10, 0); | ||
404 | break; | ||
405 | |||
406 | case ACPI_RESOURCE_TYPE_VENDOR: | 234 | case ACPI_RESOURCE_TYPE_VENDOR: |
407 | vendor_typed = &res->data.vendor_typed; | 235 | vendor_typed = &res->data.vendor_typed; |
408 | pnpacpi_parse_allocated_vendor(dev, vendor_typed); | 236 | pnpacpi_parse_allocated_vendor(dev, vendor_typed); |
@@ -411,66 +239,6 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
411 | case ACPI_RESOURCE_TYPE_END_TAG: | 239 | case ACPI_RESOURCE_TYPE_END_TAG: |
412 | break; | 240 | break; |
413 | 241 | ||
414 | case ACPI_RESOURCE_TYPE_MEMORY24: | ||
415 | memory24 = &res->data.memory24; | ||
416 | pnpacpi_parse_allocated_memresource(dev, | ||
417 | memory24->minimum, | ||
418 | memory24->address_length, | ||
419 | memory24->write_protect, 0); | ||
420 | break; | ||
421 | case ACPI_RESOURCE_TYPE_MEMORY32: | ||
422 | memory32 = &res->data.memory32; | ||
423 | pnpacpi_parse_allocated_memresource(dev, | ||
424 | memory32->minimum, | ||
425 | memory32->address_length, | ||
426 | memory32->write_protect, 0); | ||
427 | break; | ||
428 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: | ||
429 | fixed_memory32 = &res->data.fixed_memory32; | ||
430 | pnpacpi_parse_allocated_memresource(dev, | ||
431 | fixed_memory32->address, | ||
432 | fixed_memory32->address_length, | ||
433 | fixed_memory32->write_protect, 0); | ||
434 | break; | ||
435 | case ACPI_RESOURCE_TYPE_ADDRESS16: | ||
436 | case ACPI_RESOURCE_TYPE_ADDRESS32: | ||
437 | case ACPI_RESOURCE_TYPE_ADDRESS64: | ||
438 | pnpacpi_parse_allocated_address_space(dev, res); | ||
439 | break; | ||
440 | |||
441 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: | ||
442 | pnpacpi_parse_allocated_ext_address_space(dev, res); | ||
443 | break; | ||
444 | |||
445 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | ||
446 | extended_irq = &res->data.extended_irq; | ||
447 | |||
448 | if (extended_irq->interrupt_count == 0) | ||
449 | pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED); | ||
450 | else { | ||
451 | for (i = 0; i < extended_irq->interrupt_count; i++) { | ||
452 | pnpacpi_parse_allocated_irqresource(dev, | ||
453 | extended_irq->interrupts[i], | ||
454 | extended_irq->triggering, | ||
455 | extended_irq->polarity, | ||
456 | extended_irq->sharable); | ||
457 | } | ||
458 | |||
459 | /* | ||
460 | * The IRQ encoder puts a single interrupt in each | ||
461 | * descriptor, so if a _CRS descriptor has more than | ||
462 | * one interrupt, we won't be able to re-encode it. | ||
463 | */ | ||
464 | if (pnp_can_write(dev) && | ||
465 | extended_irq->interrupt_count > 1) { | ||
466 | dev_warn(&dev->dev, "multiple interrupts in " | ||
467 | "_CRS descriptor; configuration can't " | ||
468 | "be changed\n"); | ||
469 | dev->capabilities &= ~PNP_WRITE; | ||
470 | } | ||
471 | } | ||
472 | break; | ||
473 | |||
474 | case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: | 242 | case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: |
475 | break; | 243 | break; |
476 | 244 | ||
@@ -531,7 +299,7 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev, | |||
531 | if (p->interrupts[i]) | 299 | if (p->interrupts[i]) |
532 | __set_bit(p->interrupts[i], map.bits); | 300 | __set_bit(p->interrupts[i], map.bits); |
533 | 301 | ||
534 | flags = irq_flags(p->triggering, p->polarity, p->sharable); | 302 | flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable); |
535 | pnp_register_irq_resource(dev, option_flags, &map, flags); | 303 | pnp_register_irq_resource(dev, option_flags, &map, flags); |
536 | } | 304 | } |
537 | 305 | ||
@@ -555,7 +323,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev, | |||
555 | } | 323 | } |
556 | } | 324 | } |
557 | 325 | ||
558 | flags = irq_flags(p->triggering, p->polarity, p->sharable); | 326 | flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable); |
559 | pnp_register_irq_resource(dev, option_flags, &map, flags); | 327 | pnp_register_irq_resource(dev, option_flags, &map, flags); |
560 | } | 328 | } |
561 | 329 | ||
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index b0ecacbe53b1..3e6db1c1dc29 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c | |||
@@ -503,6 +503,22 @@ static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev) | |||
503 | return pnp_res; | 503 | return pnp_res; |
504 | } | 504 | } |
505 | 505 | ||
506 | struct pnp_resource *pnp_add_resource(struct pnp_dev *dev, | ||
507 | struct resource *res) | ||
508 | { | ||
509 | struct pnp_resource *pnp_res; | ||
510 | |||
511 | pnp_res = pnp_new_resource(dev); | ||
512 | if (!pnp_res) { | ||
513 | dev_err(&dev->dev, "can't add resource %pR\n", res); | ||
514 | return NULL; | ||
515 | } | ||
516 | |||
517 | pnp_res->res = *res; | ||
518 | dev_dbg(&dev->dev, "%pR\n", res); | ||
519 | return pnp_res; | ||
520 | } | ||
521 | |||
506 | struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, | 522 | struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, |
507 | int flags) | 523 | int flags) |
508 | { | 524 | { |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index c3bc4511e0c0..c4ed4c2389c7 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -412,7 +412,7 @@ acpi_handle acpi_get_child(acpi_handle, u64); | |||
412 | int acpi_is_root_bridge(acpi_handle); | 412 | int acpi_is_root_bridge(acpi_handle); |
413 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); | 413 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); |
414 | struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); | 414 | struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); |
415 | #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) | 415 | #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)ACPI_HANDLE(dev)) |
416 | 416 | ||
417 | int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); | 417 | int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); |
418 | int acpi_disable_wakeup_device_power(struct acpi_device *dev); | 418 | int acpi_disable_wakeup_device_power(struct acpi_device *dev); |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 28ba643c92c1..3574e4a2bf14 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
29 | #include <linux/ioport.h> /* for struct resource */ | 29 | #include <linux/ioport.h> /* for struct resource */ |
30 | #include <linux/device.h> | ||
30 | 31 | ||
31 | #ifdef CONFIG_ACPI | 32 | #ifdef CONFIG_ACPI |
32 | 33 | ||
@@ -251,6 +252,26 @@ extern int pnpacpi_disabled; | |||
251 | 252 | ||
252 | #define PXM_INVAL (-1) | 253 | #define PXM_INVAL (-1) |
253 | 254 | ||
255 | bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res); | ||
256 | bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res); | ||
257 | bool acpi_dev_resource_address_space(struct acpi_resource *ares, | ||
258 | struct resource *res); | ||
259 | bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, | ||
260 | struct resource *res); | ||
261 | unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable); | ||
262 | bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, | ||
263 | struct resource *res); | ||
264 | |||
265 | struct resource_list_entry { | ||
266 | struct list_head node; | ||
267 | struct resource res; | ||
268 | }; | ||
269 | |||
270 | void acpi_dev_free_resource_list(struct list_head *list); | ||
271 | int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list, | ||
272 | int (*preproc)(struct acpi_resource *, void *), | ||
273 | void *preproc_data); | ||
274 | |||
254 | int acpi_check_resource_conflict(const struct resource *res); | 275 | int acpi_check_resource_conflict(const struct resource *res); |
255 | 276 | ||
256 | int acpi_check_region(resource_size_t start, resource_size_t n, | 277 | int acpi_check_region(resource_size_t start, resource_size_t n, |
@@ -365,6 +386,17 @@ extern int acpi_nvs_register(__u64 start, __u64 size); | |||
365 | extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *), | 386 | extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *), |
366 | void *data); | 387 | void *data); |
367 | 388 | ||
389 | const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids, | ||
390 | const struct device *dev); | ||
391 | |||
392 | static inline bool acpi_driver_match_device(struct device *dev, | ||
393 | const struct device_driver *drv) | ||
394 | { | ||
395 | return !!acpi_match_device(drv->acpi_match_table, dev); | ||
396 | } | ||
397 | |||
398 | #define ACPI_PTR(_ptr) (_ptr) | ||
399 | |||
368 | #else /* !CONFIG_ACPI */ | 400 | #else /* !CONFIG_ACPI */ |
369 | 401 | ||
370 | #define acpi_disabled 1 | 402 | #define acpi_disabled 1 |
@@ -419,6 +451,22 @@ static inline int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *), | |||
419 | return 0; | 451 | return 0; |
420 | } | 452 | } |
421 | 453 | ||
454 | struct acpi_device_id; | ||
455 | |||
456 | static inline const struct acpi_device_id *acpi_match_device( | ||
457 | const struct acpi_device_id *ids, const struct device *dev) | ||
458 | { | ||
459 | return NULL; | ||
460 | } | ||
461 | |||
462 | static inline bool acpi_driver_match_device(struct device *dev, | ||
463 | const struct device_driver *drv) | ||
464 | { | ||
465 | return false; | ||
466 | } | ||
467 | |||
468 | #define ACPI_PTR(_ptr) (NULL) | ||
469 | |||
422 | #endif /* !CONFIG_ACPI */ | 470 | #endif /* !CONFIG_ACPI */ |
423 | 471 | ||
424 | #ifdef CONFIG_ACPI | 472 | #ifdef CONFIG_ACPI |
diff --git a/include/linux/device.h b/include/linux/device.h index 86ef6ab553b1..05292e488346 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -190,6 +190,7 @@ extern struct klist *bus_get_device_klist(struct bus_type *bus); | |||
190 | * @mod_name: Used for built-in modules. | 190 | * @mod_name: Used for built-in modules. |
191 | * @suppress_bind_attrs: Disables bind/unbind via sysfs. | 191 | * @suppress_bind_attrs: Disables bind/unbind via sysfs. |
192 | * @of_match_table: The open firmware table. | 192 | * @of_match_table: The open firmware table. |
193 | * @acpi_match_table: The ACPI match table. | ||
193 | * @probe: Called to query the existence of a specific device, | 194 | * @probe: Called to query the existence of a specific device, |
194 | * whether this driver can work with it, and bind the driver | 195 | * whether this driver can work with it, and bind the driver |
195 | * to a specific device. | 196 | * to a specific device. |
@@ -223,6 +224,7 @@ struct device_driver { | |||
223 | bool suppress_bind_attrs; /* disables bind/unbind via sysfs */ | 224 | bool suppress_bind_attrs; /* disables bind/unbind via sysfs */ |
224 | 225 | ||
225 | const struct of_device_id *of_match_table; | 226 | const struct of_device_id *of_match_table; |
227 | const struct acpi_device_id *acpi_match_table; | ||
226 | 228 | ||
227 | int (*probe) (struct device *dev); | 229 | int (*probe) (struct device *dev); |
228 | int (*remove) (struct device *dev); | 230 | int (*remove) (struct device *dev); |
@@ -576,6 +578,12 @@ struct device_dma_parameters { | |||
576 | unsigned long segment_boundary_mask; | 578 | unsigned long segment_boundary_mask; |
577 | }; | 579 | }; |
578 | 580 | ||
581 | struct acpi_dev_node { | ||
582 | #ifdef CONFIG_ACPI | ||
583 | void *handle; | ||
584 | #endif | ||
585 | }; | ||
586 | |||
579 | /** | 587 | /** |
580 | * struct device - The basic device structure | 588 | * struct device - The basic device structure |
581 | * @parent: The device's "parent" device, the device to which it is attached. | 589 | * @parent: The device's "parent" device, the device to which it is attached. |
@@ -616,6 +624,7 @@ struct device_dma_parameters { | |||
616 | * @dma_mem: Internal for coherent mem override. | 624 | * @dma_mem: Internal for coherent mem override. |
617 | * @archdata: For arch-specific additions. | 625 | * @archdata: For arch-specific additions. |
618 | * @of_node: Associated device tree node. | 626 | * @of_node: Associated device tree node. |
627 | * @acpi_node: Associated ACPI device node. | ||
619 | * @devt: For creating the sysfs "dev". | 628 | * @devt: For creating the sysfs "dev". |
620 | * @id: device instance | 629 | * @id: device instance |
621 | * @devres_lock: Spinlock to protect the resource of the device. | 630 | * @devres_lock: Spinlock to protect the resource of the device. |
@@ -680,6 +689,7 @@ struct device { | |||
680 | struct dev_archdata archdata; | 689 | struct dev_archdata archdata; |
681 | 690 | ||
682 | struct device_node *of_node; /* associated device tree node */ | 691 | struct device_node *of_node; /* associated device tree node */ |
692 | struct acpi_dev_node acpi_node; /* associated ACPI device node */ | ||
683 | 693 | ||
684 | dev_t devt; /* dev_t, creates the sysfs "dev" */ | 694 | dev_t devt; /* dev_t, creates the sysfs "dev" */ |
685 | u32 id; /* device instance */ | 695 | u32 id; /* device instance */ |
@@ -700,6 +710,14 @@ static inline struct device *kobj_to_dev(struct kobject *kobj) | |||
700 | return container_of(kobj, struct device, kobj); | 710 | return container_of(kobj, struct device, kobj); |
701 | } | 711 | } |
702 | 712 | ||
713 | #ifdef CONFIG_ACPI | ||
714 | #define ACPI_HANDLE(dev) ((dev)->acpi_node.handle) | ||
715 | #define ACPI_HANDLE_SET(dev, _handle_) (dev)->acpi_node.handle = (_handle_) | ||
716 | #else | ||
717 | #define ACPI_HANDLE(dev) (NULL) | ||
718 | #define ACPI_HANDLE_SET(dev, _handle_) do { } while (0) | ||
719 | #endif | ||
720 | |||
703 | /* Get the wakeup routines, which depend on struct device */ | 721 | /* Get the wakeup routines, which depend on struct device */ |
704 | #include <linux/pm_wakeup.h> | 722 | #include <linux/pm_wakeup.h> |
705 | 723 | ||
diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 800de224336b..d0c4db7b4872 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h | |||
@@ -259,6 +259,7 @@ static inline void i2c_set_clientdata(struct i2c_client *dev, void *data) | |||
259 | * @platform_data: stored in i2c_client.dev.platform_data | 259 | * @platform_data: stored in i2c_client.dev.platform_data |
260 | * @archdata: copied into i2c_client.dev.archdata | 260 | * @archdata: copied into i2c_client.dev.archdata |
261 | * @of_node: pointer to OpenFirmware device node | 261 | * @of_node: pointer to OpenFirmware device node |
262 | * @acpi_node: ACPI device node | ||
262 | * @irq: stored in i2c_client.irq | 263 | * @irq: stored in i2c_client.irq |
263 | * | 264 | * |
264 | * I2C doesn't actually support hardware probing, although controllers and | 265 | * I2C doesn't actually support hardware probing, although controllers and |
@@ -279,6 +280,7 @@ struct i2c_board_info { | |||
279 | void *platform_data; | 280 | void *platform_data; |
280 | struct dev_archdata *archdata; | 281 | struct dev_archdata *archdata; |
281 | struct device_node *of_node; | 282 | struct device_node *of_node; |
283 | struct acpi_dev_node acpi_node; | ||
282 | int irq; | 284 | int irq; |
283 | }; | 285 | }; |
284 | 286 | ||
@@ -501,4 +503,11 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap) | |||
501 | i2c_del_driver) | 503 | i2c_del_driver) |
502 | 504 | ||
503 | #endif /* I2C */ | 505 | #endif /* I2C */ |
506 | |||
507 | #if IS_ENABLED(CONFIG_ACPI_I2C) | ||
508 | extern void acpi_i2c_register_devices(struct i2c_adapter *adap); | ||
509 | #else | ||
510 | static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {} | ||
511 | #endif | ||
512 | |||
504 | #endif /* _LINUX_I2C_H */ | 513 | #endif /* _LINUX_I2C_H */ |
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 5711e9525a2a..a9ded9a3c175 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h | |||
@@ -55,6 +55,7 @@ extern int platform_add_devices(struct platform_device **, int); | |||
55 | 55 | ||
56 | struct platform_device_info { | 56 | struct platform_device_info { |
57 | struct device *parent; | 57 | struct device *parent; |
58 | struct acpi_dev_node acpi_node; | ||
58 | 59 | ||
59 | const char *name; | 60 | const char *name; |
60 | int id; | 61 | int id; |