1/* 2 * wm831x-gpio.c -- gpiolib support for Wolfson WM831x PMICs 3 * 4 * Copyright 2009 Wolfson Microelectronics PLC. 5 * 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 */ 14 15#include <linux/kernel.h> 16#include <linux/slab.h> 17#include <linux/module.h> 18#include <linux/gpio.h> 19#include <linux/mfd/core.h> 20#include <linux/platform_device.h> 21#include <linux/seq_file.h> 22 23#include <linux/mfd/wm831x/core.h> 24#include <linux/mfd/wm831x/pdata.h> 25#include <linux/mfd/wm831x/gpio.h> 26#include <linux/mfd/wm831x/irq.h> 27 28struct wm831x_gpio { 29 struct wm831x *wm831x; 30 struct gpio_chip gpio_chip; 31}; 32 33static inline struct wm831x_gpio *to_wm831x_gpio(struct gpio_chip *chip) 34{ 35 return container_of(chip, struct wm831x_gpio, gpio_chip); 36} 37 38static int wm831x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) 39{ 40 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 41 struct wm831x *wm831x = wm831x_gpio->wm831x; 42 int val = WM831X_GPN_DIR; 43 44 if (wm831x->has_gpio_ena) 45 val |= WM831X_GPN_TRI; 46 47 return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset, 48 WM831X_GPN_DIR | WM831X_GPN_TRI | 49 WM831X_GPN_FN_MASK, val); 50} 51 52static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset) 53{ 54 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 55 struct wm831x *wm831x = wm831x_gpio->wm831x; 56 int ret; 57 58 ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL); 59 if (ret < 0) 60 return ret; 61 62 if (ret & 1 << offset) 63 return 1; 64 else 65 return 0; 66} 67 68static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 69{ 70 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 71 struct wm831x *wm831x = wm831x_gpio->wm831x; 72 73 wm831x_set_bits(wm831x, WM831X_GPIO_LEVEL, 1 << offset, 74 value << offset); 75} 76 77static int wm831x_gpio_direction_out(struct gpio_chip *chip, 78 unsigned offset, int value) 79{ 80 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 81 struct wm831x *wm831x = wm831x_gpio->wm831x; 82 int val = 0; 83 int ret; 84 85 if (wm831x->has_gpio_ena) 86 val |= WM831X_GPN_TRI; 87 88 ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset, 89 WM831X_GPN_DIR | WM831X_GPN_TRI | 90 WM831X_GPN_FN_MASK, val); 91 if (ret < 0) 92 return ret; 93 94 /* Can only set GPIO state once it's in output mode */ 95 wm831x_gpio_set(chip, offset, value); 96 97 return 0; 98} 99 100static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 101{ 102 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 103 struct wm831x *wm831x = wm831x_gpio->wm831x; 104 105 if (!wm831x->irq_base) 106 return -EINVAL; 107 108 return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset; 109} 110 111static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, 112 unsigned debounce) 113{ 114 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 115 struct wm831x *wm831x = wm831x_gpio->wm831x; 116 int reg = WM831X_GPIO1_CONTROL + offset; 117 int ret, fn; 118 119 ret = wm831x_reg_read(wm831x, reg); 120 if (ret < 0) 121 return ret; 122 123 switch (ret & WM831X_GPN_FN_MASK) { 124 case 0: 125 case 1: 126 break; 127 default: 128 /* Not in GPIO mode */ 129 return -EBUSY; 130 } 131 132 if (debounce >= 32 && debounce <= 64) 133 fn = 0; 134 else if (debounce >= 4000 && debounce <= 8000) 135 fn = 1; 136 else 137 return -EINVAL; 138 139 return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn); 140} 141 142#ifdef CONFIG_DEBUG_FS 143static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) 144{ 145 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 146 struct wm831x *wm831x = wm831x_gpio->wm831x; 147 int i, tristated; 148 149 for (i = 0; i < chip->ngpio; i++) { 150 int gpio = i + chip->base; 151 int reg; 152 const char *label, *pull, *powerdomain; 153 154 /* We report the GPIO even if it's not requested since 155 * we're also reporting things like alternate 156 * functions which apply even when the GPIO is not in 157 * use as a GPIO. 158 */ 159 label = gpiochip_is_requested(chip, i); 160 if (!label) 161 label = "Unrequested"; 162 163 seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label); 164 165 reg = wm831x_reg_read(wm831x, WM831X_GPIO1_CONTROL + i); 166 if (reg < 0) { 167 dev_err(wm831x->dev, 168 "GPIO control %d read failed: %d\n", 169 gpio, reg); 170 seq_printf(s, "\n"); 171 continue; 172 } 173 174 switch (reg & WM831X_GPN_PULL_MASK) { 175 case WM831X_GPIO_PULL_NONE: 176 pull = "nopull"; 177 break; 178 case WM831X_GPIO_PULL_DOWN: 179 pull = "pulldown"; 180 break; 181 case WM831X_GPIO_PULL_UP: 182 pull = "pullup"; 183 default: 184 pull = "INVALID PULL"; 185 break; 186 } 187 188 switch (i + 1) { 189 case 1 ... 3: 190 case 7 ... 9: 191 if (reg & WM831X_GPN_PWR_DOM) 192 powerdomain = "VPMIC"; 193 else 194 powerdomain = "DBVDD"; 195 break; 196 197 case 4 ... 6: 198 case 10 ... 12: 199 if (reg & WM831X_GPN_PWR_DOM) 200 powerdomain = "SYSVDD"; 201 else 202 powerdomain = "DBVDD"; 203 break; 204 205 case 13 ... 16: 206 powerdomain = "TPVDD"; 207 break; 208 209 default: 210 BUG(); 211 break; 212 } 213 214 tristated = reg & WM831X_GPN_TRI; 215 if (wm831x->has_gpio_ena) 216 tristated = !tristated; 217 218 seq_printf(s, " %s %s %s %s%s\n" 219 " %s%s (0x%4x)\n", 220 reg & WM831X_GPN_DIR ? "in" : "out", 221 wm831x_gpio_get(chip, i) ? "high" : "low", 222 pull, 223 powerdomain, 224 reg & WM831X_GPN_POL ? "" : " inverted", 225 reg & WM831X_GPN_OD ? "open-drain" : "CMOS", 226 tristated ? " tristated" : "", 227 reg); 228 } 229} 230#else 231#define wm831x_gpio_dbg_show NULL 232#endif 233 234static struct gpio_chip template_chip = { 235 .label = "wm831x", 236 .owner = THIS_MODULE, 237 .direction_input = wm831x_gpio_direction_in, 238 .get = wm831x_gpio_get, 239 .direction_output = wm831x_gpio_direction_out, 240 .set = wm831x_gpio_set, 241 .to_irq = wm831x_gpio_to_irq, 242 .set_debounce = wm831x_gpio_set_debounce, 243 .dbg_show = wm831x_gpio_dbg_show, 244 .can_sleep = 1, 245}; 246 247static int __devinit wm831x_gpio_probe(struct platform_device *pdev) 248{ 249 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); 250 struct wm831x_pdata *pdata = wm831x->dev->platform_data; 251 struct wm831x_gpio *wm831x_gpio; 252 int ret; 253 254 wm831x_gpio = kzalloc(sizeof(*wm831x_gpio), GFP_KERNEL); 255 if (wm831x_gpio == NULL) 256 return -ENOMEM; 257 258 wm831x_gpio->wm831x = wm831x; 259 wm831x_gpio->gpio_chip = template_chip; 260 wm831x_gpio->gpio_chip.ngpio = wm831x->num_gpio; 261 wm831x_gpio->gpio_chip.dev = &pdev->dev; 262 if (pdata && pdata->gpio_base) 263 wm831x_gpio->gpio_chip.base = pdata->gpio_base; 264 else 265 wm831x_gpio->gpio_chip.base = -1; 266 267 ret = gpiochip_add(&wm831x_gpio->gpio_chip); 268 if (ret < 0) { 269 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", 270 ret); 271 goto err; 272 } 273 274 platform_set_drvdata(pdev, wm831x_gpio); 275 276 return ret; 277 278err: 279 kfree(wm831x_gpio); 280 return ret; 281} 282 283static int __devexit wm831x_gpio_remove(struct platform_device *pdev) 284{ 285 struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev); 286 int ret; 287 288 ret = gpiochip_remove(&wm831x_gpio->gpio_chip); 289 if (ret == 0) 290 kfree(wm831x_gpio); 291 292 return ret; 293} 294 295static struct platform_driver wm831x_gpio_driver = { 296 .driver.name = "wm831x-gpio", 297 .driver.owner = THIS_MODULE, 298 .probe = wm831x_gpio_probe, 299 .remove = __devexit_p(wm831x_gpio_remove), 300}; 301 302static int __init wm831x_gpio_init(void) 303{ 304 return platform_driver_register(&wm831x_gpio_driver); 305} 306subsys_initcall(wm831x_gpio_init); 307 308static void __exit wm831x_gpio_exit(void) 309{ 310 platform_driver_unregister(&wm831x_gpio_driver); 311} 312module_exit(wm831x_gpio_exit); 313 314MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 315MODULE_DESCRIPTION("GPIO interface for WM831x PMICs"); 316MODULE_LICENSE("GPL"); 317MODULE_ALIAS("platform:wm831x-gpio"); 318