aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorLan Tianyu <tianyu.lan@intel.com>2014-05-20 08:59:24 -0400
committerWolfram Sang <wsa@the-dreams.de>2014-06-27 08:50:41 -0400
commitda3c6647ee08711c7edc28d7fea4ad69fc5ffcca (patch)
tree47272da395818ecc9101b27b01808b8cf11f9b35 /drivers/i2c
parent5d98e61d337c181f199a6cb864569cc4e116ef4c (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/Kconfig18
-rw-r--r--drivers/i2c/Makefile2
-rw-r--r--drivers/i2c/i2c-acpi.c89
-rw-r--r--drivers/i2c/i2c-core.c95
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
5menuconfig I2C 5menu "I2C support"
6
7config 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
26config 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
24if I2C 38if I2C
25 39
26config I2C_BOARDINFO 40config I2C_BOARDINFO
@@ -124,3 +138,5 @@ config I2C_DEBUG_BUS
124 on. 138 on.
125 139
126endif # I2C 140endif # I2C
141
142endmenu
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
5i2ccore-y := i2c-core.o 5i2ccore-y := i2c-core.o
6i2ccore-$(CONFIG_ACPI) += i2c-acpi.o 6i2ccore-$(CONFIG_I2C_ACPI) += i2c-acpi.o
7 7
8obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o 8obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o
9obj-$(CONFIG_I2C) += i2ccore.o 9obj-$(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
40static 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
64static 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 */
110void 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
40static int acpi_gsb_i2c_read_bytes(struct i2c_client *client, 129static 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);
1092static void of_i2c_register_devices(struct i2c_adapter *adap) { } 1092static 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)
1098static 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
1122static 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 */
1168static 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
1187static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {}
1188#endif /* CONFIG_ACPI */
1189
1190static int i2c_do_add_adapter(struct i2c_driver *driver, 1095static int i2c_do_add_adapter(struct i2c_driver *driver,
1191 struct i2c_adapter *adap) 1096 struct i2c_adapter *adap)
1192{ 1097{