diff options
author | Lan Tianyu <tianyu.lan@intel.com> | 2014-05-20 08:59:24 -0400 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2014-06-27 08:50:41 -0400 |
commit | da3c6647ee08711c7edc28d7fea4ad69fc5ffcca (patch) | |
tree | 47272da395818ecc9101b27b01808b8cf11f9b35 /drivers/i2c | |
parent | 5d98e61d337c181f199a6cb864569cc4e116ef4c (diff) |
I2C/ACPI: Clean up I2C ACPI code and Add CONFIG_I2C_ACPI config
Clean up ACPI related code in the i2c core and add CONFIG_I2C_ACPI
to enable I2C ACPI code.
Current there is a race between removing I2C ACPI operation region
and ACPI AML code accessing. So make i2c core built-in if CONFIG_I2C_ACPI
is set.
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Lan Tianyu <tianyu.lan@intel.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/Kconfig | 18 | ||||
-rw-r--r-- | drivers/i2c/Makefile | 2 | ||||
-rw-r--r-- | drivers/i2c/i2c-acpi.c | 89 | ||||
-rw-r--r-- | drivers/i2c/i2c-core.c | 95 |
4 files changed, 107 insertions, 97 deletions
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 7b7ea320a258..3e3b680dc007 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig | |||
@@ -2,7 +2,9 @@ | |||
2 | # I2C subsystem configuration | 2 | # I2C subsystem configuration |
3 | # | 3 | # |
4 | 4 | ||
5 | menuconfig I2C | 5 | menu "I2C support" |
6 | |||
7 | config I2C | ||
6 | tristate "I2C support" | 8 | tristate "I2C support" |
7 | select RT_MUTEXES | 9 | select RT_MUTEXES |
8 | ---help--- | 10 | ---help--- |
@@ -21,6 +23,18 @@ menuconfig I2C | |||
21 | This I2C support can also be built as a module. If so, the module | 23 | This I2C support can also be built as a module. If so, the module |
22 | will be called i2c-core. | 24 | will be called i2c-core. |
23 | 25 | ||
26 | config I2C_ACPI | ||
27 | bool "I2C ACPI support" | ||
28 | select I2C | ||
29 | depends on ACPI | ||
30 | default y | ||
31 | help | ||
32 | Say Y here if you want to enable ACPI I2C support. This includes support | ||
33 | for automatic enumeration of I2C slave devices and support for ACPI I2C | ||
34 | Operation Regions. Operation Regions allow firmware (BIOS) code to | ||
35 | access I2C slave devices, such as smart batteries through an I2C host | ||
36 | controller driver. | ||
37 | |||
24 | if I2C | 38 | if I2C |
25 | 39 | ||
26 | config I2C_BOARDINFO | 40 | config I2C_BOARDINFO |
@@ -124,3 +138,5 @@ config I2C_DEBUG_BUS | |||
124 | on. | 138 | on. |
125 | 139 | ||
126 | endif # I2C | 140 | endif # I2C |
141 | |||
142 | endmenu | ||
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 80db3073aa84..a1f590cbb435 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | i2ccore-y := i2c-core.o | 5 | i2ccore-y := i2c-core.o |
6 | i2ccore-$(CONFIG_ACPI) += i2c-acpi.o | 6 | i2ccore-$(CONFIG_I2C_ACPI) += i2c-acpi.o |
7 | 7 | ||
8 | obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o | 8 | obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o |
9 | obj-$(CONFIG_I2C) += i2ccore.o | 9 | obj-$(CONFIG_I2C) += i2ccore.o |
diff --git a/drivers/i2c/i2c-acpi.c b/drivers/i2c/i2c-acpi.c index f7f4c89c09b3..e8b61967334b 100644 --- a/drivers/i2c/i2c-acpi.c +++ b/drivers/i2c/i2c-acpi.c | |||
@@ -37,6 +37,95 @@ struct gsb_buffer { | |||
37 | }; | 37 | }; |
38 | } __packed; | 38 | } __packed; |
39 | 39 | ||
40 | static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) | ||
41 | { | ||
42 | struct i2c_board_info *info = data; | ||
43 | |||
44 | if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { | ||
45 | struct acpi_resource_i2c_serialbus *sb; | ||
46 | |||
47 | sb = &ares->data.i2c_serial_bus; | ||
48 | if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { | ||
49 | info->addr = sb->slave_address; | ||
50 | if (sb->access_mode == ACPI_I2C_10BIT_MODE) | ||
51 | info->flags |= I2C_CLIENT_TEN; | ||
52 | } | ||
53 | } else if (info->irq < 0) { | ||
54 | struct resource r; | ||
55 | |||
56 | if (acpi_dev_resource_interrupt(ares, 0, &r)) | ||
57 | info->irq = r.start; | ||
58 | } | ||
59 | |||
60 | /* Tell the ACPI core to skip this resource */ | ||
61 | return 1; | ||
62 | } | ||
63 | |||
64 | static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, | ||
65 | void *data, void **return_value) | ||
66 | { | ||
67 | struct i2c_adapter *adapter = data; | ||
68 | struct list_head resource_list; | ||
69 | struct i2c_board_info info; | ||
70 | struct acpi_device *adev; | ||
71 | int ret; | ||
72 | |||
73 | if (acpi_bus_get_device(handle, &adev)) | ||
74 | return AE_OK; | ||
75 | if (acpi_bus_get_status(adev) || !adev->status.present) | ||
76 | return AE_OK; | ||
77 | |||
78 | memset(&info, 0, sizeof(info)); | ||
79 | info.acpi_node.companion = adev; | ||
80 | info.irq = -1; | ||
81 | |||
82 | INIT_LIST_HEAD(&resource_list); | ||
83 | ret = acpi_dev_get_resources(adev, &resource_list, | ||
84 | acpi_i2c_add_resource, &info); | ||
85 | acpi_dev_free_resource_list(&resource_list); | ||
86 | |||
87 | if (ret < 0 || !info.addr) | ||
88 | return AE_OK; | ||
89 | |||
90 | adev->power.flags.ignore_parent = true; | ||
91 | strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); | ||
92 | if (!i2c_new_device(adapter, &info)) { | ||
93 | adev->power.flags.ignore_parent = false; | ||
94 | dev_err(&adapter->dev, | ||
95 | "failed to add I2C device %s from ACPI\n", | ||
96 | dev_name(&adev->dev)); | ||
97 | } | ||
98 | |||
99 | return AE_OK; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter | ||
104 | * @adap: pointer to adapter | ||
105 | * | ||
106 | * Enumerate all I2C slave devices behind this adapter by walking the ACPI | ||
107 | * namespace. When a device is found it will be added to the Linux device | ||
108 | * model and bound to the corresponding ACPI handle. | ||
109 | */ | ||
110 | void acpi_i2c_register_devices(struct i2c_adapter *adap) | ||
111 | { | ||
112 | acpi_handle handle; | ||
113 | acpi_status status; | ||
114 | |||
115 | if (!adap->dev.parent) | ||
116 | return; | ||
117 | |||
118 | handle = ACPI_HANDLE(adap->dev.parent); | ||
119 | if (!handle) | ||
120 | return; | ||
121 | |||
122 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, | ||
123 | acpi_i2c_add_device, NULL, | ||
124 | adap, NULL); | ||
125 | if (ACPI_FAILURE(status)) | ||
126 | dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); | ||
127 | } | ||
128 | |||
40 | static int acpi_gsb_i2c_read_bytes(struct i2c_client *client, | 129 | static int acpi_gsb_i2c_read_bytes(struct i2c_client *client, |
41 | u8 cmd, u8 *data, u8 data_len) | 130 | u8 cmd, u8 *data, u8 data_len) |
42 | { | 131 | { |
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index e25cb84cb297..4ccff114b147 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -1092,101 +1092,6 @@ EXPORT_SYMBOL(of_find_i2c_adapter_by_node); | |||
1092 | static void of_i2c_register_devices(struct i2c_adapter *adap) { } | 1092 | static void of_i2c_register_devices(struct i2c_adapter *adap) { } |
1093 | #endif /* CONFIG_OF */ | 1093 | #endif /* CONFIG_OF */ |
1094 | 1094 | ||
1095 | /* ACPI support code */ | ||
1096 | |||
1097 | #if IS_ENABLED(CONFIG_ACPI) | ||
1098 | static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) | ||
1099 | { | ||
1100 | struct i2c_board_info *info = data; | ||
1101 | |||
1102 | if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { | ||
1103 | struct acpi_resource_i2c_serialbus *sb; | ||
1104 | |||
1105 | sb = &ares->data.i2c_serial_bus; | ||
1106 | if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { | ||
1107 | info->addr = sb->slave_address; | ||
1108 | if (sb->access_mode == ACPI_I2C_10BIT_MODE) | ||
1109 | info->flags |= I2C_CLIENT_TEN; | ||
1110 | } | ||
1111 | } else if (info->irq < 0) { | ||
1112 | struct resource r; | ||
1113 | |||
1114 | if (acpi_dev_resource_interrupt(ares, 0, &r)) | ||
1115 | info->irq = r.start; | ||
1116 | } | ||
1117 | |||
1118 | /* Tell the ACPI core to skip this resource */ | ||
1119 | return 1; | ||
1120 | } | ||
1121 | |||
1122 | static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, | ||
1123 | void *data, void **return_value) | ||
1124 | { | ||
1125 | struct i2c_adapter *adapter = data; | ||
1126 | struct list_head resource_list; | ||
1127 | struct i2c_board_info info; | ||
1128 | struct acpi_device *adev; | ||
1129 | int ret; | ||
1130 | |||
1131 | if (acpi_bus_get_device(handle, &adev)) | ||
1132 | return AE_OK; | ||
1133 | if (acpi_bus_get_status(adev) || !adev->status.present) | ||
1134 | return AE_OK; | ||
1135 | |||
1136 | memset(&info, 0, sizeof(info)); | ||
1137 | info.acpi_node.companion = adev; | ||
1138 | info.irq = -1; | ||
1139 | |||
1140 | INIT_LIST_HEAD(&resource_list); | ||
1141 | ret = acpi_dev_get_resources(adev, &resource_list, | ||
1142 | acpi_i2c_add_resource, &info); | ||
1143 | acpi_dev_free_resource_list(&resource_list); | ||
1144 | |||
1145 | if (ret < 0 || !info.addr) | ||
1146 | return AE_OK; | ||
1147 | |||
1148 | adev->power.flags.ignore_parent = true; | ||
1149 | strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); | ||
1150 | if (!i2c_new_device(adapter, &info)) { | ||
1151 | adev->power.flags.ignore_parent = false; | ||
1152 | dev_err(&adapter->dev, | ||
1153 | "failed to add I2C device %s from ACPI\n", | ||
1154 | dev_name(&adev->dev)); | ||
1155 | } | ||
1156 | |||
1157 | return AE_OK; | ||
1158 | } | ||
1159 | |||
1160 | /** | ||
1161 | * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter | ||
1162 | * @adap: pointer to adapter | ||
1163 | * | ||
1164 | * Enumerate all I2C slave devices behind this adapter by walking the ACPI | ||
1165 | * namespace. When a device is found it will be added to the Linux device | ||
1166 | * model and bound to the corresponding ACPI handle. | ||
1167 | */ | ||
1168 | static void acpi_i2c_register_devices(struct i2c_adapter *adap) | ||
1169 | { | ||
1170 | acpi_handle handle; | ||
1171 | acpi_status status; | ||
1172 | |||
1173 | if (!adap->dev.parent) | ||
1174 | return; | ||
1175 | |||
1176 | handle = ACPI_HANDLE(adap->dev.parent); | ||
1177 | if (!handle) | ||
1178 | return; | ||
1179 | |||
1180 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, | ||
1181 | acpi_i2c_add_device, NULL, | ||
1182 | adap, NULL); | ||
1183 | if (ACPI_FAILURE(status)) | ||
1184 | dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); | ||
1185 | } | ||
1186 | #else | ||
1187 | static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {} | ||
1188 | #endif /* CONFIG_ACPI */ | ||
1189 | |||
1190 | static int i2c_do_add_adapter(struct i2c_driver *driver, | 1095 | static int i2c_do_add_adapter(struct i2c_driver *driver, |
1191 | struct i2c_adapter *adap) | 1096 | struct i2c_adapter *adap) |
1192 | { | 1097 | { |