From 6778948f9de86c3cfaf36725a7c87dcff9ba247f Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 08:20:59 +0000
Subject: [PATCH] kernel_5.10 no rt

---
 kernel/drivers/phy/rockchip/phy-rockchip-typec.c |  221 ++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 147 insertions(+), 74 deletions(-)

diff --git a/kernel/drivers/phy/rockchip/phy-rockchip-typec.c b/kernel/drivers/phy/rockchip/phy-rockchip-typec.c
index 13d849d..f4ffb14 100644
--- a/kernel/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/kernel/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -56,7 +56,8 @@
 
 #include <linux/mfd/syscon.h>
 #include <linux/phy/phy.h>
-#include <linux/phy/phy-rockchip-typec.h>
+#include <linux/usb/typec_mux.h>
+#include <linux/usb/typec_dp.h>
 
 #define CMN_SSM_BANDGAP			(0x21 << 2)
 #define CMN_SSM_BIAS			(0x22 << 2)
@@ -844,78 +845,62 @@
 	writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
 }
 
-static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, int link_rate,
-			      u8 swing, u8 pre_emp, u32 lane)
+static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
 {
-	u16 val;
-
 	writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane));
 	writel(0x6799, tcphy->base + TX_PSC_A0(lane));
 	writel(0x6798, tcphy->base + TX_PSC_A1(lane));
 	writel(0x98, tcphy->base + TX_PSC_A2(lane));
 	writel(0x98, tcphy->base + TX_PSC_A3(lane));
-
-	writel(tcphy->config[swing][pre_emp].swing,
-	       tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
-	writel(tcphy->config[swing][pre_emp].pe,
-	       tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
-
-	if (swing == 2 && pre_emp == 0 && link_rate != 540000) {
-		writel(0x700, tcphy->base + TX_DIAG_TX_DRV(lane));
-		writel(0x13c, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
-	} else {
-		writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
-		writel(0x0400, tcphy->base + TX_DIAG_TX_DRV(lane));
-	}
-
-	val = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
-	val = val & 0x8fff;
-	switch (link_rate) {
-	case 540000:
-		val |= (5 << 12);
-		break;
-	case 162000:
-	case 270000:
-	default:
-		val |= (6 << 12);
-		break;
-	}
-	writel(val, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
 }
 
-int tcphy_dp_set_phy_config(struct phy *phy, int link_rate,
-			    int lane_count, u8 swing, u8 pre_emp)
+static int rockchip_dp_phy_set_voltages(struct rockchip_typec_phy *tcphy,
+					struct phy_configure_opts_dp *dp)
 {
-	struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
-	u8 i;
+	u8 i, j, lane;
+	u32 val;
 
-	if (!phy->power_count)
-		return -EPERM;
 
-	if (tcphy->mode == MODE_DFP_DP) {
-		for (i = 0; i < 4; i++)
-			tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, i);
+	if (dp->lanes == 4) {
+		i = 0;
+		j = 3;
 	} else {
 		if (tcphy->flip) {
-			tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 0);
-			tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 1);
+			i = 0;
+			j = 1;
 		} else {
-			tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 2);
-			tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 3);
+			i = 2;
+			j = 3;
 		}
+	}
+
+	for (lane = i; lane <= j; lane++) {
+		writel(tcphy->config[dp->voltage[lane]][dp->pre[lane]].swing,
+		       tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
+		writel(tcphy->config[dp->voltage[lane]][dp->pre[lane]].pe,
+		       tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
+
+		if (dp->voltage[lane] == 2 && dp->pre[lane] == 0 && dp->link_rate != 540000) {
+			writel(0x700, tcphy->base + TX_DIAG_TX_DRV(lane));
+			writel(0x13c, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
+		} else {
+			writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
+			writel(0x0400, tcphy->base + TX_DIAG_TX_DRV(lane));
+		}
+
+		val = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
+		val &= ~GENMASK(14, 12);
+		val |= ((dp->link_rate == 540000) ? 0x5 : 0x6) << 12;
+		writel(val, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
 	}
 
 	return 0;
 }
-EXPORT_SYMBOL(tcphy_dp_set_phy_config);
 
-int tcphy_dp_set_lane_count(struct phy *phy, u8 lane_count)
+static int rockchip_dp_phy_set_lanes(struct rockchip_typec_phy *tcphy,
+				     struct phy_configure_opts_dp *dp)
 {
-	struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
 	u32 reg;
-
-	if (!phy->power_count)
-		return -EPERM;
 
 	/*
 	 * In cases where fewer than the configured number of DP lanes are
@@ -927,7 +912,7 @@
 	reg = readl(tcphy->base + PHY_DP_MODE_CTL);
 	reg |= PHY_DP_LANE_DISABLE;
 
-	switch (lane_count) {
+	switch (dp->lanes) {
 	case 4:
 		reg &= ~(PHY_DP_LANE_3_DISABLE | PHY_DP_LANE_2_DISABLE |
 			 PHY_DP_LANE_1_DISABLE | PHY_DP_LANE_0_DISABLE);
@@ -946,18 +931,14 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(tcphy_dp_set_lane_count);
 
-int tcphy_dp_set_link_rate(struct phy *phy, int link_rate, bool ssc_on)
+static int rockchip_dp_phy_set_rate(struct rockchip_typec_phy *tcphy,
+				    struct phy_configure_opts_dp *dp)
 {
-	struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
 	const struct phy_reg *phy_cfg;
 	u32 cmn_diag_hsclk_sel, phy_dp_clk_ctl, reg;
 	u32 i, cfg_size;
 	int ret;
-
-	if (!phy->power_count)
-		return -EPERM;
 
 	/* Place the PHY lanes in the A3 power state. */
 	ret = tcphy_dp_set_power_state(tcphy, PHY_DP_POWER_STATE_A3);
@@ -1001,29 +982,29 @@
 	phy_dp_clk_ctl = readl(tcphy->base + PHY_DP_CLK_CTL);
 	phy_dp_clk_ctl &= ~(GENMASK(15, 12) | GENMASK(11, 8));
 
-	switch (link_rate) {
-	case 162000:
+	switch (dp->link_rate) {
+	case 1620:
 		cmn_diag_hsclk_sel |= (3 << 4) | (0 << 0);
 		phy_dp_clk_ctl |= (2 << 12) | (4 << 8);
 
-		phy_cfg = ssc_on ? dp_pll_rbr_ssc_cfg : dp_pll_rbr_cfg;
-		cfg_size = ssc_on ? ARRAY_SIZE(dp_pll_rbr_ssc_cfg) :
+		phy_cfg = dp->ssc ? dp_pll_rbr_ssc_cfg : dp_pll_rbr_cfg;
+		cfg_size = dp->ssc ? ARRAY_SIZE(dp_pll_rbr_ssc_cfg) :
 				    ARRAY_SIZE(dp_pll_rbr_cfg);
 		break;
-	case 270000:
+	case 2700:
 		cmn_diag_hsclk_sel |= (3 << 4) | (0 << 0);
 		phy_dp_clk_ctl |= (2 << 12) | (4 << 8);
 
-		phy_cfg = ssc_on ? dp_pll_hbr_ssc_cfg : dp_pll_hbr_cfg;
-		cfg_size = ssc_on ? ARRAY_SIZE(dp_pll_hbr_ssc_cfg) :
+		phy_cfg = dp->ssc ? dp_pll_hbr_ssc_cfg : dp_pll_hbr_cfg;
+		cfg_size = dp->ssc ? ARRAY_SIZE(dp_pll_hbr_ssc_cfg) :
 				    ARRAY_SIZE(dp_pll_hbr_cfg);
 		break;
-	case 540000:
+	case 5400:
 		cmn_diag_hsclk_sel |= (2 << 4) | (0 << 0);
 		phy_dp_clk_ctl |= (1 << 12) | (2 << 8);
 
-		phy_cfg = ssc_on ? dp_pll_hbr2_ssc_cfg : dp_pll_hbr2_cfg;
-		cfg_size = ssc_on ? ARRAY_SIZE(dp_pll_hbr2_ssc_cfg) :
+		phy_cfg = dp->ssc ? dp_pll_hbr2_ssc_cfg : dp_pll_hbr2_cfg;
+		cfg_size = dp->ssc ? ARRAY_SIZE(dp_pll_hbr2_ssc_cfg) :
 				    ARRAY_SIZE(dp_pll_hbr2_cfg);
 		break;
 	default:
@@ -1081,7 +1062,6 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(tcphy_dp_set_link_rate);
 
 static inline int property_enable(struct rockchip_typec_phy *tcphy,
 				  const struct usb3phy_reg *reg, bool en)
@@ -1287,20 +1267,20 @@
 		tcphy_cfg_usb3_to_usb2_only(tcphy, true);
 		tcphy_cfg_dp_pll(tcphy, DP_DEFAULT_RATE);
 		for (i = 0; i < 4; i++)
-			tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, i);
+			tcphy_dp_cfg_lane(tcphy, i);
 	} else {
 		tcphy_cfg_usb3_pll(tcphy);
 		tcphy_cfg_dp_pll(tcphy, DP_DEFAULT_RATE);
 		if (tcphy->flip) {
 			tcphy_tx_usb3_cfg_lane(tcphy, 3);
 			tcphy_rx_usb3_cfg_lane(tcphy, 2);
-			tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 0);
-			tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 1);
+			tcphy_dp_cfg_lane(tcphy, 0);
+			tcphy_dp_cfg_lane(tcphy, 1);
 		} else {
 			tcphy_tx_usb3_cfg_lane(tcphy, 0);
 			tcphy_rx_usb3_cfg_lane(tcphy, 1);
-			tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 2);
-			tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 3);
+			tcphy_dp_cfg_lane(tcphy, 2);
+			tcphy_dp_cfg_lane(tcphy, 3);
 		}
 	}
 
@@ -1578,9 +1558,102 @@
 	return 0;
 }
 
+static int rockchip_dp_phy_verify_config(struct rockchip_typec_phy *tcphy,
+					 struct phy_configure_opts_dp *dp)
+{
+	u8 i;
+
+	/* If changing link rate was required, verify it's supported. */
+	if (dp->set_rate) {
+		switch (dp->link_rate) {
+		case 1620:
+		case 2700:
+		case 5400:
+			/* valid bit rate */
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	/* Verify lane count. */
+	switch (dp->lanes) {
+	case 1:
+	case 2:
+	case 4:
+		/* valid lane count. */
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * If changing voltages is required, check swing and pre-emphasis
+	 * levels, per-lane.
+	 */
+	if (dp->set_voltages) {
+		/* Lane count verified previously. */
+		for (i = 0; i < dp->lanes; i++) {
+			if (dp->voltage[i] > 3 || dp->pre[i] > 3)
+				return -EINVAL;
+
+			/* Sum of voltage swing and pre-emphasis levels cannot
+			 * exceed 3.
+			 */
+			if (dp->voltage[i] + dp->pre[i] > 3)
+				return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int rockchip_dp_phy_configure(struct phy *phy,
+					union phy_configure_opts *opts)
+{
+	struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
+	int ret;
+
+	if (!phy->power_count)
+		return -EPERM;
+
+	ret = rockchip_dp_phy_verify_config(tcphy, &opts->dp);
+	if (ret) {
+		dev_err(&phy->dev, "invalid params for phy configure\n");
+		return ret;
+	}
+
+	if (opts->dp.set_lanes) {
+		ret = rockchip_dp_phy_set_lanes(tcphy, &opts->dp);
+		if (ret) {
+			dev_err(&phy->dev, "rockchip_dp_phy_set_lanes failed\n");
+			return ret;
+		}
+	}
+
+	if (opts->dp.set_rate) {
+		ret = rockchip_dp_phy_set_rate(tcphy, &opts->dp);
+		if (ret) {
+			dev_err(&phy->dev, "rockchip_dp_phy_set_rate failed\n");
+			return ret;
+		}
+	}
+
+	if (opts->dp.set_voltages) {
+		ret = rockchip_dp_phy_set_voltages(tcphy, &opts->dp);
+		if (ret) {
+			dev_err(&phy->dev, "rockchip_dp_phy_set_voltages failed\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 static const struct phy_ops rockchip_dp_phy_ops = {
 	.power_on	= rockchip_dp_phy_power_on,
 	.power_off	= rockchip_dp_phy_power_off,
+	.configure	= rockchip_dp_phy_configure,
 	.owner		= THIS_MODULE,
 };
 

--
Gitblit v1.6.2