Hi Wenyou, On 08/16/2016 10:02 AM, Jaehoon Chung wrote: > 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. >>>
Sorry for reviewing too late. First, this patch needs to rebase on latest u-boot-mmc. Then I will check this patch on my boards.. >> >> 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 */ s/Muliplier/Multiplier Best Regards, Jaehoon Chung >>> 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 > > > _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot