|
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