aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/i2c/muxes/i2c-mux-pca954x.c91
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
249static 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
264static 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
279static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type) 249static 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
286static struct irq_chip pca954x_irq_chip = { 256static 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); 288static 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) {
327err_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
427fail_del_adapters: 402fail_cleanup:
428 i2c_mux_del_adapters(muxc); 403 pca954x_cleanup(muxc);
429 return ret; 404 return ret;
430} 405}
431 406
432static int pca954x_remove(struct i2c_client *client) 407static 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