mirror of https://gitee.com/openkylin/linux.git
pinctrl: meson: add output support in pinconf
Add pinconf support for PIN_CONFIG_OUTPUT_ENABLE and PIN_CONFIG_OUTPUT in the meson pinctrl driver. Signed-off-by: Jerome Brunet <jbrunet@baylibre.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
1254db248f
commit
b22a7f8544
|
@ -174,6 +174,88 @@ int meson_pmx_get_groups(struct pinctrl_dev *pcdev, unsigned selector,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int meson_pinconf_set_gpio_bit(struct meson_pinctrl *pc,
|
||||
unsigned int pin,
|
||||
unsigned int reg_type,
|
||||
bool arg)
|
||||
{
|
||||
struct meson_bank *bank;
|
||||
unsigned int reg, bit;
|
||||
int ret;
|
||||
|
||||
ret = meson_get_bank(pc, pin, &bank);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
meson_calc_reg_and_bit(bank, pin, reg_type, ®, &bit);
|
||||
return regmap_update_bits(pc->reg_gpio, reg, BIT(bit),
|
||||
arg ? BIT(bit) : 0);
|
||||
}
|
||||
|
||||
static int meson_pinconf_get_gpio_bit(struct meson_pinctrl *pc,
|
||||
unsigned int pin,
|
||||
unsigned int reg_type)
|
||||
{
|
||||
struct meson_bank *bank;
|
||||
unsigned int reg, bit, val;
|
||||
int ret;
|
||||
|
||||
ret = meson_get_bank(pc, pin, &bank);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
meson_calc_reg_and_bit(bank, pin, reg_type, ®, &bit);
|
||||
ret = regmap_read(pc->reg_gpio, reg, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return BIT(bit) & val ? 1 : 0;
|
||||
}
|
||||
|
||||
static int meson_pinconf_set_output(struct meson_pinctrl *pc,
|
||||
unsigned int pin,
|
||||
bool out)
|
||||
{
|
||||
return meson_pinconf_set_gpio_bit(pc, pin, REG_DIR, !out);
|
||||
}
|
||||
|
||||
static int meson_pinconf_get_output(struct meson_pinctrl *pc,
|
||||
unsigned int pin)
|
||||
{
|
||||
int ret = meson_pinconf_get_gpio_bit(pc, pin, REG_DIR);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return !ret;
|
||||
}
|
||||
|
||||
static int meson_pinconf_set_drive(struct meson_pinctrl *pc,
|
||||
unsigned int pin,
|
||||
bool high)
|
||||
{
|
||||
return meson_pinconf_set_gpio_bit(pc, pin, REG_OUT, high);
|
||||
}
|
||||
|
||||
static int meson_pinconf_get_drive(struct meson_pinctrl *pc,
|
||||
unsigned int pin)
|
||||
{
|
||||
return meson_pinconf_get_gpio_bit(pc, pin, REG_OUT);
|
||||
}
|
||||
|
||||
static int meson_pinconf_set_output_drive(struct meson_pinctrl *pc,
|
||||
unsigned int pin,
|
||||
bool high)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = meson_pinconf_set_output(pc, pin, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return meson_pinconf_set_drive(pc, pin, high);
|
||||
}
|
||||
|
||||
static int meson_pinconf_disable_bias(struct meson_pinctrl *pc,
|
||||
unsigned int pin)
|
||||
{
|
||||
|
@ -267,39 +349,48 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
|
|||
{
|
||||
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
|
||||
enum pin_config_param param;
|
||||
unsigned int drive_strength_ua;
|
||||
unsigned int arg = 0;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
param = pinconf_to_config_param(configs[i]);
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_DRIVE_STRENGTH_UA:
|
||||
case PIN_CONFIG_OUTPUT_ENABLE:
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
arg = pinconf_to_config_argument(configs[i]);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
ret = meson_pinconf_disable_bias(pc, pin);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
ret = meson_pinconf_enable_bias(pc, pin, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
ret = meson_pinconf_enable_bias(pc, pin, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH_UA:
|
||||
drive_strength_ua =
|
||||
pinconf_to_config_argument(configs[i]);
|
||||
ret = meson_pinconf_set_drive_strength
|
||||
(pc, pin, drive_strength_ua);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = meson_pinconf_set_drive_strength(pc, pin, arg);
|
||||
break;
|
||||
case PIN_CONFIG_OUTPUT_ENABLE:
|
||||
ret = meson_pinconf_set_output(pc, pin, arg);
|
||||
break;
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
ret = meson_pinconf_set_output_drive(pc, pin, arg);
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
ret = -ENOTSUPP;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -403,6 +494,24 @@ static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin,
|
|||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case PIN_CONFIG_OUTPUT_ENABLE:
|
||||
ret = meson_pinconf_get_output(pc, pin);
|
||||
if (ret <= 0)
|
||||
return -EINVAL;
|
||||
arg = 1;
|
||||
break;
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
ret = meson_pinconf_get_output(pc, pin);
|
||||
if (ret <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = meson_pinconf_get_drive(pc, pin);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
arg = ret;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
@ -447,56 +556,19 @@ static const struct pinconf_ops meson_pinconf_ops = {
|
|||
|
||||
static int meson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
struct meson_pinctrl *pc = gpiochip_get_data(chip);
|
||||
unsigned int reg, bit;
|
||||
struct meson_bank *bank;
|
||||
int ret;
|
||||
|
||||
ret = meson_get_bank(pc, gpio, &bank);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
meson_calc_reg_and_bit(bank, gpio, REG_DIR, ®, &bit);
|
||||
|
||||
return regmap_update_bits(pc->reg_gpio, reg, BIT(bit), BIT(bit));
|
||||
return meson_pinconf_set_output(gpiochip_get_data(chip), gpio, false);
|
||||
}
|
||||
|
||||
static int meson_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
|
||||
int value)
|
||||
{
|
||||
struct meson_pinctrl *pc = gpiochip_get_data(chip);
|
||||
unsigned int reg, bit;
|
||||
struct meson_bank *bank;
|
||||
int ret;
|
||||
|
||||
ret = meson_get_bank(pc, gpio, &bank);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
meson_calc_reg_and_bit(bank, gpio, REG_DIR, ®, &bit);
|
||||
ret = regmap_update_bits(pc->reg_gpio, reg, BIT(bit), 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
meson_calc_reg_and_bit(bank, gpio, REG_OUT, ®, &bit);
|
||||
return regmap_update_bits(pc->reg_gpio, reg, BIT(bit),
|
||||
value ? BIT(bit) : 0);
|
||||
return meson_pinconf_set_output_drive(gpiochip_get_data(chip),
|
||||
gpio, value);
|
||||
}
|
||||
|
||||
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;
|
||||
struct meson_bank *bank;
|
||||
int ret;
|
||||
|
||||
ret = meson_get_bank(pc, gpio, &bank);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
meson_calc_reg_and_bit(bank, gpio, REG_OUT, ®, &bit);
|
||||
regmap_update_bits(pc->reg_gpio, reg, BIT(bit),
|
||||
value ? BIT(bit) : 0);
|
||||
meson_pinconf_set_drive(gpiochip_get_data(chip), gpio, value);
|
||||
}
|
||||
|
||||
static int meson_gpio_get(struct gpio_chip *chip, unsigned gpio)
|
||||
|
|
Loading…
Reference in New Issue