Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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