[U-Boot] [PATCH v3 0/4] mmc: sdhci: Add support for frequency constrained peripheral interfaces

From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The sdhci controller assumes that the base clock frequency is fully supported by the peripheral and doesn't support hardware limitations. Distinguish between base clock of the host controller and maximal supported peripheral clock frequency of the peripheral interface. This is needed for the zynq platform to support two sdhci ports with different IO routings.
Changes in v3: - Rename arguments of sdhci_setup_cfg function from max_clk/min_clk to f_max/f_min
Changes in v2: - Remove unused index from get uart clock function - Remove unused index from get sdio clock function - Introduce common get clock function
Stefan Herbrechtsmeier (4): mmc: sdhci: Distinguish between base clock and maximum peripheral frequency serial: zynq: Remove unused index from get uart clock function mmc: zynq: Determine base clock frequency via clock framework mmc: zynq: Add fdt max-frequency support
arch/arm/mach-zynq/clk.c | 51 +++++++++++++++++++++++++++-------- arch/arm/mach-zynq/include/mach/clk.h | 3 ++- drivers/mmc/atmel_sdhci.c | 7 +++-- drivers/mmc/bcm2835_sdhci.c | 3 ++- drivers/mmc/ftsdc021_sdhci.c | 3 ++- drivers/mmc/kona_sdhci.c | 3 ++- drivers/mmc/msm_sdhci.c | 2 ++ drivers/mmc/mv_sdhci.c | 3 ++- drivers/mmc/pci_mmc.c | 1 + drivers/mmc/pic32_sdhci.c | 4 ++- drivers/mmc/rockchip_sdhci.c | 4 +-- drivers/mmc/s5p_sdhci.c | 5 ++-- drivers/mmc/sdhci.c | 34 ++++++++++++----------- drivers/mmc/spear_sdhci.c | 3 ++- drivers/mmc/zynq_sdhci.c | 40 ++++++++++++++++++++++++++- drivers/serial/serial_zynq.c | 2 +- include/sdhci.h | 13 ++++----- 17 files changed, 133 insertions(+), 48 deletions(-)

From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The sdhci controller assumes that the base clock frequency is fully supported by the peripheral and doesn't support hardware limitations. The Linux kernel distinguishes between base clock (max_clk) of the host controller and maximum frequency (f_max) of the card interface. Use the same differentiation and allow the platform to constrain the peripheral interface.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
---
Changes in v3: - Rename arguments of sdhci_setup_cfg function from max_clk/min_clk to f_max/f_min
Changes in v2: None
drivers/mmc/atmel_sdhci.c | 7 +++++-- drivers/mmc/bcm2835_sdhci.c | 3 ++- drivers/mmc/ftsdc021_sdhci.c | 3 ++- drivers/mmc/kona_sdhci.c | 3 ++- drivers/mmc/msm_sdhci.c | 2 ++ drivers/mmc/mv_sdhci.c | 3 ++- drivers/mmc/pci_mmc.c | 1 + drivers/mmc/pic32_sdhci.c | 4 +++- drivers/mmc/rockchip_sdhci.c | 4 ++-- drivers/mmc/s5p_sdhci.c | 5 +++-- drivers/mmc/sdhci.c | 34 ++++++++++++++++++---------------- drivers/mmc/spear_sdhci.c | 3 ++- drivers/mmc/zynq_sdhci.c | 4 +++- include/sdhci.h | 13 +++++++------ 14 files changed, 54 insertions(+), 35 deletions(-)
diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c index 6654b54..62cb242 100644 --- a/drivers/mmc/atmel_sdhci.c +++ b/drivers/mmc/atmel_sdhci.c @@ -35,8 +35,9 @@ int atmel_sdhci_init(void *regbase, u32 id) free(host); return -ENODEV; } + host->max_clk = max_clk;
- add_sdhci(host, max_clk, min_clk); + add_sdhci(host, 0, min_clk);
return 0; } @@ -95,7 +96,9 @@ static int atmel_sdhci_probe(struct udevice *dev) if (!max_clk) return -EINVAL;
- ret = sdhci_setup_cfg(&plat->cfg, host, max_clk, ATMEL_SDHC_MIN_FREQ); + host->max_clk = max_clk; + + ret = sdhci_setup_cfg(&plat->cfg, host, 0, ATMEL_SDHC_MIN_FREQ); if (ret) return ret;
diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index cb2bd40..29c2a85 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -181,10 +181,11 @@ int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq) host->ioaddr = (void *)(unsigned long)regbase; host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_NO_HISPD_BIT; + host->max_clk = emmc_freq; host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; host->ops = &bcm2835_ops;
- add_sdhci(host, emmc_freq, MIN_FREQ); + add_sdhci(host, 0, MIN_FREQ);
return 0; } diff --git a/drivers/mmc/ftsdc021_sdhci.c b/drivers/mmc/ftsdc021_sdhci.c index 6e9fefa..4940ccb 100644 --- a/drivers/mmc/ftsdc021_sdhci.c +++ b/drivers/mmc/ftsdc021_sdhci.c @@ -27,7 +27,8 @@ int ftsdc021_sdhci_init(u32 regbase) host->name = "FTSDC021"; host->ioaddr = (void __iomem *)regbase; host->quirks = 0; - add_sdhci(host, freq, 0); + host->max_clk = freq; + add_sdhci(host, 0, 0);
return 0; } diff --git a/drivers/mmc/kona_sdhci.c b/drivers/mmc/kona_sdhci.c index 549f6bc..ddd821b 100644 --- a/drivers/mmc/kona_sdhci.c +++ b/drivers/mmc/kona_sdhci.c @@ -121,12 +121,13 @@ int kona_sdhci_init(int dev_index, u32 min_clk, u32 quirks) host->name = "kona-sdhci"; host->ioaddr = reg_base; host->quirks = quirks; + host->max_clk = max_clk;
if (init_kona_mmc_core(host)) { free(host); return -EINVAL; }
- add_sdhci(host, max_clk, min_clk); + add_sdhci(host, 0, min_clk); return ret; } diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c index f33714b..1db683d 100644 --- a/drivers/mmc/msm_sdhci.c +++ b/drivers/mmc/msm_sdhci.c @@ -96,6 +96,8 @@ static int msm_sdc_probe(struct udevice *dev)
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
+ host->max_clk = 0; + /* Init clocks */ ret = msm_sdc_clk_init(dev); if (ret) diff --git a/drivers/mmc/mv_sdhci.c b/drivers/mmc/mv_sdhci.c index e388ad1..69aa87b 100644 --- a/drivers/mmc/mv_sdhci.c +++ b/drivers/mmc/mv_sdhci.c @@ -77,6 +77,7 @@ int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks) host->name = MVSDH_NAME; host->ioaddr = (void *)regbase; host->quirks = quirks; + host->max_clk = max_clk; #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS memset(&mv_ops, 0, sizeof(struct sdhci_ops)); mv_ops.write_b = mv_sdhci_writeb; @@ -88,5 +89,5 @@ int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks) sdhci_mvebu_mbus_config((void __iomem *)regbase); }
- return add_sdhci(host, max_clk, min_clk); + return add_sdhci(host, 0, min_clk); } diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c index 3d587cc..e39b476 100644 --- a/drivers/mmc/pci_mmc.c +++ b/drivers/mmc/pci_mmc.c @@ -32,6 +32,7 @@ int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported) dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase); mmc_host->ioaddr = (void *)(ulong)iobase; mmc_host->quirks = 0; + mmc_host->max_clk = 0; ret = add_sdhci(mmc_host, 0, 0); if (ret) return ret; diff --git a/drivers/mmc/pic32_sdhci.c b/drivers/mmc/pic32_sdhci.c index 2abf943..c562aec 100644 --- a/drivers/mmc/pic32_sdhci.c +++ b/drivers/mmc/pic32_sdhci.c @@ -41,7 +41,9 @@ static int pic32_sdhci_probe(struct udevice *dev) return ret; }
- ret = add_sdhci(host, f_min_max[1], f_min_max[0]); + host->max_clk = f_min_max[1]; + + ret = add_sdhci(host, 0, f_min_max[0]); if (ret) return ret; host->mmc->dev = dev; diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index c56e1a3..4456a02 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -35,9 +35,9 @@ static int arasan_sdhci_probe(struct udevice *dev) int ret;
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD; + host->max_clk = CONFIG_ROCKCHIP_SDHCI_MAX_FREQ;
- ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ROCKCHIP_SDHCI_MAX_FREQ, - EMMC_MIN_FREQ); + ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ);
host->mmc = &plat->mmc; if (ret) diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c index ac737e0..bf0c485 100644 --- a/drivers/mmc/s5p_sdhci.c +++ b/drivers/mmc/s5p_sdhci.c @@ -80,6 +80,7 @@ static int s5p_sdhci_core_init(struct sdhci_host *host) host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_USE_WIDE8; + host->max_clk = 52000000; host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
host->set_control_reg = &s5p_sdhci_set_control_reg; @@ -89,7 +90,7 @@ static int s5p_sdhci_core_init(struct sdhci_host *host) host->host_caps |= MMC_MODE_8BIT;
#ifndef CONFIG_BLK - return add_sdhci(host, 52000000, 400000); + return add_sdhci(host, 0, 400000); #else return 0; #endif @@ -245,7 +246,7 @@ static int s5p_sdhci_probe(struct udevice *dev) if (ret) return ret;
- ret = sdhci_setup_cfg(&plat->cfg, host, 52000000, 400000); + ret = sdhci_setup_cfg(&plat->cfg, host, 0, 400000); if (ret) return ret;
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 766e9ee..0e59dbc 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -325,7 +325,7 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock) */ if (host->clk_mul) { for (div = 1; div <= 1024; div++) { - if ((mmc->cfg->f_max * host->clk_mul / div) + if ((host->max_clk * host->clk_mul / div) <= clock) break; } @@ -338,13 +338,13 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock) div--; } else { /* Version 3.00 divisors must be a multiple of 2. */ - if (mmc->cfg->f_max <= clock) { + if (host->max_clk <= clock) { div = 1; } else { for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) { - if ((mmc->cfg->f_max / div) <= clock) + if ((host->max_clk / div) <= clock) break; } } @@ -353,7 +353,7 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock) } else { /* Version 2.00 divisors must be a power of 2. */ for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) { - if ((mmc->cfg->f_max / div) <= clock) + if ((host->max_clk / div) <= clock) break; } div >>= 1; @@ -534,7 +534,7 @@ static const struct mmc_ops sdhci_ops = { #endif
int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, - u32 max_clk, u32 min_clk) + u32 f_max, u32 f_min) { u32 caps, caps_1;
@@ -557,24 +557,26 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, #ifndef CONFIG_DM_MMC_OPS cfg->ops = &sdhci_ops; #endif - if (max_clk) - cfg->f_max = max_clk; - else { + if (host->max_clk == 0) { if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) - cfg->f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK) >> + host->max_clk = (caps & SDHCI_CLOCK_V3_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; else - cfg->f_max = (caps & SDHCI_CLOCK_BASE_MASK) >> + host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; - cfg->f_max *= 1000000; + host->max_clk *= 1000000; } - if (cfg->f_max == 0) { + if (host->max_clk == 0) { printf("%s: Hardware doesn't specify base clock frequency\n", __func__); return -EINVAL; } - if (min_clk) - cfg->f_min = min_clk; + if (f_max && (f_max < host->max_clk)) + cfg->f_max = f_max; + else + cfg->f_max = host->max_clk; + if (f_min) + cfg->f_min = f_min; else { if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) cfg->f_min = cfg->f_max / SDHCI_MAX_DIV_SPEC_300; @@ -623,11 +625,11 @@ int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg) return mmc_bind(dev, mmc, cfg); } #else -int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk) +int add_sdhci(struct sdhci_host *host, u32 f_max, u32 f_min) { int ret;
- ret = sdhci_setup_cfg(&host->cfg, host, max_clk, min_clk); + ret = sdhci_setup_cfg(&host->cfg, host, f_max, f_min); if (ret) return ret;
diff --git a/drivers/mmc/spear_sdhci.c b/drivers/mmc/spear_sdhci.c index 06179cd..d3f8669 100644 --- a/drivers/mmc/spear_sdhci.c +++ b/drivers/mmc/spear_sdhci.c @@ -21,7 +21,8 @@ int spear_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks) host->name = "sdhci"; host->ioaddr = (void *)regbase; host->quirks = quirks; + host->max_clk = max_clk;
- add_sdhci(host, max_clk, min_clk); + add_sdhci(host, 0, min_clk); return 0; } diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 3da1385..69efa38 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -36,7 +36,9 @@ static int arasan_sdhci_probe(struct udevice *dev) host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; #endif
- ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, + host->max_clk = CONFIG_ZYNQ_SDHCI_MAX_FREQ; + + ret = sdhci_setup_cfg(&plat->cfg, host, 0, CONFIG_ZYNQ_SDHCI_MIN_FREQ); host->mmc = &plat->mmc; if (ret) diff --git a/include/sdhci.h b/include/sdhci.h index 144570f..6c9f7a7 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -243,6 +243,7 @@ struct sdhci_host { unsigned int quirks; unsigned int host_caps; unsigned int version; + unsigned int max_clk; /* Maximum Base Clock frequency */ unsigned int clk_mul; /* Clock Multiplier value */ unsigned int clock; struct mmc *mmc; @@ -372,11 +373,11 @@ static inline u8 sdhci_readb(struct sdhci_host *host, int reg) * * @cfg: Configuration structure to fill in (generally &plat->mmc) * @host: SDHCI host structure - * @max_clk: Maximum supported clock speed in HZ (0 for default) - * @min_clk: Minimum supported clock speed in HZ (0 for default) + * @f_max: Maximum supported clock frequency in HZ (0 for default) + * @f_min: Minimum supported clock frequency in HZ (0 for default) */ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, - u32 max_clk, u32 min_clk); + u32 f_max, u32 f_min);
/** * sdhci_bind() - Set up a new MMC block device @@ -402,11 +403,11 @@ int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg); * This is used when you are not using CONFIG_BLK. Convert your driver over! * * @host: SDHCI host structure - * @max_clk: Maximum supported clock speed in HZ (0 for default) - * @min_clk: Minimum supported clock speed in HZ (0 for default) + * @f_max: Maximum supported clock frequency in HZ (0 for default) + * @f_min: Minimum supported clock frequency in HZ (0 for default) * @return 0 if OK, -ve on error */ -int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk); +int add_sdhci(struct sdhci_host *host, u32 f_max, u32 f_min); #endif /* !CONFIG_BLK */
#ifdef CONFIG_DM_MMC_OPS

On 12/02/2016 10:24 PM, stefan.herbrechtsmeier@weidmueller.de wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The sdhci controller assumes that the base clock frequency is fully supported by the peripheral and doesn't support hardware limitations. The Linux kernel distinguishes between base clock (max_clk) of the host controller and maximum frequency (f_max) of the card interface. Use the same differentiation and allow the platform to constrain the peripheral interface.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
Even if this patch is delegated to Michal, i picked to this. Applied on u-boot-mmc.
Best Regards, Jaehoon Chung
Changes in v3:
- Rename arguments of sdhci_setup_cfg function from max_clk/min_clk to f_max/f_min
Changes in v2: None
drivers/mmc/atmel_sdhci.c | 7 +++++-- drivers/mmc/bcm2835_sdhci.c | 3 ++- drivers/mmc/ftsdc021_sdhci.c | 3 ++- drivers/mmc/kona_sdhci.c | 3 ++- drivers/mmc/msm_sdhci.c | 2 ++ drivers/mmc/mv_sdhci.c | 3 ++- drivers/mmc/pci_mmc.c | 1 + drivers/mmc/pic32_sdhci.c | 4 +++- drivers/mmc/rockchip_sdhci.c | 4 ++-- drivers/mmc/s5p_sdhci.c | 5 +++-- drivers/mmc/sdhci.c | 34 ++++++++++++++++++---------------- drivers/mmc/spear_sdhci.c | 3 ++- drivers/mmc/zynq_sdhci.c | 4 +++- include/sdhci.h | 13 +++++++------ 14 files changed, 54 insertions(+), 35 deletions(-)
diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c index 6654b54..62cb242 100644 --- a/drivers/mmc/atmel_sdhci.c +++ b/drivers/mmc/atmel_sdhci.c @@ -35,8 +35,9 @@ int atmel_sdhci_init(void *regbase, u32 id) free(host); return -ENODEV; }
- host->max_clk = max_clk;
- add_sdhci(host, max_clk, min_clk);
add_sdhci(host, 0, min_clk);
return 0;
} @@ -95,7 +96,9 @@ static int atmel_sdhci_probe(struct udevice *dev) if (!max_clk) return -EINVAL;
- ret = sdhci_setup_cfg(&plat->cfg, host, max_clk, ATMEL_SDHC_MIN_FREQ);
- host->max_clk = max_clk;
- ret = sdhci_setup_cfg(&plat->cfg, host, 0, ATMEL_SDHC_MIN_FREQ); if (ret) return ret;
diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index cb2bd40..29c2a85 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -181,10 +181,11 @@ int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq) host->ioaddr = (void *)(unsigned long)regbase; host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_NO_HISPD_BIT;
- host->max_clk = emmc_freq; host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; host->ops = &bcm2835_ops;
- add_sdhci(host, emmc_freq, MIN_FREQ);
add_sdhci(host, 0, MIN_FREQ);
return 0;
} diff --git a/drivers/mmc/ftsdc021_sdhci.c b/drivers/mmc/ftsdc021_sdhci.c index 6e9fefa..4940ccb 100644 --- a/drivers/mmc/ftsdc021_sdhci.c +++ b/drivers/mmc/ftsdc021_sdhci.c @@ -27,7 +27,8 @@ int ftsdc021_sdhci_init(u32 regbase) host->name = "FTSDC021"; host->ioaddr = (void __iomem *)regbase; host->quirks = 0;
- add_sdhci(host, freq, 0);
host->max_clk = freq;
add_sdhci(host, 0, 0);
return 0;
} diff --git a/drivers/mmc/kona_sdhci.c b/drivers/mmc/kona_sdhci.c index 549f6bc..ddd821b 100644 --- a/drivers/mmc/kona_sdhci.c +++ b/drivers/mmc/kona_sdhci.c @@ -121,12 +121,13 @@ int kona_sdhci_init(int dev_index, u32 min_clk, u32 quirks) host->name = "kona-sdhci"; host->ioaddr = reg_base; host->quirks = quirks;
host->max_clk = max_clk;
if (init_kona_mmc_core(host)) { free(host); return -EINVAL; }
- add_sdhci(host, max_clk, min_clk);
- add_sdhci(host, 0, min_clk); return ret;
} diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c index f33714b..1db683d 100644 --- a/drivers/mmc/msm_sdhci.c +++ b/drivers/mmc/msm_sdhci.c @@ -96,6 +96,8 @@ static int msm_sdc_probe(struct udevice *dev)
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
- host->max_clk = 0;
- /* Init clocks */ ret = msm_sdc_clk_init(dev); if (ret)
diff --git a/drivers/mmc/mv_sdhci.c b/drivers/mmc/mv_sdhci.c index e388ad1..69aa87b 100644 --- a/drivers/mmc/mv_sdhci.c +++ b/drivers/mmc/mv_sdhci.c @@ -77,6 +77,7 @@ int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks) host->name = MVSDH_NAME; host->ioaddr = (void *)regbase; host->quirks = quirks;
- host->max_clk = max_clk;
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS memset(&mv_ops, 0, sizeof(struct sdhci_ops)); mv_ops.write_b = mv_sdhci_writeb; @@ -88,5 +89,5 @@ int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks) sdhci_mvebu_mbus_config((void __iomem *)regbase); }
- return add_sdhci(host, max_clk, min_clk);
- return add_sdhci(host, 0, min_clk);
} diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c index 3d587cc..e39b476 100644 --- a/drivers/mmc/pci_mmc.c +++ b/drivers/mmc/pci_mmc.c @@ -32,6 +32,7 @@ int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported) dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase); mmc_host->ioaddr = (void *)(ulong)iobase; mmc_host->quirks = 0;
ret = add_sdhci(mmc_host, 0, 0); if (ret) return ret;mmc_host->max_clk = 0;
diff --git a/drivers/mmc/pic32_sdhci.c b/drivers/mmc/pic32_sdhci.c index 2abf943..c562aec 100644 --- a/drivers/mmc/pic32_sdhci.c +++ b/drivers/mmc/pic32_sdhci.c @@ -41,7 +41,9 @@ static int pic32_sdhci_probe(struct udevice *dev) return ret; }
- ret = add_sdhci(host, f_min_max[1], f_min_max[0]);
- host->max_clk = f_min_max[1];
- ret = add_sdhci(host, 0, f_min_max[0]); if (ret) return ret; host->mmc->dev = dev;
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index c56e1a3..4456a02 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -35,9 +35,9 @@ static int arasan_sdhci_probe(struct udevice *dev) int ret;
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD;
- host->max_clk = CONFIG_ROCKCHIP_SDHCI_MAX_FREQ;
- ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ROCKCHIP_SDHCI_MAX_FREQ,
EMMC_MIN_FREQ);
ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ);
host->mmc = &plat->mmc; if (ret)
diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c index ac737e0..bf0c485 100644 --- a/drivers/mmc/s5p_sdhci.c +++ b/drivers/mmc/s5p_sdhci.c @@ -80,6 +80,7 @@ static int s5p_sdhci_core_init(struct sdhci_host *host) host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_USE_WIDE8;
host->max_clk = 52000000; host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
host->set_control_reg = &s5p_sdhci_set_control_reg;
@@ -89,7 +90,7 @@ static int s5p_sdhci_core_init(struct sdhci_host *host) host->host_caps |= MMC_MODE_8BIT;
#ifndef CONFIG_BLK
- return add_sdhci(host, 52000000, 400000);
- return add_sdhci(host, 0, 400000);
#else return 0; #endif @@ -245,7 +246,7 @@ static int s5p_sdhci_probe(struct udevice *dev) if (ret) return ret;
- ret = sdhci_setup_cfg(&plat->cfg, host, 52000000, 400000);
- ret = sdhci_setup_cfg(&plat->cfg, host, 0, 400000); if (ret) return ret;
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 766e9ee..0e59dbc 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -325,7 +325,7 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock) */ if (host->clk_mul) { for (div = 1; div <= 1024; div++) {
if ((mmc->cfg->f_max * host->clk_mul / div)
if ((host->max_clk * host->clk_mul / div) <= clock) break; }
@@ -338,13 +338,13 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock) div--; } else { /* Version 3.00 divisors must be a multiple of 2. */
if (mmc->cfg->f_max <= clock) {
if (host->max_clk <= clock) { div = 1; } else { for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
if ((mmc->cfg->f_max / div) <= clock)
if ((host->max_clk / div) <= clock) break; } }
@@ -353,7 +353,7 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock) } else { /* Version 2.00 divisors must be a power of 2. */ for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) {
if ((mmc->cfg->f_max / div) <= clock)
} div >>= 1;if ((host->max_clk / div) <= clock) break;
@@ -534,7 +534,7 @@ static const struct mmc_ops sdhci_ops = { #endif
int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
u32 max_clk, u32 min_clk)
u32 f_max, u32 f_min)
{ u32 caps, caps_1;
@@ -557,24 +557,26 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, #ifndef CONFIG_DM_MMC_OPS cfg->ops = &sdhci_ops; #endif
- if (max_clk)
cfg->f_max = max_clk;
- else {
- if (host->max_clk == 0) { if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
cfg->f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK) >>
elsehost->max_clk = (caps & SDHCI_CLOCK_V3_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
cfg->f_max = (caps & SDHCI_CLOCK_BASE_MASK) >>
host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
cfg->f_max *= 1000000;
}host->max_clk *= 1000000;
- if (cfg->f_max == 0) {
- if (host->max_clk == 0) { printf("%s: Hardware doesn't specify base clock frequency\n", __func__); return -EINVAL; }
- if (min_clk)
cfg->f_min = min_clk;
- if (f_max && (f_max < host->max_clk))
cfg->f_max = f_max;
- else
cfg->f_max = host->max_clk;
- if (f_min)
else { if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) cfg->f_min = cfg->f_max / SDHCI_MAX_DIV_SPEC_300;cfg->f_min = f_min;
@@ -623,11 +625,11 @@ int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg) return mmc_bind(dev, mmc, cfg); } #else -int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk) +int add_sdhci(struct sdhci_host *host, u32 f_max, u32 f_min) { int ret;
- ret = sdhci_setup_cfg(&host->cfg, host, max_clk, min_clk);
- ret = sdhci_setup_cfg(&host->cfg, host, f_max, f_min); if (ret) return ret;
diff --git a/drivers/mmc/spear_sdhci.c b/drivers/mmc/spear_sdhci.c index 06179cd..d3f8669 100644 --- a/drivers/mmc/spear_sdhci.c +++ b/drivers/mmc/spear_sdhci.c @@ -21,7 +21,8 @@ int spear_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks) host->name = "sdhci"; host->ioaddr = (void *)regbase; host->quirks = quirks;
- host->max_clk = max_clk;
- add_sdhci(host, max_clk, min_clk);
- add_sdhci(host, 0, min_clk); return 0;
} diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 3da1385..69efa38 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -36,7 +36,9 @@ static int arasan_sdhci_probe(struct udevice *dev) host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; #endif
- ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ZYNQ_SDHCI_MAX_FREQ,
- host->max_clk = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
- ret = sdhci_setup_cfg(&plat->cfg, host, 0, CONFIG_ZYNQ_SDHCI_MIN_FREQ); host->mmc = &plat->mmc; if (ret)
diff --git a/include/sdhci.h b/include/sdhci.h index 144570f..6c9f7a7 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -243,6 +243,7 @@ struct sdhci_host { unsigned int quirks; unsigned int host_caps; unsigned int version;
- unsigned int max_clk; /* Maximum Base Clock frequency */ unsigned int clk_mul; /* Clock Multiplier value */ unsigned int clock; struct mmc *mmc;
@@ -372,11 +373,11 @@ static inline u8 sdhci_readb(struct sdhci_host *host, int reg)
- @cfg: Configuration structure to fill in (generally &plat->mmc)
- @host: SDHCI host structure
- @max_clk: Maximum supported clock speed in HZ (0 for default)
- @min_clk: Minimum supported clock speed in HZ (0 for default)
- @f_max: Maximum supported clock frequency in HZ (0 for default)
*/
- @f_min: Minimum supported clock frequency in HZ (0 for default)
int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
u32 max_clk, u32 min_clk);
u32 f_max, u32 f_min);
/**
- sdhci_bind() - Set up a new MMC block device
@@ -402,11 +403,11 @@ int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg);
- This is used when you are not using CONFIG_BLK. Convert your driver over!
- @host: SDHCI host structure
- @max_clk: Maximum supported clock speed in HZ (0 for default)
- @min_clk: Minimum supported clock speed in HZ (0 for default)
- @f_max: Maximum supported clock frequency in HZ (0 for default)
*/
- @f_min: Minimum supported clock frequency in HZ (0 for default)
- @return 0 if OK, -ve on error
-int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk); +int add_sdhci(struct sdhci_host *host, u32 f_max, u32 f_min); #endif /* !CONFIG_BLK */
#ifdef CONFIG_DM_MMC_OPS

From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The index of the zynq serial driver is always zero and could be removed.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de Acked-by: Michal Simek michal.simek@xilinx.com
---
Changes in v3: None Changes in v2: - Remove unused index from get uart clock function
arch/arm/mach-zynq/clk.c | 3 +-- arch/arm/mach-zynq/include/mach/clk.h | 2 +- drivers/serial/serial_zynq.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-zynq/clk.c b/arch/arm/mach-zynq/clk.c index 40383c1..e256b58 100644 --- a/arch/arm/mach-zynq/clk.c +++ b/arch/arm/mach-zynq/clk.c @@ -551,13 +551,12 @@ void zynq_clk_early_init(void)
/** * get_uart_clk() - Get UART input frequency - * @dev_index: UART ID * Returns UART input clock frequency in Hz. * * Compared to zynq_clk_get_rate() this function is designed to work before * relocation and can be called when the serial UART is set up. */ -unsigned long get_uart_clk(int dev_index) +unsigned long get_uart_clk(void) { u32 reg = readl(&slcr_base->uart_clk_ctrl); u32 div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; diff --git a/arch/arm/mach-zynq/include/mach/clk.h b/arch/arm/mach-zynq/include/mach/clk.h index 250c5bc..ba2210d 100644 --- a/arch/arm/mach-zynq/include/mach/clk.h +++ b/arch/arm/mach-zynq/include/mach/clk.h @@ -24,6 +24,6 @@ void zynq_clk_early_init(void); int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate); unsigned long zynq_clk_get_rate(enum zynq_clk clk); const char *zynq_clk_get_name(enum zynq_clk clk); -unsigned long get_uart_clk(int dev_id); +unsigned long get_uart_clk(void);
#endif diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c index 4f6e7e4..461ba86 100644 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@ -134,7 +134,7 @@ int zynq_serial_setbrg(struct udevice *dev, int baudrate) return ret; } #else - clock = get_uart_clk(0); + clock = get_uart_clk(); #endif _uart_zynq_serial_setbrg(priv->regs, clock, baudrate);

On 12/02/2016 10:24 PM, stefan.herbrechtsmeier@weidmueller.de wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The index of the zynq serial driver is always zero and could be removed.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de Acked-by: Michal Simek michal.simek@xilinx.com
Even if this patch is delegated to Michal, i picked to this. Applied on u-boot-mmc.
Best Regards, Jaehoon Chung
Changes in v3: None Changes in v2:
- Remove unused index from get uart clock function
arch/arm/mach-zynq/clk.c | 3 +-- arch/arm/mach-zynq/include/mach/clk.h | 2 +- drivers/serial/serial_zynq.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-zynq/clk.c b/arch/arm/mach-zynq/clk.c index 40383c1..e256b58 100644 --- a/arch/arm/mach-zynq/clk.c +++ b/arch/arm/mach-zynq/clk.c @@ -551,13 +551,12 @@ void zynq_clk_early_init(void)
/**
- get_uart_clk() - Get UART input frequency
*/
- @dev_index: UART ID
- Returns UART input clock frequency in Hz.
- Compared to zynq_clk_get_rate() this function is designed to work before
- relocation and can be called when the serial UART is set up.
-unsigned long get_uart_clk(int dev_index) +unsigned long get_uart_clk(void) { u32 reg = readl(&slcr_base->uart_clk_ctrl); u32 div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; diff --git a/arch/arm/mach-zynq/include/mach/clk.h b/arch/arm/mach-zynq/include/mach/clk.h index 250c5bc..ba2210d 100644 --- a/arch/arm/mach-zynq/include/mach/clk.h +++ b/arch/arm/mach-zynq/include/mach/clk.h @@ -24,6 +24,6 @@ void zynq_clk_early_init(void); int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate); unsigned long zynq_clk_get_rate(enum zynq_clk clk); const char *zynq_clk_get_name(enum zynq_clk clk); -unsigned long get_uart_clk(int dev_id); +unsigned long get_uart_clk(void);
#endif diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c index 4f6e7e4..461ba86 100644 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@ -134,7 +134,7 @@ int zynq_serial_setbrg(struct udevice *dev, int baudrate) return ret; } #else
- clock = get_uart_clk(0);
- clock = get_uart_clk();
#endif _uart_zynq_serial_setbrg(priv->regs, clock, baudrate);

From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The zynq_sdhci controller driver use CONFIG_ZYNQ_SDHCI_MAX_FREQ as base clock frequency but this clock is not fixed and depends on the hardware configuration. Additionally the value of CONFIG_ZYNQ_SDHCI_MAX_FREQ doesn't match the real base clock frequency of SDIO_FREQ. Use the clock framework to determine the frequency at run time.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
---
Changes in v3: None Changes in v2: - Remove unused index from get sdio clock function - Introduce common get clock function
arch/arm/mach-zynq/clk.c | 50 ++++++++++++++++++++++++++++------- arch/arm/mach-zynq/include/mach/clk.h | 1 + drivers/mmc/zynq_sdhci.c | 33 +++++++++++++++++++++-- 3 files changed, 72 insertions(+), 12 deletions(-)
diff --git a/arch/arm/mach-zynq/clk.c b/arch/arm/mach-zynq/clk.c index e256b58..8df2de2 100644 --- a/arch/arm/mach-zynq/clk.c +++ b/arch/arm/mach-zynq/clk.c @@ -550,20 +550,26 @@ void zynq_clk_early_init(void) }
/** - * get_uart_clk() - Get UART input frequency - * Returns UART input clock frequency in Hz. + * zynq_clk_get_early() - Get zynq clock frequency early + * Returns clock frequency in Hz. * * Compared to zynq_clk_get_rate() this function is designed to work before - * relocation and can be called when the serial UART is set up. + * relocation and can be called when the peripheral is set up. */ -unsigned long get_uart_clk(void) +unsigned long zynq_clk_get_early(u32 *addr) { - u32 reg = readl(&slcr_base->uart_clk_ctrl); - u32 div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; - u32 srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT; - enum zynq_clk parent = __zynq_clk_periph_get_parent(srcsel); - u32 *pllreg = clkid_2_register(parent); - unsigned long prate = __zynq_clk_pll_get_rate(pllreg); + u32 reg, div, srcsel; + enum zynq_clk parent; + u32 *pllreg; + unsigned long prate; + + reg = readl(addr); + div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; + srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT; + + parent = __zynq_clk_periph_get_parent(srcsel); + pllreg = clkid_2_register(parent); + prate = __zynq_clk_pll_get_rate(pllreg);
if (!div) div = 1; @@ -572,6 +578,30 @@ unsigned long get_uart_clk(void) }
/** + * get_uart_clk() - Get UART input frequency + * Returns UART input clock frequency in Hz. + * + * Compared to zynq_clk_get_rate() this function is designed to work before + * relocation and can be called when the serial UART is set up. + */ +unsigned long get_uart_clk(void) +{ + return zynq_clk_get_early(&slcr_base->uart_clk_ctrl); +} + +/** + * get_sdio_clk() - Get SDIO input frequency + * Returns SDIO input clock frequency in Hz. + * + * Compared to zynq_clk_get_rate() this function is designed to work before + * relocation and can be called when the SDIO is set up. + */ +unsigned long get_sdio_clk(void) +{ + return zynq_clk_get_early(&slcr_base->sdio_clk_ctrl); +} + +/** * set_cpu_clk_info() - Initialize clock framework * Always returns zero. * diff --git a/arch/arm/mach-zynq/include/mach/clk.h b/arch/arm/mach-zynq/include/mach/clk.h index ba2210d..bed4903 100644 --- a/arch/arm/mach-zynq/include/mach/clk.h +++ b/arch/arm/mach-zynq/include/mach/clk.h @@ -25,5 +25,6 @@ int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate); unsigned long zynq_clk_get_rate(enum zynq_clk clk); const char *zynq_clk_get_name(enum zynq_clk clk); unsigned long get_uart_clk(void); +unsigned long get_sdio_clk(void);
#endif diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 69efa38..26bd1be 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -6,6 +6,7 @@ * SPDX-License-Identifier: GPL-2.0+ */
+#include <clk.h> #include <common.h> #include <dm.h> #include <fdtdec.h> @@ -13,6 +14,8 @@ #include <malloc.h> #include <sdhci.h>
+#include <asm/arch/clk.h> + #ifndef CONFIG_ZYNQ_SDHCI_MIN_FREQ # define CONFIG_ZYNQ_SDHCI_MIN_FREQ 0 #endif @@ -27,8 +30,34 @@ static int arasan_sdhci_probe(struct udevice *dev) struct arasan_sdhci_plat *plat = dev_get_platdata(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct sdhci_host *host = dev_get_priv(dev); + unsigned long clock; int ret;
+#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK) + struct clk clk; + + ret = clk_get_by_index(dev, 0, &clk); + if (ret < 0) { + dev_err(dev, "failed to get clock\n"); + return ret; + } + + clock = clk_get_rate(&clk); + if (IS_ERR_VALUE(clock)) { + dev_err(dev, "failed to get rate\n"); + return clock; + } + debug("%s: CLK %ld\n", __func__, clock); + + ret = clk_enable(&clk); + if (ret && ret != -ENOSYS) { + dev_err(dev, "failed to enable clock\n"); + return ret; + } +#else + clock = get_sdio_clk(); +#endif + host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
@@ -36,9 +65,9 @@ static int arasan_sdhci_probe(struct udevice *dev) host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; #endif
- host->max_clk = CONFIG_ZYNQ_SDHCI_MAX_FREQ; + host->max_clk = clock;
- ret = sdhci_setup_cfg(&plat->cfg, host, 0, + ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, CONFIG_ZYNQ_SDHCI_MIN_FREQ); host->mmc = &plat->mmc; if (ret)

On 12/02/2016 10:24 PM, stefan.herbrechtsmeier@weidmueller.de wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The zynq_sdhci controller driver use CONFIG_ZYNQ_SDHCI_MAX_FREQ as base clock frequency but this clock is not fixed and depends on the hardware configuration. Additionally the value of CONFIG_ZYNQ_SDHCI_MAX_FREQ doesn't match the real base clock frequency of SDIO_FREQ. Use the clock framework to determine the frequency at run time.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
Even if this patch is delegated to Michal, i picked to this. Applied on u-boot-mmc.
Best Regards, Jaehoon Chung
Changes in v3: None Changes in v2:
- Remove unused index from get sdio clock function
- Introduce common get clock function
arch/arm/mach-zynq/clk.c | 50 ++++++++++++++++++++++++++++------- arch/arm/mach-zynq/include/mach/clk.h | 1 + drivers/mmc/zynq_sdhci.c | 33 +++++++++++++++++++++-- 3 files changed, 72 insertions(+), 12 deletions(-)
diff --git a/arch/arm/mach-zynq/clk.c b/arch/arm/mach-zynq/clk.c index e256b58..8df2de2 100644 --- a/arch/arm/mach-zynq/clk.c +++ b/arch/arm/mach-zynq/clk.c @@ -550,20 +550,26 @@ void zynq_clk_early_init(void) }
/**
- get_uart_clk() - Get UART input frequency
- Returns UART input clock frequency in Hz.
- zynq_clk_get_early() - Get zynq clock frequency early
- Returns clock frequency in Hz.
- Compared to zynq_clk_get_rate() this function is designed to work before
- relocation and can be called when the serial UART is set up.
*/
- relocation and can be called when the peripheral is set up.
-unsigned long get_uart_clk(void) +unsigned long zynq_clk_get_early(u32 *addr) {
- u32 reg = readl(&slcr_base->uart_clk_ctrl);
- u32 div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
- u32 srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
- enum zynq_clk parent = __zynq_clk_periph_get_parent(srcsel);
- u32 *pllreg = clkid_2_register(parent);
- unsigned long prate = __zynq_clk_pll_get_rate(pllreg);
u32 reg, div, srcsel;
enum zynq_clk parent;
u32 *pllreg;
unsigned long prate;
reg = readl(addr);
div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
parent = __zynq_clk_periph_get_parent(srcsel);
pllreg = clkid_2_register(parent);
prate = __zynq_clk_pll_get_rate(pllreg);
if (!div) div = 1;
@@ -572,6 +578,30 @@ unsigned long get_uart_clk(void) }
/**
- get_uart_clk() - Get UART input frequency
- Returns UART input clock frequency in Hz.
- Compared to zynq_clk_get_rate() this function is designed to work before
- relocation and can be called when the serial UART is set up.
- */
+unsigned long get_uart_clk(void) +{
- return zynq_clk_get_early(&slcr_base->uart_clk_ctrl);
+}
+/**
- get_sdio_clk() - Get SDIO input frequency
- Returns SDIO input clock frequency in Hz.
- Compared to zynq_clk_get_rate() this function is designed to work before
- relocation and can be called when the SDIO is set up.
- */
+unsigned long get_sdio_clk(void) +{
- return zynq_clk_get_early(&slcr_base->sdio_clk_ctrl);
+}
+/**
- set_cpu_clk_info() - Initialize clock framework
- Always returns zero.
diff --git a/arch/arm/mach-zynq/include/mach/clk.h b/arch/arm/mach-zynq/include/mach/clk.h index ba2210d..bed4903 100644 --- a/arch/arm/mach-zynq/include/mach/clk.h +++ b/arch/arm/mach-zynq/include/mach/clk.h @@ -25,5 +25,6 @@ int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate); unsigned long zynq_clk_get_rate(enum zynq_clk clk); const char *zynq_clk_get_name(enum zynq_clk clk); unsigned long get_uart_clk(void); +unsigned long get_sdio_clk(void);
#endif diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 69efa38..26bd1be 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -6,6 +6,7 @@
- SPDX-License-Identifier: GPL-2.0+
*/
+#include <clk.h> #include <common.h> #include <dm.h> #include <fdtdec.h> @@ -13,6 +14,8 @@ #include <malloc.h> #include <sdhci.h>
+#include <asm/arch/clk.h>
#ifndef CONFIG_ZYNQ_SDHCI_MIN_FREQ # define CONFIG_ZYNQ_SDHCI_MIN_FREQ 0 #endif @@ -27,8 +30,34 @@ static int arasan_sdhci_probe(struct udevice *dev) struct arasan_sdhci_plat *plat = dev_get_platdata(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct sdhci_host *host = dev_get_priv(dev);
- unsigned long clock; int ret;
+#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
- struct clk clk;
- ret = clk_get_by_index(dev, 0, &clk);
- if (ret < 0) {
dev_err(dev, "failed to get clock\n");
return ret;
- }
- clock = clk_get_rate(&clk);
- if (IS_ERR_VALUE(clock)) {
dev_err(dev, "failed to get rate\n");
return clock;
- }
- debug("%s: CLK %ld\n", __func__, clock);
- ret = clk_enable(&clk);
- if (ret && ret != -ENOSYS) {
dev_err(dev, "failed to enable clock\n");
return ret;
- }
+#else
- clock = get_sdio_clk();
+#endif
- host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
@@ -36,9 +65,9 @@ static int arasan_sdhci_probe(struct udevice *dev) host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; #endif
- host->max_clk = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
- host->max_clk = clock;
- ret = sdhci_setup_cfg(&plat->cfg, host, 0,
- ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, CONFIG_ZYNQ_SDHCI_MIN_FREQ); host->mmc = &plat->mmc; if (ret)

On 5.12.2016 23:22, Jaehoon Chung wrote:
On 12/02/2016 10:24 PM, stefan.herbrechtsmeier@weidmueller.de wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The zynq_sdhci controller driver use CONFIG_ZYNQ_SDHCI_MAX_FREQ as base clock frequency but this clock is not fixed and depends on the hardware configuration. Additionally the value of CONFIG_ZYNQ_SDHCI_MAX_FREQ doesn't match the real base clock frequency of SDIO_FREQ. Use the clock framework to determine the frequency at run time.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
Even if this patch is delegated to Michal, i picked to this. Applied on u-boot-mmc.
Based on my reply in v2 this is not ideal patch http://lists.denx.de/pipermail/u-boot/2016-November/274310.html
Not a problem to take these patches should mmc tree but please wait till you have Ack from me.
Thanks, Michal

Dear Michal,
On 12/06/2016 09:59 PM, Michal Simek wrote:
On 5.12.2016 23:22, Jaehoon Chung wrote:
On 12/02/2016 10:24 PM, stefan.herbrechtsmeier@weidmueller.de wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The zynq_sdhci controller driver use CONFIG_ZYNQ_SDHCI_MAX_FREQ as base clock frequency but this clock is not fixed and depends on the hardware configuration. Additionally the value of CONFIG_ZYNQ_SDHCI_MAX_FREQ doesn't match the real base clock frequency of SDIO_FREQ. Use the clock framework to determine the frequency at run time.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
Even if this patch is delegated to Michal, i picked to this. Applied on u-boot-mmc.
Based on my reply in v2 this is not ideal patch http://lists.denx.de/pipermail/u-boot/2016-November/274310.html
Not a problem to take these patches should mmc tree but please wait till you have Ack from me.
Thanks for noticing this. I will wait for your ack. So I will rebase u-boot-mmc without these patches.
Best Regards, Jaehoon Chung
Thanks, Michal

Hi Michael
-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com] Gesendet: Dienstag, 6. Dezember 2016 13:59 An: Jaehoon Chung; Herbrechtsmeier, Stefan; u-boot@lists.denx.de Cc: Michal Simek; Simon Glass; Albert Aribaud; Michal Simek; Stephen Warren Betreff: Re: [PATCH v3 3/4] mmc: zynq: Determine base clock frequency via clock framework
On 5.12.2016 23:22, Jaehoon Chung wrote:
On 12/02/2016 10:24 PM, stefan.herbrechtsmeier@weidmueller.de wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The zynq_sdhci controller driver use CONFIG_ZYNQ_SDHCI_MAX_FREQ as base clock frequency but this clock is not fixed and depends on the hardware configuration. Additionally the value of CONFIG_ZYNQ_SDHCI_MAX_FREQ doesn't match the real base clock frequency of SDIO_FREQ. Use the clock framework to determine the
frequency at run time.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
Even if this patch is delegated to Michal, i picked to this. Applied on u-boot-mmc.
Based on my reply in v2 this is not ideal patch http://lists.denx.de/pipermail/u-boot/2016-November/274310.html
Not a problem to take these patches should mmc tree but please wait till you have Ack from me.
Will you ack the patch if I remove the zynq specific code and remove the CONFIG_CLK check with my patch series to move zynq clk driver to DM?
Regards, Stefan
Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - Komplementärin: Weidmüller Interface Führungsgesellschaft mbH - Sitz: Detmold - Amtsgericht Lemgo HRB 3924; Geschäftsführer: José Carlos Álvarez Tobar, Elke Eckstein, Dr. Peter Köhler, Jörg Timmermann; USt-ID-Nr. DE124599660

Hi Stefan,
On 01/10/2017 06:16 PM, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michael
-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com] Gesendet: Dienstag, 6. Dezember 2016 13:59 An: Jaehoon Chung; Herbrechtsmeier, Stefan; u-boot@lists.denx.de Cc: Michal Simek; Simon Glass; Albert Aribaud; Michal Simek; Stephen Warren Betreff: Re: [PATCH v3 3/4] mmc: zynq: Determine base clock frequency via clock framework
On 5.12.2016 23:22, Jaehoon Chung wrote:
On 12/02/2016 10:24 PM, stefan.herbrechtsmeier@weidmueller.de wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The zynq_sdhci controller driver use CONFIG_ZYNQ_SDHCI_MAX_FREQ as base clock frequency but this clock is not fixed and depends on the hardware configuration. Additionally the value of CONFIG_ZYNQ_SDHCI_MAX_FREQ doesn't match the real base clock frequency of SDIO_FREQ. Use the clock framework to determine the
frequency at run time.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
Even if this patch is delegated to Michal, i picked to this. Applied on u-boot-mmc.
Based on my reply in v2 this is not ideal patch http://lists.denx.de/pipermail/u-boot/2016-November/274310.html
Not a problem to take these patches should mmc tree but please wait till you have Ack from me.
Will you ack the patch if I remove the zynq specific code and remove the CONFIG_CLK check with my patch series to move zynq clk driver to DM?
I think you can send the patch[1/4] as the split patch. Could you resend the patch after rebasing on latest u-boot? (Because our confusion needs to fix with your patch.)
Then Other patches should be left a matter in Michal.
how about?
Regards, Stefan
Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - Komplementärin: Weidmüller Interface Führungsgesellschaft mbH - Sitz: Detmold - Amtsgericht Lemgo HRB 3924; Geschäftsführer: José Carlos Álvarez Tobar, Elke Eckstein, Dr. Peter Köhler, Jörg Timmermann; USt-ID-Nr. DE124599660

On 10.1.2017 10:16, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michael
-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com] Gesendet: Dienstag, 6. Dezember 2016 13:59 An: Jaehoon Chung; Herbrechtsmeier, Stefan; u-boot@lists.denx.de Cc: Michal Simek; Simon Glass; Albert Aribaud; Michal Simek; Stephen Warren Betreff: Re: [PATCH v3 3/4] mmc: zynq: Determine base clock frequency via clock framework
On 5.12.2016 23:22, Jaehoon Chung wrote:
On 12/02/2016 10:24 PM, stefan.herbrechtsmeier@weidmueller.de wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The zynq_sdhci controller driver use CONFIG_ZYNQ_SDHCI_MAX_FREQ as base clock frequency but this clock is not fixed and depends on the hardware configuration. Additionally the value of CONFIG_ZYNQ_SDHCI_MAX_FREQ doesn't match the real base clock frequency of SDIO_FREQ. Use the clock framework to determine the
frequency at run time.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
Even if this patch is delegated to Michal, i picked to this. Applied on u-boot-mmc.
Based on my reply in v2 this is not ideal patch http://lists.denx.de/pipermail/u-boot/2016-November/274310.html
Not a problem to take these patches should mmc tree but please wait till you have Ack from me.
Will you ack the patch if I remove the zynq specific code and remove the CONFIG_CLK check with my patch series to move zynq clk driver to DM?
Just going to look at our clk changes for zynq and it can be the part of this series. Do you have branch somewhere with pending stuff?
Thanks, Michal

Hi Michal,
-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com] Gesendet: Dienstag, 10. Januar 2017 14:30 An: Herbrechtsmeier, Stefan; michal.simek@xilinx.com; jh80.chung@samsung.com; u-boot@lists.denx.de Cc: sjg@chromium.org; monstr@monstr.eu; swarren@nvidia.com Betreff: Re: AW: [PATCH v3 3/4] mmc: zynq: Determine base clock frequency via clock framework
On 10.1.2017 10:16, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michael
-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com] Gesendet: Dienstag, 6. Dezember 2016 13:59 An: Jaehoon Chung; Herbrechtsmeier, Stefan; u-boot@lists.denx.de Cc: Michal Simek; Simon Glass; Albert Aribaud; Michal Simek; Stephen Warren Betreff: Re: [PATCH v3 3/4] mmc: zynq: Determine base clock
frequency
via clock framework
On 5.12.2016 23:22, Jaehoon Chung wrote:
On 12/02/2016 10:24 PM, stefan.herbrechtsmeier@weidmueller.de
wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The zynq_sdhci controller driver use CONFIG_ZYNQ_SDHCI_MAX_FREQ as base clock frequency but this clock is not fixed and depends on
the
hardware configuration. Additionally the value of CONFIG_ZYNQ_SDHCI_MAX_FREQ doesn't match the real base clock frequency of SDIO_FREQ. Use the clock framework to determine the
frequency at run time.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
Even if this patch is delegated to Michal, i picked to this. Applied on u-boot-mmc.
Based on my reply in v2 this is not ideal patch http://lists.denx.de/pipermail/u-boot/2016-November/274310.html
Not a problem to take these patches should mmc tree but please wait till you have Ack from me.
Will you ack the patch if I remove the zynq specific code and remove
the CONFIG_CLK check with my patch series to move zynq clk driver to DM?
Just going to look at our clk changes for zynq and it can be the part of this series.
Okay.
Do you have branch somewhere with pending stuff?
I have no public branch.
Regards, Stefan
Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - Komplementärin: Weidmüller Interface Führungsgesellschaft mbH - Sitz: Detmold - Amtsgericht Lemgo HRB 3924; Geschäftsführer: José Carlos Álvarez Tobar, Elke Eckstein, Dr. Peter Köhler, Jörg Timmermann; USt-ID-Nr. DE124599660

On 10.1.2017 15:05, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michal,
-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com] Gesendet: Dienstag, 10. Januar 2017 14:30 An: Herbrechtsmeier, Stefan; michal.simek@xilinx.com; jh80.chung@samsung.com; u-boot@lists.denx.de Cc: sjg@chromium.org; monstr@monstr.eu; swarren@nvidia.com Betreff: Re: AW: [PATCH v3 3/4] mmc: zynq: Determine base clock frequency via clock framework
On 10.1.2017 10:16, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michael
-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com] Gesendet: Dienstag, 6. Dezember 2016 13:59 An: Jaehoon Chung; Herbrechtsmeier, Stefan; u-boot@lists.denx.de Cc: Michal Simek; Simon Glass; Albert Aribaud; Michal Simek; Stephen Warren Betreff: Re: [PATCH v3 3/4] mmc: zynq: Determine base clock
frequency
via clock framework
On 5.12.2016 23:22, Jaehoon Chung wrote:
On 12/02/2016 10:24 PM, stefan.herbrechtsmeier@weidmueller.de
wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The zynq_sdhci controller driver use CONFIG_ZYNQ_SDHCI_MAX_FREQ as base clock frequency but this clock is not fixed and depends on
the
hardware configuration. Additionally the value of CONFIG_ZYNQ_SDHCI_MAX_FREQ doesn't match the real base clock frequency of SDIO_FREQ. Use the clock framework to determine the
frequency at run time.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
Even if this patch is delegated to Michal, i picked to this. Applied on u-boot-mmc.
Based on my reply in v2 this is not ideal patch http://lists.denx.de/pipermail/u-boot/2016-November/274310.html
Not a problem to take these patches should mmc tree but please wait till you have Ack from me.
Will you ack the patch if I remove the zynq specific code and remove
the CONFIG_CLK check with my patch series to move zynq clk driver to DM?
Just going to look at our clk changes for zynq and it can be the part of this series.
Okay.
Do you have branch somewhere with pending stuff?
I have no public branch.
ok. Can you please send it as the part of clk series you made? I see that at least this patch will be different.
Thanks, Michal

-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com] Gesendet: Dienstag, 10. Januar 2017 16:39
On 10.1.2017 15:05, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michal,
-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com] Gesendet: Dienstag, 10. Januar 2017 14:30 An: Herbrechtsmeier, Stefan; michal.simek@xilinx.com; jh80.chung@samsung.com; u-boot@lists.denx.de Cc: sjg@chromium.org; monstr@monstr.eu; swarren@nvidia.com Betreff: Re: AW: [PATCH v3 3/4] mmc: zynq: Determine base clock frequency via clock framework
On 10.1.2017 10:16, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michael
-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com] Gesendet: Dienstag, 6. Dezember 2016 13:59 An: Jaehoon Chung; Herbrechtsmeier, Stefan; u-boot@lists.denx.de Cc: Michal Simek; Simon Glass; Albert Aribaud; Michal Simek; Stephen Warren Betreff: Re: [PATCH v3 3/4] mmc: zynq: Determine base clock
frequency
via clock framework
On 5.12.2016 23:22, Jaehoon Chung wrote:
On 12/02/2016 10:24 PM, stefan.herbrechtsmeier@weidmueller.de
wrote:
> From: Stefan Herbrechtsmeier > stefan.herbrechtsmeier@weidmueller.de > > The zynq_sdhci controller driver use CONFIG_ZYNQ_SDHCI_MAX_FREQ > as base clock frequency but this clock is not fixed and depends > on
the
> hardware configuration. Additionally the value of > CONFIG_ZYNQ_SDHCI_MAX_FREQ doesn't match the real base clock > frequency of SDIO_FREQ. Use the clock framework to determine the
frequency at run time.
> > Signed-off-by: Stefan Herbrechtsmeier > stefan.herbrechtsmeier@weidmueller.de
Even if this patch is delegated to Michal, i picked to this. Applied on u-boot-mmc.
Based on my reply in v2 this is not ideal patch http://lists.denx.de/pipermail/u-boot/2016-November/274310.html
Not a problem to take these patches should mmc tree but please
wait
till you have Ack from me.
Will you ack the patch if I remove the zynq specific code and
remove
the CONFIG_CLK check with my patch series to move zynq clk driver to DM?
Just going to look at our clk changes for zynq and it can be the
part
of this series.
Okay.
Do you have branch somewhere with pending stuff?
I have no public branch.
ok. Can you please send it as the part of clk series you made? I see that at least this patch will be different.
Okay.
Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - Komplementärin: Weidmüller Interface Führungsgesellschaft mbH - Sitz: Detmold - Amtsgericht Lemgo HRB 3924; Geschäftsführer: José Carlos Álvarez Tobar, Elke Eckstein, Dr. Peter Köhler, Jörg Timmermann; USt-ID-Nr. DE124599660

From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The maximum supported peripheral clock frequency of the zynq depends on the IO routing. The MIO and EMIO support a maximum frequency of 50 MHz respectively 25 MHz. Use the max-frequency value of the device tree to determine the maximal supported peripheral clock frequency.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de Acked-by: Michal Simek michal.simek@xilinx.com
---
Changes in v3: None Changes in v2: None
drivers/mmc/zynq_sdhci.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 26bd1be..4d2f0b5 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -16,6 +16,8 @@
#include <asm/arch/clk.h>
+DECLARE_GLOBAL_DATA_PTR; + #ifndef CONFIG_ZYNQ_SDHCI_MIN_FREQ # define CONFIG_ZYNQ_SDHCI_MIN_FREQ 0 #endif @@ -23,6 +25,7 @@ struct arasan_sdhci_plat { struct mmc_config cfg; struct mmc mmc; + unsigned int f_max; };
static int arasan_sdhci_probe(struct udevice *dev) @@ -67,7 +70,7 @@ static int arasan_sdhci_probe(struct udevice *dev)
host->max_clk = clock;
- ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, + ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max, CONFIG_ZYNQ_SDHCI_MIN_FREQ); host->mmc = &plat->mmc; if (ret) @@ -81,11 +84,15 @@ static int arasan_sdhci_probe(struct udevice *dev)
static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) { + struct arasan_sdhci_plat *plat = dev_get_platdata(dev); struct sdhci_host *host = dev_get_priv(dev);
host->name = dev->name; host->ioaddr = (void *)dev_get_addr(dev);
+ plat->f_max = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + "max-frequency", CONFIG_ZYNQ_SDHCI_MAX_FREQ); + return 0; }

On 12/02/2016 10:24 PM, stefan.herbrechtsmeier@weidmueller.de wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The maximum supported peripheral clock frequency of the zynq depends on the IO routing. The MIO and EMIO support a maximum frequency of 50 MHz respectively 25 MHz. Use the max-frequency value of the device tree to determine the maximal supported peripheral clock frequency.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de Acked-by: Michal Simek michal.simek@xilinx.com
Even if this patch is delegated to Michal, i picked to this. Applied on u-boot-mmc.
Best Regards, Jaehoon Chung
Changes in v3: None Changes in v2: None
drivers/mmc/zynq_sdhci.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 26bd1be..4d2f0b5 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -16,6 +16,8 @@
#include <asm/arch/clk.h>
+DECLARE_GLOBAL_DATA_PTR;
#ifndef CONFIG_ZYNQ_SDHCI_MIN_FREQ # define CONFIG_ZYNQ_SDHCI_MIN_FREQ 0 #endif @@ -23,6 +25,7 @@ struct arasan_sdhci_plat { struct mmc_config cfg; struct mmc mmc;
- unsigned int f_max;
};
static int arasan_sdhci_probe(struct udevice *dev) @@ -67,7 +70,7 @@ static int arasan_sdhci_probe(struct udevice *dev)
host->max_clk = clock;
- ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ZYNQ_SDHCI_MAX_FREQ,
- ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max, CONFIG_ZYNQ_SDHCI_MIN_FREQ); host->mmc = &plat->mmc; if (ret)
@@ -81,11 +84,15 @@ static int arasan_sdhci_probe(struct udevice *dev)
static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) {
struct arasan_sdhci_plat *plat = dev_get_platdata(dev); struct sdhci_host *host = dev_get_priv(dev);
host->name = dev->name; host->ioaddr = (void *)dev_get_addr(dev);
plat->f_max = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"max-frequency", CONFIG_ZYNQ_SDHCI_MAX_FREQ);
return 0;
}

Hi Stefan,
On 12/02/2016 10:24 PM, stefan.herbrechtsmeier@weidmueller.de wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The sdhci controller assumes that the base clock frequency is fully supported by the peripheral and doesn't support hardware limitations. Distinguish between base clock of the host controller and maximal supported peripheral clock frequency of the peripheral interface. This is needed for the zynq platform to support two sdhci ports with different IO routings.
I understood what your purpose is...When i checked your patch, i wonder one thing about dwmmc controller. There is also using dwmci_setup_cfg() and it is assigned to cfg->f_min/max with max_clk/min_clk.
I think it also needs to take your approach, right? do you have any plan for dwmmc controller?
I want to apply at same time..because cfg->f_min/f_max should be used in mmc.c. so It has to consider about all host controller, not only sdhci controller. :)
Best Regards, Jaehoon Chung
Changes in v3:
- Rename arguments of sdhci_setup_cfg function from max_clk/min_clk to f_max/f_min
Changes in v2:
- Remove unused index from get uart clock function
- Remove unused index from get sdio clock function
- Introduce common get clock function
Stefan Herbrechtsmeier (4): mmc: sdhci: Distinguish between base clock and maximum peripheral frequency serial: zynq: Remove unused index from get uart clock function mmc: zynq: Determine base clock frequency via clock framework mmc: zynq: Add fdt max-frequency support
arch/arm/mach-zynq/clk.c | 51 +++++++++++++++++++++++++++-------- arch/arm/mach-zynq/include/mach/clk.h | 3 ++- drivers/mmc/atmel_sdhci.c | 7 +++-- drivers/mmc/bcm2835_sdhci.c | 3 ++- drivers/mmc/ftsdc021_sdhci.c | 3 ++- drivers/mmc/kona_sdhci.c | 3 ++- drivers/mmc/msm_sdhci.c | 2 ++ drivers/mmc/mv_sdhci.c | 3 ++- drivers/mmc/pci_mmc.c | 1 + drivers/mmc/pic32_sdhci.c | 4 ++- drivers/mmc/rockchip_sdhci.c | 4 +-- drivers/mmc/s5p_sdhci.c | 5 ++-- drivers/mmc/sdhci.c | 34 ++++++++++++----------- drivers/mmc/spear_sdhci.c | 3 ++- drivers/mmc/zynq_sdhci.c | 40 ++++++++++++++++++++++++++- drivers/serial/serial_zynq.c | 2 +- include/sdhci.h | 13 ++++----- 17 files changed, 133 insertions(+), 48 deletions(-)

Hi,
-----Ursprüngliche Nachricht----- Von: Jaehoon Chung [mailto:jh80.chung@samsung.com]
On 12/02/2016 10:24 PM, stefan.herbrechtsmeier@weidmueller.de wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The sdhci controller assumes that the base clock frequency is fully supported by the peripheral and doesn't support hardware limitations. Distinguish between base clock of the host controller and maximal supported peripheral clock frequency of the peripheral interface. This is needed for the zynq platform to support two sdhci ports with different IO routings.
I understood what your purpose is...When i checked your patch, i wonder one thing about dwmmc controller. There is also using dwmci_setup_cfg() and it is assigned to cfg-
f_min/max with max_clk/min_clk.
I think it also needs to take your approach, right?
The driver already use a different source clock (host->bus_hz / host->get_mmc_clk) for the calculation in its own set_ios / dwmmi_setup_bus function.
do you have any plan for dwmmc controller?
No, because it is only a local cosmetic rename and shouldn't be affected by my changes.
Regards Stefan
Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - Komplementärin: Weidmüller Interface Führungsgesellschaft mbH - Sitz: Detmold - Amtsgericht Lemgo HRB 3924; Geschäftsführer: José Carlos Álvarez Tobar, Elke Eckstein, Dr. Peter Köhler, Jörg Timmermann; USt-ID-Nr. DE124599660

On 12/07/2016 08:47 PM, Stefan.Herbrechtsmeier@weidmueller.de wrote:
Hi,
-----Ursprüngliche Nachricht----- Von: Jaehoon Chung [mailto:jh80.chung@samsung.com]
On 12/02/2016 10:24 PM, stefan.herbrechtsmeier@weidmueller.de wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.de
The sdhci controller assumes that the base clock frequency is fully supported by the peripheral and doesn't support hardware limitations. Distinguish between base clock of the host controller and maximal supported peripheral clock frequency of the peripheral interface. This is needed for the zynq platform to support two sdhci ports with different IO routings.
I understood what your purpose is...When i checked your patch, i wonder one thing about dwmmc controller. There is also using dwmci_setup_cfg() and it is assigned to cfg-
f_min/max with max_clk/min_clk.
I think it also needs to take your approach, right?
The driver already use a different source clock (host->bus_hz / host->get_mmc_clk) for the calculation in its own set_ios / dwmmi_setup_bus function.
do you have any plan for dwmmc controller?
No, because it is only a local cosmetic rename and shouldn't be affected by my changes.
Yes, If it needs to change, i will do. :)
Best Regards, Jaehoon Chung
Regards Stefan
Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - Komplementärin: Weidmüller Interface Führungsgesellschaft mbH - Sitz: Detmold - Amtsgericht Lemgo HRB 3924; Geschäftsführer: José Carlos Álvarez Tobar, Elke Eckstein, Dr. Peter Köhler, Jörg Timmermann; USt-ID-Nr. DE124599660
participants (5)
-
Jaehoon Chung
-
Michal Simek
-
Stefan.Herbrechtsmeier@weidmueller.com
-
Stefan.Herbrechtsmeier@weidmueller.de
-
stefan.herbrechtsmeier@weidmueller.de