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 return irq_create_mapping(wm831x->irq_domain, 106 WM831X_IRQ_GPIO_1 + offset); 107 } 108 109 static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, 110 unsigned debounce) 111 { 112 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 113 struct wm831x *wm831x = wm831x_gpio->wm831x; 114 int reg = WM831X_GPIO1_CONTROL + offset; 115 int ret, fn; 116 117 ret = wm831x_reg_read(wm831x, reg); 118 if (ret < 0) 119 return ret; 120 121 switch (ret & WM831X_GPN_FN_MASK) { 122 case 0: 123 case 1: 124 break; 125 default: 126 /* Not in GPIO mode */ 127 return -EBUSY; 128 } 129 130 if (debounce >= 32 && debounce <= 64) 131 fn = 0; 132 else if (debounce >= 4000 && debounce <= 8000) 133 fn = 1; 134 else 135 return -EINVAL; 136 137 return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn); 138 } 139 140 #ifdef CONFIG_DEBUG_FS 141 static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) 142 { 143 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 144 struct wm831x *wm831x = wm831x_gpio->wm831x; 145 int i, tristated; 146 147 for (i = 0; i < chip->ngpio; i++) { 148 int gpio = i + chip->base; 149 int reg; 150 const char *label, *pull, *powerdomain; 151 152 /* We report the GPIO even if it's not requested since 153 * we're also reporting things like alternate 154 * functions which apply even when the GPIO is not in 155 * use as a GPIO. 156 */ 157 label = gpiochip_is_requested(chip, i); 158 if (!label) 159 label = "Unrequested"; 160 161 seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label); 162 163 reg = wm831x_reg_read(wm831x, WM831X_GPIO1_CONTROL + i); 164 if (reg < 0) { 165 dev_err(wm831x->dev, 166 "GPIO control %d read failed: %d\n", 167 gpio, reg); 168 seq_printf(s, "\n"); 169 continue; 170 } 171 172 switch (reg & WM831X_GPN_PULL_MASK) { 173 case WM831X_GPIO_PULL_NONE: 174 pull = "nopull"; 175 break; 176 case WM831X_GPIO_PULL_DOWN: 177 pull = "pulldown"; 178 break; 179 case WM831X_GPIO_PULL_UP: 180 pull = "pullup"; 181 break; 182 default: 183 pull = "INVALID PULL"; 184 break; 185 } 186 187 switch (i + 1) { 188 case 1 ... 3: 189 case 7 ... 9: 190 if (reg & WM831X_GPN_PWR_DOM) 191 powerdomain = "VPMIC"; 192 else 193 powerdomain = "DBVDD"; 194 break; 195 196 case 4 ... 6: 197 case 10 ... 12: 198 if (reg & WM831X_GPN_PWR_DOM) 199 powerdomain = "SYSVDD"; 200 else 201 powerdomain = "DBVDD"; 202 break; 203 204 case 13 ... 16: 205 powerdomain = "TPVDD"; 206 break; 207 208 default: 209 BUG(); 210 break; 211 } 212 213 tristated = reg & WM831X_GPN_TRI; 214 if (wm831x->has_gpio_ena) 215 tristated = !tristated; 216 217 seq_printf(s, " %s %s %s %s%s\n" 218 " %s%s (0x%4x)\n", 219 reg & WM831X_GPN_DIR ? "in" : "out", 220 wm831x_gpio_get(chip, i) ? "high" : "low", 221 pull, 222 powerdomain, 223 reg & WM831X_GPN_POL ? "" : " inverted", 224 reg & WM831X_GPN_OD ? "open-drain" : "CMOS", 225 tristated ? " tristated" : "", 226 reg); 227 } 228 } 229 #else 230 #define wm831x_gpio_dbg_show NULL 231 #endif 232 233 static struct gpio_chip template_chip = { 234 .label = "wm831x", 235 .owner = THIS_MODULE, 236 .direction_input = wm831x_gpio_direction_in, 237 .get = wm831x_gpio_get, 238 .direction_output = wm831x_gpio_direction_out, 239 .set = wm831x_gpio_set, 240 .to_irq = wm831x_gpio_to_irq, 241 .set_debounce = wm831x_gpio_set_debounce, 242 .dbg_show = wm831x_gpio_dbg_show, 243 .can_sleep = 1, 244 }; 245 246 static int __devinit wm831x_gpio_probe(struct platform_device *pdev) 247 { 248 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); 249 struct wm831x_pdata *pdata = wm831x->dev->platform_data; 250 struct wm831x_gpio *wm831x_gpio; 251 int ret; 252 253 wm831x_gpio = kzalloc(sizeof(*wm831x_gpio), GFP_KERNEL); 254 if (wm831x_gpio == NULL) 255 return -ENOMEM; 256 257 wm831x_gpio->wm831x = wm831x; 258 wm831x_gpio->gpio_chip = template_chip; 259 wm831x_gpio->gpio_chip.ngpio = wm831x->num_gpio; 260 wm831x_gpio->gpio_chip.dev = &pdev->dev; 261 if (pdata && pdata->gpio_base) 262 wm831x_gpio->gpio_chip.base = pdata->gpio_base; 263 else 264 wm831x_gpio->gpio_chip.base = -1; 265 266 ret = gpiochip_add(&wm831x_gpio->gpio_chip); 267 if (ret < 0) { 268 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", 269 ret); 270 goto err; 271 } 272 273 platform_set_drvdata(pdev, wm831x_gpio); 274 275 return ret; 276 277 err: 278 kfree(wm831x_gpio); 279 return ret; 280 } 281 282 static int __devexit wm831x_gpio_remove(struct platform_device *pdev) 283 { 284 struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev); 285 int ret; 286 287 ret = gpiochip_remove(&wm831x_gpio->gpio_chip); 288 if (ret == 0) 289 kfree(wm831x_gpio); 290 291 return ret; 292 } 293 294 static struct platform_driver wm831x_gpio_driver = { 295 .driver.name = "wm831x-gpio", 296 .driver.owner = THIS_MODULE, 297 .probe = wm831x_gpio_probe, 298 .remove = __devexit_p(wm831x_gpio_remove), 299 }; 300 301 static int __init wm831x_gpio_init(void) 302 { 303 return platform_driver_register(&wm831x_gpio_driver); 304 } 305 subsys_initcall(wm831x_gpio_init); 306 307 static void __exit wm831x_gpio_exit(void) 308 { 309 platform_driver_unregister(&wm831x_gpio_driver); 310 } 311 module_exit(wm831x_gpio_exit); 312 313 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 314 MODULE_DESCRIPTION("GPIO interface for WM831x PMICs"); 315 MODULE_LICENSE("GPL"); 316 MODULE_ALIAS("platform:wm831x-gpio"); 317