aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-02-17 13:45:25 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2010-03-07 16:17:29 -0500
commitf92e8f8144243a3651b2e350b706ea2d04931f8c (patch)
treee008f4b0896cdeb2fb354a1e1babd2a568172498
parent6b8274fafeec9b112cee5b6ced5f9189957c889f (diff)
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>
-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 */