From e3023bf80639afc6603f9633eb301845421b8917 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 13 Dec 2018 15:22:47 +0100 Subject: [PATCH] gpio: of: Handle the Freescale SPI CS The Freescale SPI chipselects are special: while everyone else is using "cs-gpios" the Freescale platforms just use "gpios". Fix this by responding with "gpios" when asking for "cs-gpios" in a freescale device node, so we hide this pecularity from the SPI core. Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index aec7bd86ae7e..00deb885409c 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -254,6 +254,37 @@ static struct gpio_desc *of_find_spi_gpio(struct device *dev, const char *con_id return desc; } +/* + * The old Freescale bindings use simply "gpios" as name for the chip select + * lines rather than "cs-gpios" like all other SPI hardware. Account for this + * with a special quirk. + */ +static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev, + const char *con_id, + unsigned int idx, + unsigned long *flags) +{ + struct device_node *np = dev->of_node; + + if (!IS_ENABLED(CONFIG_SPI_MASTER)) + return ERR_PTR(-ENOENT); + + /* Allow this specifically for Freescale devices */ + if (!of_device_is_compatible(np, "fsl,spi") && + !of_device_is_compatible(np, "aeroflexgaisler,spictrl")) + return ERR_PTR(-ENOENT); + /* Allow only if asking for "cs-gpios" */ + if (!con_id || strcmp(con_id, "cs")) + return ERR_PTR(-ENOENT); + + /* + * While all other SPI controllers use "cs-gpios" the Freescale + * uses just "gpios" so translate to that when "cs-gpios" is + * requested. + */ + return of_find_gpio(dev, NULL, idx, flags); +} + /* * Some regulator bindings happened before we managed to establish that GPIO * properties should be named "foo-gpios" so we have this special kludge for @@ -325,6 +356,12 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, /* Special handling for SPI GPIOs if used */ if (IS_ERR(desc)) desc = of_find_spi_gpio(dev, con_id, &of_flags); + if (IS_ERR(desc)) { + /* This quirk looks up flags and all */ + desc = of_find_spi_cs_gpio(dev, con_id, idx, flags); + if (!IS_ERR(desc)) + return desc; + } /* Special handling for regulator GPIOs if used */ if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER)