/* we might not have an output register if we are input only */ if (gpio->reg_dat_base)
base = gpio_regmap_addr(gpio->reg_dat_base); else
base = gpio_regmap_addr(gpio->reg_set_base);
ret = gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); if (ret) return ret;
ret = regmap_read(gpio->regmap, reg, &val); if (ret) return ret;
return !!(val & mask);
}
staticint gpio_regmap_set(struct gpio_chip *chip, unsignedint offset, int val)
{ struct gpio_regmap *gpio = gpiochip_get_data(chip); unsignedint base = gpio_regmap_addr(gpio->reg_set_base); unsignedint reg, mask; int ret;
ret = gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); if (ret) return ret;
if (val)
ret = regmap_update_bits(gpio->regmap, reg, mask, mask); else
ret = regmap_update_bits(gpio->regmap, reg, mask, 0);
return ret;
}
staticint gpio_regmap_set_with_clear(struct gpio_chip *chip, unsignedint offset, int val)
{ struct gpio_regmap *gpio = gpiochip_get_data(chip); unsignedint base, reg, mask; int ret;
if (val)
base = gpio_regmap_addr(gpio->reg_set_base); else
base = gpio_regmap_addr(gpio->reg_clr_base);
ret = gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); if (ret) return ret;
/* we need at least one */ if (!config->reg_dat_base && !config->reg_set_base) return ERR_PTR(-EINVAL);
/* if we have a direction register we need both input and output */ if ((config->reg_dir_out_base || config->reg_dir_in_base) &&
(!config->reg_dat_base || !config->reg_set_base)) return ERR_PTR(-EINVAL);
/* we don't support having both registers simultaneously for now */ if (config->reg_dir_out_base && config->reg_dir_in_base) return ERR_PTR(-EINVAL);
gpio = kzalloc(sizeof(*gpio), GFP_KERNEL); if (!gpio) return ERR_PTR(-ENOMEM);
chip->ngpio = config->ngpio; if (!chip->ngpio) {
ret = gpiochip_get_ngpios(chip, chip->parent); if (ret) goto err_free_gpio;
}
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;
}
bitmap_copy(gpio->fixed_direction_output,
config->fixed_direction_output, chip->ngpio);
}
/* if not set, assume there is only one register */
gpio->ngpio_per_reg = config->ngpio_per_reg; if (!gpio->ngpio_per_reg)
gpio->ngpio_per_reg = config->ngpio;
/* if not set, assume they are consecutive */
gpio->reg_stride = config->reg_stride; if (!gpio->reg_stride)
gpio->reg_stride = 1;
gpio->reg_mask_xlate = config->reg_mask_xlate; if (!gpio->reg_mask_xlate)
gpio->reg_mask_xlate = gpio_regmap_simple_xlate;
ret = gpiochip_add_data(chip, gpio); if (ret < 0) goto err_free_bitmap;
#ifdef CONFIG_REGMAP_IRQ if (config->regmap_irq_chip) {
gpio->regmap_irq_line = config->regmap_irq_line;
ret = regmap_add_irq_chip_fwnode(dev_fwnode(config->parent), config->regmap,
config->regmap_irq_line, config->regmap_irq_flags, 0, config->regmap_irq_chip, &gpio->irq_chip_data); if (ret) goto err_free_bitmap;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.