| .. | .. |
|---|
| 56 | 56 | |
|---|
| 57 | 57 | #include <linux/mfd/syscon.h> |
|---|
| 58 | 58 | #include <linux/phy/phy.h> |
|---|
| 59 | | -#include <linux/phy/phy-rockchip-typec.h> |
|---|
| 59 | +#include <linux/usb/typec_mux.h> |
|---|
| 60 | +#include <linux/usb/typec_dp.h> |
|---|
| 60 | 61 | |
|---|
| 61 | 62 | #define CMN_SSM_BANDGAP (0x21 << 2) |
|---|
| 62 | 63 | #define CMN_SSM_BIAS (0x22 << 2) |
|---|
| .. | .. |
|---|
| 844 | 845 | writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane)); |
|---|
| 845 | 846 | } |
|---|
| 846 | 847 | |
|---|
| 847 | | -static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, int link_rate, |
|---|
| 848 | | - u8 swing, u8 pre_emp, u32 lane) |
|---|
| 848 | +static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane) |
|---|
| 849 | 849 | { |
|---|
| 850 | | - u16 val; |
|---|
| 851 | | - |
|---|
| 852 | 850 | writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane)); |
|---|
| 853 | 851 | writel(0x6799, tcphy->base + TX_PSC_A0(lane)); |
|---|
| 854 | 852 | writel(0x6798, tcphy->base + TX_PSC_A1(lane)); |
|---|
| 855 | 853 | writel(0x98, tcphy->base + TX_PSC_A2(lane)); |
|---|
| 856 | 854 | 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)); |
|---|
| 884 | 855 | } |
|---|
| 885 | 856 | |
|---|
| 886 | | -int tcphy_dp_set_phy_config(struct phy *phy, int link_rate, |
|---|
| 887 | | - int lane_count, u8 swing, u8 pre_emp) |
|---|
| 857 | +static int rockchip_dp_phy_set_voltages(struct rockchip_typec_phy *tcphy, |
|---|
| 858 | + struct phy_configure_opts_dp *dp) |
|---|
| 888 | 859 | { |
|---|
| 889 | | - struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy); |
|---|
| 890 | | - u8 i; |
|---|
| 860 | + u8 i, j, lane; |
|---|
| 861 | + u32 val; |
|---|
| 891 | 862 | |
|---|
| 892 | | - if (!phy->power_count) |
|---|
| 893 | | - return -EPERM; |
|---|
| 894 | 863 | |
|---|
| 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); |
|---|
| 864 | + if (dp->lanes == 4) { |
|---|
| 865 | + i = 0; |
|---|
| 866 | + j = 3; |
|---|
| 898 | 867 | } else { |
|---|
| 899 | 868 | if (tcphy->flip) { |
|---|
| 900 | | - tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 0); |
|---|
| 901 | | - tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 1); |
|---|
| 869 | + i = 0; |
|---|
| 870 | + j = 1; |
|---|
| 902 | 871 | } else { |
|---|
| 903 | | - tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 2); |
|---|
| 904 | | - tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 3); |
|---|
| 872 | + i = 2; |
|---|
| 873 | + j = 3; |
|---|
| 905 | 874 | } |
|---|
| 875 | + } |
|---|
| 876 | + |
|---|
| 877 | + for (lane = i; lane <= j; lane++) { |
|---|
| 878 | + writel(tcphy->config[dp->voltage[lane]][dp->pre[lane]].swing, |
|---|
| 879 | + tcphy->base + TX_TXCC_MGNFS_MULT_000(lane)); |
|---|
| 880 | + writel(tcphy->config[dp->voltage[lane]][dp->pre[lane]].pe, |
|---|
| 881 | + tcphy->base + TX_TXCC_CPOST_MULT_00(lane)); |
|---|
| 882 | + |
|---|
| 883 | + if (dp->voltage[lane] == 2 && dp->pre[lane] == 0 && dp->link_rate != 540000) { |
|---|
| 884 | + writel(0x700, tcphy->base + TX_DIAG_TX_DRV(lane)); |
|---|
| 885 | + writel(0x13c, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane)); |
|---|
| 886 | + } else { |
|---|
| 887 | + writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane)); |
|---|
| 888 | + writel(0x0400, tcphy->base + TX_DIAG_TX_DRV(lane)); |
|---|
| 889 | + } |
|---|
| 890 | + |
|---|
| 891 | + val = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane)); |
|---|
| 892 | + val &= ~GENMASK(14, 12); |
|---|
| 893 | + val |= ((dp->link_rate == 540000) ? 0x5 : 0x6) << 12; |
|---|
| 894 | + writel(val, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane)); |
|---|
| 906 | 895 | } |
|---|
| 907 | 896 | |
|---|
| 908 | 897 | return 0; |
|---|
| 909 | 898 | } |
|---|
| 910 | | -EXPORT_SYMBOL(tcphy_dp_set_phy_config); |
|---|
| 911 | 899 | |
|---|
| 912 | | -int tcphy_dp_set_lane_count(struct phy *phy, u8 lane_count) |
|---|
| 900 | +static int rockchip_dp_phy_set_lanes(struct rockchip_typec_phy *tcphy, |
|---|
| 901 | + struct phy_configure_opts_dp *dp) |
|---|
| 913 | 902 | { |
|---|
| 914 | | - struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy); |
|---|
| 915 | 903 | u32 reg; |
|---|
| 916 | | - |
|---|
| 917 | | - if (!phy->power_count) |
|---|
| 918 | | - return -EPERM; |
|---|
| 919 | 904 | |
|---|
| 920 | 905 | /* |
|---|
| 921 | 906 | * In cases where fewer than the configured number of DP lanes are |
|---|
| .. | .. |
|---|
| 927 | 912 | reg = readl(tcphy->base + PHY_DP_MODE_CTL); |
|---|
| 928 | 913 | reg |= PHY_DP_LANE_DISABLE; |
|---|
| 929 | 914 | |
|---|
| 930 | | - switch (lane_count) { |
|---|
| 915 | + switch (dp->lanes) { |
|---|
| 931 | 916 | case 4: |
|---|
| 932 | 917 | reg &= ~(PHY_DP_LANE_3_DISABLE | PHY_DP_LANE_2_DISABLE | |
|---|
| 933 | 918 | PHY_DP_LANE_1_DISABLE | PHY_DP_LANE_0_DISABLE); |
|---|
| .. | .. |
|---|
| 946 | 931 | |
|---|
| 947 | 932 | return 0; |
|---|
| 948 | 933 | } |
|---|
| 949 | | -EXPORT_SYMBOL(tcphy_dp_set_lane_count); |
|---|
| 950 | 934 | |
|---|
| 951 | | -int tcphy_dp_set_link_rate(struct phy *phy, int link_rate, bool ssc_on) |
|---|
| 935 | +static int rockchip_dp_phy_set_rate(struct rockchip_typec_phy *tcphy, |
|---|
| 936 | + struct phy_configure_opts_dp *dp) |
|---|
| 952 | 937 | { |
|---|
| 953 | | - struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy); |
|---|
| 954 | 938 | const struct phy_reg *phy_cfg; |
|---|
| 955 | 939 | u32 cmn_diag_hsclk_sel, phy_dp_clk_ctl, reg; |
|---|
| 956 | 940 | u32 i, cfg_size; |
|---|
| 957 | 941 | int ret; |
|---|
| 958 | | - |
|---|
| 959 | | - if (!phy->power_count) |
|---|
| 960 | | - return -EPERM; |
|---|
| 961 | 942 | |
|---|
| 962 | 943 | /* Place the PHY lanes in the A3 power state. */ |
|---|
| 963 | 944 | ret = tcphy_dp_set_power_state(tcphy, PHY_DP_POWER_STATE_A3); |
|---|
| .. | .. |
|---|
| 1001 | 982 | phy_dp_clk_ctl = readl(tcphy->base + PHY_DP_CLK_CTL); |
|---|
| 1002 | 983 | phy_dp_clk_ctl &= ~(GENMASK(15, 12) | GENMASK(11, 8)); |
|---|
| 1003 | 984 | |
|---|
| 1004 | | - switch (link_rate) { |
|---|
| 1005 | | - case 162000: |
|---|
| 985 | + switch (dp->link_rate) { |
|---|
| 986 | + case 1620: |
|---|
| 1006 | 987 | cmn_diag_hsclk_sel |= (3 << 4) | (0 << 0); |
|---|
| 1007 | 988 | phy_dp_clk_ctl |= (2 << 12) | (4 << 8); |
|---|
| 1008 | 989 | |
|---|
| 1009 | | - phy_cfg = ssc_on ? dp_pll_rbr_ssc_cfg : dp_pll_rbr_cfg; |
|---|
| 1010 | | - cfg_size = ssc_on ? ARRAY_SIZE(dp_pll_rbr_ssc_cfg) : |
|---|
| 990 | + phy_cfg = dp->ssc ? dp_pll_rbr_ssc_cfg : dp_pll_rbr_cfg; |
|---|
| 991 | + cfg_size = dp->ssc ? ARRAY_SIZE(dp_pll_rbr_ssc_cfg) : |
|---|
| 1011 | 992 | ARRAY_SIZE(dp_pll_rbr_cfg); |
|---|
| 1012 | 993 | break; |
|---|
| 1013 | | - case 270000: |
|---|
| 994 | + case 2700: |
|---|
| 1014 | 995 | cmn_diag_hsclk_sel |= (3 << 4) | (0 << 0); |
|---|
| 1015 | 996 | phy_dp_clk_ctl |= (2 << 12) | (4 << 8); |
|---|
| 1016 | 997 | |
|---|
| 1017 | | - phy_cfg = ssc_on ? dp_pll_hbr_ssc_cfg : dp_pll_hbr_cfg; |
|---|
| 1018 | | - cfg_size = ssc_on ? ARRAY_SIZE(dp_pll_hbr_ssc_cfg) : |
|---|
| 998 | + phy_cfg = dp->ssc ? dp_pll_hbr_ssc_cfg : dp_pll_hbr_cfg; |
|---|
| 999 | + cfg_size = dp->ssc ? ARRAY_SIZE(dp_pll_hbr_ssc_cfg) : |
|---|
| 1019 | 1000 | ARRAY_SIZE(dp_pll_hbr_cfg); |
|---|
| 1020 | 1001 | break; |
|---|
| 1021 | | - case 540000: |
|---|
| 1002 | + case 5400: |
|---|
| 1022 | 1003 | cmn_diag_hsclk_sel |= (2 << 4) | (0 << 0); |
|---|
| 1023 | 1004 | phy_dp_clk_ctl |= (1 << 12) | (2 << 8); |
|---|
| 1024 | 1005 | |
|---|
| 1025 | | - phy_cfg = ssc_on ? dp_pll_hbr2_ssc_cfg : dp_pll_hbr2_cfg; |
|---|
| 1026 | | - cfg_size = ssc_on ? ARRAY_SIZE(dp_pll_hbr2_ssc_cfg) : |
|---|
| 1006 | + phy_cfg = dp->ssc ? dp_pll_hbr2_ssc_cfg : dp_pll_hbr2_cfg; |
|---|
| 1007 | + cfg_size = dp->ssc ? ARRAY_SIZE(dp_pll_hbr2_ssc_cfg) : |
|---|
| 1027 | 1008 | ARRAY_SIZE(dp_pll_hbr2_cfg); |
|---|
| 1028 | 1009 | break; |
|---|
| 1029 | 1010 | default: |
|---|
| .. | .. |
|---|
| 1081 | 1062 | |
|---|
| 1082 | 1063 | return 0; |
|---|
| 1083 | 1064 | } |
|---|
| 1084 | | -EXPORT_SYMBOL(tcphy_dp_set_link_rate); |
|---|
| 1085 | 1065 | |
|---|
| 1086 | 1066 | static inline int property_enable(struct rockchip_typec_phy *tcphy, |
|---|
| 1087 | 1067 | const struct usb3phy_reg *reg, bool en) |
|---|
| .. | .. |
|---|
| 1287 | 1267 | tcphy_cfg_usb3_to_usb2_only(tcphy, true); |
|---|
| 1288 | 1268 | tcphy_cfg_dp_pll(tcphy, DP_DEFAULT_RATE); |
|---|
| 1289 | 1269 | for (i = 0; i < 4; i++) |
|---|
| 1290 | | - tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, i); |
|---|
| 1270 | + tcphy_dp_cfg_lane(tcphy, i); |
|---|
| 1291 | 1271 | } else { |
|---|
| 1292 | 1272 | tcphy_cfg_usb3_pll(tcphy); |
|---|
| 1293 | 1273 | tcphy_cfg_dp_pll(tcphy, DP_DEFAULT_RATE); |
|---|
| 1294 | 1274 | if (tcphy->flip) { |
|---|
| 1295 | 1275 | tcphy_tx_usb3_cfg_lane(tcphy, 3); |
|---|
| 1296 | 1276 | tcphy_rx_usb3_cfg_lane(tcphy, 2); |
|---|
| 1297 | | - tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 0); |
|---|
| 1298 | | - tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 1); |
|---|
| 1277 | + tcphy_dp_cfg_lane(tcphy, 0); |
|---|
| 1278 | + tcphy_dp_cfg_lane(tcphy, 1); |
|---|
| 1299 | 1279 | } else { |
|---|
| 1300 | 1280 | tcphy_tx_usb3_cfg_lane(tcphy, 0); |
|---|
| 1301 | 1281 | tcphy_rx_usb3_cfg_lane(tcphy, 1); |
|---|
| 1302 | | - tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 2); |
|---|
| 1303 | | - tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 3); |
|---|
| 1282 | + tcphy_dp_cfg_lane(tcphy, 2); |
|---|
| 1283 | + tcphy_dp_cfg_lane(tcphy, 3); |
|---|
| 1304 | 1284 | } |
|---|
| 1305 | 1285 | } |
|---|
| 1306 | 1286 | |
|---|
| .. | .. |
|---|
| 1578 | 1558 | return 0; |
|---|
| 1579 | 1559 | } |
|---|
| 1580 | 1560 | |
|---|
| 1561 | +static int rockchip_dp_phy_verify_config(struct rockchip_typec_phy *tcphy, |
|---|
| 1562 | + struct phy_configure_opts_dp *dp) |
|---|
| 1563 | +{ |
|---|
| 1564 | + u8 i; |
|---|
| 1565 | + |
|---|
| 1566 | + /* If changing link rate was required, verify it's supported. */ |
|---|
| 1567 | + if (dp->set_rate) { |
|---|
| 1568 | + switch (dp->link_rate) { |
|---|
| 1569 | + case 1620: |
|---|
| 1570 | + case 2700: |
|---|
| 1571 | + case 5400: |
|---|
| 1572 | + /* valid bit rate */ |
|---|
| 1573 | + break; |
|---|
| 1574 | + default: |
|---|
| 1575 | + return -EINVAL; |
|---|
| 1576 | + } |
|---|
| 1577 | + } |
|---|
| 1578 | + |
|---|
| 1579 | + /* Verify lane count. */ |
|---|
| 1580 | + switch (dp->lanes) { |
|---|
| 1581 | + case 1: |
|---|
| 1582 | + case 2: |
|---|
| 1583 | + case 4: |
|---|
| 1584 | + /* valid lane count. */ |
|---|
| 1585 | + break; |
|---|
| 1586 | + default: |
|---|
| 1587 | + return -EINVAL; |
|---|
| 1588 | + } |
|---|
| 1589 | + |
|---|
| 1590 | + /* |
|---|
| 1591 | + * If changing voltages is required, check swing and pre-emphasis |
|---|
| 1592 | + * levels, per-lane. |
|---|
| 1593 | + */ |
|---|
| 1594 | + if (dp->set_voltages) { |
|---|
| 1595 | + /* Lane count verified previously. */ |
|---|
| 1596 | + for (i = 0; i < dp->lanes; i++) { |
|---|
| 1597 | + if (dp->voltage[i] > 3 || dp->pre[i] > 3) |
|---|
| 1598 | + return -EINVAL; |
|---|
| 1599 | + |
|---|
| 1600 | + /* Sum of voltage swing and pre-emphasis levels cannot |
|---|
| 1601 | + * exceed 3. |
|---|
| 1602 | + */ |
|---|
| 1603 | + if (dp->voltage[i] + dp->pre[i] > 3) |
|---|
| 1604 | + return -EINVAL; |
|---|
| 1605 | + } |
|---|
| 1606 | + } |
|---|
| 1607 | + |
|---|
| 1608 | + return 0; |
|---|
| 1609 | +} |
|---|
| 1610 | + |
|---|
| 1611 | +static int rockchip_dp_phy_configure(struct phy *phy, |
|---|
| 1612 | + union phy_configure_opts *opts) |
|---|
| 1613 | +{ |
|---|
| 1614 | + struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy); |
|---|
| 1615 | + int ret; |
|---|
| 1616 | + |
|---|
| 1617 | + if (!phy->power_count) |
|---|
| 1618 | + return -EPERM; |
|---|
| 1619 | + |
|---|
| 1620 | + ret = rockchip_dp_phy_verify_config(tcphy, &opts->dp); |
|---|
| 1621 | + if (ret) { |
|---|
| 1622 | + dev_err(&phy->dev, "invalid params for phy configure\n"); |
|---|
| 1623 | + return ret; |
|---|
| 1624 | + } |
|---|
| 1625 | + |
|---|
| 1626 | + if (opts->dp.set_lanes) { |
|---|
| 1627 | + ret = rockchip_dp_phy_set_lanes(tcphy, &opts->dp); |
|---|
| 1628 | + if (ret) { |
|---|
| 1629 | + dev_err(&phy->dev, "rockchip_dp_phy_set_lanes failed\n"); |
|---|
| 1630 | + return ret; |
|---|
| 1631 | + } |
|---|
| 1632 | + } |
|---|
| 1633 | + |
|---|
| 1634 | + if (opts->dp.set_rate) { |
|---|
| 1635 | + ret = rockchip_dp_phy_set_rate(tcphy, &opts->dp); |
|---|
| 1636 | + if (ret) { |
|---|
| 1637 | + dev_err(&phy->dev, "rockchip_dp_phy_set_rate failed\n"); |
|---|
| 1638 | + return ret; |
|---|
| 1639 | + } |
|---|
| 1640 | + } |
|---|
| 1641 | + |
|---|
| 1642 | + if (opts->dp.set_voltages) { |
|---|
| 1643 | + ret = rockchip_dp_phy_set_voltages(tcphy, &opts->dp); |
|---|
| 1644 | + if (ret) { |
|---|
| 1645 | + dev_err(&phy->dev, "rockchip_dp_phy_set_voltages failed\n"); |
|---|
| 1646 | + return ret; |
|---|
| 1647 | + } |
|---|
| 1648 | + } |
|---|
| 1649 | + |
|---|
| 1650 | + return 0; |
|---|
| 1651 | +} |
|---|
| 1652 | + |
|---|
| 1581 | 1653 | static const struct phy_ops rockchip_dp_phy_ops = { |
|---|
| 1582 | 1654 | .power_on = rockchip_dp_phy_power_on, |
|---|
| 1583 | 1655 | .power_off = rockchip_dp_phy_power_off, |
|---|
| 1656 | + .configure = rockchip_dp_phy_configure, |
|---|
| 1584 | 1657 | .owner = THIS_MODULE, |
|---|
| 1585 | 1658 | }; |
|---|
| 1586 | 1659 | |
|---|