diff options
-rw-r--r-- | drivers/gpio/wm831x-gpio.c | 21 | ||||
-rw-r--r-- | drivers/mfd/wm831x-core.c | 15 | ||||
-rw-r--r-- | include/linux/mfd/wm831x/core.h | 4 | ||||
-rw-r--r-- | include/linux/mfd/wm831x/gpio.h | 4 |
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 | ||
47 | static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset) | 50 | static 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 */ |