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 */ |
