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