kernel: bump 4.14 to 4.14.161
[oweals/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 @@ -374,6 +374,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 @@ -618,6 +619,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 @@ -626,6 +628,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 @@ -694,6 +697,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 @@ -702,10 +714,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 @@ -1825,6 +1841,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;