[U-Boot] [PATCH v2] mmc: sdhci: Add the programmable clock mode support
Jaehoon Chung
jh80.chung at samsung.com
Fri Sep 30 12:48:28 CEST 2016
Hi Kever,
On 09/30/2016 07:05 PM, Kever Yang wrote:
> Hi Wenyou,
>
> I can not enable my emmc device on my evb-rk3399 with this patch, could you help to fix it?
>
> Here is the debug info may help:
>
> mmc->cfg->f_max is 200000000;
>
> [with this patch]
> I get host->clk_mul 16 ;
> When driver want to set clock to 400000, always get div 1024, and then write 0x21 to SDHCI_CLOCK_CONTROL register,
> mmc controller can not work because of the wrong clock rate;
>
> [without this patch]
> we don't use host->clk_mul;
> When driver want to set clock to 400000, get div 250, and then write 0xfa01 to SDHCI_CLOCK_CONTROL register,
> mmc controller works OK.
If you don't use host->clk_mul, then your host controller is the lower version than V3.0..?
host->clk_mul is assigned to dummy value? Could you check this?
When i have checked Whenyou's patch, there is only difference about "host->clk_mul".
Best Regards,
Jaehoon Chung
>
> Thanks,
> - Kever
> On 09/18/2016 09:01 AM, Wenyou Yang wrote:
>> Add the programmable clock mode for the clock generator.
>>
>> Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
>> ---
>>
>> Changes in v2:
>> - Rebase on the latest u-boot-mmc.
>> - Fix the typo Muliplier->Multiplier.
>>
>> drivers/mmc/sdhci.c | 50 ++++++++++++++++++++++++++++++++++++++++----------
>> include/sdhci.h | 2 ++
>> 2 files changed, 42 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
>> index 504f2d2..b2bf5a0 100644
>> --- a/drivers/mmc/sdhci.c
>> +++ b/drivers/mmc/sdhci.c
>> @@ -294,7 +294,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;
>> @@ -318,14 +318,36 @@ 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. */
>> @@ -333,13 +355,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;
>> @@ -513,7 +535,7 @@ static const struct mmc_ops sdhci_ops = {
>> int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
>> u32 max_clk, u32 min_clk)
>> {
>> - u32 caps;
>> + u32 caps, caps_1;
>> caps = sdhci_readl(host, SDHCI_CAPABILITIES);
>> @@ -577,6 +599,14 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *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;
>> +
>> return 0;
>> }
>> diff --git a/include/sdhci.h b/include/sdhci.h
>> index 6844c73..144570f 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
>> @@ -242,6 +243,7 @@ struct sdhci_host {
>> unsigned int quirks;
>> unsigned int host_caps;
>> unsigned int version;
>> + unsigned int clk_mul; /* Clock Multiplier value */
>> unsigned int clock;
>> struct mmc *mmc;
>> const struct sdhci_ops *ops;
>
>
>
>
>
More information about the U-Boot
mailing list