diff options
-rw-r--r-- | drivers/i2c/muxes/i2c-mux-pca954x.c | 91 |
1 files changed, 28 insertions, 63 deletions
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index 7b992db38021..14aee65298f7 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c | |||
@@ -246,36 +246,6 @@ static irqreturn_t pca954x_irq_handler(int irq, void *dev_id) | |||
246 | return handled ? IRQ_HANDLED : IRQ_NONE; | 246 | return handled ? IRQ_HANDLED : IRQ_NONE; |
247 | } | 247 | } |
248 | 248 | ||
249 | static void pca954x_irq_mask(struct irq_data *idata) | ||
250 | { | ||
251 | struct pca954x *data = irq_data_get_irq_chip_data(idata); | ||
252 | unsigned int pos = idata->hwirq; | ||
253 | unsigned long flags; | ||
254 | |||
255 | raw_spin_lock_irqsave(&data->lock, flags); | ||
256 | |||
257 | data->irq_mask &= ~BIT(pos); | ||
258 | if (!data->irq_mask) | ||
259 | disable_irq(data->client->irq); | ||
260 | |||
261 | raw_spin_unlock_irqrestore(&data->lock, flags); | ||
262 | } | ||
263 | |||
264 | static void pca954x_irq_unmask(struct irq_data *idata) | ||
265 | { | ||
266 | struct pca954x *data = irq_data_get_irq_chip_data(idata); | ||
267 | unsigned int pos = idata->hwirq; | ||
268 | unsigned long flags; | ||
269 | |||
270 | raw_spin_lock_irqsave(&data->lock, flags); | ||
271 | |||
272 | if (!data->irq_mask) | ||
273 | enable_irq(data->client->irq); | ||
274 | data->irq_mask |= BIT(pos); | ||
275 | |||
276 | raw_spin_unlock_irqrestore(&data->lock, flags); | ||
277 | } | ||
278 | |||
279 | static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type) | 249 | static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type) |
280 | { | 250 | { |
281 | if ((type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_LOW) | 251 | if ((type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_LOW) |
@@ -285,8 +255,6 @@ static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type) | |||
285 | 255 | ||
286 | static struct irq_chip pca954x_irq_chip = { | 256 | static struct irq_chip pca954x_irq_chip = { |
287 | .name = "i2c-mux-pca954x", | 257 | .name = "i2c-mux-pca954x", |
288 | .irq_mask = pca954x_irq_mask, | ||
289 | .irq_unmask = pca954x_irq_unmask, | ||
290 | .irq_set_type = pca954x_irq_set_type, | 258 | .irq_set_type = pca954x_irq_set_type, |
291 | }; | 259 | }; |
292 | 260 | ||
@@ -294,7 +262,7 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc) | |||
294 | { | 262 | { |
295 | struct pca954x *data = i2c_mux_priv(muxc); | 263 | struct pca954x *data = i2c_mux_priv(muxc); |
296 | struct i2c_client *client = data->client; | 264 | struct i2c_client *client = data->client; |
297 | int c, err, irq; | 265 | int c, irq; |
298 | 266 | ||
299 | if (!data->chip->has_irq || client->irq <= 0) | 267 | if (!data->chip->has_irq || client->irq <= 0) |
300 | return 0; | 268 | return 0; |
@@ -314,24 +282,22 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc) | |||
314 | handle_simple_irq); | 282 | handle_simple_irq); |
315 | } | 283 | } |
316 | 284 | ||
317 | err = devm_request_threaded_irq(&client->dev, data->client->irq, NULL, | 285 | return 0; |
318 | pca954x_irq_handler, | 286 | } |
319 | IRQF_ONESHOT | IRQF_SHARED, | ||
320 | "pca954x", data); | ||
321 | if (err) | ||
322 | goto err_req_irq; | ||
323 | 287 | ||
324 | disable_irq(data->client->irq); | 288 | static void pca954x_cleanup(struct i2c_mux_core *muxc) |
289 | { | ||
290 | struct pca954x *data = i2c_mux_priv(muxc); | ||
291 | int c, irq; | ||
325 | 292 | ||
326 | return 0; | 293 | if (data->irq) { |
327 | err_req_irq: | 294 | for (c = 0; c < data->chip->nchans; c++) { |
328 | for (c = 0; c < data->chip->nchans; c++) { | 295 | irq = irq_find_mapping(data->irq, c); |
329 | irq = irq_find_mapping(data->irq, c); | 296 | irq_dispose_mapping(irq); |
330 | irq_dispose_mapping(irq); | 297 | } |
298 | irq_domain_remove(data->irq); | ||
331 | } | 299 | } |
332 | irq_domain_remove(data->irq); | 300 | i2c_mux_del_adapters(muxc); |
333 | |||
334 | return err; | ||
335 | } | 301 | } |
336 | 302 | ||
337 | /* | 303 | /* |
@@ -391,7 +357,7 @@ static int pca954x_probe(struct i2c_client *client, | |||
391 | 357 | ||
392 | ret = pca954x_irq_setup(muxc); | 358 | ret = pca954x_irq_setup(muxc); |
393 | if (ret) | 359 | if (ret) |
394 | goto fail_del_adapters; | 360 | goto fail_cleanup; |
395 | 361 | ||
396 | /* Now create an adapter for each channel */ | 362 | /* Now create an adapter for each channel */ |
397 | for (num = 0; num < data->chip->nchans; num++) { | 363 | for (num = 0; num < data->chip->nchans; num++) { |
@@ -414,7 +380,16 @@ static int pca954x_probe(struct i2c_client *client, | |||
414 | 380 | ||
415 | ret = i2c_mux_add_adapter(muxc, force, num, class); | 381 | ret = i2c_mux_add_adapter(muxc, force, num, class); |
416 | if (ret) | 382 | if (ret) |
417 | goto fail_del_adapters; | 383 | goto fail_cleanup; |
384 | } | ||
385 | |||
386 | if (data->irq) { | ||
387 | ret = devm_request_threaded_irq(&client->dev, data->client->irq, | ||
388 | NULL, pca954x_irq_handler, | ||
389 | IRQF_ONESHOT | IRQF_SHARED, | ||
390 | "pca954x", data); | ||
391 | if (ret) | ||
392 | goto fail_cleanup; | ||
418 | } | 393 | } |
419 | 394 | ||
420 | dev_info(&client->dev, | 395 | dev_info(&client->dev, |
@@ -424,26 +399,16 @@ static int pca954x_probe(struct i2c_client *client, | |||
424 | 399 | ||
425 | return 0; | 400 | return 0; |
426 | 401 | ||
427 | fail_del_adapters: | 402 | fail_cleanup: |
428 | i2c_mux_del_adapters(muxc); | 403 | pca954x_cleanup(muxc); |
429 | return ret; | 404 | return ret; |
430 | } | 405 | } |
431 | 406 | ||
432 | static int pca954x_remove(struct i2c_client *client) | 407 | static int pca954x_remove(struct i2c_client *client) |
433 | { | 408 | { |
434 | struct i2c_mux_core *muxc = i2c_get_clientdata(client); | 409 | struct i2c_mux_core *muxc = i2c_get_clientdata(client); |
435 | struct pca954x *data = i2c_mux_priv(muxc); | ||
436 | int c, irq; | ||
437 | 410 | ||
438 | if (data->irq) { | 411 | pca954x_cleanup(muxc); |
439 | for (c = 0; c < data->chip->nchans; c++) { | ||
440 | irq = irq_find_mapping(data->irq, c); | ||
441 | irq_dispose_mapping(irq); | ||
442 | } | ||
443 | irq_domain_remove(data->irq); | ||
444 | } | ||
445 | |||
446 | i2c_mux_del_adapters(muxc); | ||
447 | return 0; | 412 | return 0; |
448 | } | 413 | } |
449 | 414 | ||