Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * regmap based generic GPIO driver
0004  *
0005  * Copyright 2020 Michael Walle <michael@walle.cc>
0006  */
0007 
0008 #include <linux/gpio/driver.h>
0009 #include <linux/gpio/regmap.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/regmap.h>
0013 
0014 struct gpio_regmap {
0015     struct device *parent;
0016     struct regmap *regmap;
0017     struct gpio_chip gpio_chip;
0018 
0019     int reg_stride;
0020     int ngpio_per_reg;
0021     unsigned int reg_dat_base;
0022     unsigned int reg_set_base;
0023     unsigned int reg_clr_base;
0024     unsigned int reg_dir_in_base;
0025     unsigned int reg_dir_out_base;
0026 
0027     int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base,
0028                   unsigned int offset, unsigned int *reg,
0029                   unsigned int *mask);
0030 
0031     void *driver_data;
0032 };
0033 
0034 static unsigned int gpio_regmap_addr(unsigned int addr)
0035 {
0036     if (addr == GPIO_REGMAP_ADDR_ZERO)
0037         return 0;
0038 
0039     return addr;
0040 }
0041 
0042 static int gpio_regmap_simple_xlate(struct gpio_regmap *gpio,
0043                     unsigned int base, unsigned int offset,
0044                     unsigned int *reg, unsigned int *mask)
0045 {
0046     unsigned int line = offset % gpio->ngpio_per_reg;
0047     unsigned int stride = offset / gpio->ngpio_per_reg;
0048 
0049     *reg = base + stride * gpio->reg_stride;
0050     *mask = BIT(line);
0051 
0052     return 0;
0053 }
0054 
0055 static int gpio_regmap_get(struct gpio_chip *chip, unsigned int offset)
0056 {
0057     struct gpio_regmap *gpio = gpiochip_get_data(chip);
0058     unsigned int base, val, reg, mask;
0059     int ret;
0060 
0061     /* we might not have an output register if we are input only */
0062     if (gpio->reg_dat_base)
0063         base = gpio_regmap_addr(gpio->reg_dat_base);
0064     else
0065         base = gpio_regmap_addr(gpio->reg_set_base);
0066 
0067     ret = gpio->reg_mask_xlate(gpio, base, offset, &reg, &mask);
0068     if (ret)
0069         return ret;
0070 
0071     ret = regmap_read(gpio->regmap, reg, &val);
0072     if (ret)
0073         return ret;
0074 
0075     return !!(val & mask);
0076 }
0077 
0078 static void gpio_regmap_set(struct gpio_chip *chip, unsigned int offset,
0079                 int val)
0080 {
0081     struct gpio_regmap *gpio = gpiochip_get_data(chip);
0082     unsigned int base = gpio_regmap_addr(gpio->reg_set_base);
0083     unsigned int reg, mask;
0084 
0085     gpio->reg_mask_xlate(gpio, base, offset, &reg, &mask);
0086     if (val)
0087         regmap_update_bits(gpio->regmap, reg, mask, mask);
0088     else
0089         regmap_update_bits(gpio->regmap, reg, mask, 0);
0090 }
0091 
0092 static void gpio_regmap_set_with_clear(struct gpio_chip *chip,
0093                        unsigned int offset, int val)
0094 {
0095     struct gpio_regmap *gpio = gpiochip_get_data(chip);
0096     unsigned int base, reg, mask;
0097 
0098     if (val)
0099         base = gpio_regmap_addr(gpio->reg_set_base);
0100     else
0101         base = gpio_regmap_addr(gpio->reg_clr_base);
0102 
0103     gpio->reg_mask_xlate(gpio, base, offset, &reg, &mask);
0104     regmap_write(gpio->regmap, reg, mask);
0105 }
0106 
0107 static int gpio_regmap_get_direction(struct gpio_chip *chip,
0108                      unsigned int offset)
0109 {
0110     struct gpio_regmap *gpio = gpiochip_get_data(chip);
0111     unsigned int base, val, reg, mask;
0112     int invert, ret;
0113 
0114     if (gpio->reg_dir_out_base) {
0115         base = gpio_regmap_addr(gpio->reg_dir_out_base);
0116         invert = 0;
0117     } else if (gpio->reg_dir_in_base) {
0118         base = gpio_regmap_addr(gpio->reg_dir_in_base);
0119         invert = 1;
0120     } else {
0121         return -EOPNOTSUPP;
0122     }
0123 
0124     ret = gpio->reg_mask_xlate(gpio, base, offset, &reg, &mask);
0125     if (ret)
0126         return ret;
0127 
0128     ret = regmap_read(gpio->regmap, reg, &val);
0129     if (ret)
0130         return ret;
0131 
0132     if (!!(val & mask) ^ invert)
0133         return GPIO_LINE_DIRECTION_OUT;
0134     else
0135         return GPIO_LINE_DIRECTION_IN;
0136 }
0137 
0138 static int gpio_regmap_set_direction(struct gpio_chip *chip,
0139                      unsigned int offset, bool output)
0140 {
0141     struct gpio_regmap *gpio = gpiochip_get_data(chip);
0142     unsigned int base, val, reg, mask;
0143     int invert, ret;
0144 
0145     if (gpio->reg_dir_out_base) {
0146         base = gpio_regmap_addr(gpio->reg_dir_out_base);
0147         invert = 0;
0148     } else if (gpio->reg_dir_in_base) {
0149         base = gpio_regmap_addr(gpio->reg_dir_in_base);
0150         invert = 1;
0151     } else {
0152         return -EOPNOTSUPP;
0153     }
0154 
0155     ret = gpio->reg_mask_xlate(gpio, base, offset, &reg, &mask);
0156     if (ret)
0157         return ret;
0158 
0159     if (invert)
0160         val = output ? 0 : mask;
0161     else
0162         val = output ? mask : 0;
0163 
0164     return regmap_update_bits(gpio->regmap, reg, mask, val);
0165 }
0166 
0167 static int gpio_regmap_direction_input(struct gpio_chip *chip,
0168                        unsigned int offset)
0169 {
0170     return gpio_regmap_set_direction(chip, offset, false);
0171 }
0172 
0173 static int gpio_regmap_direction_output(struct gpio_chip *chip,
0174                     unsigned int offset, int value)
0175 {
0176     gpio_regmap_set(chip, offset, value);
0177 
0178     return gpio_regmap_set_direction(chip, offset, true);
0179 }
0180 
0181 void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio)
0182 {
0183     return gpio->driver_data;
0184 }
0185 EXPORT_SYMBOL_GPL(gpio_regmap_get_drvdata);
0186 
0187 /**
0188  * gpio_regmap_register() - Register a generic regmap GPIO controller
0189  * @config: configuration for gpio_regmap
0190  *
0191  * Return: A pointer to the registered gpio_regmap or ERR_PTR error value.
0192  */
0193 struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config)
0194 {
0195     struct gpio_regmap *gpio;
0196     struct gpio_chip *chip;
0197     int ret;
0198 
0199     if (!config->parent)
0200         return ERR_PTR(-EINVAL);
0201 
0202     if (!config->ngpio)
0203         return ERR_PTR(-EINVAL);
0204 
0205     /* we need at least one */
0206     if (!config->reg_dat_base && !config->reg_set_base)
0207         return ERR_PTR(-EINVAL);
0208 
0209     /* if we have a direction register we need both input and output */
0210     if ((config->reg_dir_out_base || config->reg_dir_in_base) &&
0211         (!config->reg_dat_base || !config->reg_set_base))
0212         return ERR_PTR(-EINVAL);
0213 
0214     /* we don't support having both registers simultaneously for now */
0215     if (config->reg_dir_out_base && config->reg_dir_in_base)
0216         return ERR_PTR(-EINVAL);
0217 
0218     gpio = kzalloc(sizeof(*gpio), GFP_KERNEL);
0219     if (!gpio)
0220         return ERR_PTR(-ENOMEM);
0221 
0222     gpio->parent = config->parent;
0223     gpio->driver_data = config->drvdata;
0224     gpio->regmap = config->regmap;
0225     gpio->ngpio_per_reg = config->ngpio_per_reg;
0226     gpio->reg_stride = config->reg_stride;
0227     gpio->reg_mask_xlate = config->reg_mask_xlate;
0228     gpio->reg_dat_base = config->reg_dat_base;
0229     gpio->reg_set_base = config->reg_set_base;
0230     gpio->reg_clr_base = config->reg_clr_base;
0231     gpio->reg_dir_in_base = config->reg_dir_in_base;
0232     gpio->reg_dir_out_base = config->reg_dir_out_base;
0233 
0234     /* if not set, assume there is only one register */
0235     if (!gpio->ngpio_per_reg)
0236         gpio->ngpio_per_reg = config->ngpio;
0237 
0238     /* if not set, assume they are consecutive */
0239     if (!gpio->reg_stride)
0240         gpio->reg_stride = 1;
0241 
0242     if (!gpio->reg_mask_xlate)
0243         gpio->reg_mask_xlate = gpio_regmap_simple_xlate;
0244 
0245     chip = &gpio->gpio_chip;
0246     chip->parent = config->parent;
0247     chip->fwnode = config->fwnode;
0248     chip->base = -1;
0249     chip->ngpio = config->ngpio;
0250     chip->names = config->names;
0251     chip->label = config->label ?: dev_name(config->parent);
0252 
0253     /*
0254      * If our regmap is fast_io we should probably set can_sleep to false.
0255      * Right now, the regmap doesn't save this property, nor is there any
0256      * access function for it.
0257      * The only regmap type which uses fast_io is regmap-mmio. For now,
0258      * assume a safe default of true here.
0259      */
0260     chip->can_sleep = true;
0261 
0262     chip->get = gpio_regmap_get;
0263     if (gpio->reg_set_base && gpio->reg_clr_base)
0264         chip->set = gpio_regmap_set_with_clear;
0265     else if (gpio->reg_set_base)
0266         chip->set = gpio_regmap_set;
0267 
0268     if (gpio->reg_dir_in_base || gpio->reg_dir_out_base) {
0269         chip->get_direction = gpio_regmap_get_direction;
0270         chip->direction_input = gpio_regmap_direction_input;
0271         chip->direction_output = gpio_regmap_direction_output;
0272     }
0273 
0274     ret = gpiochip_add_data(chip, gpio);
0275     if (ret < 0)
0276         goto err_free_gpio;
0277 
0278     if (config->irq_domain) {
0279         ret = gpiochip_irqchip_add_domain(chip, config->irq_domain);
0280         if (ret)
0281             goto err_remove_gpiochip;
0282     }
0283 
0284     return gpio;
0285 
0286 err_remove_gpiochip:
0287     gpiochip_remove(chip);
0288 err_free_gpio:
0289     kfree(gpio);
0290     return ERR_PTR(ret);
0291 }
0292 EXPORT_SYMBOL_GPL(gpio_regmap_register);
0293 
0294 /**
0295  * gpio_regmap_unregister() - Unregister a generic regmap GPIO controller
0296  * @gpio: gpio_regmap device to unregister
0297  */
0298 void gpio_regmap_unregister(struct gpio_regmap *gpio)
0299 {
0300     gpiochip_remove(&gpio->gpio_chip);
0301     kfree(gpio);
0302 }
0303 EXPORT_SYMBOL_GPL(gpio_regmap_unregister);
0304 
0305 static void devm_gpio_regmap_unregister(void *res)
0306 {
0307     gpio_regmap_unregister(res);
0308 }
0309 
0310 /**
0311  * devm_gpio_regmap_register() - resource managed gpio_regmap_register()
0312  * @dev: device that is registering this GPIO device
0313  * @config: configuration for gpio_regmap
0314  *
0315  * Managed gpio_regmap_register(). For generic regmap GPIO device registered by
0316  * this function, gpio_regmap_unregister() is automatically called on driver
0317  * detach. See gpio_regmap_register() for more information.
0318  *
0319  * Return: A pointer to the registered gpio_regmap or ERR_PTR error value.
0320  */
0321 struct gpio_regmap *devm_gpio_regmap_register(struct device *dev,
0322                           const struct gpio_regmap_config *config)
0323 {
0324     struct gpio_regmap *gpio;
0325     int ret;
0326 
0327     gpio = gpio_regmap_register(config);
0328 
0329     if (IS_ERR(gpio))
0330         return gpio;
0331 
0332     ret = devm_add_action_or_reset(dev, devm_gpio_regmap_unregister, gpio);
0333     if (ret)
0334         return ERR_PTR(ret);
0335 
0336     return gpio;
0337 }
0338 EXPORT_SYMBOL_GPL(devm_gpio_regmap_register);
0339 
0340 MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
0341 MODULE_DESCRIPTION("GPIO generic regmap driver core");
0342 MODULE_LICENSE("GPL");