Skip to content
Snippets Groups Projects
Verified Commit f9bb5394 authored by Neil Armstrong's avatar Neil Armstrong Committed by Caleb Connolly
Browse files

gpio: msm: add support for special pins


Leverage the data introduced in the struct msm_special_pin_data to allow
setting the gpio direction and value if supported by the pin data.

Signed-off-by: default avatarNeil Armstrong <neil.armstrong@linaro.org>
Reviewed-by: default avatarCaleb Connolly <caleb.connolly@linaro.org>
parent 62130bc0
No related branches found
No related tags found
No related merge requests found
......@@ -34,13 +34,31 @@ struct msm_gpio_bank {
#define GPIO_IN_OUT_REG(dev, x) \
(GPIO_CONFIG_REG(dev, x) + 0x4)
static void msm_gpio_direction_input_special(struct msm_gpio_bank *priv,
unsigned int gpio)
{
unsigned int offset = gpio - priv->pin_data->special_pins_start;
const struct msm_special_pin_data *data;
if (!priv->pin_data->special_pins_data)
return;
data = &priv->pin_data->special_pins_data[offset];
if (!data->ctl_reg || data->oe_bit >= 31)
return;
/* switch direction */
clrsetbits_le32(priv->base + data->ctl_reg,
BIT(data->oe_bit), 0);
}
static void msm_gpio_direction_input(struct udevice *dev, unsigned int gpio)
{
struct msm_gpio_bank *priv = dev_get_priv(dev);
/* Always NOP for special pins, assume they're in the correct state */
if (qcom_is_special_pin(priv->pin_data, gpio))
return;
msm_gpio_direction_input_special(priv, gpio);
/* Disable OE bit */
clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio),
......@@ -49,13 +67,33 @@ static void msm_gpio_direction_input(struct udevice *dev, unsigned int gpio)
return;
}
static int msm_gpio_set_value_special(struct msm_gpio_bank *priv,
unsigned int gpio, int value)
{
unsigned int offset = gpio - priv->pin_data->special_pins_start;
const struct msm_special_pin_data *data;
if (!priv->pin_data->special_pins_data)
return 0;
data = &priv->pin_data->special_pins_data[offset];
if (!data->io_reg || data->out_bit >= 31)
return 0;
value = !!value;
/* set value */
writel(value << data->out_bit, priv->base + data->io_reg);
return 0;
}
static int msm_gpio_set_value(struct udevice *dev, unsigned int gpio, int value)
{
struct msm_gpio_bank *priv = dev_get_priv(dev);
/* Always NOP for special pins, assume they're in the correct state */
if (qcom_is_special_pin(priv->pin_data, gpio))
return 0;
return msm_gpio_set_value_special(priv, gpio, value);
value = !!value;
/* set value */
......@@ -64,14 +102,42 @@ static int msm_gpio_set_value(struct udevice *dev, unsigned int gpio, int value)
return 0;
}
static int msm_gpio_direction_output_special(struct msm_gpio_bank *priv,
unsigned int gpio,
int value)
{
unsigned int offset = gpio - priv->pin_data->special_pins_start;
const struct msm_special_pin_data *data;
if (!priv->pin_data->special_pins_data)
return 0;
data = &priv->pin_data->special_pins_data[offset];
if (!data->io_reg || data->out_bit >= 31)
return 0;
value = !!value;
/* set value */
writel(value << data->out_bit, priv->base + data->io_reg);
if (!data->ctl_reg || data->oe_bit >= 31)
return 0;
/* switch direction */
clrsetbits_le32(priv->base + data->ctl_reg,
BIT(data->oe_bit), BIT(data->oe_bit));
return 0;
}
static int msm_gpio_direction_output(struct udevice *dev, unsigned int gpio,
int value)
{
struct msm_gpio_bank *priv = dev_get_priv(dev);
/* Always NOP for special pins, assume they're in the correct state */
if (qcom_is_special_pin(priv->pin_data, gpio))
return 0;
return msm_gpio_direction_output_special(priv, gpio, value);
value = !!value;
/* set value */
......@@ -100,13 +166,28 @@ static int msm_gpio_set_flags(struct udevice *dev, unsigned int gpio, ulong flag
return 0;
}
static int msm_gpio_get_value_special(struct msm_gpio_bank *priv, unsigned int gpio)
{
unsigned int offset = gpio - priv->pin_data->special_pins_start;
const struct msm_special_pin_data *data;
if (!priv->pin_data->special_pins_data)
return 0;
data = &priv->pin_data->special_pins_data[offset];
if (!data->io_reg || data->in_bit >= 31)
return 0;
return !!(readl(priv->base + data->io_reg) >> data->in_bit);
}
static int msm_gpio_get_value(struct udevice *dev, unsigned int gpio)
{
struct msm_gpio_bank *priv = dev_get_priv(dev);
/* Always NOP for special pins, assume they're in the correct state */
if (qcom_is_special_pin(priv->pin_data, gpio))
return 0;
return msm_gpio_get_value_special(priv, gpio);
return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) >> GPIO_IN);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment