Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Dialog DA9062 pinctrl and GPIO driver.
0004  * Based on DA9055 GPIO driver.
0005  *
0006  * TODO:
0007  *   - add pinmux and pinctrl support (gpio alternate mode)
0008  *
0009  * Documents:
0010  * [1] https://www.dialog-semiconductor.com/sites/default/files/da9062_datasheet_3v6.pdf
0011  *
0012  * Copyright (C) 2019 Pengutronix, Marco Felsch <kernel@pengutronix.de>
0013  */
0014 #include <linux/bits.h>
0015 #include <linux/module.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/property.h>
0018 #include <linux/regmap.h>
0019 
0020 #include <linux/gpio/driver.h>
0021 
0022 #include <linux/mfd/da9062/core.h>
0023 #include <linux/mfd/da9062/registers.h>
0024 
0025 /*
0026  * We need this get the gpio_desc from a <gpio_chip,offset> tuple to decide if
0027  * the gpio is active low without a vendor specific dt-binding.
0028  */
0029 #include "../gpio/gpiolib.h"
0030 
0031 #define DA9062_TYPE(offset)     (4 * (offset % 2))
0032 #define DA9062_PIN_SHIFT(offset)    (4 * (offset % 2))
0033 #define DA9062_PIN_ALTERNATE        0x00 /* gpio alternate mode */
0034 #define DA9062_PIN_GPI          0x01 /* gpio in */
0035 #define DA9062_PIN_GPO_OD       0x02 /* gpio out open-drain */
0036 #define DA9062_PIN_GPO_PP       0x03 /* gpio out push-pull */
0037 #define DA9062_GPIO_NUM         5
0038 
0039 struct da9062_pctl {
0040     struct da9062 *da9062;
0041     struct gpio_chip gc;
0042     unsigned int pin_config[DA9062_GPIO_NUM];
0043 };
0044 
0045 static int da9062_pctl_get_pin_mode(struct da9062_pctl *pctl,
0046                     unsigned int offset)
0047 {
0048     struct regmap *regmap = pctl->da9062->regmap;
0049     int ret, val;
0050 
0051     ret = regmap_read(regmap, DA9062AA_GPIO_0_1 + (offset >> 1), &val);
0052     if (ret < 0)
0053         return ret;
0054 
0055     val >>= DA9062_PIN_SHIFT(offset);
0056     val &= DA9062AA_GPIO0_PIN_MASK;
0057 
0058     return val;
0059 }
0060 
0061 static int da9062_pctl_set_pin_mode(struct da9062_pctl *pctl,
0062                     unsigned int offset, unsigned int mode_req)
0063 {
0064     struct regmap *regmap = pctl->da9062->regmap;
0065     unsigned int mode = mode_req;
0066     unsigned int mask;
0067     int ret;
0068 
0069     mode &= DA9062AA_GPIO0_PIN_MASK;
0070     mode <<= DA9062_PIN_SHIFT(offset);
0071     mask = DA9062AA_GPIO0_PIN_MASK << DA9062_PIN_SHIFT(offset);
0072 
0073     ret = regmap_update_bits(regmap, DA9062AA_GPIO_0_1 + (offset >> 1),
0074                  mask, mode);
0075     if (!ret)
0076         pctl->pin_config[offset] = mode_req;
0077 
0078     return ret;
0079 }
0080 
0081 static int da9062_gpio_get(struct gpio_chip *gc, unsigned int offset)
0082 {
0083     struct da9062_pctl *pctl = gpiochip_get_data(gc);
0084     struct regmap *regmap = pctl->da9062->regmap;
0085     int gpio_mode, val;
0086     int ret;
0087 
0088     gpio_mode = da9062_pctl_get_pin_mode(pctl, offset);
0089     if (gpio_mode < 0)
0090         return gpio_mode;
0091 
0092     switch (gpio_mode) {
0093     case DA9062_PIN_ALTERNATE:
0094         return -ENOTSUPP;
0095     case DA9062_PIN_GPI:
0096         ret = regmap_read(regmap, DA9062AA_STATUS_B, &val);
0097         if (ret < 0)
0098             return ret;
0099         break;
0100     case DA9062_PIN_GPO_OD:
0101     case DA9062_PIN_GPO_PP:
0102         ret = regmap_read(regmap, DA9062AA_GPIO_MODE0_4, &val);
0103         if (ret < 0)
0104             return ret;
0105     }
0106 
0107     return !!(val & BIT(offset));
0108 }
0109 
0110 static void da9062_gpio_set(struct gpio_chip *gc, unsigned int offset,
0111                 int value)
0112 {
0113     struct da9062_pctl *pctl = gpiochip_get_data(gc);
0114     struct regmap *regmap = pctl->da9062->regmap;
0115 
0116     regmap_update_bits(regmap, DA9062AA_GPIO_MODE0_4, BIT(offset),
0117                value << offset);
0118 }
0119 
0120 static int da9062_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
0121 {
0122     struct da9062_pctl *pctl = gpiochip_get_data(gc);
0123     int gpio_mode;
0124 
0125     gpio_mode = da9062_pctl_get_pin_mode(pctl, offset);
0126     if (gpio_mode < 0)
0127         return gpio_mode;
0128 
0129     switch (gpio_mode) {
0130     case DA9062_PIN_ALTERNATE:
0131         return -ENOTSUPP;
0132     case DA9062_PIN_GPI:
0133         return GPIO_LINE_DIRECTION_IN;
0134     case DA9062_PIN_GPO_OD:
0135     case DA9062_PIN_GPO_PP:
0136         return GPIO_LINE_DIRECTION_OUT;
0137     }
0138 
0139     return -EINVAL;
0140 }
0141 
0142 static int da9062_gpio_direction_input(struct gpio_chip *gc,
0143                        unsigned int offset)
0144 {
0145     struct da9062_pctl *pctl = gpiochip_get_data(gc);
0146     struct regmap *regmap = pctl->da9062->regmap;
0147     struct gpio_desc *desc = gpiochip_get_desc(gc, offset);
0148     unsigned int gpi_type;
0149     int ret;
0150 
0151     ret = da9062_pctl_set_pin_mode(pctl, offset, DA9062_PIN_GPI);
0152     if (ret)
0153         return ret;
0154 
0155     /*
0156      * If the gpio is active low we should set it in hw too. No worries
0157      * about gpio_get() because we read and return the gpio-level. So the
0158      * gpiolib active_low handling is still correct.
0159      *
0160      * 0 - active low, 1 - active high
0161      */
0162     gpi_type = !gpiod_is_active_low(desc);
0163 
0164     return regmap_update_bits(regmap, DA9062AA_GPIO_0_1 + (offset >> 1),
0165                 DA9062AA_GPIO0_TYPE_MASK << DA9062_TYPE(offset),
0166                 gpi_type << DA9062_TYPE(offset));
0167 }
0168 
0169 static int da9062_gpio_direction_output(struct gpio_chip *gc,
0170                     unsigned int offset, int value)
0171 {
0172     struct da9062_pctl *pctl = gpiochip_get_data(gc);
0173     unsigned int pin_config = pctl->pin_config[offset];
0174     int ret;
0175 
0176     ret = da9062_pctl_set_pin_mode(pctl, offset, pin_config);
0177     if (ret)
0178         return ret;
0179 
0180     da9062_gpio_set(gc, offset, value);
0181 
0182     return 0;
0183 }
0184 
0185 static int da9062_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
0186                   unsigned long config)
0187 {
0188     struct da9062_pctl *pctl = gpiochip_get_data(gc);
0189     struct regmap *regmap = pctl->da9062->regmap;
0190     int gpio_mode;
0191 
0192     /*
0193      * We need to meet the following restrictions [1, Figure 18]:
0194      * - PIN_CONFIG_BIAS_PULL_DOWN -> only allowed if the pin is used as
0195      *                gpio input
0196      * - PIN_CONFIG_BIAS_PULL_UP   -> only allowed if the pin is used as
0197      *                gpio output open-drain.
0198      */
0199 
0200     switch (pinconf_to_config_param(config)) {
0201     case PIN_CONFIG_BIAS_DISABLE:
0202         return regmap_update_bits(regmap, DA9062AA_CONFIG_K,
0203                       BIT(offset), 0);
0204     case PIN_CONFIG_BIAS_PULL_DOWN:
0205         gpio_mode = da9062_pctl_get_pin_mode(pctl, offset);
0206         if (gpio_mode < 0)
0207             return -EINVAL;
0208         else if (gpio_mode != DA9062_PIN_GPI)
0209             return -ENOTSUPP;
0210         return regmap_update_bits(regmap, DA9062AA_CONFIG_K,
0211                       BIT(offset), BIT(offset));
0212     case PIN_CONFIG_BIAS_PULL_UP:
0213         gpio_mode = da9062_pctl_get_pin_mode(pctl, offset);
0214         if (gpio_mode < 0)
0215             return -EINVAL;
0216         else if (gpio_mode != DA9062_PIN_GPO_OD)
0217             return -ENOTSUPP;
0218         return regmap_update_bits(regmap, DA9062AA_CONFIG_K,
0219                       BIT(offset), BIT(offset));
0220     case PIN_CONFIG_DRIVE_OPEN_DRAIN:
0221         return da9062_pctl_set_pin_mode(pctl, offset,
0222                         DA9062_PIN_GPO_OD);
0223     case PIN_CONFIG_DRIVE_PUSH_PULL:
0224         return da9062_pctl_set_pin_mode(pctl, offset,
0225                         DA9062_PIN_GPO_PP);
0226     default:
0227         return -ENOTSUPP;
0228     }
0229 }
0230 
0231 static int da9062_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
0232 {
0233     struct da9062_pctl *pctl = gpiochip_get_data(gc);
0234     struct da9062 *da9062 = pctl->da9062;
0235 
0236     return regmap_irq_get_virq(da9062->regmap_irq,
0237                    DA9062_IRQ_GPI0 + offset);
0238 }
0239 
0240 static const struct gpio_chip reference_gc = {
0241     .owner = THIS_MODULE,
0242     .get = da9062_gpio_get,
0243     .set = da9062_gpio_set,
0244     .get_direction = da9062_gpio_get_direction,
0245     .direction_input = da9062_gpio_direction_input,
0246     .direction_output = da9062_gpio_direction_output,
0247     .set_config = da9062_gpio_set_config,
0248     .to_irq = da9062_gpio_to_irq,
0249     .can_sleep = true,
0250     .ngpio = DA9062_GPIO_NUM,
0251     .base = -1,
0252 };
0253 
0254 static int da9062_pctl_probe(struct platform_device *pdev)
0255 {
0256     struct device *parent = pdev->dev.parent;
0257     struct da9062_pctl *pctl;
0258     int i;
0259 
0260     device_set_node(&pdev->dev, dev_fwnode(pdev->dev.parent));
0261 
0262     pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
0263     if (!pctl)
0264         return -ENOMEM;
0265 
0266     pctl->da9062 = dev_get_drvdata(parent);
0267     if (!pctl->da9062)
0268         return -EINVAL;
0269 
0270     if (!device_property_present(parent, "gpio-controller"))
0271         return 0;
0272 
0273     for (i = 0; i < ARRAY_SIZE(pctl->pin_config); i++)
0274         pctl->pin_config[i] = DA9062_PIN_GPO_PP;
0275 
0276     /*
0277      * Currently the driver handles only the GPIO support. The
0278      * pinctrl/pinmux support can be added later if needed.
0279      */
0280     pctl->gc = reference_gc;
0281     pctl->gc.label = dev_name(&pdev->dev);
0282     pctl->gc.parent = &pdev->dev;
0283 
0284     platform_set_drvdata(pdev, pctl);
0285 
0286     return devm_gpiochip_add_data(&pdev->dev, &pctl->gc, pctl);
0287 }
0288 
0289 static struct platform_driver da9062_pctl_driver = {
0290     .probe = da9062_pctl_probe,
0291     .driver = {
0292         .name   = "da9062-gpio",
0293     },
0294 };
0295 module_platform_driver(da9062_pctl_driver);
0296 
0297 MODULE_AUTHOR("Marco Felsch <kernel@pengutronix.de>");
0298 MODULE_DESCRIPTION("DA9062 PMIC pinctrl and GPIO Driver");
0299 MODULE_LICENSE("GPL v2");
0300 MODULE_ALIAS("platform:da9062-gpio");