| From c2fa2b0b6ed37acfbe91ee68c51bf864d8b2d199 Mon Sep 17 00:00:00 2001 |
| From: Zahari Petkov <zahari@balena.io> |
| Date: Mon, 18 Nov 2019 23:02:55 +0200 |
| Subject: [PATCH] leds: pca963x: Fix open-drain initialization |
| |
| commit 697529091ac7a0a90ca349b914bb30641c13c753 upstream. |
| |
| Before commit bb29b9cccd95 ("leds: pca963x: Add bindings to invert |
| polarity") Mode register 2 was initialized directly with either 0x01 |
| or 0x05 for open-drain or totem pole (push-pull) configuration. |
| |
| Afterwards, MODE2 initialization started using bitwise operations on |
| top of the default MODE2 register value (0x05). Using bitwise OR for |
| setting OUTDRV with 0x01 and 0x05 does not produce correct results. |
| When open-drain is used, instead of setting OUTDRV to 0, the driver |
| keeps it as 1: |
| |
| Open-drain: 0x05 | 0x01 -> 0x05 (0b101 - incorrect) |
| Totem pole: 0x05 | 0x05 -> 0x05 (0b101 - correct but still wrong) |
| |
| Now OUTDRV setting uses correct bitwise operations for initialization: |
| |
| Open-drain: 0x05 & ~0x04 -> 0x01 (0b001 - correct) |
| Totem pole: 0x05 | 0x04 -> 0x05 (0b101 - correct) |
| |
| Additional MODE2 register definitions are introduced now as well. |
| |
| Fixes: bb29b9cccd95 ("leds: pca963x: Add bindings to invert polarity") |
| Signed-off-by: Zahari Petkov <zahari@balena.io> |
| Signed-off-by: Pavel Machek <pavel@ucw.cz> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/leds/leds-pca963x.c b/drivers/leds/leds-pca963x.c |
| index 4afc317901a8..66cdc003b8f4 100644 |
| --- a/drivers/leds/leds-pca963x.c |
| +++ b/drivers/leds/leds-pca963x.c |
| @@ -40,6 +40,8 @@ |
| #define PCA963X_LED_PWM 0x2 /* Controlled through PWM */ |
| #define PCA963X_LED_GRP_PWM 0x3 /* Controlled through PWM/GRPPWM */ |
| |
| +#define PCA963X_MODE2_OUTDRV 0x04 /* Open-drain or totem pole */ |
| +#define PCA963X_MODE2_INVRT 0x10 /* Normal or inverted direction */ |
| #define PCA963X_MODE2_DMBLNK 0x20 /* Enable blinking */ |
| |
| #define PCA963X_MODE1 0x00 |
| @@ -438,12 +440,12 @@ static int pca963x_probe(struct i2c_client *client, |
| PCA963X_MODE2); |
| /* Configure output: open-drain or totem pole (push-pull) */ |
| if (pdata->outdrv == PCA963X_OPEN_DRAIN) |
| - mode2 |= 0x01; |
| + mode2 &= ~PCA963X_MODE2_OUTDRV; |
| else |
| - mode2 |= 0x05; |
| + mode2 |= PCA963X_MODE2_OUTDRV; |
| /* Configure direction: normal or inverted */ |
| if (pdata->dir == PCA963X_INVERTED) |
| - mode2 |= 0x10; |
| + mode2 |= PCA963X_MODE2_INVRT; |
| i2c_smbus_write_byte_data(pca963x->chip->client, PCA963X_MODE2, |
| mode2); |
| } |
| -- |
| 2.7.4 |
| |