diff options
-rw-r--r-- | drivers/gpio/gpio-dln2.c | 92 |
1 files changed, 51 insertions, 41 deletions
diff --git a/drivers/gpio/gpio-dln2.c b/drivers/gpio/gpio-dln2.c index 2ff46192a70d..ce3c1558cb0a 100644 --- a/drivers/gpio/gpio-dln2.c +++ b/drivers/gpio/gpio-dln2.c | |||
@@ -47,13 +47,6 @@ | |||
47 | 47 | ||
48 | #define DLN2_GPIO_MAX_PINS 32 | 48 | #define DLN2_GPIO_MAX_PINS 32 |
49 | 49 | ||
50 | struct dln2_irq_work { | ||
51 | struct work_struct work; | ||
52 | struct dln2_gpio *dln2; | ||
53 | int pin; | ||
54 | int type; | ||
55 | }; | ||
56 | |||
57 | struct dln2_gpio { | 50 | struct dln2_gpio { |
58 | struct platform_device *pdev; | 51 | struct platform_device *pdev; |
59 | struct gpio_chip gpio; | 52 | struct gpio_chip gpio; |
@@ -66,7 +59,10 @@ struct dln2_gpio { | |||
66 | 59 | ||
67 | /* active IRQs - not synced to hardware */ | 60 | /* active IRQs - not synced to hardware */ |
68 | DECLARE_BITMAP(unmasked_irqs, DLN2_GPIO_MAX_PINS); | 61 | DECLARE_BITMAP(unmasked_irqs, DLN2_GPIO_MAX_PINS); |
69 | struct dln2_irq_work *irq_work; | 62 | /* active IRQS - synced to hardware */ |
63 | DECLARE_BITMAP(enabled_irqs, DLN2_GPIO_MAX_PINS); | ||
64 | int irq_type[DLN2_GPIO_MAX_PINS]; | ||
65 | struct mutex irq_lock; | ||
70 | }; | 66 | }; |
71 | 67 | ||
72 | struct dln2_gpio_pin { | 68 | struct dln2_gpio_pin { |
@@ -303,18 +299,6 @@ static int dln2_gpio_set_event_cfg(struct dln2_gpio *dln2, unsigned pin, | |||
303 | &req, sizeof(req)); | 299 | &req, sizeof(req)); |
304 | } | 300 | } |
305 | 301 | ||
306 | static void dln2_irq_work(struct work_struct *w) | ||
307 | { | ||
308 | struct dln2_irq_work *iw = container_of(w, struct dln2_irq_work, work); | ||
309 | struct dln2_gpio *dln2 = iw->dln2; | ||
310 | u8 type = iw->type & DLN2_GPIO_EVENT_MASK; | ||
311 | |||
312 | if (test_bit(iw->pin, dln2->unmasked_irqs)) | ||
313 | dln2_gpio_set_event_cfg(dln2, iw->pin, type, 0); | ||
314 | else | ||
315 | dln2_gpio_set_event_cfg(dln2, iw->pin, DLN2_GPIO_EVENT_NONE, 0); | ||
316 | } | ||
317 | |||
318 | static void dln2_irq_unmask(struct irq_data *irqd) | 302 | static void dln2_irq_unmask(struct irq_data *irqd) |
319 | { | 303 | { |
320 | struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); | 304 | struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); |
@@ -322,7 +306,6 @@ static void dln2_irq_unmask(struct irq_data *irqd) | |||
322 | int pin = irqd_to_hwirq(irqd); | 306 | int pin = irqd_to_hwirq(irqd); |
323 | 307 | ||
324 | set_bit(pin, dln2->unmasked_irqs); | 308 | set_bit(pin, dln2->unmasked_irqs); |
325 | schedule_work(&dln2->irq_work[pin].work); | ||
326 | } | 309 | } |
327 | 310 | ||
328 | static void dln2_irq_mask(struct irq_data *irqd) | 311 | static void dln2_irq_mask(struct irq_data *irqd) |
@@ -332,7 +315,6 @@ static void dln2_irq_mask(struct irq_data *irqd) | |||
332 | int pin = irqd_to_hwirq(irqd); | 315 | int pin = irqd_to_hwirq(irqd); |
333 | 316 | ||
334 | clear_bit(pin, dln2->unmasked_irqs); | 317 | clear_bit(pin, dln2->unmasked_irqs); |
335 | schedule_work(&dln2->irq_work[pin].work); | ||
336 | } | 318 | } |
337 | 319 | ||
338 | static int dln2_irq_set_type(struct irq_data *irqd, unsigned type) | 320 | static int dln2_irq_set_type(struct irq_data *irqd, unsigned type) |
@@ -343,19 +325,19 @@ static int dln2_irq_set_type(struct irq_data *irqd, unsigned type) | |||
343 | 325 | ||
344 | switch (type) { | 326 | switch (type) { |
345 | case IRQ_TYPE_LEVEL_HIGH: | 327 | case IRQ_TYPE_LEVEL_HIGH: |
346 | dln2->irq_work[pin].type = DLN2_GPIO_EVENT_LVL_HIGH; | 328 | dln2->irq_type[pin] = DLN2_GPIO_EVENT_LVL_HIGH; |
347 | break; | 329 | break; |
348 | case IRQ_TYPE_LEVEL_LOW: | 330 | case IRQ_TYPE_LEVEL_LOW: |
349 | dln2->irq_work[pin].type = DLN2_GPIO_EVENT_LVL_LOW; | 331 | dln2->irq_type[pin] = DLN2_GPIO_EVENT_LVL_LOW; |
350 | break; | 332 | break; |
351 | case IRQ_TYPE_EDGE_BOTH: | 333 | case IRQ_TYPE_EDGE_BOTH: |
352 | dln2->irq_work[pin].type = DLN2_GPIO_EVENT_CHANGE; | 334 | dln2->irq_type[pin] = DLN2_GPIO_EVENT_CHANGE; |
353 | break; | 335 | break; |
354 | case IRQ_TYPE_EDGE_RISING: | 336 | case IRQ_TYPE_EDGE_RISING: |
355 | dln2->irq_work[pin].type = DLN2_GPIO_EVENT_CHANGE_RISING; | 337 | dln2->irq_type[pin] = DLN2_GPIO_EVENT_CHANGE_RISING; |
356 | break; | 338 | break; |
357 | case IRQ_TYPE_EDGE_FALLING: | 339 | case IRQ_TYPE_EDGE_FALLING: |
358 | dln2->irq_work[pin].type = DLN2_GPIO_EVENT_CHANGE_FALLING; | 340 | dln2->irq_type[pin] = DLN2_GPIO_EVENT_CHANGE_FALLING; |
359 | break; | 341 | break; |
360 | default: | 342 | default: |
361 | return -EINVAL; | 343 | return -EINVAL; |
@@ -364,11 +346,50 @@ static int dln2_irq_set_type(struct irq_data *irqd, unsigned type) | |||
364 | return 0; | 346 | return 0; |
365 | } | 347 | } |
366 | 348 | ||
349 | static void dln2_irq_bus_lock(struct irq_data *irqd) | ||
350 | { | ||
351 | struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); | ||
352 | struct dln2_gpio *dln2 = container_of(gc, struct dln2_gpio, gpio); | ||
353 | |||
354 | mutex_lock(&dln2->irq_lock); | ||
355 | } | ||
356 | |||
357 | static void dln2_irq_bus_unlock(struct irq_data *irqd) | ||
358 | { | ||
359 | struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); | ||
360 | struct dln2_gpio *dln2 = container_of(gc, struct dln2_gpio, gpio); | ||
361 | int pin = irqd_to_hwirq(irqd); | ||
362 | int enabled, unmasked; | ||
363 | unsigned type; | ||
364 | int ret; | ||
365 | |||
366 | enabled = test_bit(pin, dln2->enabled_irqs); | ||
367 | unmasked = test_bit(pin, dln2->unmasked_irqs); | ||
368 | |||
369 | if (enabled != unmasked) { | ||
370 | if (unmasked) { | ||
371 | type = dln2->irq_type[pin] & DLN2_GPIO_EVENT_MASK; | ||
372 | set_bit(pin, dln2->enabled_irqs); | ||
373 | } else { | ||
374 | type = DLN2_GPIO_EVENT_NONE; | ||
375 | clear_bit(pin, dln2->enabled_irqs); | ||
376 | } | ||
377 | |||
378 | ret = dln2_gpio_set_event_cfg(dln2, pin, type, 0); | ||
379 | if (ret) | ||
380 | dev_err(dln2->gpio.dev, "failed to set event\n"); | ||
381 | } | ||
382 | |||
383 | mutex_unlock(&dln2->irq_lock); | ||
384 | } | ||
385 | |||
367 | static struct irq_chip dln2_gpio_irqchip = { | 386 | static struct irq_chip dln2_gpio_irqchip = { |
368 | .name = "dln2-irq", | 387 | .name = "dln2-irq", |
369 | .irq_mask = dln2_irq_mask, | 388 | .irq_mask = dln2_irq_mask, |
370 | .irq_unmask = dln2_irq_unmask, | 389 | .irq_unmask = dln2_irq_unmask, |
371 | .irq_set_type = dln2_irq_set_type, | 390 | .irq_set_type = dln2_irq_set_type, |
391 | .irq_bus_lock = dln2_irq_bus_lock, | ||
392 | .irq_bus_sync_unlock = dln2_irq_bus_unlock, | ||
372 | }; | 393 | }; |
373 | 394 | ||
374 | static void dln2_gpio_event(struct platform_device *pdev, u16 echo, | 395 | static void dln2_gpio_event(struct platform_device *pdev, u16 echo, |
@@ -400,7 +421,7 @@ static void dln2_gpio_event(struct platform_device *pdev, u16 echo, | |||
400 | return; | 421 | return; |
401 | } | 422 | } |
402 | 423 | ||
403 | switch (dln2->irq_work[pin].type) { | 424 | switch (dln2->irq_type[pin]) { |
404 | case DLN2_GPIO_EVENT_CHANGE_RISING: | 425 | case DLN2_GPIO_EVENT_CHANGE_RISING: |
405 | if (event->value) | 426 | if (event->value) |
406 | generic_handle_irq(irq); | 427 | generic_handle_irq(irq); |
@@ -419,7 +440,7 @@ static int dln2_gpio_probe(struct platform_device *pdev) | |||
419 | struct dln2_gpio *dln2; | 440 | struct dln2_gpio *dln2; |
420 | struct device *dev = &pdev->dev; | 441 | struct device *dev = &pdev->dev; |
421 | int pins; | 442 | int pins; |
422 | int i, ret; | 443 | int ret; |
423 | 444 | ||
424 | pins = dln2_gpio_get_pin_count(pdev); | 445 | pins = dln2_gpio_get_pin_count(pdev); |
425 | if (pins < 0) { | 446 | if (pins < 0) { |
@@ -435,15 +456,7 @@ static int dln2_gpio_probe(struct platform_device *pdev) | |||
435 | if (!dln2) | 456 | if (!dln2) |
436 | return -ENOMEM; | 457 | return -ENOMEM; |
437 | 458 | ||
438 | dln2->irq_work = devm_kcalloc(&pdev->dev, pins, | 459 | mutex_init(&dln2->irq_lock); |
439 | sizeof(struct dln2_irq_work), GFP_KERNEL); | ||
440 | if (!dln2->irq_work) | ||
441 | return -ENOMEM; | ||
442 | for (i = 0; i < pins; i++) { | ||
443 | INIT_WORK(&dln2->irq_work[i].work, dln2_irq_work); | ||
444 | dln2->irq_work[i].pin = i; | ||
445 | dln2->irq_work[i].dln2 = dln2; | ||
446 | } | ||
447 | 460 | ||
448 | dln2->pdev = pdev; | 461 | dln2->pdev = pdev; |
449 | 462 | ||
@@ -497,11 +510,8 @@ out: | |||
497 | static int dln2_gpio_remove(struct platform_device *pdev) | 510 | static int dln2_gpio_remove(struct platform_device *pdev) |
498 | { | 511 | { |
499 | struct dln2_gpio *dln2 = platform_get_drvdata(pdev); | 512 | struct dln2_gpio *dln2 = platform_get_drvdata(pdev); |
500 | int i; | ||
501 | 513 | ||
502 | dln2_unregister_event_cb(pdev, DLN2_GPIO_CONDITION_MET_EV); | 514 | dln2_unregister_event_cb(pdev, DLN2_GPIO_CONDITION_MET_EV); |
503 | for (i = 0; i < dln2->gpio.ngpio; i++) | ||
504 | flush_work(&dln2->irq_work[i].work); | ||
505 | gpiochip_remove(&dln2->gpio); | 515 | gpiochip_remove(&dln2->gpio); |
506 | 516 | ||
507 | return 0; | 517 | return 0; |