aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpio/Kconfig1
-rw-r--r--drivers/gpio/gpio-pcf857x.c121
2 files changed, 28 insertions, 94 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 09bc70b3875b..249845a47624 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -604,6 +604,7 @@ config GPIO_PCA953X_IRQ
604config GPIO_PCF857X 604config GPIO_PCF857X
605 tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders" 605 tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders"
606 depends on I2C 606 depends on I2C
607 select GPIOLIB_IRQCHIP
607 select IRQ_DOMAIN 608 select IRQ_DOMAIN
608 help 609 help
609 Say yes here to provide access to most "quasi-bidirectional" I2C 610 Say yes here to provide access to most "quasi-bidirectional" I2C
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index 236708ad0a5b..126c93732101 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -88,11 +88,9 @@ struct pcf857x {
88 struct gpio_chip chip; 88 struct gpio_chip chip;
89 struct i2c_client *client; 89 struct i2c_client *client;
90 struct mutex lock; /* protect 'out' */ 90 struct mutex lock; /* protect 'out' */
91 struct irq_domain *irq_domain; /* for irq demux */
92 spinlock_t slock; /* protect irq demux */ 91 spinlock_t slock; /* protect irq demux */
93 unsigned out; /* software latch */ 92 unsigned out; /* software latch */
94 unsigned status; /* current status */ 93 unsigned status; /* current status */
95 unsigned irq_mapped; /* mapped gpio irqs */
96 94
97 int (*write)(struct i2c_client *client, unsigned data); 95 int (*write)(struct i2c_client *client, unsigned data);
98 int (*read)(struct i2c_client *client); 96 int (*read)(struct i2c_client *client);
@@ -182,18 +180,6 @@ static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value)
182 180
183/*-------------------------------------------------------------------------*/ 181/*-------------------------------------------------------------------------*/
184 182
185static int pcf857x_to_irq(struct gpio_chip *chip, unsigned offset)
186{
187 struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
188 int ret;
189
190 ret = irq_create_mapping(gpio->irq_domain, offset);
191 if (ret > 0)
192 gpio->irq_mapped |= (1 << offset);
193
194 return ret;
195}
196
197static irqreturn_t pcf857x_irq(int irq, void *data) 183static irqreturn_t pcf857x_irq(int irq, void *data)
198{ 184{
199 struct pcf857x *gpio = data; 185 struct pcf857x *gpio = data;
@@ -208,9 +194,9 @@ static irqreturn_t pcf857x_irq(int irq, void *data)
208 * interrupt source, just to avoid bad irqs 194 * interrupt source, just to avoid bad irqs
209 */ 195 */
210 196
211 change = ((gpio->status ^ status) & gpio->irq_mapped); 197 change = (gpio->status ^ status);
212 for_each_set_bit(i, &change, gpio->chip.ngpio) 198 for_each_set_bit(i, &change, gpio->chip.ngpio)
213 generic_handle_irq(irq_find_mapping(gpio->irq_domain, i)); 199 handle_nested_irq(irq_find_mapping(gpio->chip.irqdomain, i));
214 gpio->status = status; 200 gpio->status = status;
215 201
216 spin_unlock_irqrestore(&gpio->slock, flags); 202 spin_unlock_irqrestore(&gpio->slock, flags);
@@ -218,66 +204,6 @@ static irqreturn_t pcf857x_irq(int irq, void *data)
218 return IRQ_HANDLED; 204 return IRQ_HANDLED;
219} 205}
220 206
221static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int irq,
222 irq_hw_number_t hw)
223{
224 struct pcf857x *gpio = domain->host_data;
225
226 irq_set_chip_and_handler(irq,
227 &dummy_irq_chip,
228 handle_level_irq);
229#ifdef CONFIG_ARM
230 set_irq_flags(irq, IRQF_VALID);
231#else
232 irq_set_noprobe(irq);
233#endif
234 gpio->irq_mapped |= (1 << hw);
235
236 return 0;
237}
238
239static struct irq_domain_ops pcf857x_irq_domain_ops = {
240 .map = pcf857x_irq_domain_map,
241};
242
243static void pcf857x_irq_domain_cleanup(struct pcf857x *gpio)
244{
245 if (gpio->irq_domain)
246 irq_domain_remove(gpio->irq_domain);
247
248}
249
250static int pcf857x_irq_domain_init(struct pcf857x *gpio,
251 struct i2c_client *client)
252{
253 int status;
254
255 gpio->irq_domain = irq_domain_add_linear(client->dev.of_node,
256 gpio->chip.ngpio,
257 &pcf857x_irq_domain_ops,
258 gpio);
259 if (!gpio->irq_domain)
260 goto fail;
261
262 /* enable real irq */
263 status = devm_request_threaded_irq(&client->dev, client->irq,
264 NULL, pcf857x_irq, IRQF_ONESHOT |
265 IRQF_TRIGGER_FALLING | IRQF_SHARED,
266 dev_name(&client->dev), gpio);
267
268 if (status)
269 goto fail;
270
271 /* enable gpio_to_irq() */
272 gpio->chip.to_irq = pcf857x_to_irq;
273
274 return 0;
275
276fail:
277 pcf857x_irq_domain_cleanup(gpio);
278 return -EINVAL;
279}
280
281/*-------------------------------------------------------------------------*/ 207/*-------------------------------------------------------------------------*/
282 208
283static int pcf857x_probe(struct i2c_client *client, 209static int pcf857x_probe(struct i2c_client *client,
@@ -314,15 +240,6 @@ static int pcf857x_probe(struct i2c_client *client,
314 gpio->chip.direction_output = pcf857x_output; 240 gpio->chip.direction_output = pcf857x_output;
315 gpio->chip.ngpio = id->driver_data; 241 gpio->chip.ngpio = id->driver_data;
316 242
317 /* enable gpio_to_irq() if platform has settings */
318 if (client->irq) {
319 status = pcf857x_irq_domain_init(gpio, client);
320 if (status < 0) {
321 dev_err(&client->dev, "irq_domain init failed\n");
322 goto fail_irq_domain;
323 }
324 }
325
326 /* NOTE: the OnSemi jlc1562b is also largely compatible with 243 /* NOTE: the OnSemi jlc1562b is also largely compatible with
327 * these parts, notably for output. It has a low-resolution 244 * these parts, notably for output. It has a low-resolution
328 * DAC instead of pin change IRQs; and its inputs can be the 245 * DAC instead of pin change IRQs; and its inputs can be the
@@ -398,6 +315,26 @@ static int pcf857x_probe(struct i2c_client *client,
398 if (status < 0) 315 if (status < 0)
399 goto fail; 316 goto fail;
400 317
318 /* Enable irqchip if we have an interrupt */
319 if (client->irq) {
320 status = gpiochip_irqchip_add(&gpio->chip, &dummy_irq_chip, 0,
321 handle_level_irq, IRQ_TYPE_NONE);
322 if (status) {
323 dev_err(&client->dev, "cannot add irqchip\n");
324 goto fail_irq;
325 }
326
327 status = devm_request_threaded_irq(&client->dev, client->irq,
328 NULL, pcf857x_irq, IRQF_ONESHOT |
329 IRQF_TRIGGER_FALLING | IRQF_SHARED,
330 dev_name(&client->dev), gpio);
331 if (status)
332 goto fail_irq;
333
334 gpiochip_set_chained_irqchip(&gpio->chip, &dummy_irq_chip,
335 client->irq, NULL);
336 }
337
401 /* Let platform code set up the GPIOs and their users. 338 /* Let platform code set up the GPIOs and their users.
402 * Now is the first time anyone could use them. 339 * Now is the first time anyone could use them.
403 */ 340 */
@@ -413,13 +350,12 @@ static int pcf857x_probe(struct i2c_client *client,
413 350
414 return 0; 351 return 0;
415 352
416fail: 353fail_irq:
417 if (client->irq) 354 gpiochip_remove(&gpio->chip);
418 pcf857x_irq_domain_cleanup(gpio);
419 355
420fail_irq_domain: 356fail:
421 dev_dbg(&client->dev, "probe error %d for '%s'\n", 357 dev_dbg(&client->dev, "probe error %d for '%s'\n", status,
422 status, client->name); 358 client->name);
423 359
424 return status; 360 return status;
425} 361}
@@ -441,9 +377,6 @@ static int pcf857x_remove(struct i2c_client *client)
441 } 377 }
442 } 378 }
443 379
444 if (client->irq)
445 pcf857x_irq_domain_cleanup(gpio);
446
447 gpiochip_remove(&gpio->chip); 380 gpiochip_remove(&gpio->chip);
448 return status; 381 return status;
449} 382}