aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorPhil Reid <preid@electromag.com.au>2017-08-24 05:31:05 -0400
committerWolfram Sang <wsa@the-dreams.de>2017-10-28 17:43:04 -0400
commit148baf1ddfb65019ee510ba2a76c2e7cd9752982 (patch)
tree03c452b51fcf17b1ae14106c505bc3c29693eec2 /drivers/i2c
parentf8756c67b3de71a46255aa478ab590ff28e60ac9 (diff)
i2c: mux: pca954x: call request irq after adding mux segments
The pca954x device do not have the ability to mask interrupts. For i2c slave devices that also don't have masking ability (eg ltc1760 smbalert output) delay registering the irq until after the mux segments have been configured. During the mux add_adaptor call the core i2c system can register an smbalert handler which would then be called immediately when the irq is registered. This smbalert handler will then clear the pending irq. This removes the need for the irq_mask / irq_unmask calls that were original used to do this. Signed-off-by: Phil Reid <preid@electromag.com.au> Acked-by: Peter Rosin <peda@axentia.se> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-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