/* 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;
/** * gpio_regmap_register() - Register a generic regmap GPIO controller * @config: configuration for gpio_regmap * * Return: A pointer to the registered gpio_regmap or ERR_PTR error value.
*/ struct gpio_regmap *gpio_regmap_register(conststruct gpio_regmap_config *config)
{ struct irq_domain *irq_domain; struct gpio_regmap *gpio; struct gpio_chip *chip; int ret;
if (!config->parent) return ERR_PTR(-EINVAL);
/* 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;
/** * devm_gpio_regmap_register() - resource managed gpio_regmap_register() * @dev: device that is registering this GPIO device * @config: configuration for gpio_regmap * * Managed gpio_regmap_register(). For generic regmap GPIO device registered by * this function, gpio_regmap_unregister() is automatically called on driver * detach. See gpio_regmap_register() for more information. * * Return: A pointer to the registered gpio_regmap or ERR_PTR error value.
*/ struct gpio_regmap *devm_gpio_regmap_register(struct device *dev, conststruct gpio_regmap_config *config)
{ struct gpio_regmap *gpio; int ret;
gpio = gpio_regmap_register(config);
if (IS_ERR(gpio)) return gpio;
ret = devm_add_action_or_reset(dev, devm_gpio_regmap_unregister, gpio); if (ret) return ERR_PTR(ret);
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.