[PATCH] leds: pca955x: map gpio offset to led index correctly

From: Andrea Scian
Date: Tue Oct 17 2017 - 05:09:11 EST


We need to map gpio offset to led index of this device otherwise we
cannot mix led and gpios into device tree definition

Signed-off-by: Andrea Scian <andrea.scian@xxxxxxx>
---
drivers/leds/leds-pca955x.c | 38 ++++++++++++++++++++++++++++++--------
1 file changed, 30 insertions(+), 8 deletions(-)

diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index cdd7a4c..27942aa 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -122,6 +122,7 @@ struct pca955x {
struct i2c_client *client;
#ifdef CONFIG_LEDS_PCA955X_GPIO
struct gpio_chip gpio;
+ int *gpio_to_index;
#endif
};

@@ -313,25 +314,36 @@ static int pca955x_read_input(struct i2c_client *client, int n, u8 *val)
}
*val = (u8)ret;
return 0;
+}

+/*
+ * Map from gpio offset to led index.
+ * Return NULL in case of unmapped GPIO (even if it should never happens)
+ */
+static struct pca955x_led *
+pca955x_gpio_get_led_index(struct pca955x *pca955x, unsigned int offset)
+{
+ int index = pca955x->gpio_to_index[offset];
+
+ return index < 0 ? NULL : &pca955x->leds[index];
}

static int pca955x_gpio_request_pin(struct gpio_chip *gc, unsigned int offset)
{
struct pca955x *pca955x = to_pca(gc);
- struct pca955x_led *led = &pca955x->leds[offset];
-
- if (led->type == PCA955X_TYPE_GPIO)
- return 0;
+ struct pca955x_led *led = pca955x_gpio_get_led_index(pca955x, offset);

- return -EBUSY;
+ return led == NULL ? -EBUSY : 0;
}

static int pca955x_set_value(struct gpio_chip *gc, unsigned int offset,
int val)
{
struct pca955x *pca955x = to_pca(gc);
- struct pca955x_led *led = &pca955x->leds[offset];
+ struct pca955x_led *led = pca955x_gpio_get_led_index(pca955x, offset);
+
+ if (led == NULL)
+ return -EINVAL;

if (val)
return pca955x_led_set(&led->led_cdev, LED_FULL);
@@ -348,10 +360,14 @@ static void pca955x_gpio_set_value(struct gpio_chip *gc, unsigned int offset,
static int pca955x_gpio_get_value(struct gpio_chip *gc, unsigned int offset)
{
struct pca955x *pca955x = to_pca(gc);
- struct pca955x_led *led = &pca955x->leds[offset];
+ struct pca955x_led *led = pca955x_gpio_get_led_index(pca955x, offset);
u8 reg = 0;

/* There is nothing we can do about errors */
+ if (led == NULL)
+ return 0;
+
+ /* There is nothing we can do about errors */
pca955x_read_input(pca955x->client, led->led_num / 8, &reg);

return !!(reg & (1 << (led->led_num % 8)));
@@ -497,6 +513,11 @@ static int pca955x_probe(struct i2c_client *client,
if (!pca955x->leds)
return -ENOMEM;

+ pca955x->gpio_to_index = devm_kzalloc(&client->dev,
+ sizeof(int) * chip->bits, GFP_KERNEL);
+ if (!pca955x->gpio_to_index)
+ return -ENOMEM;
+
i2c_set_clientdata(client, pca955x);

mutex_init(&pca955x->lock);
@@ -508,12 +529,13 @@ static int pca955x_probe(struct i2c_client *client,
pca955x_led->led_num = i;
pca955x_led->pca955x = pca955x;
pca955x_led->type = pdata->leds[i].type;
+ pca955x->gpio_to_index[i] = -ENOENT;

switch (pca955x_led->type) {
case PCA955X_TYPE_NONE:
break;
case PCA955X_TYPE_GPIO:
- ngpios++;
+ pca955x->gpio_to_index[ngpios++] = i;
break;
case PCA955X_TYPE_LED:
/*
--
1.7.9.5


--------------CABB12C0C07A10B6E44BEE10--