1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/ 4 * Keerthy <j-keerthy@ti.com> 5 * 6 * Based on the TPS65218 driver 7 */ 8 9 #include <linux/gpio/driver.h> 10 #include <linux/module.h> 11 #include <linux/platform_device.h> 12 #include <linux/regmap.h> 13 14 #include <linux/mfd/lp873x.h> 15 16 #define BITS_PER_GPO 0x4 17 #define LP873X_GPO_CTRL_OD 0x2 18 19 struct lp873x_gpio { 20 struct gpio_chip chip; 21 struct lp873x *lp873; 22 }; 23 24 static int lp873x_gpio_get_direction(struct gpio_chip *chip, 25 unsigned int offset) 26 { 27 /* This device is output only */ 28 return GPIO_LINE_DIRECTION_OUT; 29 } 30 31 static int lp873x_gpio_direction_input(struct gpio_chip *chip, 32 unsigned int offset) 33 { 34 /* This device is output only */ 35 return -EINVAL; 36 } 37 38 static int lp873x_gpio_direction_output(struct gpio_chip *chip, 39 unsigned int offset, int value) 40 { 41 struct lp873x_gpio *gpio = gpiochip_get_data(chip); 42 43 /* Set the initial value */ 44 return regmap_update_bits(gpio->lp873->regmap, LP873X_REG_GPO_CTRL, 45 BIT(offset * BITS_PER_GPO), 46 value ? BIT(offset * BITS_PER_GPO) : 0); 47 } 48 49 static int lp873x_gpio_get(struct gpio_chip *chip, unsigned int offset) 50 { 51 struct lp873x_gpio *gpio = gpiochip_get_data(chip); 52 int ret, val; 53 54 ret = regmap_read(gpio->lp873->regmap, LP873X_REG_GPO_CTRL, &val); 55 if (ret < 0) 56 return ret; 57 58 return val & BIT(offset * BITS_PER_GPO); 59 } 60 61 static void lp873x_gpio_set(struct gpio_chip *chip, unsigned int offset, 62 int value) 63 { 64 struct lp873x_gpio *gpio = gpiochip_get_data(chip); 65 66 regmap_update_bits(gpio->lp873->regmap, LP873X_REG_GPO_CTRL, 67 BIT(offset * BITS_PER_GPO), 68 value ? BIT(offset * BITS_PER_GPO) : 0); 69 } 70 71 static int lp873x_gpio_request(struct gpio_chip *gc, unsigned int offset) 72 { 73 struct lp873x_gpio *gpio = gpiochip_get_data(gc); 74 int ret; 75 76 switch (offset) { 77 case 0: 78 /* No MUX Set up Needed for GPO */ 79 break; 80 case 1: 81 /* Setup the CLKIN_PIN_SEL MUX to GPO2 */ 82 ret = regmap_update_bits(gpio->lp873->regmap, LP873X_REG_CONFIG, 83 LP873X_CONFIG_CLKIN_PIN_SEL, 0); 84 if (ret) 85 return ret; 86 87 break; 88 default: 89 return -EINVAL; 90 } 91 92 return 0; 93 } 94 95 static int lp873x_gpio_set_config(struct gpio_chip *gc, unsigned offset, 96 unsigned long config) 97 { 98 struct lp873x_gpio *gpio = gpiochip_get_data(gc); 99 100 switch (pinconf_to_config_param(config)) { 101 case PIN_CONFIG_DRIVE_OPEN_DRAIN: 102 return regmap_update_bits(gpio->lp873->regmap, 103 LP873X_REG_GPO_CTRL, 104 BIT(offset * BITS_PER_GPO + 105 LP873X_GPO_CTRL_OD), 106 BIT(offset * BITS_PER_GPO + 107 LP873X_GPO_CTRL_OD)); 108 109 case PIN_CONFIG_DRIVE_PUSH_PULL: 110 return regmap_update_bits(gpio->lp873->regmap, 111 LP873X_REG_GPO_CTRL, 112 BIT(offset * BITS_PER_GPO + 113 LP873X_GPO_CTRL_OD), 0); 114 default: 115 return -ENOTSUPP; 116 } 117 } 118 119 static const struct gpio_chip template_chip = { 120 .label = "lp873x-gpio", 121 .owner = THIS_MODULE, 122 .request = lp873x_gpio_request, 123 .get_direction = lp873x_gpio_get_direction, 124 .direction_input = lp873x_gpio_direction_input, 125 .direction_output = lp873x_gpio_direction_output, 126 .get = lp873x_gpio_get, 127 .set = lp873x_gpio_set, 128 .set_config = lp873x_gpio_set_config, 129 .base = -1, 130 .ngpio = 2, 131 .can_sleep = true, 132 }; 133 134 static int lp873x_gpio_probe(struct platform_device *pdev) 135 { 136 struct lp873x_gpio *gpio; 137 int ret; 138 139 gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); 140 if (!gpio) 141 return -ENOMEM; 142 143 platform_set_drvdata(pdev, gpio); 144 145 gpio->lp873 = dev_get_drvdata(pdev->dev.parent); 146 gpio->chip = template_chip; 147 gpio->chip.parent = gpio->lp873->dev; 148 149 ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); 150 if (ret < 0) { 151 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); 152 return ret; 153 } 154 155 return 0; 156 } 157 158 static const struct platform_device_id lp873x_gpio_id_table[] = { 159 { "lp873x-gpio", }, 160 { /* sentinel */ } 161 }; 162 MODULE_DEVICE_TABLE(platform, lp873x_gpio_id_table); 163 164 static struct platform_driver lp873x_gpio_driver = { 165 .driver = { 166 .name = "lp873x-gpio", 167 }, 168 .probe = lp873x_gpio_probe, 169 .id_table = lp873x_gpio_id_table, 170 }; 171 module_platform_driver(lp873x_gpio_driver); 172 173 MODULE_AUTHOR("Keerthy <j-keerthy@ti.com>"); 174 MODULE_DESCRIPTION("LP873X GPIO driver"); 175 MODULE_LICENSE("GPL v2"); 176