aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpio/wm831x-gpio.c21
-rw-r--r--drivers/mfd/wm831x-core.c15
-rw-r--r--include/linux/mfd/wm831x/core.h4
-rw-r--r--include/linux/mfd/wm831x/gpio.h4
4 files changed, 39 insertions, 5 deletions
diff --git a/drivers/gpio/wm831x-gpio.c b/drivers/gpio/wm831x-gpio.c
index 2554180534a1..5b8dc098d80f 100644
--- a/drivers/gpio/wm831x-gpio.c
+++ b/drivers/gpio/wm831x-gpio.c
@@ -38,10 +38,13 @@ static int wm831x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
38{ 38{
39 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 39 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
40 struct wm831x *wm831x = wm831x_gpio->wm831x; 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 return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset, 46 return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
43 WM831X_GPN_DIR | WM831X_GPN_TRI, 47 WM831X_GPN_DIR | WM831X_GPN_TRI, val);
44 WM831X_GPN_DIR);
45} 48}
46 49
47static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset) 50static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -74,10 +77,14 @@ static int wm831x_gpio_direction_out(struct gpio_chip *chip,
74{ 77{
75 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 78 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
76 struct wm831x *wm831x = wm831x_gpio->wm831x; 79 struct wm831x *wm831x = wm831x_gpio->wm831x;
80 int val = 0;
77 int ret; 81 int ret;
78 82
83 if (wm831x->has_gpio_ena)
84 val |= WM831X_GPN_TRI;
85
79 ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset, 86 ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
80 WM831X_GPN_DIR | WM831X_GPN_TRI, 0); 87 WM831X_GPN_DIR | WM831X_GPN_TRI, val);
81 if (ret < 0) 88 if (ret < 0)
82 return ret; 89 return ret;
83 90
@@ -103,7 +110,7 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
103{ 110{
104 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 111 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
105 struct wm831x *wm831x = wm831x_gpio->wm831x; 112 struct wm831x *wm831x = wm831x_gpio->wm831x;
106 int i; 113 int i, tristated;
107 114
108 for (i = 0; i < chip->ngpio; i++) { 115 for (i = 0; i < chip->ngpio; i++) {
109 int gpio = i + chip->base; 116 int gpio = i + chip->base;
@@ -170,6 +177,10 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
170 break; 177 break;
171 } 178 }
172 179
180 tristated = reg & WM831X_GPN_TRI;
181 if (wm831x->has_gpio_ena)
182 tristated = !tristated;
183
173 seq_printf(s, " %s %s %s %s%s\n" 184 seq_printf(s, " %s %s %s %s%s\n"
174 " %s%s (0x%4x)\n", 185 " %s%s (0x%4x)\n",
175 reg & WM831X_GPN_DIR ? "in" : "out", 186 reg & WM831X_GPN_DIR ? "in" : "out",
@@ -178,7 +189,7 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
178 powerdomain, 189 powerdomain,
179 reg & WM831X_GPN_POL ? "" : " inverted", 190 reg & WM831X_GPN_POL ? "" : " inverted",
180 reg & WM831X_GPN_OD ? "open-drain" : "CMOS", 191 reg & WM831X_GPN_OD ? "open-drain" : "CMOS",
181 reg & WM831X_GPN_TRI ? " tristated" : "", 192 tristated ? " tristated" : "",
182 reg); 193 reg);
183 } 194 }
184} 195}
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index 4b2021af1d96..c428d9f918fc 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -1449,18 +1449,33 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1449 case WM8310: 1449 case WM8310:
1450 parent = WM8310; 1450 parent = WM8310;
1451 wm831x->num_gpio = 16; 1451 wm831x->num_gpio = 16;
1452 if (rev > 0) {
1453 wm831x->has_gpio_ena = 1;
1454 wm831x->has_cs_sts = 1;
1455 }
1456
1452 dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev); 1457 dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev);
1453 break; 1458 break;
1454 1459
1455 case WM8311: 1460 case WM8311:
1456 parent = WM8311; 1461 parent = WM8311;
1457 wm831x->num_gpio = 16; 1462 wm831x->num_gpio = 16;
1463 if (rev > 0) {
1464 wm831x->has_gpio_ena = 1;
1465 wm831x->has_cs_sts = 1;
1466 }
1467
1458 dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev); 1468 dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev);
1459 break; 1469 break;
1460 1470
1461 case WM8312: 1471 case WM8312:
1462 parent = WM8312; 1472 parent = WM8312;
1463 wm831x->num_gpio = 16; 1473 wm831x->num_gpio = 16;
1474 if (rev > 0) {
1475 wm831x->has_gpio_ena = 1;
1476 wm831x->has_cs_sts = 1;
1477 }
1478
1464 dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev); 1479 dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev);
1465 break; 1480 break;
1466 1481
diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h
index 5184b79c700b..53580b592bc9 100644
--- a/include/linux/mfd/wm831x/core.h
+++ b/include/linux/mfd/wm831x/core.h
@@ -254,6 +254,10 @@ struct wm831x {
254 int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */ 254 int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */
255 int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */ 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 int num_gpio; 261 int num_gpio;
258 262
259 struct mutex auxadc_lock; 263 struct mutex auxadc_lock;
diff --git a/include/linux/mfd/wm831x/gpio.h b/include/linux/mfd/wm831x/gpio.h
index 2835614af0e3..9b163c58865f 100644
--- a/include/linux/mfd/wm831x/gpio.h
+++ b/include/linux/mfd/wm831x/gpio.h
@@ -41,6 +41,10 @@
41#define WM831X_GPN_OD_MASK 0x0200 /* GPN_OD */ 41#define WM831X_GPN_OD_MASK 0x0200 /* GPN_OD */
42#define WM831X_GPN_OD_SHIFT 9 /* GPN_OD */ 42#define WM831X_GPN_OD_SHIFT 9 /* GPN_OD */
43#define WM831X_GPN_OD_WIDTH 1 /* GPN_OD */ 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#define WM831X_GPN_TRI 0x0080 /* GPN_TRI */ 48#define WM831X_GPN_TRI 0x0080 /* GPN_TRI */
45#define WM831X_GPN_TRI_MASK 0x0080 /* GPN_TRI */ 49#define WM831X_GPN_TRI_MASK 0x0080 /* GPN_TRI */
46#define WM831X_GPN_TRI_SHIFT 7 /* GPN_TRI */ 50#define WM831X_GPN_TRI_SHIFT 7 /* GPN_TRI */