1 // SPDX-License-Identifier: GPL-2.0-only
3 * regmap based generic GPIO driver
5 * Copyright 2020 Michael Walle <michael@walle.cc>
8 #include <linux/bits.h>
9 #include <linux/device.h>
10 #include <linux/err.h>
12 #include <linux/module.h>
13 #include <linux/regmap.h>
14 #include <linux/slab.h>
15 #include <linux/types.h>
17 #include <linux/gpio/driver.h>
18 #include <linux/gpio/regmap.h>
21 struct device
*parent
;
22 struct regmap
*regmap
;
23 struct gpio_chip gpio_chip
;
27 unsigned int reg_dat_base
;
28 unsigned int reg_set_base
;
29 unsigned int reg_clr_base
;
30 unsigned int reg_dir_in_base
;
31 unsigned int reg_dir_out_base
;
33 int (*reg_mask_xlate
)(struct gpio_regmap
*gpio
, unsigned int base
,
34 unsigned int offset
, unsigned int *reg
,
40 static unsigned int gpio_regmap_addr(unsigned int addr
)
42 if (addr
== GPIO_REGMAP_ADDR_ZERO
)
48 static int gpio_regmap_simple_xlate(struct gpio_regmap
*gpio
,
49 unsigned int base
, unsigned int offset
,
50 unsigned int *reg
, unsigned int *mask
)
52 unsigned int line
= offset
% gpio
->ngpio_per_reg
;
53 unsigned int stride
= offset
/ gpio
->ngpio_per_reg
;
55 *reg
= base
+ stride
* gpio
->reg_stride
;
61 static int gpio_regmap_get(struct gpio_chip
*chip
, unsigned int offset
)
63 struct gpio_regmap
*gpio
= gpiochip_get_data(chip
);
64 unsigned int base
, val
, reg
, mask
;
67 /* we might not have an output register if we are input only */
68 if (gpio
->reg_dat_base
)
69 base
= gpio_regmap_addr(gpio
->reg_dat_base
);
71 base
= gpio_regmap_addr(gpio
->reg_set_base
);
73 ret
= gpio
->reg_mask_xlate(gpio
, base
, offset
, ®
, &mask
);
77 ret
= regmap_read(gpio
->regmap
, reg
, &val
);
81 return !!(val
& mask
);
84 static void gpio_regmap_set(struct gpio_chip
*chip
, unsigned int offset
,
87 struct gpio_regmap
*gpio
= gpiochip_get_data(chip
);
88 unsigned int base
= gpio_regmap_addr(gpio
->reg_set_base
);
89 unsigned int reg
, mask
;
91 gpio
->reg_mask_xlate(gpio
, base
, offset
, ®
, &mask
);
93 regmap_update_bits(gpio
->regmap
, reg
, mask
, mask
);
95 regmap_update_bits(gpio
->regmap
, reg
, mask
, 0);
98 static void gpio_regmap_set_with_clear(struct gpio_chip
*chip
,
99 unsigned int offset
, int val
)
101 struct gpio_regmap
*gpio
= gpiochip_get_data(chip
);
102 unsigned int base
, reg
, mask
;
105 base
= gpio_regmap_addr(gpio
->reg_set_base
);
107 base
= gpio_regmap_addr(gpio
->reg_clr_base
);
109 gpio
->reg_mask_xlate(gpio
, base
, offset
, ®
, &mask
);
110 regmap_write(gpio
->regmap
, reg
, mask
);
113 static int gpio_regmap_get_direction(struct gpio_chip
*chip
,
116 struct gpio_regmap
*gpio
= gpiochip_get_data(chip
);
117 unsigned int base
, val
, reg
, mask
;
120 if (gpio
->reg_dat_base
&& !gpio
->reg_set_base
)
121 return GPIO_LINE_DIRECTION_IN
;
122 if (gpio
->reg_set_base
&& !gpio
->reg_dat_base
)
123 return GPIO_LINE_DIRECTION_OUT
;
125 if (gpio
->reg_dir_out_base
) {
126 base
= gpio_regmap_addr(gpio
->reg_dir_out_base
);
128 } else if (gpio
->reg_dir_in_base
) {
129 base
= gpio_regmap_addr(gpio
->reg_dir_in_base
);
135 ret
= gpio
->reg_mask_xlate(gpio
, base
, offset
, ®
, &mask
);
139 ret
= regmap_read(gpio
->regmap
, reg
, &val
);
143 if (!!(val
& mask
) ^ invert
)
144 return GPIO_LINE_DIRECTION_OUT
;
146 return GPIO_LINE_DIRECTION_IN
;
149 static int gpio_regmap_set_direction(struct gpio_chip
*chip
,
150 unsigned int offset
, bool output
)
152 struct gpio_regmap
*gpio
= gpiochip_get_data(chip
);
153 unsigned int base
, val
, reg
, mask
;
156 if (gpio
->reg_dir_out_base
) {
157 base
= gpio_regmap_addr(gpio
->reg_dir_out_base
);
159 } else if (gpio
->reg_dir_in_base
) {
160 base
= gpio_regmap_addr(gpio
->reg_dir_in_base
);
166 ret
= gpio
->reg_mask_xlate(gpio
, base
, offset
, ®
, &mask
);
171 val
= output
? 0 : mask
;
173 val
= output
? mask
: 0;
175 return regmap_update_bits(gpio
->regmap
, reg
, mask
, val
);
178 static int gpio_regmap_direction_input(struct gpio_chip
*chip
,
181 return gpio_regmap_set_direction(chip
, offset
, false);
184 static int gpio_regmap_direction_output(struct gpio_chip
*chip
,
185 unsigned int offset
, int value
)
187 gpio_regmap_set(chip
, offset
, value
);
189 return gpio_regmap_set_direction(chip
, offset
, true);
192 void *gpio_regmap_get_drvdata(struct gpio_regmap
*gpio
)
194 return gpio
->driver_data
;
196 EXPORT_SYMBOL_GPL(gpio_regmap_get_drvdata
);
199 * gpio_regmap_register() - Register a generic regmap GPIO controller
200 * @config: configuration for gpio_regmap
202 * Return: A pointer to the registered gpio_regmap or ERR_PTR error value.
204 struct gpio_regmap
*gpio_regmap_register(const struct gpio_regmap_config
*config
)
206 struct gpio_regmap
*gpio
;
207 struct gpio_chip
*chip
;
211 return ERR_PTR(-EINVAL
);
214 return ERR_PTR(-EINVAL
);
216 /* we need at least one */
217 if (!config
->reg_dat_base
&& !config
->reg_set_base
)
218 return ERR_PTR(-EINVAL
);
220 /* if we have a direction register we need both input and output */
221 if ((config
->reg_dir_out_base
|| config
->reg_dir_in_base
) &&
222 (!config
->reg_dat_base
|| !config
->reg_set_base
))
223 return ERR_PTR(-EINVAL
);
225 /* we don't support having both registers simultaneously for now */
226 if (config
->reg_dir_out_base
&& config
->reg_dir_in_base
)
227 return ERR_PTR(-EINVAL
);
229 gpio
= kzalloc(sizeof(*gpio
), GFP_KERNEL
);
231 return ERR_PTR(-ENOMEM
);
233 gpio
->parent
= config
->parent
;
234 gpio
->driver_data
= config
->drvdata
;
235 gpio
->regmap
= config
->regmap
;
236 gpio
->ngpio_per_reg
= config
->ngpio_per_reg
;
237 gpio
->reg_stride
= config
->reg_stride
;
238 gpio
->reg_mask_xlate
= config
->reg_mask_xlate
;
239 gpio
->reg_dat_base
= config
->reg_dat_base
;
240 gpio
->reg_set_base
= config
->reg_set_base
;
241 gpio
->reg_clr_base
= config
->reg_clr_base
;
242 gpio
->reg_dir_in_base
= config
->reg_dir_in_base
;
243 gpio
->reg_dir_out_base
= config
->reg_dir_out_base
;
245 /* if not set, assume there is only one register */
246 if (!gpio
->ngpio_per_reg
)
247 gpio
->ngpio_per_reg
= config
->ngpio
;
249 /* if not set, assume they are consecutive */
250 if (!gpio
->reg_stride
)
251 gpio
->reg_stride
= 1;
253 if (!gpio
->reg_mask_xlate
)
254 gpio
->reg_mask_xlate
= gpio_regmap_simple_xlate
;
256 chip
= &gpio
->gpio_chip
;
257 chip
->parent
= config
->parent
;
258 chip
->fwnode
= config
->fwnode
;
260 chip
->ngpio
= config
->ngpio
;
261 chip
->names
= config
->names
;
262 chip
->label
= config
->label
?: dev_name(config
->parent
);
263 chip
->can_sleep
= regmap_might_sleep(config
->regmap
);
265 chip
->get
= gpio_regmap_get
;
266 if (gpio
->reg_set_base
&& gpio
->reg_clr_base
)
267 chip
->set
= gpio_regmap_set_with_clear
;
268 else if (gpio
->reg_set_base
)
269 chip
->set
= gpio_regmap_set
;
271 chip
->get_direction
= gpio_regmap_get_direction
;
272 if (gpio
->reg_dir_in_base
|| gpio
->reg_dir_out_base
) {
273 chip
->direction_input
= gpio_regmap_direction_input
;
274 chip
->direction_output
= gpio_regmap_direction_output
;
277 ret
= gpiochip_add_data(chip
, gpio
);
281 if (config
->irq_domain
) {
282 ret
= gpiochip_irqchip_add_domain(chip
, config
->irq_domain
);
284 goto err_remove_gpiochip
;
290 gpiochip_remove(chip
);
295 EXPORT_SYMBOL_GPL(gpio_regmap_register
);
298 * gpio_regmap_unregister() - Unregister a generic regmap GPIO controller
299 * @gpio: gpio_regmap device to unregister
301 void gpio_regmap_unregister(struct gpio_regmap
*gpio
)
303 gpiochip_remove(&gpio
->gpio_chip
);
306 EXPORT_SYMBOL_GPL(gpio_regmap_unregister
);
308 static void devm_gpio_regmap_unregister(void *res
)
310 gpio_regmap_unregister(res
);
314 * devm_gpio_regmap_register() - resource managed gpio_regmap_register()
315 * @dev: device that is registering this GPIO device
316 * @config: configuration for gpio_regmap
318 * Managed gpio_regmap_register(). For generic regmap GPIO device registered by
319 * this function, gpio_regmap_unregister() is automatically called on driver
320 * detach. See gpio_regmap_register() for more information.
322 * Return: A pointer to the registered gpio_regmap or ERR_PTR error value.
324 struct gpio_regmap
*devm_gpio_regmap_register(struct device
*dev
,
325 const struct gpio_regmap_config
*config
)
327 struct gpio_regmap
*gpio
;
330 gpio
= gpio_regmap_register(config
);
335 ret
= devm_add_action_or_reset(dev
, devm_gpio_regmap_unregister
, gpio
);
341 EXPORT_SYMBOL_GPL(devm_gpio_regmap_register
);
343 MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
344 MODULE_DESCRIPTION("GPIO generic regmap driver core");
345 MODULE_LICENSE("GPL");