From: Andrew Jeffery <andrew@aj.id.au>
To: linux-gpio@vger.kernel.org
Cc: Andrew Jeffery <andrew@aj.id.au>,
linus.walleij@linaro.org, corbet@lwn.net, joel@jms.id.au,
ryan_chen@aspeedtech.com, robh+dt@kernel.org,
frowand.list@gmail.com, ckeepax@opensource.wolfsonmicro.com,
ldewangan@nvidia.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, patches@opensource.cirrus.com,
devicetree@vger.kernel.org, openbmc@lists.ozlabs.org,
linux-aspeed@lists.ozlabs.org
Subject: [RFC PATCH 1/5] gpio: gpiolib: Add core support for maintaining GPIO values on reset
Date: Fri, 20 Oct 2017 14:07:23 +1030 [thread overview]
Message-ID: <20171020033727.21557-2-andrew@aj.id.au> (raw)
In-Reply-To: <20171020033727.21557-1-andrew@aj.id.au>
GPIO state reset tolerance is implemented in gpiolib through the
addition of a new pinconf parameter. With that, some renaming of helpers
is done to clarify the scope of the already existing
gpiochip_line_is_persistent(), as it's now ambiguous as to whether that
means on suspend, reset or both. This in-turn impacts gpio-arizona, but
not in any complicated way.
This change lays the groundwork for implementing reset tolerance support
in all of the external interfaces that can influence GPIOs.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
---
drivers/gpio/gpio-arizona.c | 4 +--
drivers/gpio/gpiolib.c | 55 +++++++++++++++++++++++++++++++--
drivers/gpio/gpiolib.h | 1 +
include/linux/gpio/consumer.h | 9 ++++++
include/linux/gpio/driver.h | 5 ++-
include/linux/gpio/machine.h | 2 ++
include/linux/pinctrl/pinconf-generic.h | 2 ++
7 files changed, 73 insertions(+), 5 deletions(-)
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index d4e6ba0301bc..d3fe23569811 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -33,7 +33,7 @@ static int arizona_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
{
struct arizona_gpio *arizona_gpio = gpiochip_get_data(chip);
struct arizona *arizona = arizona_gpio->arizona;
- bool persistent = gpiochip_line_is_persistent(chip, offset);
+ bool persistent = gpiochip_line_is_persistent_suspend(chip, offset);
bool change;
int ret;
@@ -99,7 +99,7 @@ static int arizona_gpio_direction_out(struct gpio_chip *chip,
{
struct arizona_gpio *arizona_gpio = gpiochip_get_data(chip);
struct arizona *arizona = arizona_gpio->arizona;
- bool persistent = gpiochip_line_is_persistent(chip, offset);
+ bool persistent = gpiochip_line_is_persistent_suspend(chip, offset);
unsigned int val;
int ret;
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index a56b29fd8bb1..d9dc7e588699 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -2414,6 +2414,40 @@ int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
EXPORT_SYMBOL_GPL(gpiod_set_debounce);
/**
+ * gpiod_set_reset_tolerant - Hold state across controller reset
+ * @desc: descriptor of the GPIO for which to set debounce time
+ * @tolerant: True to hold state across a controller reset, false otherwise
+ *
+ * Returns:
+ * 0 on success, %-ENOTSUPP if the controller doesn't support setting the
+ * reset tolerance or less than zero on other failures.
+ */
+int gpiod_set_reset_tolerant(struct gpio_desc *desc, bool tolerant)
+{
+ struct gpio_chip *chip;
+ unsigned long packed;
+ int rc;
+
+ chip = desc->gdev->chip;
+ if (!chip->set_config)
+ return -ENOTSUPP;
+
+ packed = pinconf_to_config_packed(PIN_CONFIG_RESET_TOLERANT, tolerant);
+
+ rc = chip->set_config(chip, gpio_chip_hwgpio(desc), packed);
+ if (rc < 0)
+ return rc;
+
+ if (tolerant)
+ set_bit(FLAG_RESET_TOLERANT, &desc->flags);
+ else
+ clear_bit(FLAG_RESET_TOLERANT, &desc->flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(gpiod_set_reset_tolerant);
+
+/**
* gpiod_is_active_low - test whether a GPIO is active-low or not
* @desc: the gpio descriptor to test
*
@@ -2885,7 +2919,8 @@ bool gpiochip_line_is_open_source(struct gpio_chip *chip, unsigned int offset)
}
EXPORT_SYMBOL_GPL(gpiochip_line_is_open_source);
-bool gpiochip_line_is_persistent(struct gpio_chip *chip, unsigned int offset)
+bool gpiochip_line_is_persistent_suspend(struct gpio_chip *chip,
+ unsigned int offset)
{
if (offset >= chip->ngpio)
return false;
@@ -2893,7 +2928,18 @@ bool gpiochip_line_is_persistent(struct gpio_chip *chip, unsigned int offset)
return !test_bit(FLAG_SLEEP_MAY_LOSE_VALUE,
&chip->gpiodev->descs[offset].flags);
}
-EXPORT_SYMBOL_GPL(gpiochip_line_is_persistent);
+EXPORT_SYMBOL_GPL(gpiochip_line_is_persistent_suspend);
+
+bool gpiochip_line_is_persistent_reset(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ if (offset >= chip->ngpio)
+ return false;
+
+ return test_bit(FLAG_RESET_TOLERANT,
+ &chip->gpiodev->descs[offset].flags);
+}
+EXPORT_SYMBOL_GPL(gpiochip_line_is_persistent_reset);
/**
* gpiod_get_raw_value_cansleep() - return a gpio's raw value
@@ -3271,6 +3317,11 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
if (lflags & GPIO_SLEEP_MAY_LOSE_VALUE)
set_bit(FLAG_SLEEP_MAY_LOSE_VALUE, &desc->flags);
+ status = gpiod_set_reset_tolerant(desc,
+ !!(lflags & GPIO_RESET_TOLERANT));
+ if (status < 0)
+ return status;
+
/* No particular flag request, return here... */
if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) {
pr_debug("no flags found for %s\n", con_id);
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 799208fc189a..4ce36f14c1ad 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -202,6 +202,7 @@ struct gpio_desc {
#define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */
#define FLAG_IS_HOGGED 11 /* GPIO is hogged */
#define FLAG_SLEEP_MAY_LOSE_VALUE 12 /* GPIO may lose value in sleep */
+#define FLAG_RESET_TOLERANT 13 /* GPIO to maintain state at shutdown */
/* Connection label */
const char *label;
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 8f702fcbe485..ee5e125c8fec 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -121,6 +121,7 @@ void gpiod_set_raw_array_value_cansleep(unsigned int array_size,
int *value_array);
int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
+int gpiod_set_reset_tolerant(struct gpio_desc *desc, bool tolerant);
int gpiod_is_active_low(const struct gpio_desc *desc);
int gpiod_cansleep(const struct gpio_desc *desc);
@@ -381,6 +382,14 @@ static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
return -ENOSYS;
}
+static inline int gpiod_set_reset_tolerant(struct gpio_desc *desc,
+ bool tolerant)
+{
+ /* GPIO can never have been requested */
+ WARN_ON(1);
+ return -ENOSYS;
+}
+
static inline int gpiod_is_active_low(const struct gpio_desc *desc)
{
/* GPIO can never have been requested */
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index c97f8325e8bf..6e9d32bdab55 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -233,7 +233,10 @@ bool gpiochip_line_is_open_drain(struct gpio_chip *chip, unsigned int offset);
bool gpiochip_line_is_open_source(struct gpio_chip *chip, unsigned int offset);
/* Sleep persistence inquiry for drivers */
-bool gpiochip_line_is_persistent(struct gpio_chip *chip, unsigned int offset);
+bool gpiochip_line_is_persistent_suspend(struct gpio_chip *chip,
+ unsigned int offset);
+bool gpiochip_line_is_persistent_reset(struct gpio_chip *chip,
+ unsigned int offset);
/* get driver data */
void *gpiochip_get_data(struct gpio_chip *chip);
diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h
index 5e9f294c29eb..11b7209c7ab9 100644
--- a/include/linux/gpio/machine.h
+++ b/include/linux/gpio/machine.h
@@ -11,6 +11,8 @@ enum gpio_lookup_flags {
GPIO_OPEN_SOURCE = (1 << 2),
GPIO_SLEEP_MAINTAIN_VALUE = (0 << 3),
GPIO_SLEEP_MAY_LOSE_VALUE = (1 << 3),
+ GPIO_RESET_INTOLERANT = (0 << 4),
+ GPIO_RESET_TOLERANT = (1 << 4),
};
/**
diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h
index 5d8bc7f21c2a..487cc863cb36 100644
--- a/include/linux/pinctrl/pinconf-generic.h
+++ b/include/linux/pinctrl/pinconf-generic.h
@@ -90,6 +90,7 @@
* @PIN_CONFIG_SLEW_RATE: if the pin can select slew rate, the argument to
* this parameter (on a custom format) tells the driver which alternative
* slew rate to use.
+ * @PIN_CONFIG_RESET_TOLERANT: retains the pin state across a system reset
* @PIN_CONFIG_END: this is the last enumerator for pin configurations, if
* you need to pass in custom configurations to the pin controller, use
* PIN_CONFIG_END+1 as the base offset.
@@ -117,6 +118,7 @@ enum pin_config_param {
PIN_CONFIG_POWER_SOURCE,
PIN_CONFIG_SLEEP_HARDWARE_STATE,
PIN_CONFIG_SLEW_RATE,
+ PIN_CONFIG_RESET_TOLERANT,
PIN_CONFIG_END = 0x7F,
PIN_CONFIG_MAX = 0xFF,
};
--
2.11.0
next prev parent reply other threads:[~2017-10-20 3:37 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-20 3:37 [RFC PATCH 0/5] gpio: Expose reset tolerance capability Andrew Jeffery
2017-10-20 3:37 ` Andrew Jeffery [this message]
2017-10-20 7:17 ` [RFC PATCH 1/5] gpio: gpiolib: Add core support for maintaining GPIO values on reset Linus Walleij
2017-10-20 7:43 ` Linus Walleij
2017-10-20 8:32 ` Andrew Jeffery
2017-10-25 8:11 ` Charles Keepax
2017-10-26 0:00 ` Andrew Jeffery
2017-10-20 8:24 ` Andrew Jeffery
2017-10-20 3:37 ` [RFC PATCH 2/5] gpio: gpiolib: Add OF " Andrew Jeffery
[not found] ` <20171020033727.21557-3-andrew-zrmu5oMJ5Fs@public.gmane.org>
2017-10-20 7:18 ` Linus Walleij
2017-10-20 7:29 ` Andrew Jeffery
2017-10-20 3:37 ` [RFC PATCH 3/5] gpio: gpiolib: Add chardev " Andrew Jeffery
2017-10-20 7:27 ` Linus Walleij
2017-10-20 9:02 ` Andrew Jeffery
2017-10-25 8:14 ` Charles Keepax
2017-10-26 0:05 ` Andrew Jeffery
[not found] ` <1508976339.13477.5.camel-zrmu5oMJ5Fs@public.gmane.org>
2017-10-26 9:10 ` Charles Keepax
2017-10-31 9:59 ` Linus Walleij
2017-10-20 3:37 ` [RFC PATCH 4/5] gpio: gpiolib: Add sysfs " Andrew Jeffery
[not found] ` <20171020033727.21557-5-andrew-zrmu5oMJ5Fs@public.gmane.org>
2017-10-20 7:29 ` Linus Walleij
2017-10-20 7:40 ` Andrew Jeffery
2017-10-20 3:37 ` [RFC PATCH 5/5] gpio: aspeed: Add support for reset tolerance Andrew Jeffery
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20171020033727.21557-2-andrew@aj.id.au \
--to=andrew@aj.id.au \
--cc=ckeepax@opensource.wolfsonmicro.com \
--cc=corbet@lwn.net \
--cc=devicetree@vger.kernel.org \
--cc=frowand.list@gmail.com \
--cc=joel@jms.id.au \
--cc=ldewangan@nvidia.com \
--cc=linus.walleij@linaro.org \
--cc=linux-aspeed@lists.ozlabs.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=openbmc@lists.ozlabs.org \
--cc=patches@opensource.cirrus.com \
--cc=robh+dt@kernel.org \
--cc=ryan_chen@aspeedtech.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).