Commit f92e8f81 authored by Mark Brown's avatar Mark Brown Committed by Samuel Ortiz

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: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 6b8274fa
...@@ -38,10 +38,13 @@ static int wm831x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) ...@@ -38,10 +38,13 @@ static int wm831x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
{ {
struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
struct wm831x *wm831x = wm831x_gpio->wm831x; struct wm831x *wm831x = wm831x_gpio->wm831x;
int val = WM831X_GPN_DIR;
if (wm831x->has_gpio_ena)
val |= WM831X_GPN_TRI;
return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset, return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
WM831X_GPN_DIR | WM831X_GPN_TRI, WM831X_GPN_DIR | WM831X_GPN_TRI, val);
WM831X_GPN_DIR);
} }
static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset) 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,10 +77,14 @@ static int wm831x_gpio_direction_out(struct gpio_chip *chip,
{ {
struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
struct wm831x *wm831x = wm831x_gpio->wm831x; struct wm831x *wm831x = wm831x_gpio->wm831x;
int val = 0;
int ret; int ret;
if (wm831x->has_gpio_ena)
val |= WM831X_GPN_TRI;
ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset, ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
WM831X_GPN_DIR | WM831X_GPN_TRI, 0); WM831X_GPN_DIR | WM831X_GPN_TRI, val);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -103,7 +110,7 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) ...@@ -103,7 +110,7 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{ {
struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
struct wm831x *wm831x = wm831x_gpio->wm831x; struct wm831x *wm831x = wm831x_gpio->wm831x;
int i; int i, tristated;
for (i = 0; i < chip->ngpio; i++) { for (i = 0; i < chip->ngpio; i++) {
int gpio = i + chip->base; int gpio = i + chip->base;
...@@ -170,6 +177,10 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) ...@@ -170,6 +177,10 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
break; break;
} }
tristated = reg & WM831X_GPN_TRI;
if (wm831x->has_gpio_ena)
tristated = !tristated;
seq_printf(s, " %s %s %s %s%s\n" seq_printf(s, " %s %s %s %s%s\n"
" %s%s (0x%4x)\n", " %s%s (0x%4x)\n",
reg & WM831X_GPN_DIR ? "in" : "out", 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,7 +189,7 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
powerdomain, powerdomain,
reg & WM831X_GPN_POL ? "" : " inverted", reg & WM831X_GPN_POL ? "" : " inverted",
reg & WM831X_GPN_OD ? "open-drain" : "CMOS", reg & WM831X_GPN_OD ? "open-drain" : "CMOS",
reg & WM831X_GPN_TRI ? " tristated" : "", tristated ? " tristated" : "",
reg); reg);
} }
} }
......
...@@ -1449,18 +1449,33 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ...@@ -1449,18 +1449,33 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
case WM8310: case WM8310:
parent = WM8310; parent = WM8310;
wm831x->num_gpio = 16; wm831x->num_gpio = 16;
if (rev > 0) {
wm831x->has_gpio_ena = 1;
wm831x->has_cs_sts = 1;
}
dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev); dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev);
break; break;
case WM8311: case WM8311:
parent = WM8311; parent = WM8311;
wm831x->num_gpio = 16; wm831x->num_gpio = 16;
if (rev > 0) {
wm831x->has_gpio_ena = 1;
wm831x->has_cs_sts = 1;
}
dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev); dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev);
break; break;
case WM8312: case WM8312:
parent = WM8312; parent = WM8312;
wm831x->num_gpio = 16; wm831x->num_gpio = 16;
if (rev > 0) {
wm831x->has_gpio_ena = 1;
wm831x->has_cs_sts = 1;
}
dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev); dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev);
break; break;
......
...@@ -254,6 +254,10 @@ struct wm831x { ...@@ -254,6 +254,10 @@ struct wm831x {
int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */ int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */
int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */ int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */
/* Chip revision based flags */
unsigned has_gpio_ena:1; /* Has GPIO enable bit */
unsigned has_cs_sts:1; /* Has current sink status bit */
int num_gpio; int num_gpio;
struct mutex auxadc_lock; struct mutex auxadc_lock;
......
...@@ -41,6 +41,10 @@ ...@@ -41,6 +41,10 @@
#define WM831X_GPN_OD_MASK 0x0200 /* GPN_OD */ #define WM831X_GPN_OD_MASK 0x0200 /* GPN_OD */
#define WM831X_GPN_OD_SHIFT 9 /* GPN_OD */ #define WM831X_GPN_OD_SHIFT 9 /* GPN_OD */
#define WM831X_GPN_OD_WIDTH 1 /* GPN_OD */ #define WM831X_GPN_OD_WIDTH 1 /* GPN_OD */
#define WM831X_GPN_ENA 0x0080 /* GPN_ENA */
#define WM831X_GPN_ENA_MASK 0x0080 /* GPN_ENA */
#define WM831X_GPN_ENA_SHIFT 7 /* GPN_ENA */
#define WM831X_GPN_ENA_WIDTH 1 /* GPN_ENA */
#define WM831X_GPN_TRI 0x0080 /* GPN_TRI */ #define WM831X_GPN_TRI 0x0080 /* GPN_TRI */
#define WM831X_GPN_TRI_MASK 0x0080 /* GPN_TRI */ #define WM831X_GPN_TRI_MASK 0x0080 /* GPN_TRI */
#define WM831X_GPN_TRI_SHIFT 7 /* GPN_TRI */ #define WM831X_GPN_TRI_SHIFT 7 /* GPN_TRI */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment