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@xxxxxxxxx> --- drivers/pinctrl/pinctrl.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ include/pinctrl.h | 21 +++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/drivers/pinctrl/pinctrl.c b/drivers/pinctrl/pinctrl.c index e7b08a2..bef4fcd 100644 --- a/drivers/pinctrl/pinctrl.c +++ b/drivers/pinctrl/pinctrl.c @@ -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; diff --git a/include/pinctrl.h b/include/pinctrl.h index 0f03b10..0fde3f9 100644 --- a/include/pinctrl.h +++ b/include/pinctrl.h @@ -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(unsigend 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 */ -- 2.5.5 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox