From 19844189e4e897982593176ca684b4b64512e2f8 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megi@xff.cz>
Date: Fri, 21 Jun 2024 01:42:38 +0200
Subject: [PATCH 460/484] phy: rockchip: inno-usb2: Add support for
 RV1106/RV1103

Ported from BSP driver.

Signed-off-by: Ondrej Jirman <megi@xff.cz>
---
 drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 133 ++++++++++++++++++
 1 file changed, 133 insertions(+)

diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
index b5e6a864deeb..7e0c2f5f6bcc 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -143,6 +143,7 @@ struct rockchip_usb2phy_port_cfg {
 	struct usb2phy_reg	bvalid_det_en;
 	struct usb2phy_reg	bvalid_det_st;
 	struct usb2phy_reg	bvalid_det_clr;
+	struct usb2phy_reg	bvalid_grf_sel;
 	struct usb2phy_reg      disfall_en;
 	struct usb2phy_reg      disfall_st;
 	struct usb2phy_reg      disfall_clr;
@@ -248,6 +249,7 @@ struct rockchip_usb2phy {
 	struct regmap	*grf;
 	struct regmap	*usbgrf;
 	struct clk_bulk_data	*clks;
+	void __iomem	*phy_base;
 	struct clk	*clk480m;
 	struct clk_hw	clk480m_hw;
 	int			num_clks;
@@ -1280,6 +1282,7 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
 					  struct rockchip_usb2phy_port *rport,
 					  struct device_node *child_np)
 {
+	struct regmap *base = get_reg_base(rphy);
 	int ret, id;
 
 	rport->port_id = USB2PHY_PORT_OTG;
@@ -1313,6 +1316,23 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
 		goto out;
 	}
 
+	/*
+	 * Set the utmi bvalid come from the usb phy or grf.
+	 * For most of Rockchip SoCs, them have VBUSDET pin
+	 * for the usb phy to detect the USB VBUS and set
+	 * the bvalid signal, so select the bvalid from the
+	 * usb phy by default. And for those SoCs which don't
+	 * have VBUSDET pin (e.g. RV1103), it needs to select
+	 * the bvaid from the grf and set bvalid to be valid
+	 * (high) by default.
+	 */
+	if (rport->port_cfg->bvalid_grf_sel.enable != 0) {
+		if (of_machine_is_compatible("rockchip,rv1103"))
+			property_enable(base, &rport->port_cfg->bvalid_grf_sel, true);
+		else
+			property_enable(base, &rport->port_cfg->bvalid_grf_sel, false);
+	}
+
 	if (!IS_ERR(rphy->edev)) {
 		rport->event_nb.notifier_call = rockchip_otg_event;
 
@@ -1384,6 +1404,13 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
 		}
 	}
 
+	if (of_device_is_compatible(np, "rockchip,rv1106-usb2phy")) {
+		rphy->phy_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
+		if (IS_ERR(rphy->phy_base))
+			return dev_err_probe(dev, PTR_ERR(rphy->phy_base),
+					     "missing memory resource\n");
+	}
+
 	rphy->dev = dev;
 	phy_cfgs = device_get_match_data(dev);
 	rphy->chg_state = USB_CHG_STATE_UNDEFINED;
@@ -1502,6 +1529,63 @@ put_child:
 	return ret;
 }
 
+static inline void phy_clear_bits(void __iomem *reg, u32 bits)
+{
+	u32 tmp = readl(reg);
+
+	tmp &= ~bits;
+	writel(tmp, reg);
+}
+
+static inline void phy_set_bits(void __iomem *reg, u32 bits)
+{
+	u32 tmp = readl(reg);
+
+	tmp |= bits;
+	writel(tmp, reg);
+}
+
+static inline void phy_update_bits(void __iomem *reg, u32 mask, u32 val)
+{
+	u32 tmp = readl(reg);
+
+	tmp &= ~mask;
+	tmp |= val & mask;
+	writel(tmp, reg);
+}
+
+static int rv1106_usb2phy_tuning(struct rockchip_usb2phy *rphy)
+{
+	/* Always enable pre-emphasis in SOF & EOP & chirp & non-chirp state */
+	phy_update_bits(rphy->phy_base + 0x30, GENMASK(2, 0), 0x07);
+
+//	if (rockchip_get_cpu_version()) {
+//		/* Set Tx HS pre_emphasize strength to 3'b001 */
+//		phy_update_bits(rphy->phy_base + 0x40, GENMASK(5, 3), (0x01 << 3));
+//	} else {
+		/* Set Tx HS pre_emphasize strength to 3'b011 */
+		phy_update_bits(rphy->phy_base + 0x40, GENMASK(5, 3), (0x03 << 3));
+//	}
+
+	/* Set RX Squelch trigger point configure to 4'b0000(112.5 mV) */
+	phy_update_bits(rphy->phy_base + 0x64, GENMASK(6, 3), (0x00 << 3));
+
+	/* Turn off differential receiver by default to save power */
+	phy_clear_bits(rphy->phy_base + 0x100, BIT(6));
+
+	/* Set 45ohm HS ODT value to 5'b10111 to increase driver strength */
+	phy_update_bits(rphy->phy_base + 0x11c, GENMASK(4, 0), 0x17);
+
+	/* Set Tx HS eye height tuning to 3'b011(462 mV)*/
+	phy_update_bits(rphy->phy_base + 0x124, GENMASK(4, 2), (0x03 << 2));
+
+	/* Bypass Squelch detector calibration */
+	phy_update_bits(rphy->phy_base + 0x1a4, GENMASK(7, 4), (0x01 << 4));
+	phy_update_bits(rphy->phy_base + 0x1b4, GENMASK(7, 4), (0x01 << 4));
+
+	return 0;
+}
+
 static int rk3128_usb2phy_tuning(struct rockchip_usb2phy *rphy)
 {
 	/* Turn off differential receiver in suspend mode */
@@ -2160,6 +2244,54 @@ static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = {
 	{ /* sentinel */ }
 };
 
+static const struct rockchip_usb2phy_cfg rv1106_phy_cfgs[] = {
+	{
+		.reg = 0xff3e0000,
+		.num_ports	= 1,
+		.phy_tuning	= rv1106_usb2phy_tuning,
+		.clkout_ctl	= { 0x0058, 4, 4, 1, 0 },
+		.port_cfgs	= {
+			[USB2PHY_PORT_OTG] = {
+				.phy_sus	= { 0x0050, 8, 0, 0, 0x1d1 },
+				.bvalid_det_en	= { 0x0100, 2, 2, 0, 1 },
+				.bvalid_det_st	= { 0x0104, 2, 2, 0, 1 },
+				.bvalid_det_clr = { 0x0108, 2, 2, 0, 1 },
+				.bvalid_grf_sel	= { 0x0058, 15, 14, 0, 3 },
+				/*
+				.iddig_output	= { 0x0050, 10, 10, 0, 1 },
+				.iddig_en	= { 0x0050, 9, 9, 0, 1 },
+				*/
+				.idfall_det_en	= { 0x0100, 5, 5, 0, 1 },
+				.idfall_det_st	= { 0x0104, 5, 5, 0, 1 },
+				.idfall_det_clr = { 0x0108, 5, 5, 0, 1 },
+				.idrise_det_en	= { 0x0100, 4, 4, 0, 1 },
+				.idrise_det_st	= { 0x0104, 4, 4, 0, 1 },
+				.idrise_det_clr = { 0x0108, 4, 4, 0, 1 },
+				.ls_det_en	= { 0x0100, 0, 0, 0, 1 },
+				.ls_det_st	= { 0x0104, 0, 0, 0, 1 },
+				.ls_det_clr	= { 0x0108, 0, 0, 0, 1 },
+				.utmi_avalid	= { 0x0060, 10, 10, 0, 1 },
+				.utmi_bvalid	= { 0x0060, 9, 9, 0, 1 },
+				//.utmi_iddig	= { 0x0060, 6, 6, 0, 1 },
+				.utmi_ls	= { 0x0060, 5, 4, 0, 1 },
+			},
+		},
+		.chg_det = {
+			//.chg_mode	= { 0x0050, 8, 0, 0, 0x1d7 },
+			.cp_det		= { 0x0060, 13, 13, 0, 1 },
+			.dcp_det	= { 0x0060, 12, 12, 0, 1 },
+			.dp_det		= { 0x0060, 14, 14, 0, 1 },
+			.idm_sink_en	= { 0x0058, 8, 8, 0, 1 },
+			.idp_sink_en	= { 0x0058, 7, 7, 0, 1 },
+			.idp_src_en	= { 0x0058, 9, 9, 0, 1 },
+			.rdm_pdwn_en	= { 0x0058, 10, 10, 0, 1 },
+			.vdm_src_en	= { 0x0058, 12, 12, 0, 1 },
+			.vdp_src_en	= { 0x0058, 11, 11, 0, 1 },
+		},
+	},
+	{ /* sentinel */ }
+};
+
 static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = {
 	{
 		.reg = 0x100,
@@ -2214,6 +2346,7 @@ static const struct of_device_id rockchip_usb2phy_dt_match[] = {
 	{ .compatible = "rockchip,rk3576-usb2phy", .data = &rk3576_phy_cfgs },
 	{ .compatible = "rockchip,rk3588-usb2phy", .data = &rk3588_phy_cfgs },
 	{ .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs },
+	{ .compatible = "rockchip,rv1106-usb2phy", .data = &rv1106_phy_cfgs },
 	{}
 };
 MODULE_DEVICE_TABLE(of, rockchip_usb2phy_dt_match);
-- 
2.49.0

