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; |
