static int meson_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value) { struct meson_domain *domain = to_meson_domain(chip); unsigned int reg, bit, pin; struct meson_bank *bank; int ret; pin = domain->data->pin_base + gpio; ret = gl_pmx->soc->soc_extern_gpio_output(domain, pin, value); if (ret == 0) return 0; ret = meson_get_bank(domain, pin, &bank); if (ret) return ret; meson_calc_reg_and_bit(bank, pin, REG_DIR, ®, &bit); ret = regmap_update_bits(domain->reg_gpio, reg, BIT(bit), 0); if (ret) return ret; meson_calc_reg_and_bit(bank, pin, REG_OUT, ®, &bit); return regmap_update_bits(domain->reg_gpio, reg, BIT(bit), value ? BIT(bit) : 0); }
static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin) { struct meson_bank *bank; unsigned int reg, bit, val; int ret, conf; ret = meson_get_bank(pc, pin, &bank); if (ret) return ret; meson_calc_reg_and_bit(bank, pin, REG_PULLEN, ®, &bit); ret = regmap_read(pc->reg_pullen, reg, &val); if (ret) return ret; if (!(val & BIT(bit))) { conf = PIN_CONFIG_BIAS_DISABLE; } else { meson_calc_reg_and_bit(bank, pin, REG_PULL, ®, &bit); ret = regmap_read(pc->reg_pull, reg, &val); if (ret) return ret; if (val & BIT(bit)) conf = PIN_CONFIG_BIAS_PULL_UP; else conf = PIN_CONFIG_BIAS_PULL_DOWN; } return conf; }
static void meson_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) { struct meson_pinctrl *pc = gpiochip_get_data(chip); unsigned int reg, bit, pin; struct meson_bank *bank; int ret; pin = pc->data->pin_base + gpio; ret = meson_get_bank(pc, pin, &bank); if (ret) return; meson_calc_reg_and_bit(bank, pin, REG_OUT, ®, &bit); regmap_update_bits(pc->reg_gpio, reg, BIT(bit), value ? BIT(bit) : 0); }
static int meson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) { struct meson_pinctrl *pc = gpiochip_get_data(chip); unsigned int reg, bit, pin; struct meson_bank *bank; int ret; pin = pc->data->pin_base + gpio; ret = meson_get_bank(pc, pin, &bank); if (ret) return ret; meson_calc_reg_and_bit(bank, pin, REG_DIR, ®, &bit); return regmap_update_bits(pc->reg_gpio, reg, BIT(bit), BIT(bit)); }
static int meson_gpio_get(struct gpio_chip *chip, unsigned gpio) { struct meson_pinctrl *pc = gpiochip_get_data(chip); unsigned int reg, bit, val, pin; struct meson_bank *bank; int ret; pin = pc->data->pin_base + gpio; ret = meson_get_bank(pc, pin, &bank); if (ret) return ret; meson_calc_reg_and_bit(bank, pin, REG_IN, ®, &bit); regmap_read(pc->reg_gpio, reg, &val); return !!(val & BIT(bit)); }
static int meson_gpio_set_pullup_down(struct gpio_chip *chip, unsigned int gpio, int val) { struct meson_domain *domain = to_meson_domain(chip); unsigned int pin; struct meson_bank *bank; int ret, config; pin = domain->data->pin_base + gpio; ret = meson_get_bank(domain, pin, &bank); if (ret) return ret; config = AML_PINCONF_PACK_PULL(AML_PCON_PULLUP, val); config |= AML_PINCONF_PACK_PULLEN(AML_PCON_PULLUP, 1); meson_config_pullup(pin, domain, bank, config); return 0; }
static int meson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) { struct meson_domain *domain = to_meson_domain(chip); unsigned int reg, bit, pin; struct meson_bank *bank; int ret; pin = domain->data->pin_base + gpio; ret = meson_get_bank(domain, pin, &bank); if (ret) return ret; meson_calc_reg_and_bit(bank, pin, REG_DIR, ®, &bit); return regmap_update_bits(domain->reg_gpio, reg, BIT(bit), BIT(bit)); }
/** * meson_get_domain_and_bank() - find domain and bank containing a given pin * * @pc: Meson pin controller device * @pin: the pin number * @domain: the found domain * @bank: the found bank * * Return: 0 on success, a negative value on error */ static int meson_get_domain_and_bank(struct amlogic_pmx *pc, unsigned int pin, struct meson_domain **domain, struct meson_bank **bank) { struct meson_domain *d; int i; for (i = 0; i < pc->soc->num_domains; i++) { d = &pc->domains[i]; if (pin >= d->data->pin_base && pin < d->data->pin_base + d->data->num_pins) { *domain = d; return meson_get_bank(d, pin, bank); } } return -EINVAL; }
static int meson_gpio_get(struct gpio_chip *chip, unsigned gpio) { struct meson_domain *domain = to_meson_domain(chip); unsigned int reg, bit, val, pin; struct meson_bank *bank; int ret; pin = domain->data->pin_base + gpio; ret = gl_pmx->soc->soc_extern_gpio_get(domain, pin); if (ret != -1) return ret; ret = meson_get_bank(domain, pin, &bank); if (ret) return ret; meson_calc_reg_and_bit(bank, pin, REG_IN, ®, &bit); regmap_read(domain->reg_gpio, reg, &val); return !!(val & BIT(bit)); }
static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin, unsigned long *configs, unsigned num_configs) { struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); struct meson_bank *bank; enum pin_config_param param; unsigned int reg, bit; int i, ret; ret = meson_get_bank(pc, pin, &bank); if (ret) return ret; for (i = 0; i < num_configs; i++) { param = pinconf_to_config_param(configs[i]); switch (param) { case PIN_CONFIG_BIAS_DISABLE: dev_dbg(pc->dev, "pin %u: disable bias\n", pin); meson_calc_reg_and_bit(bank, pin, REG_PULL, ®, &bit); ret = regmap_update_bits(pc->reg_pull, reg, BIT(bit), 0); if (ret) return ret; break; case PIN_CONFIG_BIAS_PULL_UP: dev_dbg(pc->dev, "pin %u: enable pull-up\n", pin); meson_calc_reg_and_bit(bank, pin, REG_PULLEN, ®, &bit); ret = regmap_update_bits(pc->reg_pullen, reg, BIT(bit), BIT(bit)); if (ret) return ret; meson_calc_reg_and_bit(bank, pin, REG_PULL, ®, &bit); ret = regmap_update_bits(pc->reg_pull, reg, BIT(bit), BIT(bit)); if (ret) return ret; break; case PIN_CONFIG_BIAS_PULL_DOWN: dev_dbg(pc->dev, "pin %u: enable pull-down\n", pin); meson_calc_reg_and_bit(bank, pin, REG_PULLEN, ®, &bit); ret = regmap_update_bits(pc->reg_pullen, reg, BIT(bit), BIT(bit)); if (ret) return ret; meson_calc_reg_and_bit(bank, pin, REG_PULL, ®, &bit); ret = regmap_update_bits(pc->reg_pull, reg, BIT(bit), 0); if (ret) return ret; break; default: return -ENOTSUPP; } } return 0; }