History

gpio: regmap: add the .fixed_direction_output configuration parameter

There are GPIO controllers such as the one present in the LX2160ARDB QIXIS FPGA which have fixed-direction input and output GPIO lines mixed together in a single register. This cannot be modeled using the gpio-regmap as-is since there is no way to present the true direction of a GPIO line. In order to make this use case possible, add a new configuration parameter - fixed_direction_output - into the gpio_regmap_config structure. This will enable user drivers to provide a bitmap that represents the fixed direction of the GPIO lines.

Ioana Ciornei committed 1 year ago

Commit 00aaae61 parent d3762312 files · +29 −2Browse files

Unified · Split

2 files
  1. drivers/gpio/gpio-regmap.c +24 −2
  2. include/linux/gpio/regmap.h +5 −0
drivers/gpio/gpio-regmap.c+24−2
@@ -31,6 +31,7 @@ struct gpio_regmap { · 30 unmodified lines
31 unsigned int reg_clr_base;31 unsigned int reg_clr_base;
32 unsigned int reg_dir_in_base;32 unsigned int reg_dir_in_base;
33 unsigned int reg_dir_out_base;33 unsigned int reg_dir_out_base;
34 unsigned long *fixed_direction_output;
34 35
35#ifdef CONFIG_REGMAP_IRQ36#ifdef CONFIG_REGMAP_IRQ
36 int regmap_irq_line;37 int regmap_irq_line;
@@ -134,6 +135,13 @@ static int gpio_regmap_get_direction(struct gpio_chip *chip, · 97 unmodified lines
134 unsigned int base, val, reg, mask;135 unsigned int base, val, reg, mask;
135 int invert, ret;136 int invert, ret;
136 137
138 if (gpio->fixed_direction_output) {
139 if (test_bit(offset, gpio->fixed_direction_output))
140 return GPIO_LINE_DIRECTION_OUT;
141 else
142 return GPIO_LINE_DIRECTION_IN;
143 }
144
137 if (gpio->reg_dat_base && !gpio->reg_set_base)145 if (gpio->reg_dat_base && !gpio->reg_set_base)
138 return GPIO_LINE_DIRECTION_IN;146 return GPIO_LINE_DIRECTION_IN;
139 if (gpio->reg_set_base && !gpio->reg_dat_base)147 if (gpio->reg_set_base && !gpio->reg_dat_base)
@@ -284,6 +292,17 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config · 144 unmodified lines
284 goto err_free_gpio;292 goto err_free_gpio;
285 }293 }
286 294
295 if (config->fixed_direction_output) {
296 gpio->fixed_direction_output = bitmap_alloc(chip->ngpio,
297 GFP_KERNEL);
298 if (!gpio->fixed_direction_output) {
299 ret = -ENOMEM;
300 goto err_free_gpio;
301 }
302 bitmap_copy(gpio->fixed_direction_output,
303 config->fixed_direction_output, chip->ngpio);
304 }
305
287 /* if not set, assume there is only one register */306 /* if not set, assume there is only one register */
288 gpio->ngpio_per_reg = config->ngpio_per_reg;307 gpio->ngpio_per_reg = config->ngpio_per_reg;
289 if (!gpio->ngpio_per_reg)308 if (!gpio->ngpio_per_reg)
@@ -300,7 +319,7 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config · 10 unmodified lines
300 319
301 ret = gpiochip_add_data(chip, gpio);320 ret = gpiochip_add_data(chip, gpio);
302 if (ret < 0)321 if (ret < 0)
303 goto err_free_gpio;322 goto err_free_bitmap;
304 323
305#ifdef CONFIG_REGMAP_IRQ324#ifdef CONFIG_REGMAP_IRQ
306 if (config->regmap_irq_chip) {325 if (config->regmap_irq_chip) {
@@ -309,7 +328,7 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config · 2 unmodified lines
309 config->regmap_irq_line, config->regmap_irq_flags,328 config->regmap_irq_line, config->regmap_irq_flags,
310 0, config->regmap_irq_chip, &gpio->irq_chip_data);329 0, config->regmap_irq_chip, &gpio->irq_chip_data);
311 if (ret)330 if (ret)
312 goto err_free_gpio;331 goto err_free_bitmap;
313 332
314 irq_domain = regmap_irq_get_domain(gpio->irq_chip_data);333 irq_domain = regmap_irq_get_domain(gpio->irq_chip_data);
315 } else334 } else
@@ -326,6 +345,8 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config · 10 unmodified lines
326 345
327err_remove_gpiochip:346err_remove_gpiochip:
328 gpiochip_remove(chip);347 gpiochip_remove(chip);
348err_free_bitmap:
349 bitmap_free(gpio->fixed_direction_output);
329err_free_gpio:350err_free_gpio:
330 kfree(gpio);351 kfree(gpio);
331 return ERR_PTR(ret);352 return ERR_PTR(ret);
@@ -344,6 +365,7 @@ void gpio_regmap_unregister(struct gpio_regmap *gpio) · 12 unmodified lines
344#endif365#endif
345 366
346 gpiochip_remove(&gpio->gpio_chip);367 gpiochip_remove(&gpio->gpio_chip);
368 bitmap_free(gpio->fixed_direction_output);
347 kfree(gpio);369 kfree(gpio);
348}370}
349EXPORT_SYMBOL_GPL(gpio_regmap_unregister);371EXPORT_SYMBOL_GPL(gpio_regmap_unregister);
include/linux/gpio/regmap.h+5−0
@@ -38,6 +38,10 @@ struct regmap; · 37 unmodified lines
38 * offset to a register/bitmask pair. If not38 * offset to a register/bitmask pair. If not
39 * given the default gpio_regmap_simple_xlate()39 * given the default gpio_regmap_simple_xlate()
40 * is used.40 * is used.
41 * @fixed_direction_output:
42 * (Optional) Bitmap representing the fixed direction of
43 * the GPIO lines. Useful when there are GPIO lines with a
44 * fixed direction mixed together in the same register.
41 * @drvdata: (Optional) Pointer to driver specific data which is45 * @drvdata: (Optional) Pointer to driver specific data which is
42 * not used by gpio-remap but is provided "as is" to the46 * not used by gpio-remap but is provided "as is" to the
43 * driver callback(s).47 * driver callback(s).
@@ -85,6 +89,7 @@ struct gpio_regmap_config { · 41 unmodified lines
85 int reg_stride;89 int reg_stride;
86 int ngpio_per_reg;90 int ngpio_per_reg;
87 struct irq_domain *irq_domain;91 struct irq_domain *irq_domain;
92 unsigned long *fixed_direction_output;
88 93
89#ifdef CONFIG_REGMAP_IRQ94#ifdef CONFIG_REGMAP_IRQ
90 struct regmap_irq_chip *regmap_irq_chip;95 struct regmap_irq_chip *regmap_irq_chip;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t