@@ -107,12 +107,11 @@ struct acpi_i2c_lookup {
107
107
acpi_handle device_handle ;
108
108
};
109
109
110
- static int acpi_i2c_find_address (struct acpi_resource * ares , void * data )
110
+ static int acpi_i2c_fill_info (struct acpi_resource * ares , void * data )
111
111
{
112
112
struct acpi_i2c_lookup * lookup = data ;
113
113
struct i2c_board_info * info = lookup -> info ;
114
114
struct acpi_resource_i2c_serialbus * sb ;
115
- acpi_handle adapter_handle ;
116
115
acpi_status status ;
117
116
118
117
if (info -> addr || ares -> type != ACPI_RESOURCE_TYPE_SERIAL_BUS )
@@ -122,80 +121,102 @@ static int acpi_i2c_find_address(struct acpi_resource *ares, void *data)
122
121
if (sb -> type != ACPI_RESOURCE_SERIAL_TYPE_I2C )
123
122
return 1 ;
124
123
125
- /*
126
- * Extract the ResourceSource and make sure that the handle matches
127
- * with the I2C adapter handle.
128
- */
129
124
status = acpi_get_handle (lookup -> device_handle ,
130
125
sb -> resource_source .string_ptr ,
131
- & adapter_handle );
132
- if (ACPI_SUCCESS (status ) && adapter_handle == lookup -> adapter_handle ) {
133
- info -> addr = sb -> slave_address ;
134
- if (sb -> access_mode == ACPI_I2C_10BIT_MODE )
135
- info -> flags |= I2C_CLIENT_TEN ;
136
- }
126
+ & lookup -> adapter_handle );
127
+ if (!ACPI_SUCCESS (status ))
128
+ return 1 ;
129
+
130
+ info -> addr = sb -> slave_address ;
131
+ if (sb -> access_mode == ACPI_I2C_10BIT_MODE )
132
+ info -> flags |= I2C_CLIENT_TEN ;
137
133
138
134
return 1 ;
139
135
}
140
136
141
- static acpi_status acpi_i2c_add_device (acpi_handle handle , u32 level ,
142
- void * data , void * * return_value )
137
+ static int acpi_i2c_get_info (struct acpi_device * adev ,
138
+ struct i2c_board_info * info ,
139
+ acpi_handle * adapter_handle )
143
140
{
144
- struct i2c_adapter * adapter = data ;
145
141
struct list_head resource_list ;
146
- struct acpi_i2c_lookup lookup ;
147
142
struct resource_entry * entry ;
148
- struct i2c_board_info info ;
149
- struct acpi_device * adev ;
143
+ struct acpi_i2c_lookup lookup ;
150
144
int ret ;
151
145
152
- if (acpi_bus_get_device (handle , & adev ))
153
- return AE_OK ;
154
- if (acpi_bus_get_status (adev ) || !adev -> status .present )
155
- return AE_OK ;
146
+ if (acpi_bus_get_status (adev ) || !adev -> status .present ||
147
+ acpi_device_enumerated (adev ))
148
+ return - EINVAL ;
156
149
157
- memset (& info , 0 , sizeof (info ));
158
- info . fwnode = acpi_fwnode_handle (adev );
150
+ memset (info , 0 , sizeof (* info ));
151
+ info -> fwnode = acpi_fwnode_handle (adev );
159
152
160
153
memset (& lookup , 0 , sizeof (lookup ));
161
- lookup .adapter_handle = ACPI_HANDLE (& adapter -> dev );
162
- lookup .device_handle = handle ;
163
- lookup .info = & info ;
154
+ lookup .device_handle = acpi_device_handle (adev );
155
+ lookup .info = info ;
164
156
165
- /*
166
- * Look up for I2cSerialBus resource with ResourceSource that
167
- * matches with this adapter.
168
- */
157
+ /* Look up for I2cSerialBus resource */
169
158
INIT_LIST_HEAD (& resource_list );
170
159
ret = acpi_dev_get_resources (adev , & resource_list ,
171
- acpi_i2c_find_address , & lookup );
160
+ acpi_i2c_fill_info , & lookup );
172
161
acpi_dev_free_resource_list (& resource_list );
173
162
174
- if (ret < 0 || !info .addr )
175
- return AE_OK ;
163
+ if (ret < 0 || !info -> addr )
164
+ return - EINVAL ;
165
+
166
+ * adapter_handle = lookup .adapter_handle ;
176
167
177
168
/* Then fill IRQ number if any */
178
169
ret = acpi_dev_get_resources (adev , & resource_list , NULL , NULL );
179
170
if (ret < 0 )
180
- return AE_OK ;
171
+ return - EINVAL ;
181
172
182
173
resource_list_for_each_entry (entry , & resource_list ) {
183
174
if (resource_type (entry -> res ) == IORESOURCE_IRQ ) {
184
- info . irq = entry -> res -> start ;
175
+ info -> irq = entry -> res -> start ;
185
176
break ;
186
177
}
187
178
}
188
179
189
180
acpi_dev_free_resource_list (& resource_list );
190
181
182
+ strlcpy (info -> type , dev_name (& adev -> dev ), sizeof (info -> type ));
183
+
184
+ return 0 ;
185
+ }
186
+
187
+ static void acpi_i2c_register_device (struct i2c_adapter * adapter ,
188
+ struct acpi_device * adev ,
189
+ struct i2c_board_info * info )
190
+ {
191
191
adev -> power .flags .ignore_parent = true;
192
- strlcpy (info .type , dev_name (& adev -> dev ), sizeof (info .type ));
193
- if (!i2c_new_device (adapter , & info )) {
192
+ acpi_device_set_enumerated (adev );
193
+
194
+ if (!i2c_new_device (adapter , info )) {
194
195
adev -> power .flags .ignore_parent = false;
195
196
dev_err (& adapter -> dev ,
196
197
"failed to add I2C device %s from ACPI\n" ,
197
198
dev_name (& adev -> dev ));
198
199
}
200
+ }
201
+
202
+ static acpi_status acpi_i2c_add_device (acpi_handle handle , u32 level ,
203
+ void * data , void * * return_value )
204
+ {
205
+ struct i2c_adapter * adapter = data ;
206
+ struct acpi_device * adev ;
207
+ acpi_handle adapter_handle ;
208
+ struct i2c_board_info info ;
209
+
210
+ if (acpi_bus_get_device (handle , & adev ))
211
+ return AE_OK ;
212
+
213
+ if (acpi_i2c_get_info (adev , & info , & adapter_handle ))
214
+ return AE_OK ;
215
+
216
+ if (adapter_handle != ACPI_HANDLE (& adapter -> dev ))
217
+ return AE_OK ;
218
+
219
+ acpi_i2c_register_device (adapter , adev , & info );
199
220
200
221
return AE_OK ;
201
222
}
@@ -225,8 +246,80 @@ static void acpi_i2c_register_devices(struct i2c_adapter *adap)
225
246
dev_warn (& adap -> dev , "failed to enumerate I2C slaves\n" );
226
247
}
227
248
249
+ static int acpi_i2c_match_adapter (struct device * dev , void * data )
250
+ {
251
+ struct i2c_adapter * adapter = i2c_verify_adapter (dev );
252
+
253
+ if (!adapter )
254
+ return 0 ;
255
+
256
+ return ACPI_HANDLE (dev ) == (acpi_handle )data ;
257
+ }
258
+
259
+ static int acpi_i2c_match_device (struct device * dev , void * data )
260
+ {
261
+ return ACPI_COMPANION (dev ) == data ;
262
+ }
263
+
264
+ static struct i2c_adapter * acpi_i2c_find_adapter_by_handle (acpi_handle handle )
265
+ {
266
+ struct device * dev ;
267
+
268
+ dev = bus_find_device (& i2c_bus_type , NULL , handle ,
269
+ acpi_i2c_match_adapter );
270
+ return dev ? i2c_verify_adapter (dev ) : NULL ;
271
+ }
272
+
273
+ static struct i2c_client * acpi_i2c_find_client_by_adev (struct acpi_device * adev )
274
+ {
275
+ struct device * dev ;
276
+
277
+ dev = bus_find_device (& i2c_bus_type , NULL , adev , acpi_i2c_match_device );
278
+ return dev ? i2c_verify_client (dev ) : NULL ;
279
+ }
280
+
281
+ static int acpi_i2c_notify (struct notifier_block * nb , unsigned long value ,
282
+ void * arg )
283
+ {
284
+ struct acpi_device * adev = arg ;
285
+ struct i2c_board_info info ;
286
+ acpi_handle adapter_handle ;
287
+ struct i2c_adapter * adapter ;
288
+ struct i2c_client * client ;
289
+
290
+ switch (value ) {
291
+ case ACPI_RECONFIG_DEVICE_ADD :
292
+ if (acpi_i2c_get_info (adev , & info , & adapter_handle ))
293
+ break ;
294
+
295
+ adapter = acpi_i2c_find_adapter_by_handle (adapter_handle );
296
+ if (!adapter )
297
+ break ;
298
+
299
+ acpi_i2c_register_device (adapter , adev , & info );
300
+ break ;
301
+ case ACPI_RECONFIG_DEVICE_REMOVE :
302
+ if (!acpi_device_enumerated (adev ))
303
+ break ;
304
+
305
+ client = acpi_i2c_find_client_by_adev (adev );
306
+ if (!client )
307
+ break ;
308
+
309
+ i2c_unregister_device (client );
310
+ put_device (& client -> dev );
311
+ break ;
312
+ }
313
+
314
+ return NOTIFY_OK ;
315
+ }
316
+
317
+ static struct notifier_block i2c_acpi_notifier = {
318
+ .notifier_call = acpi_i2c_notify ,
319
+ };
228
320
#else /* CONFIG_ACPI */
229
321
static inline void acpi_i2c_register_devices (struct i2c_adapter * adap ) { }
322
+ extern struct notifier_block i2c_acpi_notifier ;
230
323
#endif /* CONFIG_ACPI */
231
324
232
325
#ifdef CONFIG_ACPI_I2C_OPREGION
@@ -1089,6 +1182,8 @@ void i2c_unregister_device(struct i2c_client *client)
1089
1182
{
1090
1183
if (client -> dev .of_node )
1091
1184
of_node_clear_flag (client -> dev .of_node , OF_POPULATED );
1185
+ if (ACPI_COMPANION (& client -> dev ))
1186
+ acpi_device_clear_enumerated (ACPI_COMPANION (& client -> dev ));
1092
1187
device_unregister (& client -> dev );
1093
1188
}
1094
1189
EXPORT_SYMBOL_GPL (i2c_unregister_device );
@@ -2117,6 +2212,8 @@ static int __init i2c_init(void)
2117
2212
2118
2213
if (IS_ENABLED (CONFIG_OF_DYNAMIC ))
2119
2214
WARN_ON (of_reconfig_notifier_register (& i2c_of_notifier ));
2215
+ if (IS_ENABLED (CONFIG_ACPI ))
2216
+ WARN_ON (acpi_reconfig_notifier_register (& i2c_acpi_notifier ));
2120
2217
2121
2218
return 0 ;
2122
2219
@@ -2132,6 +2229,8 @@ static int __init i2c_init(void)
2132
2229
2133
2230
static void __exit i2c_exit (void )
2134
2231
{
2232
+ if (IS_ENABLED (CONFIG_ACPI ))
2233
+ WARN_ON (acpi_reconfig_notifier_unregister (& i2c_acpi_notifier ));
2135
2234
if (IS_ENABLED (CONFIG_OF_DYNAMIC ))
2136
2235
WARN_ON (of_reconfig_notifier_unregister (& i2c_of_notifier ));
2137
2236
i2c_del_driver (& dummy_driver );
0 commit comments