unsigned int reg_clr_base;
unsigned int reg_dir_in_base;
unsigned int reg_dir_out_base;
+ unsigned long *fixed_direction_mask;
unsigned long *fixed_direction_output;
#ifdef CONFIG_REGMAP_IRQ
return regmap_write(gpio->regmap, reg, mask);
}
+static bool gpio_regmap_fixed_direction(struct gpio_regmap *gpio,
+ unsigned int offset)
+{
+ if (!gpio->fixed_direction_output)
+ return false;
+
+ /* In this case only some GPIOs are fixed as input/output */
+ if (gpio->fixed_direction_mask &&
+ !test_bit(offset, gpio->fixed_direction_mask))
+ return false;
+
+ return true;
+}
+
static int gpio_regmap_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
unsigned int base, val, reg, mask;
int invert, ret;
- if (gpio->fixed_direction_output) {
+ if (gpio_regmap_fixed_direction(gpio, offset)) {
if (test_bit(offset, gpio->fixed_direction_output))
return GPIO_LINE_DIRECTION_OUT;
else
goto err_free_gpio;
}
+ if (config->fixed_direction_mask) {
+ gpio->fixed_direction_mask = bitmap_alloc(chip->ngpio,
+ GFP_KERNEL);
+ if (!gpio->fixed_direction_mask) {
+ ret = -ENOMEM;
+ goto err_free_gpio;
+ }
+ bitmap_copy(gpio->fixed_direction_mask,
+ config->fixed_direction_mask, chip->ngpio);
+ }
+
if (config->fixed_direction_output) {
gpio->fixed_direction_output = bitmap_alloc(chip->ngpio,
GFP_KERNEL);
if (!gpio->fixed_direction_output) {
ret = -ENOMEM;
- goto err_free_gpio;
+ goto err_free_bitmap_dirmask;
}
bitmap_copy(gpio->fixed_direction_output,
config->fixed_direction_output, chip->ngpio);
ret = gpiochip_add_data(chip, gpio);
if (ret < 0)
- goto err_free_bitmap;
+ goto err_free_bitmap_output;
#ifdef CONFIG_REGMAP_IRQ
if (config->regmap_irq_chip) {
err_remove_gpiochip:
gpiochip_remove(chip);
-err_free_bitmap:
+err_free_bitmap_output:
bitmap_free(gpio->fixed_direction_output);
+err_free_bitmap_dirmask:
+ bitmap_free(gpio->fixed_direction_mask);
err_free_gpio:
kfree(gpio);
return ERR_PTR(ret);
gpiochip_remove(&gpio->gpio_chip);
bitmap_free(gpio->fixed_direction_output);
+ bitmap_free(gpio->fixed_direction_mask);
kfree(gpio);
}
EXPORT_SYMBOL_GPL(gpio_regmap_unregister);
* offset to a register/bitmask pair. If not
* given the default gpio_regmap_simple_xlate()
* is used.
+ * @fixed_direction_mask:
+ * (Optional) Bitmap representing the GPIO lines that
+ * make use of the @fixed_direction_output list to
+ * enforce direction of the GPIO. If this is NULL
+ * and @fixed_direction_output is defined, ALL GPIOs
+ * are assumed to be fixed direction (out or in).
* @fixed_direction_output:
* (Optional) Bitmap representing the fixed direction of
* the GPIO lines. Useful when there are GPIO lines with a
int reg_stride;
int ngpio_per_reg;
struct irq_domain *irq_domain;
+ unsigned long *fixed_direction_mask;
unsigned long *fixed_direction_output;
#ifdef CONFIG_REGMAP_IRQ