hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/phy/rockchip/phy-rockchip-typec.c
....@@ -1,16 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
34 * Author: Chris Zhong <zyw@rock-chips.com>
45 * Kever Yang <kever.yang@rock-chips.com>
5
- *
6
- * This software is licensed under the terms of the GNU General Public
7
- * License version 2, as published by the Free Software Foundation, and
8
- * may be copied, distributed, and modified under those terms.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
146 *
157 * The ROCKCHIP Type-C PHY has two PLL clocks. The first PLL clock
168 * is used for USB3, the second PLL clock is used for DP. This Type-C PHY has
....@@ -42,7 +34,6 @@
4234 * This Type-C PHY driver supports normal and flip orientation. The orientation
4335 * is reported by the EXTCON_PROP_USB_TYPEC_POLARITY property: true is flip
4436 * orientation, false is normal orientation.
45
- *
4637 */
4738
4839 #include <linux/clk.h>
....@@ -60,6 +51,8 @@
6051 #include <linux/platform_device.h>
6152 #include <linux/regmap.h>
6253 #include <linux/reset.h>
54
+#include <linux/usb/typec_dp.h>
55
+#include <linux/usb/typec_mux.h>
6356
6457 #include <linux/mfd/syscon.h>
6558 #include <linux/phy/phy.h>
....@@ -393,7 +386,7 @@
393386 };
394387
395388 /**
396
- * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
389
+ * struct rockchip_usb3phy_port_cfg - usb3-phy port configuration.
397390 * @reg: the base address for usb3-phy config.
398391 * @typec_conn_dir: the register of type-c connector direction.
399392 * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
....@@ -419,22 +412,31 @@
419412 int pe;
420413 };
421414
415
+enum {
416
+ TYPEC_PHY_USB,
417
+ TYPEC_PHY_DP,
418
+ TYPEC_PHY_MAX,
419
+};
420
+
422421 struct rockchip_typec_phy {
423422 struct device *dev;
424423 void __iomem *base;
425
- struct extcon_dev *extcon;
424
+ struct typec_mux *mux;
425
+ struct typec_switch *sw;
426426 struct regmap *grf_regs;
427427 struct clk *clk_core;
428428 struct clk *clk_ref;
429429 struct reset_control *uphy_rst;
430430 struct reset_control *pipe_rst;
431431 struct reset_control *tcphy_rst;
432
+ struct phy *phys[TYPEC_PHY_MAX];
432433 const struct rockchip_usb3phy_port_cfg *port_cfgs;
433434 /* mutex to protect access to individual PHYs */
434435 struct mutex lock;
435436
436437 bool flip;
437438 u8 mode;
439
+ u8 new_mode;
438440 struct phy_config config[3][4];
439441 };
440442
....@@ -635,7 +637,6 @@
635637 };
636638
637639 enum phy_dp_power_state {
638
- PHY_DP_POWER_STATE_DISABLED = -1,
639640 PHY_DP_POWER_STATE_A0,
640641 PHY_DP_POWER_STATE_A1,
641642 PHY_DP_POWER_STATE_A2,
....@@ -843,56 +844,65 @@
843844 writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
844845 }
845846
846
-static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
847
+static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, int link_rate,
848
+ u8 swing, u8 pre_emp, u32 lane)
847849 {
850
+ u16 val;
851
+
848852 writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane));
849853 writel(0x6799, tcphy->base + TX_PSC_A0(lane));
850854 writel(0x6798, tcphy->base + TX_PSC_A1(lane));
851855 writel(0x98, tcphy->base + TX_PSC_A2(lane));
852856 writel(0x98, tcphy->base + TX_PSC_A3(lane));
857
+
858
+ writel(tcphy->config[swing][pre_emp].swing,
859
+ tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
860
+ writel(tcphy->config[swing][pre_emp].pe,
861
+ tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
862
+
863
+ if (swing == 2 && pre_emp == 0 && link_rate != 540000) {
864
+ writel(0x700, tcphy->base + TX_DIAG_TX_DRV(lane));
865
+ writel(0x13c, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
866
+ } else {
867
+ writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
868
+ writel(0x0400, tcphy->base + TX_DIAG_TX_DRV(lane));
869
+ }
870
+
871
+ val = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
872
+ val = val & 0x8fff;
873
+ switch (link_rate) {
874
+ case 540000:
875
+ val |= (5 << 12);
876
+ break;
877
+ case 162000:
878
+ case 270000:
879
+ default:
880
+ val |= (6 << 12);
881
+ break;
882
+ }
883
+ writel(val, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
853884 }
854885
855886 int tcphy_dp_set_phy_config(struct phy *phy, int link_rate,
856887 int lane_count, u8 swing, u8 pre_emp)
857888 {
858889 struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
859
- u8 i, j, lane;
860
- u32 val;
890
+ u8 i;
861891
862892 if (!phy->power_count)
863893 return -EPERM;
864894
865
- if (lane_count == 4) {
866
- i = 0;
867
- j = 3;
895
+ if (tcphy->mode == MODE_DFP_DP) {
896
+ for (i = 0; i < 4; i++)
897
+ tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, i);
868898 } else {
869899 if (tcphy->flip) {
870
- i = 0;
871
- j = 1;
900
+ tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 0);
901
+ tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 1);
872902 } else {
873
- i = 2;
874
- j = 3;
903
+ tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 2);
904
+ tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 3);
875905 }
876
- }
877
-
878
- for (lane = i; lane <= j; lane++) {
879
- writel(tcphy->config[swing][pre_emp].swing,
880
- tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
881
- writel(tcphy->config[swing][pre_emp].pe,
882
- tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
883
-
884
- if (swing == 2 && pre_emp == 0 && link_rate != 540000) {
885
- writel(0x700, tcphy->base + TX_DIAG_TX_DRV(lane));
886
- writel(0x13c, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
887
- } else {
888
- writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
889
- writel(0x0400, tcphy->base + TX_DIAG_TX_DRV(lane));
890
- }
891
-
892
- val = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
893
- val &= ~GENMASK(14, 12);
894
- val |= ((link_rate == 540000) ? 0x5 : 0x6) << 12;
895
- writel(val, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
896906 }
897907
898908 return 0;
....@@ -1277,20 +1287,20 @@
12771287 tcphy_cfg_usb3_to_usb2_only(tcphy, true);
12781288 tcphy_cfg_dp_pll(tcphy, DP_DEFAULT_RATE);
12791289 for (i = 0; i < 4; i++)
1280
- tcphy_dp_cfg_lane(tcphy, i);
1290
+ tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, i);
12811291 } else {
12821292 tcphy_cfg_usb3_pll(tcphy);
12831293 tcphy_cfg_dp_pll(tcphy, DP_DEFAULT_RATE);
12841294 if (tcphy->flip) {
12851295 tcphy_tx_usb3_cfg_lane(tcphy, 3);
12861296 tcphy_rx_usb3_cfg_lane(tcphy, 2);
1287
- tcphy_dp_cfg_lane(tcphy, 0);
1288
- tcphy_dp_cfg_lane(tcphy, 1);
1297
+ tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 0);
1298
+ tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 1);
12891299 } else {
12901300 tcphy_tx_usb3_cfg_lane(tcphy, 0);
12911301 tcphy_rx_usb3_cfg_lane(tcphy, 1);
1292
- tcphy_dp_cfg_lane(tcphy, 2);
1293
- tcphy_dp_cfg_lane(tcphy, 3);
1302
+ tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 2);
1303
+ tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 3);
12941304 }
12951305 }
12961306
....@@ -1334,50 +1344,52 @@
13341344
13351345 static int tcphy_get_mode(struct rockchip_typec_phy *tcphy)
13361346 {
1337
- struct extcon_dev *edev = tcphy->extcon;
1338
- union extcon_property_value property;
1339
- unsigned int id;
1340
- bool ufp, dp;
1341
- u8 mode;
1342
- int ret;
1347
+ return tcphy->new_mode;
1348
+}
13431349
1344
- if (!edev)
1345
- return MODE_DFP_USB;
1350
+static int tcphy_orien_sw_set(struct typec_switch *sw,
1351
+ enum typec_orientation orien)
1352
+{
1353
+ struct rockchip_typec_phy *tcphy = typec_switch_get_drvdata(sw);
13461354
1347
- ufp = extcon_get_state(edev, EXTCON_USB);
1348
- dp = extcon_get_state(edev, EXTCON_DISP_DP);
1355
+ mutex_lock(&tcphy->lock);
13491356
1350
- mode = MODE_DFP_USB;
1351
- id = EXTCON_USB_HOST;
1352
-
1353
- if (ufp) {
1354
- mode = MODE_UFP_USB;
1355
- id = EXTCON_USB;
1356
- } else if (dp) {
1357
- mode = MODE_DFP_DP;
1358
- id = EXTCON_DISP_DP;
1359
-
1360
- ret = extcon_get_property(edev, id, EXTCON_PROP_USB_SS,
1361
- &property);
1362
- if (ret) {
1363
- dev_err(tcphy->dev, "get superspeed property failed\n");
1364
- return ret;
1365
- }
1366
-
1367
- if (property.intval)
1368
- mode |= MODE_DFP_USB;
1357
+ if (orien == TYPEC_ORIENTATION_NONE) {
1358
+ tcphy->new_mode = MODE_DISCONNECT;
1359
+ goto unlock_ret;
13691360 }
13701361
1371
- ret = extcon_get_property(edev, id, EXTCON_PROP_USB_TYPEC_POLARITY,
1372
- &property);
1373
- if (ret) {
1374
- dev_err(tcphy->dev, "get polarity property failed\n");
1375
- return ret;
1362
+ tcphy->flip = (orien == TYPEC_ORIENTATION_REVERSE) ? true : false;
1363
+ tcphy->new_mode = MODE_DFP_USB;
1364
+
1365
+unlock_ret:
1366
+ mutex_unlock(&tcphy->lock);
1367
+ return 0;
1368
+}
1369
+
1370
+static int tcphy_setup_orien_switch(struct rockchip_typec_phy *tcphy)
1371
+{
1372
+ struct typec_switch_desc sw_desc = { };
1373
+
1374
+ sw_desc.drvdata = tcphy;
1375
+ sw_desc.fwnode = dev_fwnode(tcphy->dev);
1376
+ sw_desc.set = tcphy_orien_sw_set;
1377
+
1378
+ tcphy->sw = typec_switch_register(tcphy->dev, &sw_desc);
1379
+ if (IS_ERR(tcphy->sw)) {
1380
+ dev_err(tcphy->dev, "Error register typec orientation switch: %ld\n",
1381
+ PTR_ERR(tcphy->sw));
1382
+ return PTR_ERR(tcphy->sw);
13761383 }
13771384
1378
- tcphy->flip = property.intval ? 1 : 0;
1385
+ return 0;
1386
+}
13791387
1380
- return mode;
1388
+static void udphy_orien_switch_unregister(void *data)
1389
+{
1390
+ struct rockchip_typec_phy *tcphy = data;
1391
+
1392
+ typec_switch_unregister(tcphy->sw);
13811393 }
13821394
13831395 static int _rockchip_usb3_phy_power_on(struct rockchip_typec_phy *tcphy)
....@@ -1415,7 +1427,6 @@
14151427 regmap_read(tcphy->grf_regs, reg->offset, &val);
14161428 if (!(val & BIT(reg->enable_bit))) {
14171429 tcphy->mode |= new_mode & (MODE_DFP_USB | MODE_UFP_USB);
1418
-
14191430 /* enable usb3 host */
14201431 tcphy_cfg_usb3_to_usb2_only(tcphy, false);
14211432 goto unlock_ret;
....@@ -1573,6 +1584,68 @@
15731584 .owner = THIS_MODULE,
15741585 };
15751586
1587
+static int tcphy_typec_mux_set(struct typec_mux *mux, struct typec_mux_state *state)
1588
+{
1589
+ struct rockchip_typec_phy *tcphy = typec_mux_get_drvdata(mux);
1590
+ struct typec_displayport_data *data;
1591
+ int hpd = 0;
1592
+
1593
+ mutex_lock(&tcphy->lock);
1594
+
1595
+ switch (state->mode) {
1596
+ case TYPEC_STATE_SAFE:
1597
+ fallthrough;
1598
+ case TYPEC_STATE_USB:
1599
+ tcphy->new_mode = MODE_DFP_USB;
1600
+ phy_set_bus_width(tcphy->phys[TYPEC_PHY_DP], 0);
1601
+ break;
1602
+ case TYPEC_DP_STATE_C:
1603
+ case TYPEC_DP_STATE_E:
1604
+ tcphy->new_mode = MODE_DFP_DP;
1605
+ data = state->data;
1606
+ hpd = !!(data->status & DP_STATUS_HPD_STATE);
1607
+ phy_set_bus_width(tcphy->phys[TYPEC_PHY_DP], hpd ? 4 : 0);
1608
+ break;
1609
+ case TYPEC_DP_STATE_D:
1610
+ tcphy->new_mode = MODE_DFP_DP | MODE_DFP_USB;
1611
+ data = state->data;
1612
+ hpd = !!(data->status & DP_STATUS_HPD_STATE);
1613
+ phy_set_bus_width(tcphy->phys[TYPEC_PHY_DP], hpd ? 2 : 0);
1614
+ break;
1615
+ default:
1616
+ break;
1617
+ }
1618
+
1619
+ mutex_unlock(&tcphy->lock);
1620
+
1621
+ return 0;
1622
+}
1623
+
1624
+static int tcphy_setup_typec_mux(struct rockchip_typec_phy *tcphy)
1625
+{
1626
+ struct typec_mux_desc mux_desc = {};
1627
+
1628
+ mux_desc.drvdata = tcphy;
1629
+ mux_desc.fwnode = dev_fwnode(tcphy->dev);
1630
+ mux_desc.set = tcphy_typec_mux_set;
1631
+
1632
+ tcphy->mux = typec_mux_register(tcphy->dev, &mux_desc);
1633
+ if (IS_ERR(tcphy->mux)) {
1634
+ dev_err(tcphy->dev, "Error register typec mux: %ld\n",
1635
+ PTR_ERR(tcphy->mux));
1636
+ return PTR_ERR(tcphy->mux);
1637
+ }
1638
+
1639
+ return 0;
1640
+}
1641
+
1642
+static void tcphy_typec_mux_unregister(void *data)
1643
+{
1644
+ struct rockchip_typec_phy *tcphy = data;
1645
+
1646
+ typec_mux_unregister(tcphy->mux);
1647
+}
1648
+
15761649 static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy,
15771650 struct device *dev)
15781651 {
....@@ -1683,8 +1756,8 @@
16831756 }
16841757
16851758 if (!tcphy->port_cfgs) {
1686
- dev_err(dev, "no phy-config can be matched with %s node\n",
1687
- np->name);
1759
+ dev_err(dev, "no phy-config can be matched with %pOFn node\n",
1760
+ np);
16881761 return -EINVAL;
16891762 }
16901763
....@@ -1693,20 +1766,30 @@
16931766 return ret;
16941767
16951768 tcphy->dev = dev;
1769
+ tcphy->new_mode = MODE_DFP_USB;
16961770 platform_set_drvdata(pdev, tcphy);
16971771 mutex_init(&tcphy->lock);
16981772
16991773 typec_phy_pre_init(tcphy);
17001774
1701
- tcphy->extcon = extcon_get_edev_by_phandle(dev, 0);
1702
- if (IS_ERR(tcphy->extcon)) {
1703
- if (PTR_ERR(tcphy->extcon) == -ENODEV) {
1704
- tcphy->extcon = NULL;
1705
- } else {
1706
- if (PTR_ERR(tcphy->extcon) != -EPROBE_DEFER)
1707
- dev_err(dev, "Invalid or missing extcon\n");
1708
- return PTR_ERR(tcphy->extcon);
1709
- }
1775
+ if (device_property_present(dev, "orientation-switch")) {
1776
+ ret = tcphy_setup_orien_switch(tcphy);
1777
+ if (ret)
1778
+ return ret;
1779
+ ret = devm_add_action_or_reset(dev, udphy_orien_switch_unregister,
1780
+ tcphy);
1781
+ if (ret)
1782
+ return ret;
1783
+ }
1784
+
1785
+ if (device_property_present(dev, "svid")) {
1786
+ ret = tcphy_setup_typec_mux(tcphy);
1787
+ if (ret)
1788
+ return ret;
1789
+
1790
+ ret = devm_add_action_or_reset(dev, tcphy_typec_mux_unregister, tcphy);
1791
+ if (ret)
1792
+ return ret;
17101793 }
17111794
17121795 pm_runtime_enable(dev);
....@@ -1714,20 +1797,31 @@
17141797 for_each_available_child_of_node(np, child_np) {
17151798 struct phy *phy;
17161799
1717
- if (!of_node_cmp(child_np->name, "dp-port"))
1800
+ if (!of_node_cmp(child_np->name, "dp-port")) {
17181801 phy = devm_phy_create(dev, child_np,
17191802 &rockchip_dp_phy_ops);
1720
- else if (!of_node_cmp(child_np->name, "usb3-port"))
1803
+ if (IS_ERR(phy)) {
1804
+ dev_err(dev, "failed to create phy: %s\n",
1805
+ child_np->name);
1806
+ of_node_put(child_np);
1807
+ ret = PTR_ERR(phy);
1808
+ goto error;
1809
+ }
1810
+ tcphy->phys[TYPEC_PHY_DP] = phy;
1811
+ } else if (!of_node_cmp(child_np->name, "usb3-port")) {
17211812 phy = devm_phy_create(dev, child_np,
17221813 &rockchip_usb3_phy_ops);
1723
- else
1814
+ if (IS_ERR(phy)) {
1815
+ dev_err(dev, "failed to create phy: %s\n",
1816
+ child_np->name);
1817
+ of_node_put(child_np);
1818
+ ret = PTR_ERR(phy);
1819
+ goto error;
1820
+ }
1821
+ tcphy->phys[TYPEC_PHY_USB] = phy;
1822
+ } else {
17241823 continue;
17251824
1726
- if (IS_ERR(phy)) {
1727
- dev_err(dev, "failed to create phy: %s\n",
1728
- child_np->name);
1729
- pm_runtime_disable(dev);
1730
- return PTR_ERR(phy);
17311825 }
17321826
17331827 phy_set_drvdata(phy, tcphy);
....@@ -1736,11 +1830,15 @@
17361830 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
17371831 if (IS_ERR(phy_provider)) {
17381832 dev_err(dev, "Failed to register phy provider\n");
1739
- pm_runtime_disable(dev);
1740
- return PTR_ERR(phy_provider);
1833
+ ret = PTR_ERR(phy_provider);
1834
+ goto error;
17411835 }
17421836
17431837 return 0;
1838
+
1839
+error:
1840
+ pm_runtime_disable(dev);
1841
+ return ret;
17441842 }
17451843
17461844 static int rockchip_typec_phy_remove(struct platform_device *pdev)