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..7d87169 100644 --- a/include/pinctrl.h +++ b/include/pinctrl.h @@ -5,6 +5,8 @@ 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_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_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 @@ { 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 */