gpio: nomadik: support mobileye,eyeq5-gpio
authorThéo Lebrun <theo.lebrun@bootlin.com>
Wed, 28 Feb 2024 11:28:22 +0000 (12:28 +0100)
committerLinus Walleij <linus.walleij@linaro.org>
Thu, 29 Feb 2024 09:36:55 +0000 (10:36 +0100)
We create a custom compatible for the STA2X11 IP block as integrated
into the Mobileye EyeQ5 platform. Its wake and alternate functions have
been disabled, we want to avoid touching those registers.

We both do: (1) early return in functions that do not support the
platform, but with warnings, and (2) avoid calling those functions in
the first place.

We ensure that pinctrl-nomadik is not used with this STA2X11 variant.

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
Link: https://lore.kernel.org/r/20240228-mbly-gpio-v2-24-3ba757474006@bootlin.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/gpio/Kconfig
drivers/gpio/gpio-nomadik.c
drivers/pinctrl/nomadik/pinctrl-nomadik.c
include/linux/gpio/gpio-nomadik.h

index ff83371251c1d19b01a5f489b27aa53393728f05..fe6112abb73a3bf63843d0c4a7c8e0c08b72bfa3 100644 (file)
@@ -480,11 +480,12 @@ config GPIO_MXS
 
 config GPIO_NOMADIK
        bool "Nomadik GPIO driver"
-       depends on ARCH_U8500 || ARCH_NOMADIK || COMPILE_TEST
+       depends on ARCH_U8500 || ARCH_NOMADIK || MACH_EYEQ5 || COMPILE_TEST
        select OF_GPIO
        select GPIOLIB_IRQCHIP
        help
-         Say yes here to support the Nomadik SoC GPIO block.
+         Say yes here to support the Nomadik SoC GPIO block. This block is also
+         used by the Mobileye EyeQ5 SoC.
 
          It handles up to 32 GPIOs per bank, that can all be interrupt sources.
          It is deeply interconnected with the associated pinctrl driver as GPIO
index 19394dc7e34a09cea5fc31c8d8bcea9b200ebc75..6adb3c4417d3e3778ae241ee41cb1b15cd85e186 100644 (file)
@@ -7,6 +7,12 @@
  * The GPIO chips are shared with pinctrl-nomadik if used; it needs access for
  * pinmuxing functionality and others.
  *
+ * This driver also handles the mobileye,eyeq5-gpio compatible. It is an STA2X11
+ * but with only data, direction and interrupts register active. We want to
+ * avoid touching SLPM, RWIMSC, FWIMSC, AFSLA and AFSLB registers; that is,
+ * wake and alternate function registers. It is NOT compatible with
+ * pinctrl-nomadik.
+ *
  * Copyright (C) 2008,2009 STMicroelectronics
  * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
  *   Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
@@ -37,6 +43,10 @@ void __nmk_gpio_set_slpm(struct nmk_gpio_chip *nmk_chip, unsigned int offset,
 {
        u32 slpm;
 
+       /* We should NOT have been called. */
+       if (WARN_ON(nmk_chip->is_mobileye_soc))
+               return;
+
        slpm = readl(nmk_chip->addr + NMK_GPIO_SLPC);
        if (mode == NMK_GPIO_SLPM_NOCHANGE)
                slpm |= BIT(offset);
@@ -93,6 +103,9 @@ static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
                rimscval = &nmk_chip->rimsc;
                fimscval = &nmk_chip->fimsc;
        } else  {
+               /* We should NOT have been called. */
+               if (WARN_ON(nmk_chip->is_mobileye_soc))
+                       return;
                rimscreg = NMK_GPIO_RWIMSC;
                fimscreg = NMK_GPIO_FWIMSC;
                rimscval = &nmk_chip->rwimsc;
@@ -119,6 +132,10 @@ static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
 static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
                                int offset, bool on)
 {
+       /* We should NOT have been called. */
+       if (WARN_ON(nmk_chip->is_mobileye_soc))
+               return;
+
        /*
         * Ensure WAKEUP_ENABLE is on.  No need to disable it if wakeup is
         * disabled, since setting SLPM to 1 increases power consumption, and
@@ -143,7 +160,7 @@ static void nmk_gpio_irq_maskunmask(struct nmk_gpio_chip *nmk_chip,
 
        __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, enable);
 
-       if (!(nmk_chip->real_wake & BIT(d->hwirq)))
+       if (!nmk_chip->is_mobileye_soc && !(nmk_chip->real_wake & BIT(d->hwirq)))
                __nmk_gpio_set_wake(nmk_chip, d->hwirq, enable);
 
        spin_unlock(&nmk_chip->lock);
@@ -175,6 +192,10 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
        struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc);
        unsigned long flags;
 
+       /* Handler is registered in all cases. */
+       if (nmk_chip->is_mobileye_soc)
+               return -ENXIO;
+
        clk_enable(nmk_chip->clk);
        spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
        spin_lock(&nmk_chip->lock);
@@ -213,7 +234,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
        if (enabled)
                __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, false);
 
-       if (enabled || wake)
+       if (!nmk_chip->is_mobileye_soc && (enabled || wake))
                __nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, false);
 
        nmk_chip->edge_rising &= ~BIT(d->hwirq);
@@ -227,7 +248,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
        if (enabled)
                __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, true);
 
-       if (enabled || wake)
+       if (!nmk_chip->is_mobileye_soc && (enabled || wake))
                __nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, true);
 
        spin_unlock_irqrestore(&nmk_chip->lock, flags);
@@ -357,6 +378,10 @@ static int nmk_gpio_get_mode(struct nmk_gpio_chip *nmk_chip, int offset)
 {
        u32 afunc, bfunc;
 
+       /* We don't support modes. */
+       if (nmk_chip->is_mobileye_soc)
+               return NMK_GPIO_ALT_GPIO;
+
        clk_enable(nmk_chip->clk);
 
        afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & BIT(offset);
@@ -523,6 +548,8 @@ struct nmk_gpio_chip *nmk_gpio_populate_chip(struct device_node *np,
                dev_dbg(&pdev->dev, "populate: using default ngpio (%d)\n", ngpio);
        }
 
+       nmk_chip->is_mobileye_soc = device_is_compatible(gpio_dev,
+                                                        "mobileye,eyeq5-gpio");
        nmk_chip->bank = id;
        chip = &nmk_chip->chip;
        chip->base = -1;
@@ -636,9 +663,11 @@ static int nmk_gpio_probe(struct platform_device *pdev)
                return ret;
        }
 
-       clk_enable(nmk_chip->clk);
-       nmk_chip->lowemi = readl_relaxed(nmk_chip->addr + NMK_GPIO_LOWEMI);
-       clk_disable(nmk_chip->clk);
+       if (!nmk_chip->is_mobileye_soc) {
+               clk_enable(nmk_chip->clk);
+               nmk_chip->lowemi = readl_relaxed(nmk_chip->addr + NMK_GPIO_LOWEMI);
+               clk_disable(nmk_chip->clk);
+       }
 
        ret = gpiochip_add_data(chip, nmk_chip);
        if (ret)
@@ -653,6 +682,7 @@ static int nmk_gpio_probe(struct platform_device *pdev)
 
 static const struct of_device_id nmk_gpio_match[] = {
        { .compatible = "st,nomadik-gpio", },
+       { .compatible = "mobileye,eyeq5-gpio", },
        {}
 };
 
index 5633f0ec271521c1f21f630e037cc6cc23b16f07..7849144b3b8028246b4838d81da8200794e4af49 100644 (file)
@@ -1230,6 +1230,8 @@ static int nmk_pinctrl_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev,
                                "could not populate nmk chip struct - continue anyway\n");
                of_node_put(gpio_np);
+               /* We are NOT compatible with mobileye,eyeq5-gpio. */
+               BUG_ON(nmk_chip->is_mobileye_soc);
        }
 
        prcm_np = of_parse_phandle(np, "prcm", 0);
index 0166ddb71f4345afbaf7c569b58e8be7c10b8409..9bdb09fda4c909708c910c4c7ca814c107b6decb 100644 (file)
@@ -57,6 +57,7 @@ struct nmk_gpio_chip {
        void (*set_ioforce)(bool enable);
        spinlock_t lock;
        bool sleepmode;
+       bool is_mobileye_soc;
        /* Keep track of configured edges */
        u32 edge_rising;
        u32 edge_falling;