Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
0004  *  Keerthy <j-keerthy@ti.com>
0005  *
0006  * Based on the LP873X driver
0007  */
0008 
0009 #include <linux/gpio/driver.h>
0010 #include <linux/module.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/regmap.h>
0013 
0014 #include <linux/mfd/lp87565.h>
0015 
0016 struct lp87565_gpio {
0017     struct gpio_chip chip;
0018     struct regmap *map;
0019 };
0020 
0021 static int lp87565_gpio_get(struct gpio_chip *chip, unsigned int offset)
0022 {
0023     struct lp87565_gpio *gpio = gpiochip_get_data(chip);
0024     int ret, val;
0025 
0026     ret = regmap_read(gpio->map, LP87565_REG_GPIO_IN, &val);
0027     if (ret < 0)
0028         return ret;
0029 
0030     return !!(val & BIT(offset));
0031 }
0032 
0033 static void lp87565_gpio_set(struct gpio_chip *chip, unsigned int offset,
0034                  int value)
0035 {
0036     struct lp87565_gpio *gpio = gpiochip_get_data(chip);
0037 
0038     regmap_update_bits(gpio->map, LP87565_REG_GPIO_OUT,
0039                BIT(offset), value ? BIT(offset) : 0);
0040 }
0041 
0042 static int lp87565_gpio_get_direction(struct gpio_chip *chip,
0043                       unsigned int offset)
0044 {
0045     struct lp87565_gpio *gpio = gpiochip_get_data(chip);
0046     int ret, val;
0047 
0048     ret = regmap_read(gpio->map, LP87565_REG_GPIO_CONFIG, &val);
0049     if (ret < 0)
0050         return ret;
0051 
0052     if (val & BIT(offset))
0053         return GPIO_LINE_DIRECTION_OUT;
0054 
0055     return GPIO_LINE_DIRECTION_IN;
0056 }
0057 
0058 static int lp87565_gpio_direction_input(struct gpio_chip *chip,
0059                     unsigned int offset)
0060 {
0061     struct lp87565_gpio *gpio = gpiochip_get_data(chip);
0062 
0063     return regmap_update_bits(gpio->map,
0064                   LP87565_REG_GPIO_CONFIG,
0065                   BIT(offset), 0);
0066 }
0067 
0068 static int lp87565_gpio_direction_output(struct gpio_chip *chip,
0069                      unsigned int offset, int value)
0070 {
0071     struct lp87565_gpio *gpio = gpiochip_get_data(chip);
0072 
0073     lp87565_gpio_set(chip, offset, value);
0074 
0075     return regmap_update_bits(gpio->map,
0076                   LP87565_REG_GPIO_CONFIG,
0077                   BIT(offset), BIT(offset));
0078 }
0079 
0080 static int lp87565_gpio_request(struct gpio_chip *gc, unsigned int offset)
0081 {
0082     struct lp87565_gpio *gpio = gpiochip_get_data(gc);
0083     int ret;
0084 
0085     switch (offset) {
0086     case 0:
0087     case 1:
0088     case 2:
0089         /*
0090          * MUX can program the pin to be in EN1/2/3 pin mode
0091          * Or GPIO1/2/3 mode.
0092          * Setup the GPIO*_SEL MUX to GPIO mode
0093          */
0094         ret = regmap_update_bits(gpio->map,
0095                      LP87565_REG_PIN_FUNCTION,
0096                      BIT(offset), BIT(offset));
0097         if (ret)
0098             return ret;
0099 
0100         break;
0101     default:
0102         return -EINVAL;
0103     }
0104 
0105     return 0;
0106 }
0107 
0108 static int lp87565_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
0109                    unsigned long config)
0110 {
0111     struct lp87565_gpio *gpio = gpiochip_get_data(gc);
0112 
0113     switch (pinconf_to_config_param(config)) {
0114     case PIN_CONFIG_DRIVE_OPEN_DRAIN:
0115         return regmap_update_bits(gpio->map,
0116                       LP87565_REG_GPIO_CONFIG,
0117                       BIT(offset +
0118                           __ffs(LP87565_GPIO1_OD)),
0119                       BIT(offset +
0120                           __ffs(LP87565_GPIO1_OD)));
0121     case PIN_CONFIG_DRIVE_PUSH_PULL:
0122         return regmap_update_bits(gpio->map,
0123                       LP87565_REG_GPIO_CONFIG,
0124                       BIT(offset +
0125                           __ffs(LP87565_GPIO1_OD)), 0);
0126     default:
0127         return -ENOTSUPP;
0128     }
0129 }
0130 
0131 static const struct gpio_chip template_chip = {
0132     .label          = "lp87565-gpio",
0133     .owner          = THIS_MODULE,
0134     .request        = lp87565_gpio_request,
0135     .get_direction      = lp87565_gpio_get_direction,
0136     .direction_input    = lp87565_gpio_direction_input,
0137     .direction_output   = lp87565_gpio_direction_output,
0138     .get            = lp87565_gpio_get,
0139     .set            = lp87565_gpio_set,
0140     .set_config     = lp87565_gpio_set_config,
0141     .base           = -1,
0142     .ngpio          = 3,
0143     .can_sleep      = true,
0144 };
0145 
0146 static int lp87565_gpio_probe(struct platform_device *pdev)
0147 {
0148     struct lp87565_gpio *gpio;
0149     struct lp87565 *lp87565;
0150     int ret;
0151 
0152     gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
0153     if (!gpio)
0154         return -ENOMEM;
0155 
0156     lp87565 = dev_get_drvdata(pdev->dev.parent);
0157     gpio->chip = template_chip;
0158     gpio->chip.parent = lp87565->dev;
0159     gpio->map = lp87565->regmap;
0160 
0161     ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
0162     if (ret < 0) {
0163         dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
0164         return ret;
0165     }
0166 
0167     return 0;
0168 }
0169 
0170 static const struct platform_device_id lp87565_gpio_id_table[] = {
0171     { "lp87565-q1-gpio", },
0172     { /* sentinel */ }
0173 };
0174 MODULE_DEVICE_TABLE(platform, lp87565_gpio_id_table);
0175 
0176 static struct platform_driver lp87565_gpio_driver = {
0177     .driver = {
0178         .name = "lp87565-gpio",
0179     },
0180     .probe = lp87565_gpio_probe,
0181     .id_table = lp87565_gpio_id_table,
0182 };
0183 module_platform_driver(lp87565_gpio_driver);
0184 
0185 MODULE_AUTHOR("Keerthy <j-keerthy@ti.com>");
0186 MODULE_DESCRIPTION("LP87565 GPIO driver");
0187 MODULE_LICENSE("GPL v2");