mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-20 20:04:46 +00:00
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: Neil Armstrong <neil.armstrong@linaro.org> Reviewed-by: Caleb Connolly <caleb.connolly@linaro.org>
This commit is contained in:
parent
62130bc0cb
commit
f9bb539460
1 changed files with 91 additions and 10 deletions
|
@ -34,13 +34,31 @@ struct msm_gpio_bank {
|
||||||
#define GPIO_IN_OUT_REG(dev, x) \
|
#define GPIO_IN_OUT_REG(dev, x) \
|
||||||
(GPIO_CONFIG_REG(dev, x) + 0x4)
|
(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)
|
static void msm_gpio_direction_input(struct udevice *dev, unsigned int gpio)
|
||||||
{
|
{
|
||||||
struct msm_gpio_bank *priv = dev_get_priv(dev);
|
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))
|
if (qcom_is_special_pin(priv->pin_data, gpio))
|
||||||
return;
|
msm_gpio_direction_input_special(priv, gpio);
|
||||||
|
|
||||||
/* Disable OE bit */
|
/* Disable OE bit */
|
||||||
clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio),
|
clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio),
|
||||||
|
@ -49,14 +67,34 @@ static void msm_gpio_direction_input(struct udevice *dev, unsigned int gpio)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int msm_gpio_set_value(struct udevice *dev, unsigned int gpio, int value)
|
static int msm_gpio_set_value_special(struct msm_gpio_bank *priv,
|
||||||
|
unsigned int gpio, int value)
|
||||||
{
|
{
|
||||||
struct msm_gpio_bank *priv = dev_get_priv(dev);
|
unsigned int offset = gpio - priv->pin_data->special_pins_start;
|
||||||
|
const struct msm_special_pin_data *data;
|
||||||
|
|
||||||
/* Always NOP for special pins, assume they're in the correct state */
|
if (!priv->pin_data->special_pins_data)
|
||||||
if (qcom_is_special_pin(priv->pin_data, gpio))
|
return 0;
|
||||||
|
|
||||||
|
data = &priv->pin_data->special_pins_data[offset];
|
||||||
|
|
||||||
|
if (!data->io_reg || data->out_bit >= 31)
|
||||||
return 0;
|
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);
|
||||||
|
|
||||||
|
if (qcom_is_special_pin(priv->pin_data, gpio))
|
||||||
|
return msm_gpio_set_value_special(priv, gpio, value);
|
||||||
|
|
||||||
value = !!value;
|
value = !!value;
|
||||||
/* set value */
|
/* set value */
|
||||||
writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_REG(dev, gpio));
|
writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_REG(dev, gpio));
|
||||||
|
@ -64,14 +102,42 @@ static int msm_gpio_set_value(struct udevice *dev, unsigned int gpio, int value)
|
||||||
return 0;
|
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,
|
static int msm_gpio_direction_output(struct udevice *dev, unsigned int gpio,
|
||||||
int value)
|
int value)
|
||||||
{
|
{
|
||||||
struct msm_gpio_bank *priv = dev_get_priv(dev);
|
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))
|
if (qcom_is_special_pin(priv->pin_data, gpio))
|
||||||
return 0;
|
return msm_gpio_direction_output_special(priv, gpio, value);
|
||||||
|
|
||||||
value = !!value;
|
value = !!value;
|
||||||
/* set value */
|
/* set value */
|
||||||
|
@ -100,13 +166,28 @@ static int msm_gpio_set_flags(struct udevice *dev, unsigned int gpio, ulong flag
|
||||||
return 0;
|
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)
|
static int msm_gpio_get_value(struct udevice *dev, unsigned int gpio)
|
||||||
{
|
{
|
||||||
struct msm_gpio_bank *priv = dev_get_priv(dev);
|
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))
|
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);
|
return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) >> GPIO_IN);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue