1 // SPDX-License-Identifier: GPL-2.0-only 2 // Copyright (C) 2018 ROHM Semiconductors 3 4 #include <linux/gpio/driver.h> 5 #include <linux/mfd/rohm-bd71828.h> 6 #include <linux/module.h> 7 #include <linux/platform_device.h> 8 #include <linux/regmap.h> 9 10 #define GPIO_OUT_REG(off) (BD71828_REG_GPIO_CTRL1 + (off)) 11 #define HALL_GPIO_OFFSET 3 12 13 struct bd71828_gpio { 14 struct regmap *regmap; 15 struct device *dev; 16 struct gpio_chip gpio; 17 }; 18 19 static int bd71828_gpio_set(struct gpio_chip *chip, unsigned int offset, 20 int value) 21 { 22 struct bd71828_gpio *bdgpio = gpiochip_get_data(chip); 23 u8 val = (value) ? BD71828_GPIO_OUT_HI : BD71828_GPIO_OUT_LO; 24 25 /* 26 * The HALL input pin can only be used as input. If this is the pin 27 * we are dealing with - then we are done 28 */ 29 if (offset == HALL_GPIO_OFFSET) 30 return 0; 31 32 return regmap_update_bits(bdgpio->regmap, GPIO_OUT_REG(offset), 33 BD71828_GPIO_OUT_MASK, val); 34 } 35 36 static int bd71828_gpio_get(struct gpio_chip *chip, unsigned int offset) 37 { 38 int ret; 39 unsigned int val; 40 struct bd71828_gpio *bdgpio = gpiochip_get_data(chip); 41 42 if (offset == HALL_GPIO_OFFSET) 43 ret = regmap_read(bdgpio->regmap, BD71828_REG_IO_STAT, 44 &val); 45 else 46 ret = regmap_read(bdgpio->regmap, GPIO_OUT_REG(offset), 47 &val); 48 if (!ret) 49 ret = (val & BD71828_GPIO_OUT_MASK); 50 51 return ret; 52 } 53 54 static int bd71828_gpio_set_config(struct gpio_chip *chip, unsigned int offset, 55 unsigned long config) 56 { 57 struct bd71828_gpio *bdgpio = gpiochip_get_data(chip); 58 59 if (offset == HALL_GPIO_OFFSET) 60 return -ENOTSUPP; 61 62 switch (pinconf_to_config_param(config)) { 63 case PIN_CONFIG_DRIVE_OPEN_DRAIN: 64 return regmap_update_bits(bdgpio->regmap, 65 GPIO_OUT_REG(offset), 66 BD71828_GPIO_DRIVE_MASK, 67 BD71828_GPIO_OPEN_DRAIN); 68 case PIN_CONFIG_DRIVE_PUSH_PULL: 69 return regmap_update_bits(bdgpio->regmap, 70 GPIO_OUT_REG(offset), 71 BD71828_GPIO_DRIVE_MASK, 72 BD71828_GPIO_PUSH_PULL); 73 default: 74 break; 75 } 76 return -ENOTSUPP; 77 } 78 79 static int bd71828_get_direction(struct gpio_chip *chip, unsigned int offset) 80 { 81 /* 82 * Pin usage is selected by OTP data. We can't read it runtime. Hence 83 * we trust that if the pin is not excluded by "gpio-reserved-ranges" 84 * the OTP configuration is set to OUT. (Other pins but HALL input pin 85 * on BD71828 can't really be used for general purpose input - input 86 * states are used for specific cases like regulator control or 87 * PMIC_ON_REQ. 88 */ 89 if (offset == HALL_GPIO_OFFSET) 90 return GPIO_LINE_DIRECTION_IN; 91 92 return GPIO_LINE_DIRECTION_OUT; 93 } 94 95 static int bd71828_probe(struct platform_device *pdev) 96 { 97 struct device *dev = &pdev->dev; 98 struct bd71828_gpio *bdgpio; 99 100 bdgpio = devm_kzalloc(dev, sizeof(*bdgpio), GFP_KERNEL); 101 if (!bdgpio) 102 return -ENOMEM; 103 104 bdgpio->dev = dev; 105 bdgpio->gpio.parent = dev->parent; 106 bdgpio->gpio.label = "bd71828-gpio"; 107 bdgpio->gpio.owner = THIS_MODULE; 108 bdgpio->gpio.get_direction = bd71828_get_direction; 109 bdgpio->gpio.set_config = bd71828_gpio_set_config; 110 bdgpio->gpio.can_sleep = true; 111 bdgpio->gpio.get = bd71828_gpio_get; 112 bdgpio->gpio.set_rv = bd71828_gpio_set; 113 bdgpio->gpio.base = -1; 114 115 /* 116 * See if we need some implementation to mark some PINs as 117 * not controllable based on DT info or if core can handle 118 * "gpio-reserved-ranges" and exclude them from control 119 */ 120 bdgpio->gpio.ngpio = 4; 121 bdgpio->regmap = dev_get_regmap(dev->parent, NULL); 122 if (!bdgpio->regmap) 123 return -ENODEV; 124 125 return devm_gpiochip_add_data(dev, &bdgpio->gpio, bdgpio); 126 } 127 128 static struct platform_driver bd71828_gpio = { 129 .driver = { 130 .name = "bd71828-gpio" 131 }, 132 .probe = bd71828_probe, 133 }; 134 135 module_platform_driver(bd71828_gpio); 136 137 MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); 138 MODULE_DESCRIPTION("BD71828 voltage regulator driver"); 139 MODULE_LICENSE("GPL"); 140 MODULE_ALIAS("platform:bd71828-gpio"); 141