mediatek: backport upstream mediatek patches
[openwrt/openwrt.git] / target / linux / mediatek / patches-4.14 / 0157-mmc-mediatek-add-support-of-source_cg-clock.patch
1 From 3c6b94d7091f0793445f2faf777e584af643e9da Mon Sep 17 00:00:00 2001
2 From: Chaotian Jing <chaotian.jing@mediatek.com>
3 Date: Mon, 16 Oct 2017 09:46:36 +0800
4 Subject: [PATCH 157/224] mmc: mediatek: add support of source_cg clock
5
6 source clock need an independent cg to control, when doing clk mode
7 switch, need gate source clock to avoid hw issue(multi-bit sync hw hang)
8
9 Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
10 Tested-by: Sean Wang <sean.wang@mediatek.com>
11 Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
12 ---
13 drivers/mmc/host/mtk-sd.c | 23 ++++++++++++++++++++++-
14 1 file changed, 22 insertions(+), 1 deletion(-)
15
16 diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
17 index 94d16a3a8d94..a2f26c9b17b4 100644
18 --- a/drivers/mmc/host/mtk-sd.c
19 +++ b/drivers/mmc/host/mtk-sd.c
20 @@ -372,6 +372,7 @@ struct msdc_host {
21
22 struct clk *src_clk; /* msdc source clock */
23 struct clk *h_clk; /* msdc h_clk */
24 + struct clk *src_clk_cg; /* msdc source clock control gate */
25 u32 mclk; /* mmc subsystem clock frequency */
26 u32 src_clk_freq; /* source clock frequency */
27 u32 sclk; /* SD/MS bus clock frequency */
28 @@ -616,6 +617,7 @@ static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
29
30 static void msdc_gate_clock(struct msdc_host *host)
31 {
32 + clk_disable_unprepare(host->src_clk_cg);
33 clk_disable_unprepare(host->src_clk);
34 clk_disable_unprepare(host->h_clk);
35 }
36 @@ -624,6 +626,7 @@ static void msdc_ungate_clock(struct msdc_host *host)
37 {
38 clk_prepare_enable(host->h_clk);
39 clk_prepare_enable(host->src_clk);
40 + clk_prepare_enable(host->src_clk_cg);
41 while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
42 cpu_relax();
43 }
44 @@ -692,6 +695,15 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
45 sclk = (host->src_clk_freq >> 2) / div;
46 }
47 }
48 + sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
49 + /*
50 + * As src_clk/HCLK use the same bit to gate/ungate,
51 + * So if want to only gate src_clk, need gate its parent(mux).
52 + */
53 + if (host->src_clk_cg)
54 + clk_disable_unprepare(host->src_clk_cg);
55 + else
56 + clk_disable_unprepare(clk_get_parent(host->src_clk));
57 if (host->dev_comp->clk_div_bits == 8)
58 sdr_set_field(host->base + MSDC_CFG,
59 MSDC_CFG_CKMOD | MSDC_CFG_CKDIV,
60 @@ -700,10 +712,14 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
61 sdr_set_field(host->base + MSDC_CFG,
62 MSDC_CFG_CKMOD_EXTRA | MSDC_CFG_CKDIV_EXTRA,
63 (mode << 12) | div);
64 + if (host->src_clk_cg)
65 + clk_prepare_enable(host->src_clk_cg);
66 + else
67 + clk_prepare_enable(clk_get_parent(host->src_clk));
68
69 - sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
70 while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
71 cpu_relax();
72 + sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
73 host->sclk = sclk;
74 host->mclk = hz;
75 host->timing = timing;
76 @@ -1822,6 +1838,11 @@ static int msdc_drv_probe(struct platform_device *pdev)
77 goto host_free;
78 }
79
80 + /*source clock control gate is optional clock*/
81 + host->src_clk_cg = devm_clk_get(&pdev->dev, "source_cg");
82 + if (IS_ERR(host->src_clk_cg))
83 + host->src_clk_cg = NULL;
84 +
85 host->irq = platform_get_irq(pdev, 0);
86 if (host->irq < 0) {
87 ret = -EINVAL;
88 --
89 2.11.0
90