>From 5f8be223e8b302dbba2690560c1ea74b6e26c07f Mon Sep 17 00:00:00 2001 From: Andrea Scian Date: Tue, 17 Oct 2017 11:09:11 +0200 Subject: [PATCH] leds: pca955x: map gpio offset to led index correctly 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 --- 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, ®); 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