hc
2023-11-06 e3e12f52b214121840b44c91de5b3e5af5d3eb84
kernel/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
....@@ -59,6 +59,7 @@
5959 PHY_STATE_DISCONNECT = 1,
6060 PHY_STATE_CONNECT = 2,
6161 PHY_STATE_FS_LS_ONLINE = 4,
62
+ PHY_STATE_SE1 = 6,
6263 };
6364
6465 /**
....@@ -158,6 +159,7 @@
158159 * @utmi_ls: utmi linestate state register.
159160 * @utmi_hstdet: utmi host disconnect register.
160161 * @vbus_det_en: vbus detect function power down register.
162
+ * @port_ls_filter_con: set linestate filter time for otg port or host port.
161163 */
162164 struct rockchip_usb2phy_port_cfg {
163165 struct usb2phy_reg phy_sus;
....@@ -188,6 +190,7 @@
188190 struct usb2phy_reg utmi_ls;
189191 struct usb2phy_reg utmi_hstdet;
190192 struct usb2phy_reg vbus_det_en;
193
+ struct usb2phy_reg port_ls_filter_con;
191194 };
192195
193196 /**
....@@ -196,7 +199,9 @@
196199 * @num_ports: specify how many ports that the phy has.
197200 * @phy_tuning: phy default parameters tunning.
198201 * @vbus_detect: vbus voltage level detection function.
199
- * @clkout_ctl: keep on/turn off output clk of phy.
202
+ * @clkout_ctl: keep on/turn off output clk of phy via commonon bit.
203
+ * @clkout_ctl_phy: keep on/turn off output clk of phy via phy inner
204
+ * debug register.
200205 * @ls_filter_con: set linestate filter time.
201206 * @chg_det: charger detection registers.
202207 */
....@@ -204,8 +209,11 @@
204209 unsigned int reg;
205210 unsigned int num_ports;
206211 int (*phy_tuning)(struct rockchip_usb2phy *);
207
- int (*vbus_detect)(struct rockchip_usb2phy *rphy, bool en);
212
+ int (*vbus_detect)(struct rockchip_usb2phy *rphy,
213
+ const struct usb2phy_reg *vbus_det_en,
214
+ bool en);
208215 struct usb2phy_reg clkout_ctl;
216
+ struct usb2phy_reg clkout_ctl_phy;
209217 struct usb2phy_reg ls_filter_con;
210218 const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS];
211219 const struct rockchip_chg_det_reg chg_det;
....@@ -253,6 +261,7 @@
253261 bool vbus_always_on;
254262 bool vbus_enabled;
255263 bool bypass_uart_en;
264
+ bool dis_u2_susphy;
256265 int bvalid_irq;
257266 int ls_irq;
258267 int id_irq;
....@@ -275,9 +284,10 @@
275284 * @grf: General Register Files regmap.
276285 * @usbgrf: USB General Register Files regmap.
277286 * *phy_base: the base address of USB PHY.
278
- * @clk: clock struct of phy input clk.
287
+ * @clks: array of phy input clocks.
279288 * @clk480m: clock struct of phy output clk.
280289 * @clk_hw: clock struct of phy output clk management.
290
+ * @num_clks: number of phy input clocks.
281291 * @chg_state: states involved in USB charger detection.
282292 * @chg_type: USB charger types.
283293 * @dcd_retries: The retry count used to track Data contact
....@@ -297,9 +307,10 @@
297307 struct regmap *grf;
298308 struct regmap *usbgrf;
299309 void __iomem *phy_base;
300
- struct clk *clk;
310
+ struct clk_bulk_data *clks;
301311 struct clk *clk480m;
302312 struct clk_hw clk480m_hw;
313
+ int num_clks;
303314 enum usb_chg_state chg_state;
304315 enum power_supply_type chg_type;
305316 u8 dcd_retries;
....@@ -344,6 +355,29 @@
344355 return tmp == reg->enable;
345356 }
346357
358
+static inline void phy_property_enable(void __iomem *base,
359
+ const struct usb2phy_reg *reg, bool en)
360
+{
361
+ unsigned int val, tmp;
362
+
363
+ val = readl(base + reg->offset);
364
+ tmp = en ? reg->enable : reg->disable;
365
+ val &= ~GENMASK(reg->bitend, reg->bitstart);
366
+ val |= tmp << reg->bitstart;
367
+ writel(val, base + reg->offset);
368
+}
369
+
370
+static inline bool phy_property_enabled(void __iomem *base,
371
+ const struct usb2phy_reg *reg)
372
+{
373
+ unsigned int orig, tmp;
374
+ unsigned int mask = GENMASK(reg->bitend, reg->bitstart);
375
+
376
+ orig = readl(base + reg->offset);
377
+ tmp = (orig & mask) >> reg->bitstart;
378
+ return tmp == reg->enable;
379
+}
380
+
347381 static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
348382 {
349383 struct rockchip_usb2phy *rphy =
....@@ -352,7 +386,14 @@
352386 int ret;
353387
354388 /* turn on 480m clk output if it is off */
355
- if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) {
389
+ if (rphy->phy_cfg->clkout_ctl_phy.enable) {
390
+ if (!phy_property_enabled(rphy->phy_base, &rphy->phy_cfg->clkout_ctl_phy)) {
391
+ phy_property_enable(rphy->phy_base, &rphy->phy_cfg->clkout_ctl_phy, true);
392
+
393
+ /* waiting for the clk become stable */
394
+ usleep_range(1200, 1300);
395
+ }
396
+ } else if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) {
356397 ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true);
357398 if (ret)
358399 return ret;
....@@ -371,7 +412,10 @@
371412 struct regmap *base = get_reg_base(rphy);
372413
373414 /* turn off 480m clk output */
374
- property_enable(base, &rphy->phy_cfg->clkout_ctl, false);
415
+ if (rphy->phy_cfg->clkout_ctl_phy.enable)
416
+ phy_property_enable(rphy->phy_base, &rphy->phy_cfg->clkout_ctl_phy, false);
417
+ else
418
+ property_enable(base, &rphy->phy_cfg->clkout_ctl, false);
375419 }
376420
377421 static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw)
....@@ -380,7 +424,10 @@
380424 container_of(hw, struct rockchip_usb2phy, clk480m_hw);
381425 struct regmap *base = get_reg_base(rphy);
382426
383
- return property_enabled(base, &rphy->phy_cfg->clkout_ctl);
427
+ if (rphy->phy_cfg->clkout_ctl_phy.enable)
428
+ return phy_property_enabled(rphy->phy_base, &rphy->phy_cfg->clkout_ctl_phy);
429
+ else
430
+ return property_enabled(base, &rphy->phy_cfg->clkout_ctl);
384431 }
385432
386433 static unsigned long
....@@ -410,6 +457,7 @@
410457 {
411458 struct device_node *node = rphy->dev->of_node;
412459 struct clk_init_data init = {};
460
+ struct clk *refclk = of_clk_get_by_name(node, "phyclk");
413461 const char *clk_name;
414462 int ret;
415463
....@@ -420,8 +468,8 @@
420468 /* optional override of the clockname */
421469 of_property_read_string(node, "clock-output-names", &init.name);
422470
423
- if (rphy->clk) {
424
- clk_name = __clk_get_name(rphy->clk);
471
+ if (!IS_ERR(refclk)) {
472
+ clk_name = __clk_get_name(refclk);
425473 init.parent_names = &clk_name;
426474 init.num_parents = 1;
427475 } else {
....@@ -855,7 +903,8 @@
855903 }
856904
857905 if (rphy->phy_cfg->vbus_detect)
858
- rphy->phy_cfg->vbus_detect(rphy, vbus_det_en);
906
+ rphy->phy_cfg->vbus_detect(rphy, &rport->port_cfg->vbus_det_en,
907
+ vbus_det_en);
859908 else
860909 ret = property_enable(rphy->grf, &rport->port_cfg->vbus_det_en,
861910 vbus_det_en);
....@@ -1029,7 +1078,8 @@
10291078 rport->state = OTG_STATE_B_IDLE;
10301079 if (!rport->vbus_attached) {
10311080 mutex_unlock(&rport->mutex);
1032
- rockchip_usb2phy_power_off(rport->phy);
1081
+ if (!rport->dis_u2_susphy)
1082
+ rockchip_usb2phy_power_off(rport->phy);
10331083 mutex_lock(&rport->mutex);
10341084 }
10351085 /* fall through */
....@@ -1090,7 +1140,8 @@
10901140 rphy->chg_state = USB_CHG_STATE_UNDEFINED;
10911141 rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
10921142 mutex_unlock(&rport->mutex);
1093
- rockchip_usb2phy_power_off(rport->phy);
1143
+ if (!rport->dis_u2_susphy)
1144
+ rockchip_usb2phy_power_off(rport->phy);
10941145 mutex_lock(&rport->mutex);
10951146 }
10961147 break;
....@@ -1434,6 +1485,15 @@
14341485 dev_dbg(&rport->phy->dev, "FS/LS online\n");
14351486 }
14361487 break;
1488
+ case PHY_STATE_SE1:
1489
+ if (rport->suspended) {
1490
+ dev_dbg(&rport->phy->dev, "linestate is SE1, power on phy\n");
1491
+ mutex_unlock(&rport->mutex);
1492
+ rockchip_usb2phy_power_on(rport->phy);
1493
+ mutex_lock(&rport->mutex);
1494
+ rport->suspended = false;
1495
+ }
1496
+ break;
14371497 case PHY_STATE_DISCONNECT:
14381498 if (!rport->suspended) {
14391499 dev_dbg(&rport->phy->dev, "Disconnected\n");
....@@ -1764,6 +1824,11 @@
17641824 return NOTIFY_DONE;
17651825 }
17661826
1827
+static void rockchip_otg_wake_lock_destroy(void *data)
1828
+{
1829
+ wake_lock_destroy((struct wake_lock *)(data));
1830
+}
1831
+
17671832 static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
17681833 struct rockchip_usb2phy_port *rport,
17691834 struct device_node *child_np)
....@@ -1789,6 +1854,8 @@
17891854 of_property_read_bool(child_np, "rockchip,vbus-always-on");
17901855 rport->utmi_avalid =
17911856 of_property_read_bool(child_np, "rockchip,utmi-avalid");
1857
+ rport->dis_u2_susphy =
1858
+ of_property_read_bool(child_np, "rockchip,dis-u2-susphy");
17921859
17931860 /* enter lower power state when suspend */
17941861 rport->low_power_en =
....@@ -1833,6 +1900,11 @@
18331900 property_enable(base, &rport->port_cfg->bvalid_set, false);
18341901
18351902 wake_lock_init(&rport->wakelock, WAKE_LOCK_SUSPEND, "rockchip_otg");
1903
+ ret = devm_add_action_or_reset(rphy->dev, rockchip_otg_wake_lock_destroy,
1904
+ &rport->wakelock);
1905
+ if (ret)
1906
+ return ret;
1907
+
18361908 INIT_DELAYED_WORK(&rport->bypass_uart_work,
18371909 rockchip_usb_bypass_uart_work);
18381910 INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work);
....@@ -1845,7 +1917,7 @@
18451917 EXTCON_USB_HOST, &rport->event_nb);
18461918 if (ret) {
18471919 dev_err(rphy->dev, "register USB HOST notifier failed\n");
1848
- goto err;
1920
+ return ret;
18491921 }
18501922 }
18511923
....@@ -1861,10 +1933,6 @@
18611933 rport->suspended = true;
18621934
18631935 return 0;
1864
-
1865
-err:
1866
- wake_lock_destroy(&rport->wakelock);
1867
- return ret;
18681936 }
18691937
18701938 static int rockchip_usb2phy_probe(struct platform_device *pdev)
....@@ -1963,13 +2031,19 @@
19632031 pm_runtime_enable(dev);
19642032 pm_runtime_get_sync(dev);
19652033
1966
- rphy->clk = of_clk_get_by_name(np, "phyclk");
1967
- if (!IS_ERR(rphy->clk)) {
1968
- clk_prepare_enable(rphy->clk);
1969
- } else {
1970
- dev_info(&pdev->dev, "no phyclk specified\n");
1971
- rphy->clk = NULL;
1972
- }
2034
+ ret = devm_clk_bulk_get_all(dev, &rphy->clks);
2035
+ if (ret == -EPROBE_DEFER)
2036
+ return ret;
2037
+
2038
+ /* Clocks are optional */
2039
+ if (ret < 0)
2040
+ rphy->num_clks = 0;
2041
+ else
2042
+ rphy->num_clks = ret;
2043
+
2044
+ ret = clk_bulk_prepare_enable(rphy->num_clks, rphy->clks);
2045
+ if (ret)
2046
+ return ret;
19732047
19742048 if (rphy->phy_cfg->phy_tuning) {
19752049 ret = rphy->phy_cfg->phy_tuning(rphy);
....@@ -2061,10 +2135,8 @@
20612135 disable_clks:
20622136 pm_runtime_put_sync(dev);
20632137 pm_runtime_disable(dev);
2064
- if (rphy->clk) {
2065
- clk_disable_unprepare(rphy->clk);
2066
- clk_put(rphy->clk);
2067
- }
2138
+ clk_bulk_disable_unprepare(rphy->num_clks, rphy->clks);
2139
+
20682140 return ret;
20692141 }
20702142
....@@ -2305,6 +2377,43 @@
23052377 return ret;
23062378 }
23072379
2380
+static int rk3528_usb2phy_tuning(struct rockchip_usb2phy *rphy)
2381
+{
2382
+ u32 reg;
2383
+ int ret = 0;
2384
+
2385
+ /* Turn off otg port differential receiver in suspend mode */
2386
+ reg = readl(rphy->phy_base + 0x30);
2387
+ writel(reg & ~BIT(2), rphy->phy_base + 0x30);
2388
+
2389
+ /* Turn off host port differential receiver in suspend mode */
2390
+ reg = readl(rphy->phy_base + 0x0430);
2391
+ writel(reg & ~BIT(2), rphy->phy_base + 0x0430);
2392
+
2393
+ /* Set otg port HS eye height to 400mv(default is 450mv) */
2394
+ reg = readl(rphy->phy_base + 0x30);
2395
+ reg &= ~GENMASK(6, 4);
2396
+ reg |= (0x00 << 4);
2397
+ writel(reg, rphy->phy_base + 0x30);
2398
+
2399
+ /* Set host port HS eye height to 400mv(default is 450mv) */
2400
+ reg = readl(rphy->phy_base + 0x430);
2401
+ reg &= ~GENMASK(6, 4);
2402
+ reg |= (0x00 << 4);
2403
+ writel(reg, rphy->phy_base + 0x430);
2404
+
2405
+ /* Choose the Tx fs/ls data as linestate from TX driver for otg port */
2406
+ reg = readl(rphy->phy_base + 0x94);
2407
+ reg &= ~GENMASK(6, 3);
2408
+ reg |= (0x03 << 3);
2409
+ writel(reg, rphy->phy_base + 0x94);
2410
+
2411
+ /* Enable otg and host ports phy irq to pmu wakeup source */
2412
+ ret |= regmap_write(rphy->grf, 0x80004, 0x00030003);
2413
+
2414
+ return ret;
2415
+}
2416
+
23082417 static int rk3568_usb2phy_tuning(struct rockchip_usb2phy *rphy)
23092418 {
23102419 u32 reg;
....@@ -2352,18 +2461,20 @@
23522461 return ret;
23532462 }
23542463
2355
-static int rk3568_vbus_detect_control(struct rockchip_usb2phy *rphy, bool en)
2464
+static int rockchip_usb2phy_vbus_det_control(struct rockchip_usb2phy *rphy,
2465
+ const struct usb2phy_reg *vbus_det_en,
2466
+ bool en)
23562467 {
23572468 u32 reg;
23582469
23592470 if (en) {
2360
- reg = readl(rphy->phy_base + 0x3c);
2471
+ reg = readl(rphy->phy_base + vbus_det_en->offset);
23612472 /* Enable vbus voltage level detection function */
2362
- writel(reg & ~BIT(7), rphy->phy_base + 0x3c);
2473
+ writel(reg & ~BIT(7), rphy->phy_base + vbus_det_en->offset);
23632474 } else {
2364
- reg = readl(rphy->phy_base + 0x3c);
2475
+ reg = readl(rphy->phy_base + vbus_det_en->offset);
23652476 /* Disable vbus voltage level detection function */
2366
- writel(reg | BIT(7), rphy->phy_base + 0x3c);
2477
+ writel(reg | BIT(7), rphy->phy_base + vbus_det_en->offset);
23672478 }
23682479
23692480 return 0;
....@@ -2397,6 +2508,14 @@
23972508 rport = &rphy->ports[index];
23982509 if (!rport->phy)
23992510 continue;
2511
+
2512
+ if (rport->port_cfg->port_ls_filter_con.enable) {
2513
+ ret = regmap_write(rphy->grf,
2514
+ rport->port_cfg->port_ls_filter_con.offset,
2515
+ rport->port_cfg->port_ls_filter_con.enable);
2516
+ if (ret)
2517
+ dev_err(rphy->dev, "failed to set port ls filter %d\n", ret);
2518
+ }
24002519
24012520 if (rport->port_id == USB2PHY_PORT_OTG &&
24022521 (rport->id_irq > 0 || rphy->irq > 0)) {
....@@ -2466,6 +2585,14 @@
24662585 rport = &rphy->ports[index];
24672586 if (!rport->phy)
24682587 continue;
2588
+
2589
+ if (rport->port_cfg->port_ls_filter_con.disable) {
2590
+ ret = regmap_write(rphy->grf,
2591
+ rport->port_cfg->port_ls_filter_con.offset,
2592
+ rport->port_cfg->port_ls_filter_con.disable);
2593
+ if (ret)
2594
+ dev_err(rphy->dev, "failed to set port ls filter %d\n", ret);
2595
+ }
24692596
24702597 if (rport->port_id == USB2PHY_PORT_OTG &&
24712598 (rport->id_irq > 0 || rphy->irq > 0)) {
....@@ -2988,12 +3115,69 @@
29883115 { /* sentinel */ }
29893116 };
29903117
3118
+static const struct rockchip_usb2phy_cfg rk3528_phy_cfgs[] = {
3119
+ {
3120
+ .reg = 0xffdf0000,
3121
+ .num_ports = 2,
3122
+ .phy_tuning = rk3528_usb2phy_tuning,
3123
+ .vbus_detect = rockchip_usb2phy_vbus_det_control,
3124
+ .clkout_ctl_phy = { 0x041c, 7, 2, 0, 0x27 },
3125
+ .port_cfgs = {
3126
+ [USB2PHY_PORT_OTG] = {
3127
+ .phy_sus = { 0x6004c, 8, 0, 0, 0x1d1 },
3128
+ .bvalid_det_en = { 0x60074, 2, 2, 0, 1 },
3129
+ .bvalid_det_st = { 0x60078, 2, 2, 0, 1 },
3130
+ .bvalid_det_clr = { 0x6007c, 2, 2, 0, 1 },
3131
+ .bvalid_set = { 0x6004c, 15, 14, 0, 3 },
3132
+ .iddig_output = { 0x6004c, 10, 10, 0, 1 },
3133
+ .iddig_en = { 0x6004c, 9, 9, 0, 1 },
3134
+ .idfall_det_en = { 0x60074, 5, 5, 0, 1 },
3135
+ .idfall_det_st = { 0x60078, 5, 5, 0, 1 },
3136
+ .idfall_det_clr = { 0x6007c, 5, 5, 0, 1 },
3137
+ .idrise_det_en = { 0x60074, 4, 4, 0, 1 },
3138
+ .idrise_det_st = { 0x60078, 4, 4, 0, 1 },
3139
+ .idrise_det_clr = { 0x6007c, 4, 4, 0, 1 },
3140
+ .ls_det_en = { 0x60074, 0, 0, 0, 1 },
3141
+ .ls_det_st = { 0x60078, 0, 0, 0, 1 },
3142
+ .ls_det_clr = { 0x6007c, 0, 0, 0, 1 },
3143
+ .utmi_avalid = { 0x6006c, 1, 1, 0, 1 },
3144
+ .utmi_bvalid = { 0x6006c, 0, 0, 0, 1 },
3145
+ .utmi_iddig = { 0x6006c, 6, 6, 0, 1 },
3146
+ .utmi_ls = { 0x6006c, 5, 4, 0, 1 },
3147
+ .vbus_det_en = { 0x003c, 7, 7, 0, 1 },
3148
+ .port_ls_filter_con = { 0x60080, 19, 0, 0x30100, 0x20 },
3149
+ },
3150
+ [USB2PHY_PORT_HOST] = {
3151
+ .phy_sus = { 0x6005c, 8, 0, 0x1d2, 0x1d1 },
3152
+ .ls_det_en = { 0x60090, 0, 0, 0, 1 },
3153
+ .ls_det_st = { 0x60094, 0, 0, 0, 1 },
3154
+ .ls_det_clr = { 0x60098, 0, 0, 0, 1 },
3155
+ .utmi_ls = { 0x6006c, 13, 12, 0, 1 },
3156
+ .utmi_hstdet = { 0x6006c, 15, 15, 0, 1 },
3157
+ .port_ls_filter_con = { 0x6009c, 19, 0, 0x30100, 0x20 },
3158
+ }
3159
+ },
3160
+ .chg_det = {
3161
+ .chg_mode = { 0x6004c, 8, 0, 0, 0x1d7 },
3162
+ .cp_det = { 0x6006c, 19, 19, 0, 1 },
3163
+ .dcp_det = { 0x6006c, 18, 18, 0, 1 },
3164
+ .dp_det = { 0x6006c, 20, 20, 0, 1 },
3165
+ .idm_sink_en = { 0x60058, 1, 1, 0, 1 },
3166
+ .idp_sink_en = { 0x60058, 0, 0, 0, 1 },
3167
+ .idp_src_en = { 0x60058, 2, 2, 0, 1 },
3168
+ .rdm_pdwn_en = { 0x60058, 3, 3, 0, 1 },
3169
+ .vdm_src_en = { 0x60058, 5, 5, 0, 1 },
3170
+ .vdp_src_en = { 0x60058, 4, 4, 0, 1 },
3171
+ },
3172
+ }
3173
+};
3174
+
29913175 static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = {
29923176 {
29933177 .reg = 0xfe8a0000,
29943178 .num_ports = 2,
29953179 .phy_tuning = rk3568_usb2phy_tuning,
2996
- .vbus_detect = rk3568_vbus_detect_control,
3180
+ .vbus_detect = rockchip_usb2phy_vbus_det_control,
29973181 .clkout_ctl = { 0x0008, 4, 4, 1, 0 },
29983182 .ls_filter_con = { 0x0040, 19, 0, 0x30100, 0x00020 },
29993183 .port_cfgs = {
....@@ -3020,6 +3204,7 @@
30203204 .utmi_bvalid = { 0x00c0, 9, 9, 0, 1 },
30213205 .utmi_iddig = { 0x00c0, 6, 6, 0, 1 },
30223206 .utmi_ls = { 0x00c0, 5, 4, 0, 1 },
3207
+ .vbus_det_en = { 0x003c, 7, 7, 0, 1 },
30233208 },
30243209 [USB2PHY_PORT_HOST] = {
30253210 /* Select suspend control from controller */
....@@ -3123,6 +3308,7 @@
31233308 { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
31243309 { .compatible = "rockchip,rk3368-usb2phy", .data = &rk3368_phy_cfgs },
31253310 { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
3311
+ { .compatible = "rockchip,rk3528-usb2phy", .data = &rk3528_phy_cfgs },
31263312 { .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs },
31273313 { .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs },
31283314 {}