From 9467d298e92455e6fd411d7ef1f367ced940587c Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 1 Feb 2012 12:09:04 +0530 Subject: gpio: tps65910: Add sleep control support The device tps65910/tps65911 supports the sleep functionality in some of gpios. If gpio is configured in output mode and sleep is enabled then during device sleep state, the output of gpio becomes LOW regardless of non-sleep output value. Such gpio can be used to control regulator switch such that output of regulator is off in device sleep state. Signed-off-by: Laxman Dewangan Signed-off-by: Grant Likely Acked-by: Linus Walleij --- include/linux/mfd/tps65910.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include/linux') diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index d0cb12eba402..9071902bd222 100644 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h @@ -657,6 +657,8 @@ /*Register GPIO (0x80) register.RegisterDescription */ +#define GPIO_SLEEP_MASK 0x80 +#define GPIO_SLEEP_SHIFT 7 #define GPIO_DEB_MASK 0x10 #define GPIO_DEB_SHIFT 4 #define GPIO_PUEN_MASK 0x08 @@ -740,6 +742,11 @@ #define TPS65910_GPIO_STS BIT(1) #define TPS65910_GPIO_SET BIT(0) +/* Max number of TPS65910/11 GPIOs */ +#define TPS65910_NUM_GPIO 6 +#define TPS65911_NUM_GPIO 9 +#define TPS6591X_MAX_NUM_GPIO 9 + /* Regulator Index Definitions */ #define TPS65910_REG_VRTC 0 #define TPS65910_REG_VIO 1 @@ -779,6 +786,7 @@ struct tps65910_board { int irq_base; int vmbch_threshold; int vmbch2_threshold; + bool en_gpio_sleep[TPS6591X_MAX_NUM_GPIO]; struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS]; }; -- cgit v1.2.3-55-g7522 From ff64abefb6680dfc2aca7ecaa5e695949e7335c9 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Thu, 2 Feb 2012 16:20:01 +0100 Subject: of_gpio: add support of of_gpio_named_count to be able to count named gpio Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: devicetree-discuss@lists.ozlabs.org Signed-off-by: Grant Likely --- drivers/of/gpio.c | 9 +++++---- include/linux/of_gpio.h | 27 +++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c index 7e62d15d60f6..e034b38590a8 100644 --- a/drivers/of/gpio.c +++ b/drivers/of/gpio.c @@ -78,8 +78,9 @@ err0: EXPORT_SYMBOL(of_get_named_gpio_flags); /** - * of_gpio_count - Count GPIOs for a device + * of_gpio_named_count - Count GPIOs for a device * @np: device node to count GPIOs for + * @propname: property name containing gpio specifier(s) * * The function returns the count of GPIOs specified for a node. * @@ -93,14 +94,14 @@ EXPORT_SYMBOL(of_get_named_gpio_flags); * defines four GPIOs (so this function will return 4), two of which * are not specified. */ -unsigned int of_gpio_count(struct device_node *np) +unsigned int of_gpio_named_count(struct device_node *np, const char* propname) { unsigned int cnt = 0; do { int ret; - ret = of_parse_phandle_with_args(np, "gpios", "#gpio-cells", + ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", cnt, NULL); /* A hole in the gpios = <> counts anyway. */ if (ret < 0 && ret != -EEXIST) @@ -109,7 +110,7 @@ unsigned int of_gpio_count(struct device_node *np) return cnt; } -EXPORT_SYMBOL(of_gpio_count); +EXPORT_SYMBOL(of_gpio_named_count); /** * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h index b254052a49d7..81733d12cbea 100644 --- a/include/linux/of_gpio.h +++ b/include/linux/of_gpio.h @@ -50,7 +50,8 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc) extern int of_get_named_gpio_flags(struct device_node *np, const char *list_name, int index, enum of_gpio_flags *flags); -extern unsigned int of_gpio_count(struct device_node *np); +extern unsigned int of_gpio_named_count(struct device_node *np, + const char* propname); extern int of_mm_gpiochip_add(struct device_node *np, struct of_mm_gpio_chip *mm_gc); @@ -71,7 +72,8 @@ static inline int of_get_named_gpio_flags(struct device_node *np, return -ENOSYS; } -static inline unsigned int of_gpio_count(struct device_node *np) +static inline unsigned int of_gpio_named_count(struct device_node *np, + const char* propname) { return 0; } @@ -88,6 +90,27 @@ static inline void of_gpiochip_remove(struct gpio_chip *gc) { } #endif /* CONFIG_OF_GPIO */ +/** + * of_gpio_count - Count GPIOs for a device + * @np: device node to count GPIOs for + * + * The function returns the count of GPIOs specified for a node. + * + * Note that the empty GPIO specifiers counts too. For example, + * + * gpios = <0 + * &pio1 1 2 + * 0 + * &pio2 3 4>; + * + * defines four GPIOs (so this function will return 4), two of which + * are not specified. + */ +static inline unsigned int of_gpio_count(struct device_node *np) +{ + return of_gpio_named_count(np, "gpios"); +} + /** * of_get_gpio_flags() - Get a GPIO number and flags to use with GPIO API * @np: device node to get GPIO from -- cgit v1.2.3-55-g7522 From aca5ce14eb773a75e5d935968b2e390dc5bd29c3 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 17 Feb 2012 20:26:21 +0530 Subject: gpio: gpiolib: Support for open drain/collector gpios Adding support for the open drain gpio on which client can specify the open drain property through GPIO flag GPIOF_OPEN_DRAIN at the time of gpio request. The open drain pins are normally pulled high and it cannot be driven to output with value of 1 and so when client request for setting the pin to HIGH, the gpio will be set to input direction to make pin in tristate and hence PULL-UP on pins will make the state to HIGH. The open drain pin can be driven to LOW by setting output with value of 0. Signed-off-by: Laxman Dewangan Reviwed-by: Mark Brown Acked-by: Linus Walleij Signed-off-by: Grant Likely --- drivers/gpio/gpiolib.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- include/linux/gpio.h | 3 +++ 2 files changed, 45 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e633a2afbe90..5d25a33d5359 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -58,6 +58,7 @@ struct gpio_desc { #define FLAG_TRIG_FALL 5 /* trigger on falling edge */ #define FLAG_TRIG_RISE 6 /* trigger on rising edge */ #define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */ +#define FLAG_OPEN_DRAIN 8 /* Gpio is open drain type */ #define ID_SHIFT 16 /* add new flags before this one */ @@ -1264,6 +1265,7 @@ void gpio_free(unsigned gpio) module_put(desc->chip->owner); clear_bit(FLAG_ACTIVE_LOW, &desc->flags); clear_bit(FLAG_REQUESTED, &desc->flags); + clear_bit(FLAG_OPEN_DRAIN, &desc->flags); } else WARN_ON(extra_checks); @@ -1285,6 +1287,9 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) if (err) return err; + if (flags & GPIOF_OPEN_DRAIN) + set_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags); + if (flags & GPIOF_DIR_IN) err = gpio_direction_input(gpio); else @@ -1434,6 +1439,10 @@ int gpio_direction_output(unsigned gpio, int value) struct gpio_desc *desc = &gpio_desc[gpio]; int status = -EINVAL; + /* Open drain pin should not be driven to 1 */ + if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) + return gpio_direction_input(gpio); + spin_lock_irqsave(&gpio_lock, flags); if (!gpio_is_valid(gpio)) @@ -1570,6 +1579,31 @@ int __gpio_get_value(unsigned gpio) } EXPORT_SYMBOL_GPL(__gpio_get_value); +/* + * _gpio_set_open_drain_value() - Set the open drain gpio's value. + * @gpio: Gpio whose state need to be set. + * @chip: Gpio chip. + * @value: Non-zero for setting it HIGH otherise it will set to LOW. + */ +static void _gpio_set_open_drain_value(unsigned gpio, + struct gpio_chip *chip, int value) +{ + int err = 0; + if (value) { + err = chip->direction_input(chip, gpio - chip->base); + if (!err) + clear_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags); + } else { + err = chip->direction_output(chip, gpio - chip->base, 0); + if (!err) + set_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags); + } + trace_gpio_direction(gpio, value, err); + if (err < 0) + pr_err("%s: Error in set_value for open drain gpio%d err %d\n", + __func__, gpio, err); +} + /** * __gpio_set_value() - assign a gpio's value * @gpio: gpio whose value will be assigned @@ -1586,7 +1620,10 @@ void __gpio_set_value(unsigned gpio, int value) chip = gpio_to_chip(gpio); WARN_ON(chip->can_sleep); trace_gpio_value(gpio, 0, value); - chip->set(chip, gpio - chip->base, value); + if (test_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags)) + _gpio_set_open_drain_value(gpio, chip, value); + else + chip->set(chip, gpio - chip->base, value); } EXPORT_SYMBOL_GPL(__gpio_set_value); @@ -1653,7 +1690,10 @@ void gpio_set_value_cansleep(unsigned gpio, int value) might_sleep_if(extra_checks); chip = gpio_to_chip(gpio); trace_gpio_value(gpio, 0, value); - chip->set(chip, gpio - chip->base, value); + if (test_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags)) + _gpio_set_open_drain_value(gpio, chip, value); + else + chip->set(chip, gpio - chip->base, value); } EXPORT_SYMBOL_GPL(gpio_set_value_cansleep); diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 38ac48b7d3a8..66a5b2e9d35a 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -14,6 +14,9 @@ #define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW) #define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH) +/* Gpio pin is open drain */ +#define GPIOF_OPEN_DRAIN (1 << 2) + /** * struct gpio - a structure describing a GPIO with configuration * @gpio: the GPIO number -- cgit v1.2.3-55-g7522 From 25553ff0756c59b617af6bdd280c94e943164184 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 17 Feb 2012 20:26:22 +0530 Subject: gpio: gpiolib: Support for open source/emitter gpios Adding support for the open source gpio on which client can specify the open source property through GPIO flag GPIOF_OPEN_SOURCE at the time of gpio request. The open source pins are normally pulled low and it cannot be driven to output with value of 0 and so when client request for setting the pin to LOW, the gpio will be set to input direction to make pin in tristate and hence PULL-DOWN on pins will make the state to LOW. The open source pin can be driven to HIGH by setting output with value of 1. Signed-off-by: Laxman Dewangan Reviwed-by: Mark Brown Acked-by: Linus Walleij Signed-off-by: Grant Likely --- drivers/gpio/gpiolib.c | 39 +++++++++++++++++++++++++++++++++++++++ include/linux/gpio.h | 3 +++ 2 files changed, 42 insertions(+) (limited to 'include/linux') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5d25a33d5359..58f40dfc5265 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -59,6 +59,7 @@ struct gpio_desc { #define FLAG_TRIG_RISE 6 /* trigger on rising edge */ #define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */ #define FLAG_OPEN_DRAIN 8 /* Gpio is open drain type */ +#define FLAG_OPEN_SOURCE 9 /* Gpio is open source type */ #define ID_SHIFT 16 /* add new flags before this one */ @@ -1266,6 +1267,7 @@ void gpio_free(unsigned gpio) clear_bit(FLAG_ACTIVE_LOW, &desc->flags); clear_bit(FLAG_REQUESTED, &desc->flags); clear_bit(FLAG_OPEN_DRAIN, &desc->flags); + clear_bit(FLAG_OPEN_SOURCE, &desc->flags); } else WARN_ON(extra_checks); @@ -1290,6 +1292,9 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) if (flags & GPIOF_OPEN_DRAIN) set_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags); + if (flags & GPIOF_OPEN_SOURCE) + set_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags); + if (flags & GPIOF_DIR_IN) err = gpio_direction_input(gpio); else @@ -1443,6 +1448,10 @@ int gpio_direction_output(unsigned gpio, int value) if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) return gpio_direction_input(gpio); + /* Open source pin should not be driven to 0 */ + if (!value && test_bit(FLAG_OPEN_SOURCE, &desc->flags)) + return gpio_direction_input(gpio); + spin_lock_irqsave(&gpio_lock, flags); if (!gpio_is_valid(gpio)) @@ -1604,6 +1613,32 @@ static void _gpio_set_open_drain_value(unsigned gpio, __func__, gpio, err); } +/* + * _gpio_set_open_source() - Set the open source gpio's value. + * @gpio: Gpio whose state need to be set. + * @chip: Gpio chip. + * @value: Non-zero for setting it HIGH otherise it will set to LOW. + */ +static void _gpio_set_open_source_value(unsigned gpio, + struct gpio_chip *chip, int value) +{ + int err = 0; + if (value) { + err = chip->direction_output(chip, gpio - chip->base, 1); + if (!err) + set_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags); + } else { + err = chip->direction_input(chip, gpio - chip->base); + if (!err) + clear_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags); + } + trace_gpio_direction(gpio, !value, err); + if (err < 0) + pr_err("%s: Error in set_value for open source gpio%d err %d\n", + __func__, gpio, err); +} + + /** * __gpio_set_value() - assign a gpio's value * @gpio: gpio whose value will be assigned @@ -1622,6 +1657,8 @@ void __gpio_set_value(unsigned gpio, int value) trace_gpio_value(gpio, 0, value); if (test_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags)) _gpio_set_open_drain_value(gpio, chip, value); + else if (test_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags)) + _gpio_set_open_source_value(gpio, chip, value); else chip->set(chip, gpio - chip->base, value); } @@ -1692,6 +1729,8 @@ void gpio_set_value_cansleep(unsigned gpio, int value) trace_gpio_value(gpio, 0, value); if (test_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags)) _gpio_set_open_drain_value(gpio, chip, value); + else if (test_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags)) + _gpio_set_open_source_value(gpio, chip, value); else chip->set(chip, gpio - chip->base, value); } diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 66a5b2e9d35a..67851bbd3a42 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -17,6 +17,9 @@ /* Gpio pin is open drain */ #define GPIOF_OPEN_DRAIN (1 << 2) +/* Gpio pin is open source */ +#define GPIOF_OPEN_SOURCE (1 << 3) + /** * struct gpio - a structure describing a GPIO with configuration * @gpio: the GPIO number -- cgit v1.2.3-55-g7522