summaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2016-07-30 16:25:47 +0200
committerUlf Hansson <ulf.hansson@linaro.org>2016-09-26 21:31:05 +0200
commitb465646ef41f2f8a397f42a956d9788e898185d7 (patch)
treeef29b400763af26873d61079bc70e95273542c08 /drivers/mmc
parentf2cecb70941c8d4a9445ee85926202f7157e1222 (diff)
downloadlinux-b465646ef41f2f8a397f42a956d9788e898185d7.tar.gz
linux-b465646ef41f2f8a397f42a956d9788e898185d7.tar.bz2
linux-b465646ef41f2f8a397f42a956d9788e898185d7.zip
mmc: sunxi: sun4i / sun5i do not have sample clocks
It turns out that sun4i (A10) and sun5i (A13 & co) do not have sample clocks, so add a new sun7i-a20-mmc compatible and do not try to use sample clocks on sun4i / sun5i. Since sun4i / sun5i do not have sample clocks, they cannot (reliably) do DDR rates, so only set MMC_CAP_1_8V_DDR when we do have sample clks. Note this patch leaves the clk_prepare_enable() / clk_disable_unprepare() calls to the sample clks as-is, without adding checks for them being NULL. All the clk_foo calls accept a NULL clk and will return success when called with a NULL clk. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/sunxi-mmc.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index af30d87a56db..2ec91ce1fb0a 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -662,6 +662,9 @@ static int sunxi_mmc_clk_set_phase(struct sunxi_mmc_host *host,
{
int index;
+ if (!host->cfg->clk_delays)
+ return 0;
+
/* determine delays */
if (rate <= 400000) {
index = SDXC_CLK_400K;
@@ -978,11 +981,16 @@ static const struct sunxi_mmc_clk_delay sun9i_mmc_clk_delays[] = {
static const struct sunxi_mmc_cfg sun4i_a10_cfg = {
.idma_des_size_bits = 13,
- .clk_delays = sunxi_mmc_clk_delays,
+ .clk_delays = NULL,
};
static const struct sunxi_mmc_cfg sun5i_a13_cfg = {
.idma_des_size_bits = 16,
+ .clk_delays = NULL,
+};
+
+static const struct sunxi_mmc_cfg sun7i_a20_cfg = {
+ .idma_des_size_bits = 16,
.clk_delays = sunxi_mmc_clk_delays,
};
@@ -994,6 +1002,7 @@ static const struct sunxi_mmc_cfg sun9i_a80_cfg = {
static const struct of_device_id sunxi_mmc_of_match[] = {
{ .compatible = "allwinner,sun4i-a10-mmc", .data = &sun4i_a10_cfg },
{ .compatible = "allwinner,sun5i-a13-mmc", .data = &sun5i_a13_cfg },
+ { .compatible = "allwinner,sun7i-a20-mmc", .data = &sun7i_a20_cfg },
{ .compatible = "allwinner,sun9i-a80-mmc", .data = &sun9i_a80_cfg },
{ /* sentinel */ }
};
@@ -1032,16 +1041,18 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
return PTR_ERR(host->clk_mmc);
}
- host->clk_output = devm_clk_get(&pdev->dev, "output");
- if (IS_ERR(host->clk_output)) {
- dev_err(&pdev->dev, "Could not get output clock\n");
- return PTR_ERR(host->clk_output);
- }
+ if (host->cfg->clk_delays) {
+ host->clk_output = devm_clk_get(&pdev->dev, "output");
+ if (IS_ERR(host->clk_output)) {
+ dev_err(&pdev->dev, "Could not get output clock\n");
+ return PTR_ERR(host->clk_output);
+ }
- host->clk_sample = devm_clk_get(&pdev->dev, "sample");
- if (IS_ERR(host->clk_sample)) {
- dev_err(&pdev->dev, "Could not get sample clock\n");
- return PTR_ERR(host->clk_sample);
+ host->clk_sample = devm_clk_get(&pdev->dev, "sample");
+ if (IS_ERR(host->clk_sample)) {
+ dev_err(&pdev->dev, "Could not get sample clock\n");
+ return PTR_ERR(host->clk_sample);
+ }
}
host->reset = devm_reset_control_get_optional(&pdev->dev, "ahb");
@@ -1144,9 +1155,11 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
mmc->f_min = 400000;
mmc->f_max = 52000000;
mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
- MMC_CAP_1_8V_DDR |
MMC_CAP_ERASE | MMC_CAP_SDIO_IRQ;
+ if (host->cfg->clk_delays)
+ mmc->caps |= MMC_CAP_1_8V_DDR;
+
ret = mmc_of_parse(mmc);
if (ret)
goto error_free_dma;