kernel: bump 4.14 to 4.14.52 for 18.06
[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 --- a/drivers/mmc/host/mtk-sd.c
17 +++ b/drivers/mmc/host/mtk-sd.c
18 @@ -372,6 +372,7 @@ struct msdc_host {
19
20 struct clk *src_clk; /* msdc source clock */
21 struct clk *h_clk; /* msdc h_clk */
22 + struct clk *src_clk_cg; /* msdc source clock control gate */
23 u32 mclk; /* mmc subsystem clock frequency */
24 u32 src_clk_freq; /* source clock frequency */
25 u32 sclk; /* SD/MS bus clock frequency */
26 @@ -616,6 +617,7 @@ static void msdc_set_timeout(struct msdc
27
28 static void msdc_gate_clock(struct msdc_host *host)
29 {
30 + clk_disable_unprepare(host->src_clk_cg);
31 clk_disable_unprepare(host->src_clk);
32 clk_disable_unprepare(host->h_clk);
33 }
34 @@ -624,6 +626,7 @@ static void msdc_ungate_clock(struct msd
35 {
36 clk_prepare_enable(host->h_clk);
37 clk_prepare_enable(host->src_clk);
38 + clk_prepare_enable(host->src_clk_cg);
39 while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
40 cpu_relax();
41 }
42 @@ -692,6 +695,15 @@ static void msdc_set_mclk(struct msdc_ho
43 sclk = (host->src_clk_freq >> 2) / div;
44 }
45 }
46 + sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
47 + /*
48 + * As src_clk/HCLK use the same bit to gate/ungate,
49 + * So if want to only gate src_clk, need gate its parent(mux).
50 + */
51 + if (host->src_clk_cg)
52 + clk_disable_unprepare(host->src_clk_cg);
53 + else
54 + clk_disable_unprepare(clk_get_parent(host->src_clk));
55 if (host->dev_comp->clk_div_bits == 8)
56 sdr_set_field(host->base + MSDC_CFG,
57 MSDC_CFG_CKMOD | MSDC_CFG_CKDIV,
58 @@ -700,10 +712,14 @@ static void msdc_set_mclk(struct msdc_ho
59 sdr_set_field(host->base + MSDC_CFG,
60 MSDC_CFG_CKMOD_EXTRA | MSDC_CFG_CKDIV_EXTRA,
61 (mode << 12) | div);
62 + if (host->src_clk_cg)
63 + clk_prepare_enable(host->src_clk_cg);
64 + else
65 + clk_prepare_enable(clk_get_parent(host->src_clk));
66
67 - sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
68 while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
69 cpu_relax();
70 + sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
71 host->sclk = sclk;
72 host->mclk = hz;
73 host->timing = timing;
74 @@ -1822,6 +1838,11 @@ static int msdc_drv_probe(struct platfor
75 goto host_free;
76 }
77
78 + /*source clock control gate is optional clock*/
79 + host->src_clk_cg = devm_clk_get(&pdev->dev, "source_cg");
80 + if (IS_ERR(host->src_clk_cg))
81 + host->src_clk_cg = NULL;
82 +
83 host->irq = platform_get_irq(pdev, 0);
84 if (host->irq < 0) {
85 ret = -EINVAL;