aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/i2c-core.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-11-10 14:58:25 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-10 14:58:25 -0500
commitd55fc37856244c929965c190c8e9dcb49e2c07aa (patch)
treeccb348340a6f0aac546b06487ea6a1d1d35490f6 /drivers/i2c/i2c-core.c
parent42d4ebb42a17754d2e8344dc1aa486119671d0eb (diff)
parent75ecc64ef5a1f310fc80f732ad8cfb7e1bdc59d5 (diff)
Merge branch 'i2c/for-4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang: - New drivers: UniPhier (with and without FIFO) - some drivers got some bigger rework: ismt, designware, img-scb (rcar had to be reverted because issues were showing up just lately) - ACPI: reworked the device scanning and added support for muxes ... and quite a lot of driver bugfixes and cleanups this time. All files touched outside of the i2c realm have proper acks. * 'i2c/for-4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (70 commits) i2c: rcar: Revert the latest refactoring series i2c: pnx: remove superfluous assignment MAINTAINERS: i2c: drop i2c-pnx maintainer MAINTAINERS: i2c: mark also subdirectories as maintained i2c: cadence: enable driver for ARM64 i2c: i801: Document Intel DNV and Broxton i2c: at91: manage unexpected RXRDY flag when starting a transfer i2c: pnx: Use setup_timer instead of open coding it i2c: add ACPI support for I2C mux ports acpi: add acpi_preset_companion() stub i2c: pxa: Add support for pxa910/988 & new configuration features i2c: au1550: Convert to devm_kzalloc and devm_ioremap_resource i2c-dev: Fix I2C_SLAVE ioctl comment i2c-dev: Fix typo in ioctl name reference i2c: sirf: tune the divider to make i2c bus freq more accurate i2c: imx: Use -ENXIO as error in the NACK case i2c: i801: Add support for Intel Broxton i2c: i801: Add support for Intel DNV i2c: mediatek: add i2c resume support i2c: imx: implement bus recovery ...
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r--drivers/i2c/i2c-core.c82
1 files changed, 59 insertions, 23 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index a59c3111f7fb..040af5cc8143 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -99,27 +99,40 @@ struct gsb_buffer {
99 }; 99 };
100} __packed; 100} __packed;
101 101
102static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) 102struct acpi_i2c_lookup {
103 struct i2c_board_info *info;
104 acpi_handle adapter_handle;
105 acpi_handle device_handle;
106};
107
108static int acpi_i2c_find_address(struct acpi_resource *ares, void *data)
103{ 109{
104 struct i2c_board_info *info = data; 110 struct acpi_i2c_lookup *lookup = data;
111 struct i2c_board_info *info = lookup->info;
112 struct acpi_resource_i2c_serialbus *sb;
113 acpi_handle adapter_handle;
114 acpi_status status;
105 115
106 if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { 116 if (info->addr || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
107 struct acpi_resource_i2c_serialbus *sb; 117 return 1;
108 118
109 sb = &ares->data.i2c_serial_bus; 119 sb = &ares->data.i2c_serial_bus;
110 if (!info->addr && sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { 120 if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C)
111 info->addr = sb->slave_address; 121 return 1;
112 if (sb->access_mode == ACPI_I2C_10BIT_MODE)
113 info->flags |= I2C_CLIENT_TEN;
114 }
115 } else if (!info->irq) {
116 struct resource r;
117 122
118 if (acpi_dev_resource_interrupt(ares, 0, &r)) 123 /*
119 info->irq = r.start; 124 * Extract the ResourceSource and make sure that the handle matches
125 * with the I2C adapter handle.
126 */
127 status = acpi_get_handle(lookup->device_handle,
128 sb->resource_source.string_ptr,
129 &adapter_handle);
130 if (ACPI_SUCCESS(status) && adapter_handle == lookup->adapter_handle) {
131 info->addr = sb->slave_address;
132 if (sb->access_mode == ACPI_I2C_10BIT_MODE)
133 info->flags |= I2C_CLIENT_TEN;
120 } 134 }
121 135
122 /* Tell the ACPI core to skip this resource */
123 return 1; 136 return 1;
124} 137}
125 138
@@ -128,6 +141,8 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
128{ 141{
129 struct i2c_adapter *adapter = data; 142 struct i2c_adapter *adapter = data;
130 struct list_head resource_list; 143 struct list_head resource_list;
144 struct acpi_i2c_lookup lookup;
145 struct resource_entry *entry;
131 struct i2c_board_info info; 146 struct i2c_board_info info;
132 struct acpi_device *adev; 147 struct acpi_device *adev;
133 int ret; 148 int ret;
@@ -140,14 +155,37 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
140 memset(&info, 0, sizeof(info)); 155 memset(&info, 0, sizeof(info));
141 info.fwnode = acpi_fwnode_handle(adev); 156 info.fwnode = acpi_fwnode_handle(adev);
142 157
158 memset(&lookup, 0, sizeof(lookup));
159 lookup.adapter_handle = ACPI_HANDLE(&adapter->dev);
160 lookup.device_handle = handle;
161 lookup.info = &info;
162
163 /*
164 * Look up for I2cSerialBus resource with ResourceSource that
165 * matches with this adapter.
166 */
143 INIT_LIST_HEAD(&resource_list); 167 INIT_LIST_HEAD(&resource_list);
144 ret = acpi_dev_get_resources(adev, &resource_list, 168 ret = acpi_dev_get_resources(adev, &resource_list,
145 acpi_i2c_add_resource, &info); 169 acpi_i2c_find_address, &lookup);
146 acpi_dev_free_resource_list(&resource_list); 170 acpi_dev_free_resource_list(&resource_list);
147 171
148 if (ret < 0 || !info.addr) 172 if (ret < 0 || !info.addr)
149 return AE_OK; 173 return AE_OK;
150 174
175 /* Then fill IRQ number if any */
176 ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
177 if (ret < 0)
178 return AE_OK;
179
180 resource_list_for_each_entry(entry, &resource_list) {
181 if (resource_type(entry->res) == IORESOURCE_IRQ) {
182 info.irq = entry->res->start;
183 break;
184 }
185 }
186
187 acpi_dev_free_resource_list(&resource_list);
188
151 adev->power.flags.ignore_parent = true; 189 adev->power.flags.ignore_parent = true;
152 strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); 190 strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
153 if (!i2c_new_device(adapter, &info)) { 191 if (!i2c_new_device(adapter, &info)) {
@@ -160,6 +198,8 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
160 return AE_OK; 198 return AE_OK;
161} 199}
162 200
201#define ACPI_I2C_MAX_SCAN_DEPTH 32
202
163/** 203/**
164 * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter 204 * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
165 * @adap: pointer to adapter 205 * @adap: pointer to adapter
@@ -170,17 +210,13 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
170 */ 210 */
171static void acpi_i2c_register_devices(struct i2c_adapter *adap) 211static void acpi_i2c_register_devices(struct i2c_adapter *adap)
172{ 212{
173 acpi_handle handle;
174 acpi_status status; 213 acpi_status status;
175 214
176 if (!adap->dev.parent) 215 if (!has_acpi_companion(&adap->dev))
177 return;
178
179 handle = ACPI_HANDLE(adap->dev.parent);
180 if (!handle)
181 return; 216 return;
182 217
183 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, 218 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
219 ACPI_I2C_MAX_SCAN_DEPTH,
184 acpi_i2c_add_device, NULL, 220 acpi_i2c_add_device, NULL,
185 adap, NULL); 221 adap, NULL);
186 if (ACPI_FAILURE(status)) 222 if (ACPI_FAILURE(status))