kernel: bump 4.14 to 4.14.125 (FS#2305 FS#2297)
[oweals/openwrt.git] / target / linux / mediatek / patches-4.14 / 0188-usb-mtu3-supports-remote-wakeup-for-mt2712-with-two-.patch
1 From 354655aaf0f71ce2b567cbc02afb0664c99e434e Mon Sep 17 00:00:00 2001
2 From: Chunfeng Yun <chunfeng.yun@mediatek.com>
3 Date: Wed, 3 Jan 2018 16:53:18 +0800
4 Subject: [PATCH 188/224] usb: mtu3: supports remote wakeup for mt2712 with two
5  SSUSB IPs
6
7 The old way of usb wakeup only supports platform with single SSUSB IP,
8 such as mt8173, but mt2712 has two SSUSB IPs, so rebuild its flow and
9 also supports the new glue layer of usb wakeup on mt2712 which is
10 different from mt8173.
11
12 Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
13 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
14 ---
15  drivers/usb/mtu3/mtu3.h      |  11 +++--
16  drivers/usb/mtu3/mtu3_dr.h   |   3 +-
17  drivers/usb/mtu3/mtu3_host.c | 115 +++++++++++++++++++++----------------------
18  drivers/usb/mtu3/mtu3_plat.c |   8 +--
19  4 files changed, 70 insertions(+), 67 deletions(-)
20
21 --- a/drivers/usb/mtu3/mtu3.h
22 +++ b/drivers/usb/mtu3/mtu3.h
23 @@ -238,7 +238,10 @@ struct otg_switch_mtk {
24   * @u3p_dis_msk: mask of disabling usb3 ports, for example, bit0==1 to
25   *             disable u3port0, bit1==1 to disable u3port1,... etc
26   * @dbgfs_root: only used when supports manual dual-role switch via debugfs
27 - * @wakeup_en: it's true when supports remote wakeup in host mode
28 + * @uwk_en: it's true when supports remote wakeup in host mode
29 + * @uwk: syscon including usb wakeup glue layer between SSUSB IP and SPM
30 + * @uwk_reg_base: the base address of the wakeup glue layer in @uwk
31 + * @uwk_vers: the version of the wakeup glue layer
32   */
33  struct ssusb_mtk {
34         struct device *dev;
35 @@ -262,8 +265,10 @@ struct ssusb_mtk {
36         int u3p_dis_msk;
37         struct dentry *dbgfs_root;
38         /* usb wakeup for host mode */
39 -       bool wakeup_en;
40 -       struct regmap *pericfg;
41 +       bool uwk_en;
42 +       struct regmap *uwk;
43 +       u32 uwk_reg_base;
44 +       u32 uwk_vers;
45  };
46  
47  /**
48 --- a/drivers/usb/mtu3/mtu3_dr.h
49 +++ b/drivers/usb/mtu3/mtu3_dr.h
50 @@ -27,8 +27,7 @@ int ssusb_wakeup_of_property_parse(struc
51                                 struct device_node *dn);
52  int ssusb_host_enable(struct ssusb_mtk *ssusb);
53  int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend);
54 -int ssusb_wakeup_enable(struct ssusb_mtk *ssusb);
55 -void ssusb_wakeup_disable(struct ssusb_mtk *ssusb);
56 +void ssusb_wakeup_set(struct ssusb_mtk *ssusb, bool enable);
57  
58  #else
59  
60 --- a/drivers/usb/mtu3/mtu3_host.c
61 +++ b/drivers/usb/mtu3/mtu3_host.c
62 @@ -27,66 +27,77 @@
63  #include "mtu3.h"
64  #include "mtu3_dr.h"
65  
66 -#define PERI_WK_CTRL1          0x404
67 -#define UWK_CTL1_IS_C(x)       (((x) & 0xf) << 26)
68 -#define UWK_CTL1_IS_E          BIT(25)
69 -#define UWK_CTL1_IDDIG_C(x)    (((x) & 0xf) << 11)  /* cycle debounce */
70 -#define UWK_CTL1_IDDIG_E       BIT(10) /* enable debounce */
71 -#define UWK_CTL1_IDDIG_P       BIT(9)  /* polarity */
72 -#define UWK_CTL1_IS_P          BIT(6)  /* polarity for ip sleep */
73 +/* mt8173 etc */
74 +#define PERI_WK_CTRL1  0x4
75 +#define WC1_IS_C(x)    (((x) & 0xf) << 26)  /* cycle debounce */
76 +#define WC1_IS_EN      BIT(25)
77 +#define WC1_IS_P       BIT(6)  /* polarity for ip sleep */
78 +
79 +/* mt2712 etc */
80 +#define PERI_SSUSB_SPM_CTRL    0x0
81 +#define SSC_IP_SLEEP_EN        BIT(4)
82 +#define SSC_SPM_INT_EN         BIT(1)
83 +
84 +enum ssusb_uwk_vers {
85 +       SSUSB_UWK_V1 = 1,
86 +       SSUSB_UWK_V2,
87 +};
88  
89  /*
90   * ip-sleep wakeup mode:
91   * all clocks can be turn off, but power domain should be kept on
92   */
93 -static void ssusb_wakeup_ip_sleep_en(struct ssusb_mtk *ssusb)
94 +static void ssusb_wakeup_ip_sleep_set(struct ssusb_mtk *ssusb, bool enable)
95  {
96 -       u32 tmp;
97 -       struct regmap *pericfg = ssusb->pericfg;
98 +       u32 reg, msk, val;
99  
100 -       regmap_read(pericfg, PERI_WK_CTRL1, &tmp);
101 -       tmp &= ~UWK_CTL1_IS_P;
102 -       tmp &= ~(UWK_CTL1_IS_C(0xf));
103 -       tmp |= UWK_CTL1_IS_C(0x8);
104 -       regmap_write(pericfg, PERI_WK_CTRL1, tmp);
105 -       regmap_write(pericfg, PERI_WK_CTRL1, tmp | UWK_CTL1_IS_E);
106 -
107 -       regmap_read(pericfg, PERI_WK_CTRL1, &tmp);
108 -       dev_dbg(ssusb->dev, "%s(): WK_CTRL1[P6,E25,C26:29]=%#x\n",
109 -               __func__, tmp);
110 -}
111 -
112 -static void ssusb_wakeup_ip_sleep_dis(struct ssusb_mtk *ssusb)
113 -{
114 -       u32 tmp;
115 -
116 -       regmap_read(ssusb->pericfg, PERI_WK_CTRL1, &tmp);
117 -       tmp &= ~UWK_CTL1_IS_E;
118 -       regmap_write(ssusb->pericfg, PERI_WK_CTRL1, tmp);
119 +       switch (ssusb->uwk_vers) {
120 +       case SSUSB_UWK_V1:
121 +               reg = ssusb->uwk_reg_base + PERI_WK_CTRL1;
122 +               msk = WC1_IS_EN | WC1_IS_C(0xf) | WC1_IS_P;
123 +               val = enable ? (WC1_IS_EN | WC1_IS_C(0x8)) : 0;
124 +               break;
125 +       case SSUSB_UWK_V2:
126 +               reg = ssusb->uwk_reg_base + PERI_SSUSB_SPM_CTRL;
127 +               msk = SSC_IP_SLEEP_EN | SSC_SPM_INT_EN;
128 +               val = enable ? msk : 0;
129 +               break;
130 +       default:
131 +               return;
132 +       };
133 +       regmap_update_bits(ssusb->uwk, reg, msk, val);
134  }
135  
136  int ssusb_wakeup_of_property_parse(struct ssusb_mtk *ssusb,
137                                 struct device_node *dn)
138  {
139 -       struct device *dev = ssusb->dev;
140 +       struct of_phandle_args args;
141 +       int ret;
142  
143 -       /*
144 -        * Wakeup function is optional, so it is not an error if this property
145 -        * does not exist, and in such case, no need to get relative
146 -        * properties anymore.
147 -        */
148 -       ssusb->wakeup_en = of_property_read_bool(dn, "mediatek,enable-wakeup");
149 -       if (!ssusb->wakeup_en)
150 +       /* wakeup function is optional */
151 +       ssusb->uwk_en = of_property_read_bool(dn, "wakeup-source");
152 +       if (!ssusb->uwk_en)
153                 return 0;
154  
155 -       ssusb->pericfg = syscon_regmap_lookup_by_phandle(dn,
156 -                                               "mediatek,syscon-wakeup");
157 -       if (IS_ERR(ssusb->pericfg)) {
158 -               dev_err(dev, "fail to get pericfg regs\n");
159 -               return PTR_ERR(ssusb->pericfg);
160 -       }
161 +       ret = of_parse_phandle_with_fixed_args(dn,
162 +                               "mediatek,syscon-wakeup", 2, 0, &args);
163 +       if (ret)
164 +               return ret;
165  
166 -       return 0;
167 +       ssusb->uwk_reg_base = args.args[0];
168 +       ssusb->uwk_vers = args.args[1];
169 +       ssusb->uwk = syscon_node_to_regmap(args.np);
170 +       of_node_put(args.np);
171 +       dev_info(ssusb->dev, "uwk - reg:0x%x, version:%d\n",
172 +                       ssusb->uwk_reg_base, ssusb->uwk_vers);
173 +
174 +       return PTR_ERR_OR_ZERO(ssusb->uwk);
175 +}
176 +
177 +void ssusb_wakeup_set(struct ssusb_mtk *ssusb, bool enable)
178 +{
179 +       if (ssusb->uwk_en)
180 +               ssusb_wakeup_ip_sleep_set(ssusb, enable);
181  }
182  
183  static void host_ports_num_get(struct ssusb_mtk *ssusb)
184 @@ -244,17 +255,3 @@ void ssusb_host_exit(struct ssusb_mtk *s
185         of_platform_depopulate(ssusb->dev);
186         ssusb_host_cleanup(ssusb);
187  }
188 -
189 -int ssusb_wakeup_enable(struct ssusb_mtk *ssusb)
190 -{
191 -       if (ssusb->wakeup_en)
192 -               ssusb_wakeup_ip_sleep_en(ssusb);
193 -
194 -       return 0;
195 -}
196 -
197 -void ssusb_wakeup_disable(struct ssusb_mtk *ssusb)
198 -{
199 -       if (ssusb->wakeup_en)
200 -               ssusb_wakeup_ip_sleep_dis(ssusb);
201 -}
202 --- a/drivers/usb/mtu3/mtu3_plat.c
203 +++ b/drivers/usb/mtu3/mtu3_plat.c
204 @@ -291,8 +291,10 @@ static int get_ssusb_rscs(struct platfor
205  
206         /* if host role is supported */
207         ret = ssusb_wakeup_of_property_parse(ssusb, node);
208 -       if (ret)
209 +       if (ret) {
210 +               dev_err(dev, "failed to parse uwk property\n");
211                 return ret;
212 +       }
213  
214         /* optional property, ignore the error if it does not exist */
215         of_property_read_u32(node, "mediatek,u3p-dis-msk",
216 @@ -466,7 +468,7 @@ static int __maybe_unused mtu3_suspend(s
217         ssusb_host_disable(ssusb, true);
218         ssusb_phy_power_off(ssusb);
219         ssusb_clks_disable(ssusb);
220 -       ssusb_wakeup_enable(ssusb);
221 +       ssusb_wakeup_set(ssusb, true);
222  
223         return 0;
224  }
225 @@ -482,7 +484,7 @@ static int __maybe_unused mtu3_resume(st
226         if (!ssusb->is_host)
227                 return 0;
228  
229 -       ssusb_wakeup_disable(ssusb);
230 +       ssusb_wakeup_set(ssusb, false);
231         ret = ssusb_clks_enable(ssusb);
232         if (ret)
233                 goto clks_err;