9
0
Fork 0

pinctrl: Add provisions to control GPIO pin direction

Some SoC (of which Vybrid is a one example) relegate GPIO direction
control to their pinmux IP block, instead of having that functionality
within GPIO IP. Add provisions to control that aspect of pinmux to
support such SoCs.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Andrey Smirnov 2016-11-09 08:13:54 -08:00 committed by Sascha Hauer
parent d8162dd6f1
commit a4e1f15b6b
2 changed files with 66 additions and 0 deletions

View File

@ -24,6 +24,51 @@
static LIST_HEAD(pinctrl_list);
static struct pinctrl_device *pin_to_pinctrl(unsigned int pin)
{
struct pinctrl_device *pinctrl;
list_for_each_entry(pinctrl, &pinctrl_list, list)
if (pin > pinctrl->base &&
pin < pinctrl->base + pinctrl->npins)
return pinctrl;
return NULL;
}
static int pinctrl_gpio_direction(unsigned pin, bool input)
{
struct pinctrl_device *pinctrl = pin_to_pinctrl(pin);
if (!pinctrl)
return -EINVAL;
BUG_ON(!pinctrl->ops->set_direction);
return pinctrl->ops->set_direction(pinctrl, pin, input);
}
int pinctrl_gpio_direction_input(unsigned int pin)
{
return pinctrl_gpio_direction(pin, true);
}
int pinctrl_gpio_direction_output(unsigned int pin)
{
return pinctrl_gpio_direction(pin, false);
}
int pinctrl_gpio_get_direction(unsigned pin)
{
struct pinctrl_device *pinctrl = pin_to_pinctrl(pin);
if (!pinctrl)
return -EINVAL;
BUG_ON(!pinctrl->ops->get_direction);
return pinctrl->ops->get_direction(pinctrl, pin);
}
static struct pinctrl_device *find_pinctrl(struct device_node *node)
{
struct pinctrl_device *pdev;

View File

@ -5,6 +5,8 @@ struct pinctrl_device;
struct pinctrl_ops {
int (*set_state)(struct pinctrl_device *, struct device_node *);
int (*set_direction)(struct pinctrl_device *, unsigned int, bool);
int (*get_direction)(struct pinctrl_device *, unsigned int);
};
struct pinctrl_device {
@ -12,6 +14,7 @@ struct pinctrl_device {
struct pinctrl_ops *ops;
struct list_head list;
struct device_node *node;
unsigned int base, npins;
};
int pinctrl_register(struct pinctrl_device *pdev);
@ -22,6 +25,9 @@ int pinctrl_select_state(struct device_d *dev, const char *state);
int pinctrl_select_state_default(struct device_d *dev);
int of_pinctrl_select_state(struct device_node *np, const char *state);
int of_pinctrl_select_state_default(struct device_node *np);
int pinctrl_gpio_direction_input(unsigned pin);
int pinctrl_gpio_direction_output(unsigned int pin);
int pinctrl_gpio_get_direction(unsigned pin);
#else
static inline int pinctrl_select_state(struct device_d *dev, const char *state)
{
@ -42,6 +48,21 @@ static inline int of_pinctrl_select_state_default(struct device_node *np)
{
return -ENODEV;
}
static inline int pinctrl_gpio_direction_input(unsigned pin)
{
return -ENOTSUPP;
}
static inline int pinctrl_gpio_direction_output(unsigned int pin)
{
return -ENOTSUPP;
}
static inline int pinctrl_gpio_get_direction(unsigned pin)
{
return -ENOTSUPP;
}
#endif
#endif /* PINCTRL_H */