Hi Andreas, On 08/15/2016 01:17 AM, Andreas Bießmann wrote: > 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?
I will be delegated to me. I will check this patch. Thanks. Best Regards, Jaehoon Chung > > 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 > > > _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot