1// SPDX-License-Identifier: GPL-2.0 2// Copyright (C) 2018 ROHM Semiconductors 3// gpio-bd70528.c ROHM BD70528MWV gpio driver 4 5#include <linux/gpio/driver.h> 6#include <linux/mfd/rohm-bd70528.h> 7#include <linux/module.h> 8#include <linux/platform_device.h> 9#include <linux/regmap.h> 10 11#define GPIO_IN_REG(offset) (BD70528_REG_GPIO1_IN + (offset) * 2) 12#define GPIO_OUT_REG(offset) (BD70528_REG_GPIO1_OUT + (offset) * 2) 13 14struct bd70528_gpio { 15 struct rohm_regmap_dev chip; 16 struct gpio_chip gpio; 17}; 18 19static int bd70528_set_debounce(struct bd70528_gpio *bdgpio, 20 unsigned int offset, unsigned int debounce) 21{ 22 u8 val; 23 24 switch (debounce) { 25 case 0: 26 val = BD70528_DEBOUNCE_DISABLE; 27 break; 28 case 1 ... 15000: 29 val = BD70528_DEBOUNCE_15MS; 30 break; 31 case 15001 ... 30000: 32 val = BD70528_DEBOUNCE_30MS; 33 break; 34 case 30001 ... 50000: 35 val = BD70528_DEBOUNCE_50MS; 36 break; 37 default: 38 dev_err(bdgpio->chip.dev, 39 "Invalid debounce value %u\n", debounce); 40 return -EINVAL; 41 } 42 return regmap_update_bits(bdgpio->chip.regmap, GPIO_IN_REG(offset), 43 BD70528_DEBOUNCE_MASK, val); 44} 45 46static int bd70528_get_direction(struct gpio_chip *chip, unsigned int offset) 47{ 48 struct bd70528_gpio *bdgpio = gpiochip_get_data(chip); 49 int val, ret; 50 51 /* Do we need to do something to IRQs here? */ 52 ret = regmap_read(bdgpio->chip.regmap, GPIO_OUT_REG(offset), &val); 53 if (ret) { 54 dev_err(bdgpio->chip.dev, "Could not read gpio direction\n"); 55 return ret; 56 } 57 if (val & BD70528_GPIO_OUT_EN_MASK) 58 return GPIO_LINE_DIRECTION_OUT; 59 60 return GPIO_LINE_DIRECTION_IN; 61} 62 63static int bd70528_gpio_set_config(struct gpio_chip *chip, unsigned int offset, 64 unsigned long config) 65{ 66 struct bd70528_gpio *bdgpio = gpiochip_get_data(chip); 67 68 switch (pinconf_to_config_param(config)) { 69 case PIN_CONFIG_DRIVE_OPEN_DRAIN: 70 return regmap_update_bits(bdgpio->chip.regmap, 71 GPIO_OUT_REG(offset), 72 BD70528_GPIO_DRIVE_MASK, 73 BD70528_GPIO_OPEN_DRAIN); 74 break; 75 case PIN_CONFIG_DRIVE_PUSH_PULL: 76 return regmap_update_bits(bdgpio->chip.regmap, 77 GPIO_OUT_REG(offset), 78 BD70528_GPIO_DRIVE_MASK, 79 BD70528_GPIO_PUSH_PULL); 80 break; 81 case PIN_CONFIG_INPUT_DEBOUNCE: 82 return bd70528_set_debounce(bdgpio, offset, 83 pinconf_to_config_argument(config)); 84 break; 85 default: 86 break; 87 } 88 return -ENOTSUPP; 89} 90 91static int bd70528_direction_input(struct gpio_chip *chip, unsigned int offset) 92{ 93 struct bd70528_gpio *bdgpio = gpiochip_get_data(chip); 94 95 /* Do we need to do something to IRQs here? */ 96 return regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset), 97 BD70528_GPIO_OUT_EN_MASK, 98 BD70528_GPIO_OUT_DISABLE); 99} 100 101static void bd70528_gpio_set(struct gpio_chip *chip, unsigned int offset, 102 int value) 103{ 104 int ret; 105 struct bd70528_gpio *bdgpio = gpiochip_get_data(chip); 106 u8 val = (value) ? BD70528_GPIO_OUT_HI : BD70528_GPIO_OUT_LO; 107 108 ret = regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset), 109 BD70528_GPIO_OUT_MASK, val); 110 if (ret) 111 dev_err(bdgpio->chip.dev, "Could not set gpio to %d\n", value); 112} 113 114static int bd70528_direction_output(struct gpio_chip *chip, unsigned int offset, 115 int value) 116{ 117 struct bd70528_gpio *bdgpio = gpiochip_get_data(chip); 118 119 bd70528_gpio_set(chip, offset, value); 120 return regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset), 121 BD70528_GPIO_OUT_EN_MASK, 122 BD70528_GPIO_OUT_ENABLE); 123} 124 125#define GPIO_IN_STATE_MASK(offset) (BD70528_GPIO_IN_STATE_BASE << (offset)) 126 127static int bd70528_gpio_get_o(struct bd70528_gpio *bdgpio, unsigned int offset) 128{ 129 int ret; 130 unsigned int val; 131 132 ret = regmap_read(bdgpio->chip.regmap, GPIO_OUT_REG(offset), &val); 133 if (!ret) 134 ret = !!(val & BD70528_GPIO_OUT_MASK); 135 else 136 dev_err(bdgpio->chip.dev, "GPIO (out) state read failed\n"); 137 138 return ret; 139} 140 141static int bd70528_gpio_get_i(struct bd70528_gpio *bdgpio, unsigned int offset) 142{ 143 unsigned int val; 144 int ret; 145 146 ret = regmap_read(bdgpio->chip.regmap, BD70528_REG_GPIO_STATE, &val); 147 148 if (!ret) 149 ret = !(val & GPIO_IN_STATE_MASK(offset)); 150 else 151 dev_err(bdgpio->chip.dev, "GPIO (in) state read failed\n"); 152 153 return ret; 154} 155 156static int bd70528_gpio_get(struct gpio_chip *chip, unsigned int offset) 157{ 158 int ret; 159 struct bd70528_gpio *bdgpio = gpiochip_get_data(chip); 160 161 /* 162 * There is a race condition where someone might be changing the 163 * GPIO direction after we get it but before we read the value. But 164 * application design where GPIO direction may be changed just when 165 * we read GPIO value would be pointless as reader could not know 166 * whether the returned high/low state is caused by input or output. 167 * Or then there must be other ways to mitigate the issue. Thus 168 * locking would make no sense. 169 */ 170 ret = bd70528_get_direction(chip, offset); 171 if (ret == GPIO_LINE_DIRECTION_OUT) 172 ret = bd70528_gpio_get_o(bdgpio, offset); 173 else if (ret == GPIO_LINE_DIRECTION_IN) 174 ret = bd70528_gpio_get_i(bdgpio, offset); 175 else 176 dev_err(bdgpio->chip.dev, "failed to read GPIO direction\n"); 177 178 return ret; 179} 180 181static int bd70528_probe(struct platform_device *pdev) 182{ 183 struct bd70528_gpio *bdgpio; 184 struct rohm_regmap_dev *bd70528; 185 int ret; 186 187 bd70528 = dev_get_drvdata(pdev->dev.parent); 188 if (!bd70528) { 189 dev_err(&pdev->dev, "No MFD driver data\n"); 190 return -EINVAL; 191 } 192 193 bdgpio = devm_kzalloc(&pdev->dev, sizeof(*bdgpio), 194 GFP_KERNEL); 195 if (!bdgpio) 196 return -ENOMEM; 197 bdgpio->chip.dev = &pdev->dev; 198 bdgpio->gpio.parent = pdev->dev.parent; 199 bdgpio->gpio.label = "bd70528-gpio"; 200 bdgpio->gpio.owner = THIS_MODULE; 201 bdgpio->gpio.get_direction = bd70528_get_direction; 202 bdgpio->gpio.direction_input = bd70528_direction_input; 203 bdgpio->gpio.direction_output = bd70528_direction_output; 204 bdgpio->gpio.set_config = bd70528_gpio_set_config; 205 bdgpio->gpio.can_sleep = true; 206 bdgpio->gpio.get = bd70528_gpio_get; 207 bdgpio->gpio.set = bd70528_gpio_set; 208 bdgpio->gpio.ngpio = 4; 209 bdgpio->gpio.base = -1; 210#ifdef CONFIG_OF_GPIO 211 bdgpio->gpio.of_node = pdev->dev.parent->of_node; 212#endif 213 bdgpio->chip.regmap = bd70528->regmap; 214 215 ret = devm_gpiochip_add_data(&pdev->dev, &bdgpio->gpio, 216 bdgpio); 217 if (ret) 218 dev_err(&pdev->dev, "gpio_init: Failed to add bd70528-gpio\n"); 219 220 return ret; 221} 222 223static struct platform_driver bd70528_gpio = { 224 .driver = { 225 .name = "bd70528-gpio" 226 }, 227 .probe = bd70528_probe, 228}; 229 230module_platform_driver(bd70528_gpio); 231 232MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); 233MODULE_DESCRIPTION("BD70528 voltage regulator driver"); 234MODULE_LICENSE("GPL"); 235MODULE_ALIAS("platform:bd70528-gpio"); 236