aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorJarkko Nikula <jarkko.nikula@linux.intel.com>2016-06-06 07:26:22 -0400
committerWolfram Sang <wsa@the-dreams.de>2016-07-14 09:25:10 -0400
commit55d38d060e999ca1a3ea6eb132105a0301e4cd04 (patch)
treedb0d07a56dd5af1d74943232e8c53c7a0fb5555d /drivers/i2c
parenta7003b65801e17a19617a509b2dbae3442ddd709 (diff)
i2c: core: Add function for finding the bus speed from ACPI
ACPI 5 specification doesn't have property for the I2C bus speed but I2cSerialBus resource descriptors which define each controller-slave connection define the maximum speed supported by that connection. Thus finding the maximum safe speed for the bus is to walk all I2cSerialBus resources that are associated to I2C controller and use the speed of slowest connection. Add function i2c_acpi_find_bus_speed() to the i2c-core that adapter drivers can call prior registering itself to core. This implies two-step walk through the I2cSerialBus resources: call to i2c_acpi_find_bus_speed() does the first scan and finds the safe bus speed that adapter drivers can set up. Adapter driver registration does the second scan when i2c-core creates the I2C slaves by calling the i2c_acpi_register_devices(). In that way the bus speed is set in case slave device probe gets called during registration and does communication. Implement this by reusing the existing ACPI I2C walk routines in the i2c-core. Extend them so that slowest connection speed is saved during the walk and I2C slaves are registered only when calling through the i2c_acpi_register_devices() with the i2c_adapter pointer. Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/i2c-core.c74
1 files changed, 59 insertions, 15 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index abe41369eec1..347494a8750e 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -105,11 +105,13 @@ struct gsb_buffer {
105 105
106struct i2c_acpi_lookup { 106struct i2c_acpi_lookup {
107 struct i2c_board_info *info; 107 struct i2c_board_info *info;
108 struct i2c_adapter *adapter; /* set only when registering slaves */
108 acpi_handle adapter_handle; 109 acpi_handle adapter_handle;
109 acpi_handle device_handle; 110 acpi_handle device_handle;
111 u32 min_speed;
110}; 112};
111 113
112static int i2c_acpi_find_address(struct acpi_resource *ares, void *data) 114static int i2c_acpi_find_resource(struct acpi_resource *ares, void *data)
113{ 115{
114 struct i2c_acpi_lookup *lookup = data; 116 struct i2c_acpi_lookup *lookup = data;
115 struct i2c_board_info *info = lookup->info; 117 struct i2c_board_info *info = lookup->info;
@@ -135,17 +137,20 @@ static int i2c_acpi_find_address(struct acpi_resource *ares, void *data)
135 info->addr = sb->slave_address; 137 info->addr = sb->slave_address;
136 if (sb->access_mode == ACPI_I2C_10BIT_MODE) 138 if (sb->access_mode == ACPI_I2C_10BIT_MODE)
137 info->flags |= I2C_CLIENT_TEN; 139 info->flags |= I2C_CLIENT_TEN;
140 /* Save speed of the slowest device */
141 if (sb->connection_speed < lookup->min_speed)
142 lookup->min_speed = sb->connection_speed;
138 } 143 }
139 144
140 return 1; 145 return 1;
141} 146}
142 147
143static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level, 148static acpi_status i2c_acpi_slave_lookup(acpi_handle handle, u32 level,
144 void *data, void **return_value) 149 void *data, void **return_value)
145{ 150{
146 struct i2c_adapter *adapter = data; 151 struct i2c_acpi_lookup *lookup = data;
152 struct i2c_adapter *adapter = lookup->adapter;
147 struct list_head resource_list; 153 struct list_head resource_list;
148 struct i2c_acpi_lookup lookup;
149 struct resource_entry *entry; 154 struct resource_entry *entry;
150 struct i2c_board_info info; 155 struct i2c_board_info info;
151 struct acpi_device *adev; 156 struct acpi_device *adev;
@@ -159,10 +164,8 @@ static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level,
159 memset(&info, 0, sizeof(info)); 164 memset(&info, 0, sizeof(info));
160 info.fwnode = acpi_fwnode_handle(adev); 165 info.fwnode = acpi_fwnode_handle(adev);
161 166
162 memset(&lookup, 0, sizeof(lookup)); 167 lookup->device_handle = handle;
163 lookup.adapter_handle = ACPI_HANDLE(&adapter->dev); 168 lookup->info = &info;
164 lookup.device_handle = handle;
165 lookup.info = &info;
166 169
167 /* 170 /*
168 * Look up for I2cSerialBus resource with ResourceSource that 171 * Look up for I2cSerialBus resource with ResourceSource that
@@ -170,10 +173,10 @@ static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level,
170 */ 173 */
171 INIT_LIST_HEAD(&resource_list); 174 INIT_LIST_HEAD(&resource_list);
172 ret = acpi_dev_get_resources(adev, &resource_list, 175 ret = acpi_dev_get_resources(adev, &resource_list,
173 i2c_acpi_find_address, &lookup); 176 i2c_acpi_find_resource, lookup);
174 acpi_dev_free_resource_list(&resource_list); 177 acpi_dev_free_resource_list(&resource_list);
175 178
176 if (ret < 0 || !info.addr) 179 if (ret < 0 || !info.addr || !lookup->adapter)
177 return AE_OK; 180 return AE_OK;
178 181
179 /* Then fill IRQ number if any */ 182 /* Then fill IRQ number if any */
@@ -204,6 +207,14 @@ static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level,
204 207
205#define I2C_ACPI_MAX_SCAN_DEPTH 32 208#define I2C_ACPI_MAX_SCAN_DEPTH 32
206 209
210static acpi_status i2c_acpi_walk(struct i2c_acpi_lookup *lookup)
211{
212 return acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
213 I2C_ACPI_MAX_SCAN_DEPTH,
214 i2c_acpi_slave_lookup, NULL,
215 lookup, NULL);
216}
217
207/** 218/**
208 * i2c_acpi_register_devices - enumerate I2C slave devices behind adapter 219 * i2c_acpi_register_devices - enumerate I2C slave devices behind adapter
209 * @adap: pointer to adapter 220 * @adap: pointer to adapter
@@ -214,19 +225,52 @@ static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level,
214 */ 225 */
215static void i2c_acpi_register_devices(struct i2c_adapter *adap) 226static void i2c_acpi_register_devices(struct i2c_adapter *adap)
216{ 227{
228 struct i2c_acpi_lookup lookup;
217 acpi_status status; 229 acpi_status status;
218 230
219 if (!has_acpi_companion(&adap->dev)) 231 if (!has_acpi_companion(&adap->dev))
220 return; 232 return;
221 233
222 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 234 memset(&lookup, 0, sizeof(lookup));
223 I2C_ACPI_MAX_SCAN_DEPTH, 235 lookup.adapter = adap;
224 i2c_acpi_add_device, NULL, 236 lookup.adapter_handle = ACPI_HANDLE(&adap->dev);
225 adap, NULL); 237
238 status = i2c_acpi_walk(&lookup);
226 if (ACPI_FAILURE(status)) 239 if (ACPI_FAILURE(status))
227 dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); 240 dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
228} 241}
229 242
243/**
244 * i2c_acpi_find_bus_speed - find I2C bus speed from ACPI
245 * @dev: The device owning the bus
246 *
247 * Find the I2C bus speed by walking the ACPI namespace for all I2C slaves
248 * devices connected to this bus and use the speed of slowest device.
249 *
250 * Returns the speed in Hz or zero
251 */
252u32 i2c_acpi_find_bus_speed(struct device *dev)
253{
254 struct i2c_acpi_lookup lookup;
255 acpi_status status;
256
257 if (!has_acpi_companion(dev))
258 return 0;
259
260 memset(&lookup, 0, sizeof(lookup));
261 lookup.adapter_handle = ACPI_HANDLE(dev);
262 lookup.min_speed = UINT_MAX;
263
264 status = i2c_acpi_walk(&lookup);
265 if (ACPI_FAILURE(status)) {
266 dev_warn(dev, "unable to find I2C bus speed from ACPI\n");
267 return 0;
268 }
269
270 return lookup.min_speed != UINT_MAX ? lookup.min_speed : 0;
271}
272EXPORT_SYMBOL_GPL(i2c_acpi_find_bus_speed);
273
230#else /* CONFIG_ACPI */ 274#else /* CONFIG_ACPI */
231static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { } 275static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { }
232#endif /* CONFIG_ACPI */ 276#endif /* CONFIG_ACPI */