summaryrefslogtreecommitdiffstats
path: root/target/linux/mediatek/patches-4.14/0157-mmc-mediatek-add-support-of-source_cg-clock.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/mediatek/patches-4.14/0157-mmc-mediatek-add-support-of-source_cg-clock.patch')
-rw-r--r--target/linux/mediatek/patches-4.14/0157-mmc-mediatek-add-support-of-source_cg-clock.patch90
1 files changed, 90 insertions, 0 deletions
diff --git a/target/linux/mediatek/patches-4.14/0157-mmc-mediatek-add-support-of-source_cg-clock.patch b/target/linux/mediatek/patches-4.14/0157-mmc-mediatek-add-support-of-source_cg-clock.patch
new file mode 100644
index 0000000000..89cb7c8617
--- /dev/null
+++ b/target/linux/mediatek/patches-4.14/0157-mmc-mediatek-add-support-of-source_cg-clock.patch
@@ -0,0 +1,90 @@
+From 3c6b94d7091f0793445f2faf777e584af643e9da Mon Sep 17 00:00:00 2001
+From: Chaotian Jing <chaotian.jing@mediatek.com>
+Date: Mon, 16 Oct 2017 09:46:36 +0800
+Subject: [PATCH 157/224] mmc: mediatek: add support of source_cg clock
+
+source clock need an independent cg to control, when doing clk mode
+switch, need gate source clock to avoid hw issue(multi-bit sync hw hang)
+
+Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
+Tested-by: Sean Wang <sean.wang@mediatek.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/mtk-sd.c | 23 ++++++++++++++++++++++-
+ 1 file changed, 22 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
+index 94d16a3a8d94..a2f26c9b17b4 100644
+--- a/drivers/mmc/host/mtk-sd.c
++++ b/drivers/mmc/host/mtk-sd.c
+@@ -372,6 +372,7 @@ struct msdc_host {
+
+ struct clk *src_clk; /* msdc source clock */
+ struct clk *h_clk; /* msdc h_clk */
++ struct clk *src_clk_cg; /* msdc source clock control gate */
+ u32 mclk; /* mmc subsystem clock frequency */
+ u32 src_clk_freq; /* source clock frequency */
+ u32 sclk; /* SD/MS bus clock frequency */
+@@ -616,6 +617,7 @@ static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
+
+ static void msdc_gate_clock(struct msdc_host *host)
+ {
++ clk_disable_unprepare(host->src_clk_cg);
+ clk_disable_unprepare(host->src_clk);
+ clk_disable_unprepare(host->h_clk);
+ }
+@@ -624,6 +626,7 @@ static void msdc_ungate_clock(struct msdc_host *host)
+ {
+ clk_prepare_enable(host->h_clk);
+ clk_prepare_enable(host->src_clk);
++ clk_prepare_enable(host->src_clk_cg);
+ while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
+ cpu_relax();
+ }
+@@ -692,6 +695,15 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
+ sclk = (host->src_clk_freq >> 2) / div;
+ }
+ }
++ sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
++ /*
++ * As src_clk/HCLK use the same bit to gate/ungate,
++ * So if want to only gate src_clk, need gate its parent(mux).
++ */
++ if (host->src_clk_cg)
++ clk_disable_unprepare(host->src_clk_cg);
++ else
++ clk_disable_unprepare(clk_get_parent(host->src_clk));
+ if (host->dev_comp->clk_div_bits == 8)
+ sdr_set_field(host->base + MSDC_CFG,
+ MSDC_CFG_CKMOD | MSDC_CFG_CKDIV,
+@@ -700,10 +712,14 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
+ sdr_set_field(host->base + MSDC_CFG,
+ MSDC_CFG_CKMOD_EXTRA | MSDC_CFG_CKDIV_EXTRA,
+ (mode << 12) | div);
++ if (host->src_clk_cg)
++ clk_prepare_enable(host->src_clk_cg);
++ else
++ clk_prepare_enable(clk_get_parent(host->src_clk));
+
+- sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
+ while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
+ cpu_relax();
++ sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
+ host->sclk = sclk;
+ host->mclk = hz;
+ host->timing = timing;
+@@ -1822,6 +1838,11 @@ static int msdc_drv_probe(struct platform_device *pdev)
+ goto host_free;
+ }
+
++ /*source clock control gate is optional clock*/
++ host->src_clk_cg = devm_clk_get(&pdev->dev, "source_cg");
++ if (IS_ERR(host->src_clk_cg))
++ host->src_clk_cg = NULL;
++
+ host->irq = platform_get_irq(pdev, 0);
+ if (host->irq < 0) {
+ ret = -EINVAL;
+--
+2.11.0
+