예제 #1
0
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, &reg, &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, &reg, &bit);

	return regmap_update_bits(domain->reg_gpio, reg, BIT(bit),
				  value ? BIT(bit) : 0);
}
예제 #2
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, &reg, &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, &reg, &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;
}
예제 #3
0
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, &reg, &bit);
	regmap_update_bits(pc->reg_gpio, reg, BIT(bit),
			   value ? BIT(bit) : 0);
}
예제 #4
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, &reg, &bit);

	return regmap_update_bits(pc->reg_gpio, reg, BIT(bit), BIT(bit));
}
예제 #5
0
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, &reg, &bit);
	regmap_read(pc->reg_gpio, reg, &val);

	return !!(val & BIT(bit));
}
예제 #6
0
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;
}
예제 #7
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, &reg, &bit);

	return regmap_update_bits(domain->reg_gpio, reg, BIT(bit), BIT(bit));
}
예제 #8
0
/**
 * 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;
}
예제 #9
0
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, &reg, &bit);
	regmap_read(domain->reg_gpio, reg, &val);
	return !!(val & BIT(bit));
}
예제 #10
0
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, &reg, &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,
					       &reg, &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, &reg, &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,
					       &reg, &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, &reg, &bit);
			ret = regmap_update_bits(pc->reg_pull, reg,
						 BIT(bit), 0);
			if (ret)
				return ret;
			break;
		default:
			return -ENOTSUPP;
		}
	}

	return 0;
}