Skip to content

Commit 6953c57

Browse files
author
Linus Walleij
committed
gpio: of: Handle SPI chipselect legacy bindings
The SPI chipselects are assumed to be active low in the current binding, so when we want to use GPIO descriptors and handle the active low/high semantics in gpiolib, we need a special parsing quirk to deal with this. We check for the property "spi-cs-high" and if that is NOT present we assume the CS line is active low. If the line is tagged as active low in the device tree and has no "spi-cs-high" property all is fine, the device tree and the SPI bindings are in agreement. If the line is tagged as active high in the device tree with the second cell flag and has no "spi-cs-high" property we enforce active low semantics (as this is the exception we can just tag on the flag). If the line is tagged as active low with the second cell flag AND tagged with "spi-cs-high" the SPI active high property takes precedence and we print a warning. Cc: Mark Brown <broonie@kernel.org> Cc: linux-spi@vger.kernel.org Cc: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
1 parent 1c939cb commit 6953c57

File tree

1 file changed

+48
-2
lines changed

1 file changed

+48
-2
lines changed

drivers/gpio/gpiolib-of.c

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip,
5757
}
5858

5959
static void of_gpio_flags_quirks(struct device_node *np,
60-
enum of_gpio_flags *flags)
60+
enum of_gpio_flags *flags,
61+
int index)
6162
{
6263
/*
6364
* Some GPIO fixed regulator quirks.
@@ -91,6 +92,51 @@ static void of_gpio_flags_quirks(struct device_node *np,
9192
pr_info("%s uses legacy open drain flag - update the DTS if you can\n",
9293
of_node_full_name(np));
9394
}
95+
96+
/*
97+
* Legacy handling of SPI active high chip select. If we have a
98+
* property named "cs-gpios" we need to inspect the child node
99+
* to determine if the flags should have inverted semantics.
100+
*/
101+
if (IS_ENABLED(CONFIG_SPI_MASTER) &&
102+
of_property_read_bool(np, "cs-gpios")) {
103+
struct device_node *child;
104+
u32 cs;
105+
int ret;
106+
107+
for_each_child_of_node(np, child) {
108+
ret = of_property_read_u32(child, "reg", &cs);
109+
if (!ret)
110+
continue;
111+
if (cs == index) {
112+
/*
113+
* SPI children have active low chip selects
114+
* by default. This can be specified negatively
115+
* by just omitting "spi-cs-high" in the
116+
* device node, or actively by tagging on
117+
* GPIO_ACTIVE_LOW as flag in the device
118+
* tree. If the line is simultaneously
119+
* tagged as active low in the device tree
120+
* and has the "spi-cs-high" set, we get a
121+
* conflict and the "spi-cs-high" flag will
122+
* take precedence.
123+
*/
124+
if (of_property_read_bool(np, "spi-cs-high")) {
125+
if (*flags & OF_GPIO_ACTIVE_LOW) {
126+
pr_warn("%s GPIO handle specifies active low - ignored\n",
127+
of_node_full_name(np));
128+
*flags &= ~OF_GPIO_ACTIVE_LOW;
129+
}
130+
} else {
131+
if (!(*flags & OF_GPIO_ACTIVE_LOW))
132+
pr_info("%s enforce active low on chipselect handle\n",
133+
of_node_full_name(np));
134+
*flags |= OF_GPIO_ACTIVE_LOW;
135+
}
136+
break;
137+
}
138+
}
139+
}
94140
}
95141

96142
/**
@@ -131,7 +177,7 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
131177
goto out;
132178

133179
if (flags)
134-
of_gpio_flags_quirks(np, flags);
180+
of_gpio_flags_quirks(np, flags, index);
135181

136182
pr_debug("%s: parsed '%s' property of node '%pOF[%d]' - status (%d)\n",
137183
__func__, propname, np, index,

0 commit comments

Comments
 (0)