0001
0002
0003
0004
0005
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
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, ®, &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, ®, &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, ®, &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, ®, &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, ®, &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
0189
0190
0191
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
0206 if (!config->reg_dat_base && !config->reg_set_base)
0207 return ERR_PTR(-EINVAL);
0208
0209
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
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
0235 if (!gpio->ngpio_per_reg)
0236 gpio->ngpio_per_reg = config->ngpio;
0237
0238
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
0255
0256
0257
0258
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
0296
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
0312
0313
0314
0315
0316
0317
0318
0319
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");