Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: Add WM831x revision B support

Revision B of the WM831x devices changes the sense of the tristate
bit for GPIO configuration, inverting it to become an enable instead.
Take account of this in the gpiolib driver.

A current sink regulation status bit has also been added in revision B,
add a flag indicating if it's present but don't use it yet.

This revision also adds an interrupt on key up for the ON pin event
which the existing code is able to take advantage of.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Mark Brown and committed by
Samuel Ortiz
f92e8f81 6b8274fa

+39 -5
+16 -5
drivers/gpio/wm831x-gpio.c
··· 38 38 { 39 39 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 40 40 struct wm831x *wm831x = wm831x_gpio->wm831x; 41 + int val = WM831X_GPN_DIR; 42 + 43 + if (wm831x->has_gpio_ena) 44 + val |= WM831X_GPN_TRI; 41 45 42 46 return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset, 43 - WM831X_GPN_DIR | WM831X_GPN_TRI, 44 - WM831X_GPN_DIR); 47 + WM831X_GPN_DIR | WM831X_GPN_TRI, val); 45 48 } 46 49 47 50 static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset) ··· 77 74 { 78 75 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 79 76 struct wm831x *wm831x = wm831x_gpio->wm831x; 77 + int val = 0; 80 78 int ret; 81 79 80 + if (wm831x->has_gpio_ena) 81 + val |= WM831X_GPN_TRI; 82 + 82 83 ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset, 83 - WM831X_GPN_DIR | WM831X_GPN_TRI, 0); 84 + WM831X_GPN_DIR | WM831X_GPN_TRI, val); 84 85 if (ret < 0) 85 86 return ret; 86 87 ··· 110 103 { 111 104 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 112 105 struct wm831x *wm831x = wm831x_gpio->wm831x; 113 - int i; 106 + int i, tristated; 114 107 115 108 for (i = 0; i < chip->ngpio; i++) { 116 109 int gpio = i + chip->base; ··· 177 170 break; 178 171 } 179 172 173 + tristated = reg & WM831X_GPN_TRI; 174 + if (wm831x->has_gpio_ena) 175 + tristated = !tristated; 176 + 180 177 seq_printf(s, " %s %s %s %s%s\n" 181 178 " %s%s (0x%4x)\n", 182 179 reg & WM831X_GPN_DIR ? "in" : "out", ··· 189 178 powerdomain, 190 179 reg & WM831X_GPN_POL ? "" : " inverted", 191 180 reg & WM831X_GPN_OD ? "open-drain" : "CMOS", 192 - reg & WM831X_GPN_TRI ? " tristated" : "", 181 + tristated ? " tristated" : "", 193 182 reg); 194 183 } 195 184 }
+15
drivers/mfd/wm831x-core.c
··· 1449 1449 case WM8310: 1450 1450 parent = WM8310; 1451 1451 wm831x->num_gpio = 16; 1452 + if (rev > 0) { 1453 + wm831x->has_gpio_ena = 1; 1454 + wm831x->has_cs_sts = 1; 1455 + } 1456 + 1452 1457 dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev); 1453 1458 break; 1454 1459 1455 1460 case WM8311: 1456 1461 parent = WM8311; 1457 1462 wm831x->num_gpio = 16; 1463 + if (rev > 0) { 1464 + wm831x->has_gpio_ena = 1; 1465 + wm831x->has_cs_sts = 1; 1466 + } 1467 + 1458 1468 dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev); 1459 1469 break; 1460 1470 1461 1471 case WM8312: 1462 1472 parent = WM8312; 1463 1473 wm831x->num_gpio = 16; 1474 + if (rev > 0) { 1475 + wm831x->has_gpio_ena = 1; 1476 + wm831x->has_cs_sts = 1; 1477 + } 1478 + 1464 1479 dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev); 1465 1480 break; 1466 1481
+4
include/linux/mfd/wm831x/core.h
··· 254 254 int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */ 255 255 int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */ 256 256 257 + /* Chip revision based flags */ 258 + unsigned has_gpio_ena:1; /* Has GPIO enable bit */ 259 + unsigned has_cs_sts:1; /* Has current sink status bit */ 260 + 257 261 int num_gpio; 258 262 259 263 struct mutex auxadc_lock;
+4
include/linux/mfd/wm831x/gpio.h
··· 41 41 #define WM831X_GPN_OD_MASK 0x0200 /* GPN_OD */ 42 42 #define WM831X_GPN_OD_SHIFT 9 /* GPN_OD */ 43 43 #define WM831X_GPN_OD_WIDTH 1 /* GPN_OD */ 44 + #define WM831X_GPN_ENA 0x0080 /* GPN_ENA */ 45 + #define WM831X_GPN_ENA_MASK 0x0080 /* GPN_ENA */ 46 + #define WM831X_GPN_ENA_SHIFT 7 /* GPN_ENA */ 47 + #define WM831X_GPN_ENA_WIDTH 1 /* GPN_ENA */ 44 48 #define WM831X_GPN_TRI 0x0080 /* GPN_TRI */ 45 49 #define WM831X_GPN_TRI_MASK 0x0080 /* GPN_TRI */ 46 50 #define WM831X_GPN_TRI_SHIFT 7 /* GPN_TRI */