176 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/4 * Keerthy <j-keerthy@ti.com>5 *6 * Based on the TPS65218 driver7 */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 0x417#define LP873X_GPO_CTRL_OD 0x218 19struct lp873x_gpio {20 struct gpio_chip chip;21 struct lp873x *lp873;22};23 24static 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 31static 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 38static 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 49static 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 61static 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 71static 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 95static 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 119static 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 134static 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 158static const struct platform_device_id lp873x_gpio_id_table[] = {159 { "lp873x-gpio", },160 { /* sentinel */ }161};162MODULE_DEVICE_TABLE(platform, lp873x_gpio_id_table);163 164static 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};171module_platform_driver(lp873x_gpio_driver);172 173MODULE_AUTHOR("Keerthy <j-keerthy@ti.com>");174MODULE_DESCRIPTION("LP873X GPIO driver");175MODULE_LICENSE("GPL v2");176