Dear Pantelis,

On 20.06.16 03:58, Wenyou Yang wrote:
> Add the programmable clock mode for the clock generator.
> 

this one is delegated to me, but I think it is out of my scope. Could
you please have a look?

Andreas

> Signed-off-by: Wenyou Yang <wenyou.y...@atmel.com>
> ---
> 
>  drivers/mmc/sdhci.c | 49 +++++++++++++++++++++++++++++++++++++++----------
>  include/sdhci.h     | 15 +++++++++++++++
>  2 files changed, 54 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
> index 5c71ab8..ee6d4a1 100644
> --- a/drivers/mmc/sdhci.c
> +++ b/drivers/mmc/sdhci.c
> @@ -286,7 +286,7 @@ static int sdhci_send_command(struct mmc *mmc, struct 
> mmc_cmd *cmd,
>  static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
>  {
>       struct sdhci_host *host = mmc->priv;
> -     unsigned int div, clk, timeout, reg;
> +     unsigned int div, clk = 0, timeout, reg;
>  
>       /* Wait max 20 ms */
>       timeout = 200;
> @@ -310,14 +310,35 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned 
> int clock)
>               return 0;
>  
>       if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
> -             /* Version 3.00 divisors must be a multiple of 2. */
> -             if (mmc->cfg->f_max <= clock)
> -                     div = 1;
> -             else {
> -                     for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
> -                             if ((mmc->cfg->f_max / div) <= clock)
> +             /*
> +              * Check if the Host Controller supports Programmable Clock
> +              * Mode.
> +              */
> +             if (host->clk_mul) {
> +                     for (div = 1; div <= 1024; div++) {
> +                             if ((mmc->cfg->f_max * host->clk_mul / div)
> +                                     <= clock)
>                                       break;
>                       }
> +
> +                     /*
> +                      * Set Programmable Clock Mode in the Clock
> +                      * Control register.
> +                      */
> +                     clk = SDHCI_PROG_CLOCK_MODE;
> +                     div--;
> +             } else {
> +                     /* Version 3.00 divisors must be a multiple of 2. */
> +                     if (mmc->cfg->f_max <= clock) {
> +                             div = 1;
> +                     } else {
> +                             for (div = 2;
> +                                  div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
> +                                     if ((mmc->cfg->f_max / div) <= clock)
> +                                             break;
> +                             }
> +                     }
> +                     div >>= 1;
>               }
>       } else {
>               /* Version 2.00 divisors must be a power of 2. */
> @@ -325,13 +346,13 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned 
> int clock)
>                       if ((mmc->cfg->f_max / div) <= clock)
>                               break;
>               }
> +             div >>= 1;
>       }
> -     div >>= 1;
>  
>       if (host->set_clock)
>               host->set_clock(host->index, div);
>  
> -     clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
> +     clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
>       clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
>               << SDHCI_DIVIDER_HI_SHIFT;
>       clk |= SDHCI_CLOCK_INT_EN;
> @@ -480,7 +501,7 @@ static const struct mmc_ops sdhci_ops = {
>  
>  int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
>  {
> -     unsigned int caps;
> +     unsigned int caps, caps_1;
>  
>       host->cfg.name = host->name;
>       host->cfg.ops = &sdhci_ops;
> @@ -546,6 +567,14 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 
> min_clk)
>  
>       host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
>  
> +     /*
> +      * In case of Host Controller v3.00, find out whether clock
> +      * multiplier is supported.
> +      */
> +     caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
> +     host->clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >>
> +                     SDHCI_CLOCK_MUL_SHIFT;
> +
>       sdhci_reset(host, SDHCI_RESET_ALL);
>  
>       host->mmc = mmc_create(&host->cfg, host);
> diff --git a/include/sdhci.h b/include/sdhci.h
> index e0f6667..5abe0a2 100644
> --- a/include/sdhci.h
> +++ b/include/sdhci.h
> @@ -97,6 +97,7 @@
>  #define  SDHCI_DIV_MASK      0xFF
>  #define  SDHCI_DIV_MASK_LEN  8
>  #define  SDHCI_DIV_HI_MASK   0x300
> +#define  SDHCI_PROG_CLOCK_MODE  0x0020
>  #define  SDHCI_CLOCK_CARD_EN 0x0004
>  #define  SDHCI_CLOCK_INT_STABLE      0x0002
>  #define  SDHCI_CLOCK_INT_EN  0x0001
> @@ -166,6 +167,19 @@
>  #define  SDHCI_CAN_64BIT     0x10000000
>  
>  #define SDHCI_CAPABILITIES_1 0x44
> +#define  SDHCI_SUPPORT_SDR50 0x00000001
> +#define  SDHCI_SUPPORT_SDR104        0x00000002
> +#define  SDHCI_SUPPORT_DDR50 0x00000004
> +#define  SDHCI_DRIVER_TYPE_A 0x00000010
> +#define  SDHCI_DRIVER_TYPE_C 0x00000020
> +#define  SDHCI_DRIVER_TYPE_D 0x00000040
> +#define  SDHCI_RETUNING_TIMER_COUNT_MASK     0x00000F00
> +#define  SDHCI_RETUNING_TIMER_COUNT_SHIFT    8
> +#define  SDHCI_USE_SDR50_TUNING                      0x00002000
> +#define  SDHCI_RETUNING_MODE_MASK            0x0000C000
> +#define  SDHCI_RETUNING_MODE_SHIFT           14
> +#define  SDHCI_CLOCK_MUL_MASK        0x00FF0000
> +#define  SDHCI_CLOCK_MUL_SHIFT       16
>  
>  #define SDHCI_MAX_CURRENT    0x48
>  
> @@ -240,6 +254,7 @@ struct sdhci_host {
>       unsigned int quirks;
>       unsigned int host_caps;
>       unsigned int version;
> +     unsigned int clk_mul;   /* Clock Muliplier value */
>       unsigned int clock;
>       struct mmc *mmc;
>       const struct sdhci_ops *ops;
> 
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to