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.
Unified · Split
| @@ -31,6 +31,7 @@ struct gpio_regmap { · 30 unmodified lines | ||
| 31 | 31 | unsigned int reg_clr_base; |
| 32 | 32 | unsigned int reg_dir_in_base; |
| 33 | 33 | unsigned int reg_dir_out_base; |
| 34 | + unsigned long *fixed_direction_output; | |
| 34 | 35 | |
| 35 | 36 | #ifdef CONFIG_REGMAP_IRQ |
| 36 | 37 | int regmap_irq_line; |
| @@ -134,6 +135,13 @@ static int gpio_regmap_get_direction(struct gpio_chip *chip, · 97 unmodified lines | ||
| 134 | 135 | unsigned int base, val, reg, mask; |
| 135 | 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 | 145 | if (gpio->reg_dat_base && !gpio->reg_set_base) |
| 138 | 146 | return GPIO_LINE_DIRECTION_IN; |
| 139 | 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 | 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 | 306 | /* if not set, assume there is only one register */ |
| 288 | 307 | gpio->ngpio_per_reg = config->ngpio_per_reg; |
| 289 | 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 | 320 | ret = gpiochip_add_data(chip, gpio); |
| 302 | 321 | if (ret < 0) |
| 303 | − goto err_free_gpio; | |
| 322 | + goto err_free_bitmap; | |
| 304 | 323 | |
| 305 | 324 | #ifdef CONFIG_REGMAP_IRQ |
| 306 | 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 | 328 | config->regmap_irq_line, config->regmap_irq_flags, |
| 310 | 329 | 0, config->regmap_irq_chip, &gpio->irq_chip_data); |
| 311 | 330 | if (ret) |
| 312 | − goto err_free_gpio; | |
| 331 | + goto err_free_bitmap; | |
| 313 | 332 | |
| 314 | 333 | irq_domain = regmap_irq_get_domain(gpio->irq_chip_data); |
| 315 | 334 | } else |
| @@ -326,6 +345,8 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config · 10 unmodified lines | ||
| 326 | 345 | |
| 327 | 346 | err_remove_gpiochip: |
| 328 | 347 | gpiochip_remove(chip); |
| 348 | +err_free_bitmap: | |
| 349 | + bitmap_free(gpio->fixed_direction_output); | |
| 329 | 350 | err_free_gpio: |
| 330 | 351 | kfree(gpio); |
| 331 | 352 | return ERR_PTR(ret); |
| @@ -344,6 +365,7 @@ void gpio_regmap_unregister(struct gpio_regmap *gpio) · 12 unmodified lines | ||
| 344 | 365 | #endif |
| 345 | 366 | |
| 346 | 367 | gpiochip_remove(&gpio->gpio_chip); |
| 368 | + bitmap_free(gpio->fixed_direction_output); | |
| 347 | 369 | kfree(gpio); |
| 348 | 370 | } |
| 349 | 371 | EXPORT_SYMBOL_GPL(gpio_regmap_unregister); |
| @@ -38,6 +38,10 @@ struct regmap; · 37 unmodified lines | ||
| 38 | 38 | * offset to a register/bitmask pair. If not |
| 39 | 39 | * given the default gpio_regmap_simple_xlate() |
| 40 | 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 | 45 | * @drvdata: (Optional) Pointer to driver specific data which is |
| 42 | 46 | * not used by gpio-remap but is provided "as is" to the |
| 43 | 47 | * driver callback(s). |
| @@ -85,6 +89,7 @@ struct gpio_regmap_config { · 41 unmodified lines | ||
| 85 | 89 | int reg_stride; |
| 86 | 90 | int ngpio_per_reg; |
| 87 | 91 | struct irq_domain *irq_domain; |
| 92 | + unsigned long *fixed_direction_output; | |
| 88 | 93 | |
| 89 | 94 | #ifdef CONFIG_REGMAP_IRQ |
| 90 | 95 | struct regmap_irq_chip *regmap_irq_chip; |