|
19 | 19 | #include <linux/regulator/consumer.h>
|
20 | 20 | #include <linux/reset.h>
|
21 | 21 | #include <linux/slab.h>
|
| 22 | +#include <linux/usb/typec.h> |
22 | 23 |
|
23 | 24 | #include <dt-bindings/phy/phy-qcom-qmp.h>
|
24 | 25 |
|
|
63 | 64 | /* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
|
64 | 65 | #define CLAMP_EN BIT(0) /* enables i/o clamp_n */
|
65 | 66 |
|
| 67 | +/* QPHY_V3_DP_COM_TYPEC_CTRL register bits */ |
| 68 | +#define SW_PORTSELECT_VAL BIT(0) |
| 69 | +#define SW_PORTSELECT_MUX BIT(1) |
| 70 | + |
66 | 71 | #define PHY_INIT_COMPLETE_TIMEOUT 10000
|
67 | 72 |
|
68 | 73 | struct qmp_phy_init_tbl {
|
@@ -1323,6 +1328,8 @@ struct qmp_combo {
|
1323 | 1328 | struct clk_fixed_rate pipe_clk_fixed;
|
1324 | 1329 | struct clk_hw dp_link_hw;
|
1325 | 1330 | struct clk_hw dp_pixel_hw;
|
| 1331 | + |
| 1332 | + enum typec_orientation orientation; |
1326 | 1333 | };
|
1327 | 1334 |
|
1328 | 1335 | static void qmp_v3_dp_aux_init(struct qmp_combo *qmp);
|
@@ -1954,30 +1961,24 @@ static void qmp_v3_configure_dp_tx(struct qmp_combo *qmp)
|
1954 | 1961 |
|
1955 | 1962 | static bool qmp_combo_configure_dp_mode(struct qmp_combo *qmp)
|
1956 | 1963 | {
|
| 1964 | + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); |
| 1965 | + const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; |
1957 | 1966 | u32 val;
|
1958 |
| - bool reverse = false; |
1959 | 1967 |
|
1960 | 1968 | val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
|
1961 | 1969 | DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN;
|
1962 | 1970 |
|
1963 |
| - /* |
1964 |
| - * TODO: Assume orientation is CC1 for now and two lanes, need to |
1965 |
| - * use type-c connector to understand orientation and lanes. |
1966 |
| - * |
1967 |
| - * Otherwise val changes to be like below if this code understood |
1968 |
| - * the orientation of the type-c cable. |
1969 |
| - * |
1970 |
| - * if (lane_cnt == 4 || orientation == ORIENTATION_CC2) |
1971 |
| - * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN; |
1972 |
| - * if (lane_cnt == 4 || orientation == ORIENTATION_CC1) |
1973 |
| - * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; |
1974 |
| - * if (orientation == ORIENTATION_CC2) |
1975 |
| - * writel(0x4c, qmp->dp_dp_phy + QSERDES_V3_DP_PHY_MODE); |
1976 |
| - */ |
1977 |
| - val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; |
| 1971 | + if (dp_opts->lanes == 4 || reverse) |
| 1972 | + val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN; |
| 1973 | + if (dp_opts->lanes == 4 || !reverse) |
| 1974 | + val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; |
| 1975 | + |
1978 | 1976 | writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL);
|
1979 | 1977 |
|
1980 |
| - writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE); |
| 1978 | + if (reverse) |
| 1979 | + writel(0x4c, qmp->pcs + QSERDES_DP_PHY_MODE); |
| 1980 | + else |
| 1981 | + writel(0x5c, qmp->pcs + QSERDES_DP_PHY_MODE); |
1981 | 1982 |
|
1982 | 1983 | return reverse;
|
1983 | 1984 | }
|
@@ -2233,9 +2234,9 @@ static int qmp_v456_configure_dp_phy(struct qmp_combo *qmp,
|
2233 | 2234 |
|
2234 | 2235 | static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp)
|
2235 | 2236 | {
|
| 2237 | + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); |
2236 | 2238 | const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
|
2237 | 2239 | u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
|
2238 |
| - bool reverse = false; |
2239 | 2240 | u32 status;
|
2240 | 2241 | int ret;
|
2241 | 2242 |
|
@@ -2297,9 +2298,9 @@ static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp)
|
2297 | 2298 |
|
2298 | 2299 | static int qmp_v5_configure_dp_phy(struct qmp_combo *qmp)
|
2299 | 2300 | {
|
| 2301 | + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); |
2300 | 2302 | const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
|
2301 | 2303 | u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
|
2302 |
| - bool reverse = false; |
2303 | 2304 | u32 status;
|
2304 | 2305 | int ret;
|
2305 | 2306 |
|
@@ -2356,9 +2357,9 @@ static int qmp_v5_configure_dp_phy(struct qmp_combo *qmp)
|
2356 | 2357 |
|
2357 | 2358 | static int qmp_v6_configure_dp_phy(struct qmp_combo *qmp)
|
2358 | 2359 | {
|
| 2360 | + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); |
2359 | 2361 | const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
|
2360 | 2362 | u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
|
2361 |
| - bool reverse = false; |
2362 | 2363 | u32 status;
|
2363 | 2364 | int ret;
|
2364 | 2365 |
|
@@ -2471,6 +2472,7 @@ static int qmp_combo_com_init(struct qmp_combo *qmp)
|
2471 | 2472 | const struct qmp_phy_cfg *cfg = qmp->cfg;
|
2472 | 2473 | void __iomem *com = qmp->com;
|
2473 | 2474 | int ret;
|
| 2475 | + u32 val; |
2474 | 2476 |
|
2475 | 2477 | if (qmp->init_count++)
|
2476 | 2478 | return 0;
|
@@ -2504,10 +2506,12 @@ static int qmp_combo_com_init(struct qmp_combo *qmp)
|
2504 | 2506 | SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
|
2505 | 2507 | SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
|
2506 | 2508 |
|
2507 |
| - /* Default type-c orientation, i.e CC1 */ |
2508 |
| - qphy_setbits(com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02); |
2509 |
| - |
2510 |
| - qphy_setbits(com, QPHY_V3_DP_COM_PHY_MODE_CTRL, USB3_MODE | DP_MODE); |
| 2509 | + /* Use software based port select and switch on typec orientation */ |
| 2510 | + val = SW_PORTSELECT_MUX; |
| 2511 | + if (qmp->orientation == TYPEC_ORIENTATION_REVERSE) |
| 2512 | + val |= SW_PORTSELECT_VAL; |
| 2513 | + writel(val, com + QPHY_V3_DP_COM_TYPEC_CTRL); |
| 2514 | + writel(USB3_MODE | DP_MODE, com + QPHY_V3_DP_COM_PHY_MODE_CTRL); |
2511 | 2515 |
|
2512 | 2516 | /* bring both QMP USB and QMP DP PHYs PCS block out of reset */
|
2513 | 2517 | qphy_clrbits(com, QPHY_V3_DP_COM_RESET_OVRD_CTRL,
|
@@ -3379,6 +3383,8 @@ static int qmp_combo_probe(struct platform_device *pdev)
|
3379 | 3383 |
|
3380 | 3384 | qmp->dev = dev;
|
3381 | 3385 |
|
| 3386 | + qmp->orientation = TYPEC_ORIENTATION_NORMAL; |
| 3387 | + |
3382 | 3388 | qmp->cfg = of_device_get_match_data(dev);
|
3383 | 3389 | if (!qmp->cfg)
|
3384 | 3390 | return -EINVAL;
|
|
0 commit comments