1 /* 2 * 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 28 struct wm831x_gpio { 29 struct wm831x *wm831x; 30 struct gpio_chip gpio_chip; 31 }; 32 33 static inline struct wm831x_gpio *to_wm831x_gpio(struct gpio_chip *chip) 34 { 35 return container_of(chip, struct wm831x_gpio, gpio_chip); 36 } 37 38 static 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 52 static 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 68 static 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 77 static 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 100 static 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 111 static 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 143 static 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 break; 184 default: 185 pull = "INVALID PULL"; 186 break; 187 } 188 189 switch (i + 1) { 190 case 1 ... 3: 191 case 7 ... 9: 192 if (reg & WM831X_GPN_PWR_DOM) 193 powerdomain = "VPMIC"; 194 else 195 powerdomain = "DBVDD"; 196 break; 197 198 case 4 ... 6: 199 case 10 ... 12: 200 if (reg & WM831X_GPN_PWR_DOM) 201 powerdomain = "SYSVDD"; 202 else 203 powerdomain = "DBVDD"; 204 break; 205 206 case 13 ... 16: 207 powerdomain = "TPVDD"; 208 break; 209 210 default: 211 BUG(); 212 break; 213 } 214 215 tristated = reg & WM831X_GPN_TRI; 216 if (wm831x->has_gpio_ena) 217 tristated = !tristated; 218 219 seq_printf(s, " %s %s %s %s%s\n" 220 " %s%s (0x%4x)\n", 221 reg & WM831X_GPN_DIR ? "in" : "out", 222 wm831x_gpio_get(chip, i) ? "high" : "low", 223 pull, 224 powerdomain, 225 reg & WM831X_GPN_POL ? "" : " inverted", 226 reg & WM831X_GPN_OD ? "open-drain" : "CMOS", 227 tristated ? " tristated" : "", 228 reg); 229 } 230 } 231 #else 232 #define wm831x_gpio_dbg_show NULL 233 #endif 234 235 static struct gpio_chip template_chip = { 236 .label = "wm831x", 237 .owner = THIS_MODULE, 238 .direction_input = wm831x_gpio_direction_in, 239 .get = wm831x_gpio_get, 240 .direction_output = wm831x_gpio_direction_out, 241 .set = wm831x_gpio_set, 242 .to_irq = wm831x_gpio_to_irq, 243 .set_debounce = wm831x_gpio_set_debounce, 244 .dbg_show = wm831x_gpio_dbg_show, 245 .can_sleep = 1, 246 }; 247 248 static int __devinit wm831x_gpio_probe(struct platform_device *pdev) 249 { 250 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); 251 struct wm831x_pdata *pdata = wm831x->dev->platform_data; 252 struct wm831x_gpio *wm831x_gpio; 253 int ret; 254 255 wm831x_gpio = kzalloc(sizeof(*wm831x_gpio), GFP_KERNEL); 256 if (wm831x_gpio == NULL) 257 return -ENOMEM; 258 259 wm831x_gpio->wm831x = wm831x; 260 wm831x_gpio->gpio_chip = template_chip; 261 wm831x_gpio->gpio_chip.ngpio = wm831x->num_gpio; 262 wm831x_gpio->gpio_chip.dev = &pdev->dev; 263 if (pdata && pdata->gpio_base) 264 wm831x_gpio->gpio_chip.base = pdata->gpio_base; 265 else 266 wm831x_gpio->gpio_chip.base = -1; 267 268 ret = gpiochip_add(&wm831x_gpio->gpio_chip); 269 if (ret < 0) { 270 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", 271 ret); 272 goto err; 273 } 274 275 platform_set_drvdata(pdev, wm831x_gpio); 276 277 return ret; 278 279 err: 280 kfree(wm831x_gpio); 281 return ret; 282 } 283 284 static int __devexit wm831x_gpio_remove(struct platform_device *pdev) 285 { 286 struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev); 287 int ret; 288 289 ret = gpiochip_remove(&wm831x_gpio->gpio_chip); 290 if (ret == 0) 291 kfree(wm831x_gpio); 292 293 return ret; 294 } 295 296 static struct platform_driver wm831x_gpio_driver = { 297 .driver.name = "wm831x-gpio", 298 .driver.owner = THIS_MODULE, 299 .probe = wm831x_gpio_probe, 300 .remove = __devexit_p(wm831x_gpio_remove), 301 }; 302 303 static int __init wm831x_gpio_init(void) 304 { 305 return platform_driver_register(&wm831x_gpio_driver); 306 } 307 subsys_initcall(wm831x_gpio_init); 308 309 static void __exit wm831x_gpio_exit(void) 310 { 311 platform_driver_unregister(&wm831x_gpio_driver); 312 } 313 module_exit(wm831x_gpio_exit); 314 315 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 316 MODULE_DESCRIPTION("GPIO interface for WM831x PMICs"); 317 MODULE_LICENSE("GPL"); 318 MODULE_ALIAS("platform:wm831x-gpio"); 319