summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpiolib-of.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-01-31 12:25:27 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2018-01-31 12:25:27 -0800
commit9798f5178f5791f964562eccedcf4dabe02fd825 (patch)
treed0d76b4202eaa3d3be3aaa05206e57e02e16ac5b /drivers/gpio/gpiolib-of.c
parent50081e437872e68300750068754f21d0faac5d86 (diff)
parentd58f2bf261fdf3a3fc916c9999a686f959dcf6b6 (diff)
Merge tag 'gpio-v4.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij: "The is the bulk of GPIO changes for the v4.16 kernel cycle. It is pretty calm this time around I think. I even got time to get to things like starting to clean up header includes. Core changes: - Disallow open drain and open source flags to be set simultaneously. This doesn't make electrical sense, and would the hardware actually respond to this setting, the result would be short circuit. - ACPI GPIO has a new core infrastructure for handling quirks. The quirks are there to deal with broken ACPI tables centrally instead of pushing the work to individual drivers. In the world of BIOS writers, the ACPI tables are perfect. Until they find a mistake in it. When such a mistake is found, we can patch it with a quirk. It should never happen, the problem is that it happens. So we accomodate for it. - Several documentation updates. - Revert the patch setting up initial direction state from reading the device. This was causing bad things for drivers that can't read status on all its pins. It is only affecting debugfs information quality. - Label descriptors with the device name if no explicit label is passed in. - Pave the ground for transitioning SPI and regulators to use GPIO descriptors by implementing some quirks in the device tree GPIO parsing code. New drivers: - New driver for the Access PCIe IDIO 24 family. Other: - Major refactorings and improvements to the GPIO mockup driver used for test and verification. - Moved the AXP209 driver over to pin control since it gained a pin control back-end. These patches will appear (with the same hashes) in the pin control pull request as well. - Convert the onewire GPIO driver w1-gpio to use descriptors. This is merged here since the W1 maintainers send very few pull requests and he ACKed it. - Start to clean up driver headers using <linux/gpio.h> to just use <linux/gpio/driver.h> as appropriate" * tag 'gpio-v4.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (103 commits) gpio: Timestamp events in hardirq handler gpio: Fix kernel stack leak to userspace gpio: Fix a documentation spelling mistake gpio: Documentation update gpiolib: remove redundant initialization of pointer desc gpio: of: Fix NPE from OF flags gpio: stmpe: Delete an unnecessary variable initialisation in stmpe_gpio_probe() gpio: stmpe: Move an assignment in stmpe_gpio_probe() gpio: stmpe: Improve a size determination in stmpe_gpio_probe() gpio: stmpe: Use seq_putc() in stmpe_dbg_show() gpio: No NULL owner gpio: stmpe: i2c transfer are forbiden in atomic context gpio: davinci: Include proper header gpio: da905x: Include proper header gpio: cs5535: Include proper header gpio: crystalcove: Include proper header gpio: bt8xx: Include proper header gpio: bcm-kona: Include proper header gpio: arizona: Include proper header gpio: amd8111: Include proper header ...
Diffstat (limited to 'drivers/gpio/gpiolib-of.c')
-rw-r--r--drivers/gpio/gpiolib-of.c119
1 files changed, 117 insertions, 2 deletions
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index 72a0695d2ac3..564bb7a31da4 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -56,6 +56,42 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip,
return gpiochip_get_desc(chip, ret);
}
+static void of_gpio_flags_quirks(struct device_node *np,
+ enum of_gpio_flags *flags)
+{
+ /*
+ * Some GPIO fixed regulator quirks.
+ * Note that active low is the default.
+ */
+ if (IS_ENABLED(CONFIG_REGULATOR) &&
+ (of_device_is_compatible(np, "reg-fixed-voltage") ||
+ of_device_is_compatible(np, "regulator-gpio"))) {
+ /*
+ * The regulator GPIO handles are specified such that the
+ * presence or absence of "enable-active-high" solely controls
+ * the polarity of the GPIO line. Any phandle flags must
+ * be actively ignored.
+ */
+ if (*flags & OF_GPIO_ACTIVE_LOW) {
+ pr_warn("%s GPIO handle specifies active low - ignored\n",
+ of_node_full_name(np));
+ *flags &= ~OF_GPIO_ACTIVE_LOW;
+ }
+ if (!of_property_read_bool(np, "enable-active-high"))
+ *flags |= OF_GPIO_ACTIVE_LOW;
+ }
+ /*
+ * Legacy open drain handling for fixed voltage regulators.
+ */
+ if (IS_ENABLED(CONFIG_REGULATOR) &&
+ of_device_is_compatible(np, "reg-fixed-voltage") &&
+ of_property_read_bool(np, "gpio-open-drain")) {
+ *flags |= (OF_GPIO_SINGLE_ENDED | OF_GPIO_OPEN_DRAIN);
+ pr_info("%s uses legacy open drain flag - update the DTS if you can\n",
+ of_node_full_name(np));
+ }
+}
+
/**
* of_get_named_gpiod_flags() - Get a GPIO descriptor and flags for GPIO API
* @np: device node to get GPIO from
@@ -93,6 +129,9 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
if (IS_ERR(desc))
goto out;
+ if (flags)
+ of_gpio_flags_quirks(np, flags);
+
pr_debug("%s: parsed '%s' property of node '%pOF[%d]' - status (%d)\n",
__func__, propname, np, index,
PTR_ERR_OR_ZERO(desc));
@@ -117,6 +156,71 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
}
EXPORT_SYMBOL(of_get_named_gpio_flags);
+/*
+ * The SPI GPIO bindings happened before we managed to establish that GPIO
+ * properties should be named "foo-gpios" so we have this special kludge for
+ * them.
+ */
+static struct gpio_desc *of_find_spi_gpio(struct device *dev, const char *con_id,
+ enum of_gpio_flags *of_flags)
+{
+ char prop_name[32]; /* 32 is max size of property name */
+ struct device_node *np = dev->of_node;
+ struct gpio_desc *desc;
+
+ /*
+ * Hopefully the compiler stubs the rest of the function if this
+ * is false.
+ */
+ if (!IS_ENABLED(CONFIG_SPI_MASTER))
+ return ERR_PTR(-ENOENT);
+
+ /* Allow this specifically for "spi-gpio" devices */
+ if (!of_device_is_compatible(np, "spi-gpio") || !con_id)
+ return ERR_PTR(-ENOENT);
+
+ /* Will be "gpio-sck", "gpio-mosi" or "gpio-miso" */
+ snprintf(prop_name, sizeof(prop_name), "%s-%s", "gpio", con_id);
+
+ desc = of_get_named_gpiod_flags(np, prop_name, 0, of_flags);
+ return desc;
+}
+
+/*
+ * Some regulator bindings happened before we managed to establish that GPIO
+ * properties should be named "foo-gpios" so we have this special kludge for
+ * them.
+ */
+static struct gpio_desc *of_find_regulator_gpio(struct device *dev, const char *con_id,
+ enum of_gpio_flags *of_flags)
+{
+ /* These are the connection IDs we accept as legacy GPIO phandles */
+ const char *whitelist[] = {
+ "wlf,ldoena", /* Arizona */
+ "wlf,ldo1ena", /* WM8994 */
+ "wlf,ldo2ena", /* WM8994 */
+ };
+ struct device_node *np = dev->of_node;
+ struct gpio_desc *desc;
+ int i;
+
+ if (!IS_ENABLED(CONFIG_REGULATOR))
+ return ERR_PTR(-ENOENT);
+
+ if (!con_id)
+ return ERR_PTR(-ENOENT);
+
+ for (i = 0; i < ARRAY_SIZE(whitelist); i++)
+ if (!strcmp(con_id, whitelist[i]))
+ break;
+
+ if (i == ARRAY_SIZE(whitelist))
+ return ERR_PTR(-ENOENT);
+
+ desc = of_get_named_gpiod_flags(np, con_id, 0, of_flags);
+ return desc;
+}
+
struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
unsigned int idx,
enum gpio_lookup_flags *flags)
@@ -126,6 +230,7 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
struct gpio_desc *desc;
unsigned int i;
+ /* Try GPIO property "foo-gpios" and "foo-gpio" */
for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
if (con_id)
snprintf(prop_name, sizeof(prop_name), "%s-%s", con_id,
@@ -140,6 +245,14 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
break;
}
+ /* Special handling for SPI GPIOs if used */
+ if (IS_ERR(desc))
+ desc = of_find_spi_gpio(dev, con_id, &of_flags);
+
+ /* Special handling for regulator GPIOs if used */
+ if (IS_ERR(desc))
+ desc = of_find_regulator_gpio(dev, con_id, &of_flags);
+
if (IS_ERR(desc))
return desc;
@@ -153,8 +266,8 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
*flags |= GPIO_OPEN_SOURCE;
}
- if (of_flags & OF_GPIO_SLEEP_MAY_LOSE_VALUE)
- *flags |= GPIO_SLEEP_MAY_LOSE_VALUE;
+ if (of_flags & OF_GPIO_TRANSITORY)
+ *flags |= GPIO_TRANSITORY;
return desc;
}
@@ -214,6 +327,8 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np,
if (xlate_flags & OF_GPIO_ACTIVE_LOW)
*lflags |= GPIO_ACTIVE_LOW;
+ if (xlate_flags & OF_GPIO_TRANSITORY)
+ *lflags |= GPIO_TRANSITORY;
if (of_property_read_bool(np, "input"))
*dflags |= GPIOD_IN;