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 rohm_regmap_dev chip; 15 struct gpio_chip gpio; 16 }; 17 18 static void bd71828_gpio_set(struct gpio_chip *chip, unsigned int offset, 19 int value) 20 { 21 int ret; 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; 31 32 ret = regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset), 33 BD71828_GPIO_OUT_MASK, val); 34 if (ret) 35 dev_err(bdgpio->chip.dev, "Could not set gpio to %d\n", value); 36 } 37 38 static int bd71828_gpio_get(struct gpio_chip *chip, unsigned int offset) 39 { 40 int ret; 41 unsigned int val; 42 struct bd71828_gpio *bdgpio = gpiochip_get_data(chip); 43 44 if (offset == HALL_GPIO_OFFSET) 45 ret = regmap_read(bdgpio->chip.regmap, BD71828_REG_IO_STAT, 46 &val); 47 else 48 ret = regmap_read(bdgpio->chip.regmap, GPIO_OUT_REG(offset), 49 &val); 50 if (!ret) 51 ret = (val & BD71828_GPIO_OUT_MASK); 52 53 return ret; 54 } 55 56 static int bd71828_gpio_set_config(struct gpio_chip *chip, unsigned int offset, 57 unsigned long config) 58 { 59 struct bd71828_gpio *bdgpio = gpiochip_get_data(chip); 60 61 if (offset == HALL_GPIO_OFFSET) 62 return -ENOTSUPP; 63 64 switch (pinconf_to_config_param(config)) { 65 case PIN_CONFIG_DRIVE_OPEN_DRAIN: 66 return regmap_update_bits(bdgpio->chip.regmap, 67 GPIO_OUT_REG(offset), 68 BD71828_GPIO_DRIVE_MASK, 69 BD71828_GPIO_OPEN_DRAIN); 70 case PIN_CONFIG_DRIVE_PUSH_PULL: 71 return regmap_update_bits(bdgpio->chip.regmap, 72 GPIO_OUT_REG(offset), 73 BD71828_GPIO_DRIVE_MASK, 74 BD71828_GPIO_PUSH_PULL); 75 default: 76 break; 77 } 78 return -ENOTSUPP; 79 } 80 81 static int bd71828_get_direction(struct gpio_chip *chip, unsigned int offset) 82 { 83 /* 84 * Pin usage is selected by OTP data. We can't read it runtime. Hence 85 * we trust that if the pin is not excluded by "gpio-reserved-ranges" 86 * the OTP configuration is set to OUT. (Other pins but HALL input pin 87 * on BD71828 can't really be used for general purpose input - input 88 * states are used for specific cases like regulator control or 89 * PMIC_ON_REQ. 90 */ 91 if (offset == HALL_GPIO_OFFSET) 92 return GPIO_LINE_DIRECTION_IN; 93 94 return GPIO_LINE_DIRECTION_OUT; 95 } 96 97 static int bd71828_probe(struct platform_device *pdev) 98 { 99 struct bd71828_gpio *bdgpio; 100 struct rohm_regmap_dev *bd71828; 101 102 bd71828 = dev_get_drvdata(pdev->dev.parent); 103 if (!bd71828) { 104 dev_err(&pdev->dev, "No MFD driver data\n"); 105 return -EINVAL; 106 } 107 108 bdgpio = devm_kzalloc(&pdev->dev, sizeof(*bdgpio), 109 GFP_KERNEL); 110 if (!bdgpio) 111 return -ENOMEM; 112 113 bdgpio->chip.dev = &pdev->dev; 114 bdgpio->gpio.parent = pdev->dev.parent; 115 bdgpio->gpio.label = "bd71828-gpio"; 116 bdgpio->gpio.owner = THIS_MODULE; 117 bdgpio->gpio.get_direction = bd71828_get_direction; 118 bdgpio->gpio.set_config = bd71828_gpio_set_config; 119 bdgpio->gpio.can_sleep = true; 120 bdgpio->gpio.get = bd71828_gpio_get; 121 bdgpio->gpio.set = bd71828_gpio_set; 122 bdgpio->gpio.base = -1; 123 124 /* 125 * See if we need some implementation to mark some PINs as 126 * not controllable based on DT info or if core can handle 127 * "gpio-reserved-ranges" and exclude them from control 128 */ 129 bdgpio->gpio.ngpio = 4; 130 bdgpio->gpio.of_node = pdev->dev.parent->of_node; 131 bdgpio->chip.regmap = bd71828->regmap; 132 133 return devm_gpiochip_add_data(&pdev->dev, &bdgpio->gpio, 134 bdgpio); 135 } 136 137 static struct platform_driver bd71828_gpio = { 138 .driver = { 139 .name = "bd71828-gpio" 140 }, 141 .probe = bd71828_probe, 142 }; 143 144 module_platform_driver(bd71828_gpio); 145 146 MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); 147 MODULE_DESCRIPTION("BD71828 voltage regulator driver"); 148 MODULE_LICENSE("GPL"); 149 MODULE_ALIAS("platform:bd71828-gpio"); 150