[PATCH linux dev-4.10] leds: pca955x: map gpio offset to led index correctly
Cédric Le Goater
clg at kaod.org
Wed Oct 25 19:36:53 AEDT 2017
From: Andrea Scian <andrea.scian at dave.eu>
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 at dave.eu>
[clg: ported on linux openbmc 4.10 kernel ]
Signed-off-by: Cédric Le Goater <clg at kaod.org>
---
This should help in defining mixed GPIO/LED pca9952 devices. I don't
think we need to change our bindings but could we include this patch
to chek is it not breaking anything. I only tested the basics under
QEMU.
drivers/leds/leds-pca955x.c | 38 ++++++++++++++++++++++++++++++--------
1 file changed, 30 insertions(+), 8 deletions(-)
Index: linux-openbmc-4.10.git/drivers/leds/leds-pca955x.c
===================================================================
--- linux-openbmc-4.10.git.orig/drivers/leds/leds-pca955x.c
+++ linux-openbmc-4.10.git/drivers/leds/leds-pca955x.c
@@ -126,6 +126,7 @@ struct pca955x {
struct i2c_client *client;
#ifdef CONFIG_LEDS_PCA955X_GPIO
struct gpio_chip gpio;
+ int *gpio_to_index;
#endif
};
@@ -315,22 +316,34 @@ static int pca955x_read_input(struct i2c
}
+/*
+ * 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 = gpiochip_get_data(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 = gpiochip_get_data(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, PCA955X_GPIO_HIGH);
@@ -347,10 +360,13 @@ static void pca955x_gpio_set_value(struc
static int pca955x_gpio_get_value(struct gpio_chip *gc, unsigned int offset)
{
struct pca955x *pca955x = gpiochip_get_data(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;
+
pca955x_read_input(pca955x->client, led->led_num / 8, ®);
return !!(reg & (1 << (led->led_num % 8)));
@@ -499,6 +515,11 @@ static int pca955x_probe(struct i2c_clie
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);
@@ -510,12 +531,13 @@ static int pca955x_probe(struct i2c_clie
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:
/*
More information about the openbmc
mailing list