summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorStefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>2017-01-17 15:58:48 +0100
committerJaehoon Chung <jh80.chung@samsung.com>2017-01-23 15:37:42 +0900
commit6d0e34bf4e21596563e5f5950d097a2eab4c81a8 (patch)
treed1d82e018cb8b85d7f0ddb102667b676fe891237 /drivers/mmc
parent0c9e85f67cd86d2d7a3424ea3ebff0e6db7a3915 (diff)
mmc: sdhci: Distinguish between base clock and maximum peripheral frequency
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.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/atmel_sdhci.c7
-rw-r--r--drivers/mmc/bcm2835_sdhci.c3
-rw-r--r--drivers/mmc/ftsdc021_sdhci.c3
-rw-r--r--drivers/mmc/kona_sdhci.c3
-rw-r--r--drivers/mmc/msm_sdhci.c2
-rw-r--r--drivers/mmc/mv_sdhci.c3
-rw-r--r--drivers/mmc/pci_mmc.c1
-rw-r--r--drivers/mmc/pic32_sdhci.c4
-rw-r--r--drivers/mmc/rockchip_sdhci.c4
-rw-r--r--drivers/mmc/s5p_sdhci.c5
-rw-r--r--drivers/mmc/sdhci.c34
-rw-r--r--drivers/mmc/zynq_sdhci.c4
12 files changed, 45 insertions, 28 deletions
diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c
index 6654b54278..62cb242343 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 cb2bd40c65..29c2a85812 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 6e9fefab33..4940ccb357 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 549f6bcbbd..ddd821bfc3 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 f33714b1d8..1db683d01e 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 e388ad171b..69aa87babe 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 3d587cc97d..e39b476834 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 c06364cfc1..1e14fa14d6 100644
--- a/drivers/mmc/pic32_sdhci.c
+++ b/drivers/mmc/pic32_sdhci.c
@@ -56,7 +56,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 e33e35e4fa..1358864701 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -50,9 +50,9 @@ static int arasan_sdhci_probe(struct udevice *dev)
}
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD;
+ host->max_clk = max_frequency;
- ret = sdhci_setup_cfg(&plat->cfg, host, max_frequency,
- 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 1f1d2ed865..28327d5f0b 100644
--- a/drivers/mmc/s5p_sdhci.c
+++ b/drivers/mmc/s5p_sdhci.c
@@ -91,6 +91,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->ops = &s5p_sdhci_ops;
@@ -98,7 +99,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
@@ -254,7 +255,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 5b404ff4a3..84e05815bf 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;
@@ -513,7 +513,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;
@@ -536,24 +536,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;
@@ -598,11 +600,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/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 3da138562a..69efa3857a 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)