[PATCH v2 06/10] mmc: am654_sdhci: Implement workaround for card detect

Simon Goldschmidt simon.k.r.goldschmidt at gmail.com
Wed Jan 29 15:18:43 CET 2020


On Fri, Jan 24, 2020 at 12:52 PM Faiz Abbas <faiz_abbas at ti.com> wrote:
>
> The 4 bit MMC controllers have an internal debounce for the SDCD line
> with a debounce delay of 1 second. Therefore, after clocks to the IP are
> enabled, software has to wait for this time before it can power on the
> controller.
>
> Add an init() callback which polls on sdcd for a maximum of 2 seconds
> before switching on power to the controller or (in the case of no card)
> returning a ENOMEDIUM. This pushes the 1 second wait time to when the
> card is actually needed rather than at every probe() making sure that
> users who don't insert an SD card in the slot don't have to wait such a
> long time.
>
> Signed-off-by: Faiz Abbas <faiz_abbas at ti.com>
> Signed-off-by: Lokesh Vutla <lokeshvutla at ti.com>
> ---
>  drivers/mmc/am654_sdhci.c | 35 ++++++++++++++++++++++++++++++++---
>  1 file changed, 32 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
> index ff0a81eaab..ccae3fea31 100644
> --- a/drivers/mmc/am654_sdhci.c
> +++ b/drivers/mmc/am654_sdhci.c
> @@ -254,7 +254,7 @@ const struct am654_driver_data j721e_4bit_drv_data = {
>         .flags = IOMUX_PRESENT,
>  };
>
> -int am654_sdhci_init(struct am654_sdhci_plat *plat)
> +int am654_sdhci_init_phy(struct am654_sdhci_plat *plat)
>  {
>         u32 ctl_cfg_2 = 0;
>         u32 mask, val;
> @@ -331,8 +331,37 @@ static int sdhci_am654_get_otap_delay(struct udevice *dev,
>         return 0;
>  }
>
> +#define MAX_SDCD_DEBOUNCE_TIME 2000
> +int am654_sdhci_init(struct udevice *dev)
> +{
> +       struct am654_sdhci_plat *plat = dev_get_platdata(dev);
> +       struct mmc *mmc = mmc_get_mmc_dev(dev);
> +       struct sdhci_host *host = mmc->priv;
> +       unsigned long start;
> +       int val;
> +
> +       /*
> +        * The controller takes about 1 second to debounce the card detect line
> +        * and doesn't let us power on until that time is up. Instead of waiting
> +        * for 1 second at every stage, poll on the CARD_PRESENT bit upto a
> +        * maximum of 2 seconds to be safe..
> +        */
> +       start = get_timer(0);
> +       do {
> +               if (get_timer(start) > MAX_SDCD_DEBOUNCE_TIME)
> +                       return -ENOMEDIUM;
> +
> +               val = mmc_getcd(host->mmc);
> +       } while (!val);
> +
> +       am654_sdhci_init_phy(plat);
> +
> +       return sdhci_init(mmc);
> +}
> +
>  static int am654_sdhci_probe(struct udevice *dev)
>  {
> +       struct dm_mmc_ops *ops = mmc_get_ops(dev);
>         struct am654_driver_data *drv_data =
>                         (struct am654_driver_data *)dev_get_driver_data(dev);
>         struct am654_sdhci_plat *plat = dev_get_platdata(dev);
> @@ -373,9 +402,9 @@ static int am654_sdhci_probe(struct udevice *dev)
>
>         regmap_init_mem_index(dev_ofnode(dev), &plat->base, 1);
>
> -       am654_sdhci_init(plat);
> +       ops->init = am654_sdhci_init;

Is this a valid approach? I mean, many drivers create their 'ops' const like
this:
   static const struct ram_ops altera_gen5_sdram_ops (...)

That would mean you write to a const region. I know the U-Boot sources make
this easy for you by providing the ops non-const via mmc_get_ops, but I still
think this is not good.

Regards,
Simon

>
> -       return sdhci_probe(dev);
> +       return 0;
>  }
>
>  static int am654_sdhci_ofdata_to_platdata(struct udevice *dev)
> --
> 2.19.2
>


More information about the U-Boot mailing list