mmc: pwrseq_simple: Add wilc3000 pwrseq adding chip_en gpio and proper power on and...
authorJosep Orga <jorga@somdevices.com>
Sun, 19 Apr 2020 12:18:43 +0000 (14:18 +0200)
committerJosep Orga <jorga@somdevices.com>
Sun, 19 Apr 2020 12:18:43 +0000 (14:18 +0200)
Signed-off-by: Josep Orga <jorga@somdevices.com>
drivers/mmc/core/pwrseq_simple.c

index a8b9fee..6ce9ce1 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, *values;
@@ -50,7 +52,37 @@ static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq,
                for (i = 0; i < nvalues; i++)
                        values[i] = value;
 
-               gpiod_set_array_value_cansleep(nvalues, reset_gpios->desc, values);
+               if (!IS_ERR(reset_gpios) && !IS_ERR(chip_en_gpios)) {
+                       int *values_chip_en;
+                       int nvalues_chip_en = chip_en_gpios->ndescs;
+                       values_chip_en = kmalloc_array(nvalues_chip_en, sizeof(int), GFP_KERNEL);
+                       if (!values_chip_en) {
+                               kfree(values);
+                               return;
+                       }
+                       for (i = 0; i < nvalues_chip_en; i++)
+                               values_chip_en[i] = value;
+
+                       if (!value) {
+                               //Power on sequence
+                               gpiod_set_array_value_cansleep(
+                                       nvalues_chip_en, chip_en_gpios->desc, values_chip_en);
+                               msleep(5);
+                               gpiod_set_array_value_cansleep(
+                                       nvalues, reset_gpios->desc, values);
+                       } else {
+                               //Power off sequence
+                               gpiod_set_array_value_cansleep(
+                                       nvalues, reset_gpios->desc, values);
+                               msleep(5);
+                               gpiod_set_array_value_cansleep(
+                                       nvalues_chip_en, chip_en_gpios->desc, values_chip_en);
+                       }
+                       kfree(values_chip_en);
+               } else {
+                       gpiod_set_array_value_cansleep(
+                               nvalues, reset_gpios->desc, values);
+               }
                kfree(values);
        }
 }
@@ -126,6 +158,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",