leds: pca963x: Fix open-drain initialization
authorZahari Petkov <zahari@balena.io>
Mon, 18 Nov 2019 21:02:55 +0000 (23:02 +0200)
committerPavel <pavel@ucw.cz>
Sat, 21 Dec 2019 19:09:51 +0000 (20:09 +0100)
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>
drivers/leds/leds-pca963x.c

index 4afc317901a89178631766076e179209b983ad60..66cdc003b8f42cff8f15ba4634266a169e76150f 100644 (file)
@@ -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);
        }