|
37 | 37 | * bits the chip supports.
|
38 | 38 | */
|
39 | 39 |
|
| 40 | +#include <linux/bitops.h> |
40 | 41 | #include <linux/ctype.h>
|
41 | 42 | #include <linux/delay.h>
|
42 | 43 | #include <linux/err.h>
|
@@ -118,6 +119,7 @@ struct pca955x {
|
118 | 119 | struct pca955x_led *leds;
|
119 | 120 | struct pca955x_chipdef *chipdef;
|
120 | 121 | struct i2c_client *client;
|
| 122 | + unsigned long active_pins; |
121 | 123 | #ifdef CONFIG_LEDS_PCA955X_GPIO
|
122 | 124 | struct gpio_chip gpio;
|
123 | 125 | #endif
|
@@ -360,12 +362,15 @@ static int pca955x_read_input(struct i2c_client *client, int n, u8 *val)
|
360 | 362 | static int pca955x_gpio_request_pin(struct gpio_chip *gc, unsigned int offset)
|
361 | 363 | {
|
362 | 364 | struct pca955x *pca955x = gpiochip_get_data(gc);
|
363 |
| - struct pca955x_led *led = &pca955x->leds[offset]; |
364 | 365 |
|
365 |
| - if (led->type == PCA955X_TYPE_GPIO) |
366 |
| - return 0; |
| 366 | + return test_and_set_bit(offset, &pca955x->active_pins) ? -EBUSY : 0; |
| 367 | +} |
| 368 | + |
| 369 | +static void pca955x_gpio_free_pin(struct gpio_chip *gc, unsigned int offset) |
| 370 | +{ |
| 371 | + struct pca955x *pca955x = gpiochip_get_data(gc); |
367 | 372 |
|
368 |
| - return -EBUSY; |
| 373 | + clear_bit(offset, &pca955x->active_pins); |
369 | 374 | }
|
370 | 375 |
|
371 | 376 | static int pca955x_set_value(struct gpio_chip *gc, unsigned int offset,
|
@@ -489,7 +494,6 @@ static int pca955x_probe(struct i2c_client *client)
|
489 | 494 | struct i2c_adapter *adapter;
|
490 | 495 | int i, err;
|
491 | 496 | struct pca955x_platform_data *pdata;
|
492 |
| - int ngpios = 0; |
493 | 497 | bool set_default_label = false;
|
494 | 498 | bool keep_pwm = false;
|
495 | 499 | char default_label[8];
|
@@ -567,9 +571,7 @@ static int pca955x_probe(struct i2c_client *client)
|
567 | 571 |
|
568 | 572 | switch (pca955x_led->type) {
|
569 | 573 | case PCA955X_TYPE_NONE:
|
570 |
| - break; |
571 | 574 | case PCA955X_TYPE_GPIO:
|
572 |
| - ngpios++; |
573 | 575 | break;
|
574 | 576 | case PCA955X_TYPE_LED:
|
575 | 577 | led = &pca955x_led->led_cdev;
|
@@ -613,6 +615,8 @@ static int pca955x_probe(struct i2c_client *client)
|
613 | 615 | if (err)
|
614 | 616 | return err;
|
615 | 617 |
|
| 618 | + set_bit(i, &pca955x->active_pins); |
| 619 | + |
616 | 620 | /*
|
617 | 621 | * For default-state == "keep", let the core update the
|
618 | 622 | * brightness from the hardware, then check the
|
@@ -650,31 +654,30 @@ static int pca955x_probe(struct i2c_client *client)
|
650 | 654 | return err;
|
651 | 655 |
|
652 | 656 | #ifdef CONFIG_LEDS_PCA955X_GPIO
|
653 |
| - if (ngpios) { |
654 |
| - pca955x->gpio.label = "gpio-pca955x"; |
655 |
| - pca955x->gpio.direction_input = pca955x_gpio_direction_input; |
656 |
| - pca955x->gpio.direction_output = pca955x_gpio_direction_output; |
657 |
| - pca955x->gpio.set = pca955x_gpio_set_value; |
658 |
| - pca955x->gpio.get = pca955x_gpio_get_value; |
659 |
| - pca955x->gpio.request = pca955x_gpio_request_pin; |
660 |
| - pca955x->gpio.can_sleep = 1; |
661 |
| - pca955x->gpio.base = -1; |
662 |
| - pca955x->gpio.ngpio = ngpios; |
663 |
| - pca955x->gpio.parent = &client->dev; |
664 |
| - pca955x->gpio.owner = THIS_MODULE; |
665 |
| - |
666 |
| - err = devm_gpiochip_add_data(&client->dev, &pca955x->gpio, |
667 |
| - pca955x); |
668 |
| - if (err) { |
669 |
| - /* Use data->gpio.dev as a flag for freeing gpiochip */ |
670 |
| - pca955x->gpio.parent = NULL; |
671 |
| - dev_warn(&client->dev, "could not add gpiochip\n"); |
672 |
| - return err; |
673 |
| - } |
674 |
| - dev_info(&client->dev, "gpios %i...%i\n", |
675 |
| - pca955x->gpio.base, pca955x->gpio.base + |
676 |
| - pca955x->gpio.ngpio - 1); |
| 657 | + pca955x->gpio.label = "gpio-pca955x"; |
| 658 | + pca955x->gpio.direction_input = pca955x_gpio_direction_input; |
| 659 | + pca955x->gpio.direction_output = pca955x_gpio_direction_output; |
| 660 | + pca955x->gpio.set = pca955x_gpio_set_value; |
| 661 | + pca955x->gpio.get = pca955x_gpio_get_value; |
| 662 | + pca955x->gpio.request = pca955x_gpio_request_pin; |
| 663 | + pca955x->gpio.free = pca955x_gpio_free_pin; |
| 664 | + pca955x->gpio.can_sleep = 1; |
| 665 | + pca955x->gpio.base = -1; |
| 666 | + pca955x->gpio.ngpio = chip->bits; |
| 667 | + pca955x->gpio.parent = &client->dev; |
| 668 | + pca955x->gpio.owner = THIS_MODULE; |
| 669 | + |
| 670 | + err = devm_gpiochip_add_data(&client->dev, &pca955x->gpio, |
| 671 | + pca955x); |
| 672 | + if (err) { |
| 673 | + /* Use data->gpio.dev as a flag for freeing gpiochip */ |
| 674 | + pca955x->gpio.parent = NULL; |
| 675 | + dev_warn(&client->dev, "could not add gpiochip\n"); |
| 676 | + return err; |
677 | 677 | }
|
| 678 | + dev_info(&client->dev, "gpios %i...%i\n", |
| 679 | + pca955x->gpio.base, pca955x->gpio.base + |
| 680 | + pca955x->gpio.ngpio - 1); |
678 | 681 | #endif
|
679 | 682 |
|
680 | 683 | return 0;
|
|
0 commit comments