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