ARM: Add WILC3000 pwrseq adding chip_en gpio and proper power on and off sequences.
authorJosep Orga <jorga@somdevices.com>
Tue, 14 Apr 2020 17:51:59 +0000 (19:51 +0200)
committerJosep Orga <jorga@somdevices.com>
Tue, 14 Apr 2020 17:51:59 +0000 (19:51 +0200)
Signed-off-by: Josep Orga <jorga@somdevices.com>
arch/arm/boot/dts/imx6ull-somdevices.dtsi
drivers/mmc/core/pwrseq_simple.c

index 5cdb844..4924f84 100644 (file)
@@ -82,8 +82,8 @@
 
        wifi_pwrseq: wifi_pwrseq {
                compatible = "mmc-pwrseq-simple";
-               reset-gpios =   <&gpio5 7 GPIO_ACTIVE_LOW>, //RESET
-                                               <&gpio5 6 GPIO_ACTIVE_LOW>; //CHIP_EN
+               reset-gpios =   <&gpio5 7 GPIO_ACTIVE_LOW>; //RESET
+               chip_en-gpios = <&gpio5 6 GPIO_ACTIVE_LOW>; //CHIP_EN
                post-power-on-delay-ms = <10>;
        };
 };
index 13ef162..4e537e8 100644 (file)
@@ -30,6 +30,7 @@ struct mmc_pwrseq_simple {
        u32 power_off_delay_us;
        struct clk *ext_clk;
        struct gpio_descs *reset_gpios;
+       struct gpio_descs *chip_en_gpios;
 };
 
 #define to_pwrseq_simple(p) container_of(p, struct mmc_pwrseq_simple, pwrseq)
@@ -38,6 +39,7 @@ static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq,
                                              int value)
 {
        struct gpio_descs *reset_gpios = pwrseq->reset_gpios;
+       struct gpio_descs *chip_en_gpios = pwrseq->chip_en_gpios;
 
        if (!IS_ERR(reset_gpios)) {
                int i;
@@ -46,8 +48,30 @@ static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq,
                for (i = 0; i < reset_gpios->ndescs; i++)
                        values[i] = value;
 
-               gpiod_set_array_value_cansleep(
-                       reset_gpios->ndescs, reset_gpios->desc, values);
+               if (!IS_ERR(reset_gpios) && !IS_ERR(chip_en_gpios)) {
+                       int values_chip_en[chip_en_gpios->ndescs];
+                       for (i = 0; i < chip_en_gpios->ndescs; i++)
+                               values_chip_en[i] = value;
+
+                       if (!value) {
+                               //Power on sequence
+                               gpiod_set_array_value_cansleep(
+                                       chip_en_gpios->ndescs, chip_en_gpios->desc, values);
+                               msleep(5);
+                               gpiod_set_array_value_cansleep(
+                                       reset_gpios->ndescs, reset_gpios->desc, values);
+                       } else {
+                               //Power off sequence
+                               gpiod_set_array_value_cansleep(
+                                       reset_gpios->ndescs, reset_gpios->desc, values);
+                               msleep(5);
+                               gpiod_set_array_value_cansleep(
+                                       chip_en_gpios->ndescs, chip_en_gpios->desc, values);
+                       }
+               } else {
+                       gpiod_set_array_value_cansleep(
+                               reset_gpios->ndescs, reset_gpios->desc, values);
+               }
        }
 }
 
@@ -122,6 +146,14 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
                return PTR_ERR(pwrseq->reset_gpios);
        }
 
+       pwrseq->chip_en_gpios = devm_gpiod_get_array(dev, "chip_en",
+                                                       GPIOD_OUT_HIGH);
+       if (IS_ERR(pwrseq->chip_en_gpios) &&
+           PTR_ERR(pwrseq->chip_en_gpios) != -ENOENT &&
+           PTR_ERR(pwrseq->chip_en_gpios) != -ENOSYS) {
+               return PTR_ERR(pwrseq->chip_en_gpios);
+       }
+
        device_property_read_u32(dev, "post-power-on-delay-ms",
                                 &pwrseq->post_power_on_delay_ms);
        device_property_read_u32(dev, "power-off-delay-us",