pinctrl-da9062.c (8009B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Dialog DA9062 pinctrl and GPIO driver. 4 * Based on DA9055 GPIO driver. 5 * 6 * TODO: 7 * - add pinmux and pinctrl support (gpio alternate mode) 8 * 9 * Documents: 10 * [1] https://www.dialog-semiconductor.com/sites/default/files/da9062_datasheet_3v6.pdf 11 * 12 * Copyright (C) 2019 Pengutronix, Marco Felsch <kernel@pengutronix.de> 13 */ 14#include <linux/bits.h> 15#include <linux/module.h> 16#include <linux/platform_device.h> 17#include <linux/property.h> 18#include <linux/regmap.h> 19 20#include <linux/gpio/driver.h> 21 22#include <linux/mfd/da9062/core.h> 23#include <linux/mfd/da9062/registers.h> 24 25/* 26 * We need this get the gpio_desc from a <gpio_chip,offset> tuple to decide if 27 * the gpio is active low without a vendor specific dt-binding. 28 */ 29#include "../gpio/gpiolib.h" 30 31#define DA9062_TYPE(offset) (4 * (offset % 2)) 32#define DA9062_PIN_SHIFT(offset) (4 * (offset % 2)) 33#define DA9062_PIN_ALTERNATE 0x00 /* gpio alternate mode */ 34#define DA9062_PIN_GPI 0x01 /* gpio in */ 35#define DA9062_PIN_GPO_OD 0x02 /* gpio out open-drain */ 36#define DA9062_PIN_GPO_PP 0x03 /* gpio out push-pull */ 37#define DA9062_GPIO_NUM 5 38 39struct da9062_pctl { 40 struct da9062 *da9062; 41 struct gpio_chip gc; 42 unsigned int pin_config[DA9062_GPIO_NUM]; 43}; 44 45static int da9062_pctl_get_pin_mode(struct da9062_pctl *pctl, 46 unsigned int offset) 47{ 48 struct regmap *regmap = pctl->da9062->regmap; 49 int ret, val; 50 51 ret = regmap_read(regmap, DA9062AA_GPIO_0_1 + (offset >> 1), &val); 52 if (ret < 0) 53 return ret; 54 55 val >>= DA9062_PIN_SHIFT(offset); 56 val &= DA9062AA_GPIO0_PIN_MASK; 57 58 return val; 59} 60 61static int da9062_pctl_set_pin_mode(struct da9062_pctl *pctl, 62 unsigned int offset, unsigned int mode_req) 63{ 64 struct regmap *regmap = pctl->da9062->regmap; 65 unsigned int mode = mode_req; 66 unsigned int mask; 67 int ret; 68 69 mode &= DA9062AA_GPIO0_PIN_MASK; 70 mode <<= DA9062_PIN_SHIFT(offset); 71 mask = DA9062AA_GPIO0_PIN_MASK << DA9062_PIN_SHIFT(offset); 72 73 ret = regmap_update_bits(regmap, DA9062AA_GPIO_0_1 + (offset >> 1), 74 mask, mode); 75 if (!ret) 76 pctl->pin_config[offset] = mode_req; 77 78 return ret; 79} 80 81static int da9062_gpio_get(struct gpio_chip *gc, unsigned int offset) 82{ 83 struct da9062_pctl *pctl = gpiochip_get_data(gc); 84 struct regmap *regmap = pctl->da9062->regmap; 85 int gpio_mode, val; 86 int ret; 87 88 gpio_mode = da9062_pctl_get_pin_mode(pctl, offset); 89 if (gpio_mode < 0) 90 return gpio_mode; 91 92 switch (gpio_mode) { 93 case DA9062_PIN_ALTERNATE: 94 return -ENOTSUPP; 95 case DA9062_PIN_GPI: 96 ret = regmap_read(regmap, DA9062AA_STATUS_B, &val); 97 if (ret < 0) 98 return ret; 99 break; 100 case DA9062_PIN_GPO_OD: 101 case DA9062_PIN_GPO_PP: 102 ret = regmap_read(regmap, DA9062AA_GPIO_MODE0_4, &val); 103 if (ret < 0) 104 return ret; 105 } 106 107 return !!(val & BIT(offset)); 108} 109 110static void da9062_gpio_set(struct gpio_chip *gc, unsigned int offset, 111 int value) 112{ 113 struct da9062_pctl *pctl = gpiochip_get_data(gc); 114 struct regmap *regmap = pctl->da9062->regmap; 115 116 regmap_update_bits(regmap, DA9062AA_GPIO_MODE0_4, BIT(offset), 117 value << offset); 118} 119 120static int da9062_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) 121{ 122 struct da9062_pctl *pctl = gpiochip_get_data(gc); 123 int gpio_mode; 124 125 gpio_mode = da9062_pctl_get_pin_mode(pctl, offset); 126 if (gpio_mode < 0) 127 return gpio_mode; 128 129 switch (gpio_mode) { 130 case DA9062_PIN_ALTERNATE: 131 return -ENOTSUPP; 132 case DA9062_PIN_GPI: 133 return GPIO_LINE_DIRECTION_IN; 134 case DA9062_PIN_GPO_OD: 135 case DA9062_PIN_GPO_PP: 136 return GPIO_LINE_DIRECTION_OUT; 137 } 138 139 return -EINVAL; 140} 141 142static int da9062_gpio_direction_input(struct gpio_chip *gc, 143 unsigned int offset) 144{ 145 struct da9062_pctl *pctl = gpiochip_get_data(gc); 146 struct regmap *regmap = pctl->da9062->regmap; 147 struct gpio_desc *desc = gpiochip_get_desc(gc, offset); 148 unsigned int gpi_type; 149 int ret; 150 151 ret = da9062_pctl_set_pin_mode(pctl, offset, DA9062_PIN_GPI); 152 if (ret) 153 return ret; 154 155 /* 156 * If the gpio is active low we should set it in hw too. No worries 157 * about gpio_get() because we read and return the gpio-level. So the 158 * gpiolib active_low handling is still correct. 159 * 160 * 0 - active low, 1 - active high 161 */ 162 gpi_type = !gpiod_is_active_low(desc); 163 164 return regmap_update_bits(regmap, DA9062AA_GPIO_0_1 + (offset >> 1), 165 DA9062AA_GPIO0_TYPE_MASK << DA9062_TYPE(offset), 166 gpi_type << DA9062_TYPE(offset)); 167} 168 169static int da9062_gpio_direction_output(struct gpio_chip *gc, 170 unsigned int offset, int value) 171{ 172 struct da9062_pctl *pctl = gpiochip_get_data(gc); 173 unsigned int pin_config = pctl->pin_config[offset]; 174 int ret; 175 176 ret = da9062_pctl_set_pin_mode(pctl, offset, pin_config); 177 if (ret) 178 return ret; 179 180 da9062_gpio_set(gc, offset, value); 181 182 return 0; 183} 184 185static int da9062_gpio_set_config(struct gpio_chip *gc, unsigned int offset, 186 unsigned long config) 187{ 188 struct da9062_pctl *pctl = gpiochip_get_data(gc); 189 struct regmap *regmap = pctl->da9062->regmap; 190 int gpio_mode; 191 192 /* 193 * We need to meet the following restrictions [1, Figure 18]: 194 * - PIN_CONFIG_BIAS_PULL_DOWN -> only allowed if the pin is used as 195 * gpio input 196 * - PIN_CONFIG_BIAS_PULL_UP -> only allowed if the pin is used as 197 * gpio output open-drain. 198 */ 199 200 switch (pinconf_to_config_param(config)) { 201 case PIN_CONFIG_BIAS_DISABLE: 202 return regmap_update_bits(regmap, DA9062AA_CONFIG_K, 203 BIT(offset), 0); 204 case PIN_CONFIG_BIAS_PULL_DOWN: 205 gpio_mode = da9062_pctl_get_pin_mode(pctl, offset); 206 if (gpio_mode < 0) 207 return -EINVAL; 208 else if (gpio_mode != DA9062_PIN_GPI) 209 return -ENOTSUPP; 210 return regmap_update_bits(regmap, DA9062AA_CONFIG_K, 211 BIT(offset), BIT(offset)); 212 case PIN_CONFIG_BIAS_PULL_UP: 213 gpio_mode = da9062_pctl_get_pin_mode(pctl, offset); 214 if (gpio_mode < 0) 215 return -EINVAL; 216 else if (gpio_mode != DA9062_PIN_GPO_OD) 217 return -ENOTSUPP; 218 return regmap_update_bits(regmap, DA9062AA_CONFIG_K, 219 BIT(offset), BIT(offset)); 220 case PIN_CONFIG_DRIVE_OPEN_DRAIN: 221 return da9062_pctl_set_pin_mode(pctl, offset, 222 DA9062_PIN_GPO_OD); 223 case PIN_CONFIG_DRIVE_PUSH_PULL: 224 return da9062_pctl_set_pin_mode(pctl, offset, 225 DA9062_PIN_GPO_PP); 226 default: 227 return -ENOTSUPP; 228 } 229} 230 231static int da9062_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) 232{ 233 struct da9062_pctl *pctl = gpiochip_get_data(gc); 234 struct da9062 *da9062 = pctl->da9062; 235 236 return regmap_irq_get_virq(da9062->regmap_irq, 237 DA9062_IRQ_GPI0 + offset); 238} 239 240static const struct gpio_chip reference_gc = { 241 .owner = THIS_MODULE, 242 .get = da9062_gpio_get, 243 .set = da9062_gpio_set, 244 .get_direction = da9062_gpio_get_direction, 245 .direction_input = da9062_gpio_direction_input, 246 .direction_output = da9062_gpio_direction_output, 247 .set_config = da9062_gpio_set_config, 248 .to_irq = da9062_gpio_to_irq, 249 .can_sleep = true, 250 .ngpio = DA9062_GPIO_NUM, 251 .base = -1, 252}; 253 254static int da9062_pctl_probe(struct platform_device *pdev) 255{ 256 struct device *parent = pdev->dev.parent; 257 struct da9062_pctl *pctl; 258 int i; 259 260 device_set_node(&pdev->dev, dev_fwnode(pdev->dev.parent)); 261 262 pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); 263 if (!pctl) 264 return -ENOMEM; 265 266 pctl->da9062 = dev_get_drvdata(parent); 267 if (!pctl->da9062) 268 return -EINVAL; 269 270 if (!device_property_present(parent, "gpio-controller")) 271 return 0; 272 273 for (i = 0; i < ARRAY_SIZE(pctl->pin_config); i++) 274 pctl->pin_config[i] = DA9062_PIN_GPO_PP; 275 276 /* 277 * Currently the driver handles only the GPIO support. The 278 * pinctrl/pinmux support can be added later if needed. 279 */ 280 pctl->gc = reference_gc; 281 pctl->gc.label = dev_name(&pdev->dev); 282 pctl->gc.parent = &pdev->dev; 283 284 platform_set_drvdata(pdev, pctl); 285 286 return devm_gpiochip_add_data(&pdev->dev, &pctl->gc, pctl); 287} 288 289static struct platform_driver da9062_pctl_driver = { 290 .probe = da9062_pctl_probe, 291 .driver = { 292 .name = "da9062-gpio", 293 }, 294}; 295module_platform_driver(da9062_pctl_driver); 296 297MODULE_AUTHOR("Marco Felsch <kernel@pengutronix.de>"); 298MODULE_DESCRIPTION("DA9062 PMIC pinctrl and GPIO Driver"); 299MODULE_LICENSE("GPL v2"); 300MODULE_ALIAS("platform:da9062-gpio");