Re: [PATCH v2] mmc: pwrseq_simple: add support for one reset control

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 17 Oct 2024 at 15:20, Catalin Popescu
<catalin.popescu@xxxxxxxxxxxxxxxxxxxx> wrote:
>
> Reset controls being refcounted, they allow to share gpios across
> drivers. Right now, reset framework and reset-gpio driver supports only
> one reset gpio, so add support for one single reset control. If more
> than one reset gpio is configured in the device tree, then fallback to
> classic gpio control.
>
> Signed-off-by: Catalin Popescu <catalin.popescu@xxxxxxxxxxxxxxxxxxxx>

Applied for next, thanks!

Kind regards
Uffe


> ---
> v2:
>  - drop DT bindings patch
>  - use reset control with 1 reset gpio and fallback to gpio with
>    multiple reset gpios
> ---
>  drivers/mmc/core/pwrseq_simple.c | 44 +++++++++++++++++++++++++-------
>  1 file changed, 35 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c
> index 9e016b0746f5..24e4e63a5dc8 100644
> --- a/drivers/mmc/core/pwrseq_simple.c
> +++ b/drivers/mmc/core/pwrseq_simple.c
> @@ -17,6 +17,8 @@
>  #include <linux/gpio/consumer.h>
>  #include <linux/delay.h>
>  #include <linux/property.h>
> +#include <linux/of.h>
> +#include <linux/reset.h>
>
>  #include <linux/mmc/host.h>
>
> @@ -29,6 +31,8 @@ struct mmc_pwrseq_simple {
>         u32 power_off_delay_us;
>         struct clk *ext_clk;
>         struct gpio_descs *reset_gpios;
> +       struct reset_control *reset_ctrl;
> +       bool use_reset;
>  };
>
>  #define to_pwrseq_simple(p) container_of(p, struct mmc_pwrseq_simple, pwrseq)
> @@ -67,14 +71,21 @@ static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host)
>                 pwrseq->clk_enabled = true;
>         }
>
> -       mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
> +       if (pwrseq->use_reset) {
> +               reset_control_deassert(pwrseq->reset_ctrl);
> +               reset_control_assert(pwrseq->reset_ctrl);
> +       } else
> +               mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
>  }
>
>  static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host)
>  {
>         struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);
>
> -       mmc_pwrseq_simple_set_gpios_value(pwrseq, 0);
> +       if (pwrseq->use_reset)
> +               reset_control_deassert(pwrseq->reset_ctrl);
> +       else
> +               mmc_pwrseq_simple_set_gpios_value(pwrseq, 0);
>
>         if (pwrseq->post_power_on_delay_ms)
>                 msleep(pwrseq->post_power_on_delay_ms);
> @@ -84,7 +95,10 @@ static void mmc_pwrseq_simple_power_off(struct mmc_host *host)
>  {
>         struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);
>
> -       mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
> +       if (pwrseq->use_reset)
> +               reset_control_assert(pwrseq->reset_ctrl);
> +       else
> +               mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
>
>         if (pwrseq->power_off_delay_us)
>                 usleep_range(pwrseq->power_off_delay_us,
> @@ -112,6 +126,7 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
>  {
>         struct mmc_pwrseq_simple *pwrseq;
>         struct device *dev = &pdev->dev;
> +       int ngpio;
>
>         pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL);
>         if (!pwrseq)
> @@ -121,12 +136,23 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
>         if (IS_ERR(pwrseq->ext_clk) && PTR_ERR(pwrseq->ext_clk) != -ENOENT)
>                 return dev_err_probe(dev, PTR_ERR(pwrseq->ext_clk), "external clock not ready\n");
>
> -       pwrseq->reset_gpios = devm_gpiod_get_array(dev, "reset",
> -                                                       GPIOD_OUT_HIGH);
> -       if (IS_ERR(pwrseq->reset_gpios) &&
> -           PTR_ERR(pwrseq->reset_gpios) != -ENOENT &&
> -           PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) {
> -               return dev_err_probe(dev, PTR_ERR(pwrseq->reset_gpios), "reset GPIOs not ready\n");
> +       ngpio = of_count_phandle_with_args(dev->of_node, "reset-gpios", "#gpio-cells");
> +       if (ngpio == 1)
> +               pwrseq->use_reset = true;
> +
> +       if (pwrseq->use_reset) {
> +               pwrseq->reset_ctrl = devm_reset_control_get_optional_shared(dev, NULL);
> +               if (IS_ERR(pwrseq->reset_ctrl))
> +                       return dev_err_probe(dev, PTR_ERR(pwrseq->reset_ctrl),
> +                                            "reset control not ready\n");
> +       } else {
> +               pwrseq->reset_gpios = devm_gpiod_get_array(dev, "reset", GPIOD_OUT_HIGH);
> +               if (IS_ERR(pwrseq->reset_gpios) &&
> +                   PTR_ERR(pwrseq->reset_gpios) != -ENOENT &&
> +                   PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) {
> +                       return dev_err_probe(dev, PTR_ERR(pwrseq->reset_gpios),
> +                                            "reset GPIOs not ready\n");
> +               }
>         }
>
>         device_property_read_u32(dev, "post-power-on-delay-ms",
>
> base-commit: 58ca61c1a866bfdaa5e19fb19a2416764f847d75
> prerequisite-patch-id: 0000000000000000000000000000000000000000
> --
> 2.34.1
>




[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux