From 5fd590b43372d5bc6bb2c82d060808c537f8979a Mon Sep 17 00:00:00 2001
From: Takuma Fujiwara <t-fujiwara1@ti.com>
Date: Fri, 3 Nov 2023 10:44:32 -0500
Subject: [PATCH] PCIe internal refclk patches for 8.6 SDK on TDA4VM/J721E
 Changes include device tree changes to select core_ref_clk and applying
 changes from FAQ:
 https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1004565/faq-tda4vm-tda4vm-dra829v-routing-pcie-reference-clock-externally

---
 .../dts/ti/k3-j721e-common-proc-board.dts     | 62 +++++++------
 drivers/phy/cadence/phy-cadence-sierra.c      | 93 +++++++++++++++++--
 2 files changed, 119 insertions(+), 36 deletions(-)

diff --git a/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts
index 72f37f447..384632bba 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts
+++ b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts
@@ -955,36 +955,38 @@ &cmn_refclk1 {
 	clock-frequency = <100000000>;
 };
 
-&wiz0_pll1_refclk {
-	assigned-clocks = <&wiz0_pll1_refclk>;
-	assigned-clock-parents = <&cmn_refclk1>;
-};
-
-&wiz0_refclk_dig {
-	assigned-clocks = <&wiz0_refclk_dig>;
-	assigned-clock-parents = <&cmn_refclk1>;
-};
-
-&wiz1_pll1_refclk {
-	assigned-clocks = <&wiz1_pll1_refclk>;
-	assigned-clock-parents = <&cmn_refclk1>;
-};
-
-&wiz1_refclk_dig {
-	assigned-clocks = <&wiz1_refclk_dig>;
-	assigned-clock-parents = <&cmn_refclk1>;
-};
-
-&wiz2_pll1_refclk {
-	assigned-clocks = <&wiz2_pll1_refclk>;
-	assigned-clock-parents = <&cmn_refclk1>;
-};
-
-&wiz2_refclk_dig {
-	assigned-clocks = <&wiz2_refclk_dig>;
-	assigned-clock-parents = <&cmn_refclk1>;
-};
-
+/* 
+ * comment out wiz configuration, because default values of wiz*_pll*_refclk is core_ref_clk in k3-j721e-common-proc-board.dts
+ * &wiz0_pll1_refclk {
+ * 	assigned-clocks = <&wiz0_pll1_refclk>;
+ * 	assigned-clock-parents = <&cmn_refclk1>;
+ * };
+ *
+ * &wiz0_refclk_dig {
+ * 	assigned-clocks = <&wiz0_refclk_dig>;
+ * 	assigned-clock-parents = <&cmn_refclk1>;
+ * };
+ *
+ * &wiz1_pll1_refclk { 
+ * 	assigned-clocks = <&wiz1_pll1_refclk>;
+ * 	assigned-clock-parents = <&cmn_refclk1>;
+ * };
+ *
+ * &wiz1_refclk_dig {
+ * 	assigned-clocks = <&wiz1_refclk_dig>;
+ * 	assigned-clock-parents = <&cmn_refclk1>;
+ * };
+ *
+ * &wiz2_pll1_refclk {
+ * 	assigned-clocks = <&wiz2_pll1_refclk>;
+ * 	assigned-clock-parents = <&cmn_refclk1>;
+ * };
+ *
+ * &wiz2_refclk_dig {
+ * 	assigned-clocks = <&wiz2_refclk_dig>;
+ * 	assigned-clock-parents = <&cmn_refclk1>;
+ * };
+ */
 &cmn_refclk1 {
 	clock-frequency = <100000000>;
 };
diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c
index 588a23b83..b38d7e1a9 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -236,6 +236,16 @@ static const struct reg_field cmn_plllc_clk1outdiv_preg =
 static const struct reg_field cmn_plllc_clk1_en_preg =
 				REG_FIELD(SIERRA_CMN_PLLLC_CLK1_PREG, 12, 12);
 
+
+#define PHY_PMA_CMN_CTRL1					0x0000U
+
+static const struct reg_field phy_pma_cmn_ctrl_rcv_out_en =
+				REG_FIELD(PHY_PMA_CMN_CTRL1, 6, 7);
+static const struct reg_field cmn_plllc_clk1outdiv =
+				REG_FIELD(SIERRA_CMN_PLLLC_CLK1_PREG, 0, 6);
+static const struct reg_field cmn_plllc_clk1_en =
+				REG_FIELD(SIERRA_CMN_PLLLC_CLK1_PREG, 12, 12);
+
 static const char * const clk_names[] = {
 	[CDNS_SIERRA_PLL_CMNLC] = "pll_cmnlc",
 	[CDNS_SIERRA_PLL_CMNLC1] = "pll_cmnlc1",
@@ -365,12 +375,15 @@ struct cdns_sierra_phy {
 	struct regmap *regmap_common_cdb;
 	struct regmap_field *macro_id_type;
 	struct regmap_field *phy_pll_cfg_1;
+	struct regmap_field *phy_pma_cmn_ctrl_rcv_out_en;
 	struct regmap_field *pma_cmn_ready;
 	struct regmap_field *pllctrl_lock[SIERRA_MAX_LANES];
 	struct regmap_field *phy_iso_link_ctrl_1[SIERRA_MAX_LANES];
 	struct regmap_field *cmn_refrcv_refclk_plllc1en_preg[SIERRA_NUM_CMN_PLLC];
 	struct regmap_field *cmn_refrcv_refclk_termen_preg[SIERRA_NUM_CMN_PLLC];
 	struct regmap_field *cmn_plllc_pfdclk1_sel_preg[SIERRA_NUM_CMN_PLLC];
+	struct regmap_field *cmn_plllc_clk1outdiv;
+	struct regmap_field *cmn_plllc_clk1_en;
 	struct clk *input_clks[CDNS_SIERRA_INPUT_CLOCKS];
 	int nsubnodes;
 	u32 num_lanes;
@@ -488,6 +501,14 @@ static const struct regmap_config cdns_sierra_phy_pma_cmn_cdb_config = {
 	.reg_read = cdns_regmap_read, \
 }
 
+static struct regmap_config cdns_sierra_phy_pma_cmn_config = {
+	.name = "sierra_phy_pma_cmn",
+	.reg_stride = 1,
+	.fast_io = true,
+	.reg_write = cdns_regmap_write,
+	.reg_read = cdns_regmap_read,
+};
+
 static const struct regmap_config cdns_sierra_phy_pma_lane_cdb_config[] = {
 	SIERRA_PHY_PMA_LANE_CDB_REGMAP_CONF("0"),
 	SIERRA_PHY_PMA_LANE_CDB_REGMAP_CONF("1"),
@@ -904,12 +925,14 @@ static int cdns_sierra_clk_register(struct cdns_sierra_phy *sp)
 		dev_err(dev, "Failed to pll mux clocks\n");
 		return ret;
 	}
-
-	ret = cdns_sierra_derived_refclk_register(sp);
-	if (ret) {
-		dev_err(dev, "Failed to register derived refclk\n");
-		return ret;
-	}
+    /*
+	 * comment out derived refclk initialization as this conflicts with internal refclk patches
+	 *	ret = cdns_sierra_derived_refclk_register(sp);
+	 *	if (ret) {
+	 *		dev_err(dev, "Failed to register derived refclk\n");
+	 *		return ret;
+	 *	} 
+	 */ 
 
 	sp->clk_data.clks = sp->output_clks;
 	sp->clk_data.clk_num = CDNS_SIERRA_OUTPUT_CLOCKS;
@@ -1016,6 +1039,20 @@ static int cdns_regfield_init(struct cdns_sierra_phy *sp)
 		sp->cmn_refrcv_refclk_termen_preg[i] = field;
 	}
 
+	field = devm_regmap_field_alloc(dev, regmap, cmn_plllc_clk1outdiv);
+	if (IS_ERR(field)) {
+		dev_err(dev, "cmn_plllc_clk1outdiv reg field init failed\n");
+		return PTR_ERR(field);
+	}
+	sp->cmn_plllc_clk1outdiv = field;
+
+	field = devm_regmap_field_alloc(dev, regmap, cmn_plllc_clk1_en);
+	if (IS_ERR(field)) {
+		dev_err(dev, "cmn_plllc_clk1_en field init failed\n");
+		return PTR_ERR(field);
+	}
+	sp->cmn_plllc_clk1_en = field;
+
 	regmap = sp->regmap_phy_pcs_common_cdb;
 	field = devm_regmap_field_alloc(dev, regmap, phy_pll_cfg_1);
 	if (IS_ERR(field)) {
@@ -1024,6 +1061,14 @@ static int cdns_regfield_init(struct cdns_sierra_phy *sp)
 	}
 	sp->phy_pll_cfg_1 = field;
 
+	regmap = sp->regmap_phy_pma_common_cdb;
+	field = devm_regmap_field_alloc(dev, regmap, phy_pma_cmn_ctrl_rcv_out_en);
+	if (IS_ERR(field)) {
+		dev_err(dev, "phy_pma_cmn_ctrl_rcv_out_en field init failed\n");
+		return PTR_ERR(field);
+	}
+	sp->phy_pma_cmn_ctrl_rcv_out_en = field;
+
 	regmap = sp->regmap_phy_pma_common_cdb;
 	field = devm_regmap_field_alloc(dev, regmap, pma_cmn_ready);
 	if (IS_ERR(field)) {
@@ -1130,6 +1175,15 @@ static int cdns_regmap_init_blocks(struct cdns_sierra_phy *sp,
 		sp->regmap_phy_pma_lane_cdb[i] = regmap;
 	}
 
+	block_offset = SIERRA_PHY_PMA_COMMON_OFFSET(block_offset_shift);
+	regmap = cdns_regmap_init(dev, base, block_offset, reg_offset_shift,
+				  &cdns_sierra_phy_pma_cmn_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "Failed to init PHY PMA common CDB regmap\n");
+		return PTR_ERR(regmap);
+	}
+	sp->regmap_phy_pma_common_cdb = regmap;
+
 	return 0;
 }
 
@@ -1499,6 +1553,33 @@ static int cdns_sierra_phy_probe(struct platform_device *pdev)
 			goto put_control;
 	}
 
+	dev_dbg(dev, "\t[SIERRA] %s : Configuring Clock Out from SoC...\n", __func__);
+	regmap_field_write(sp->cmn_plllc_clk1_en, 0x1);
+	/* Programming to get 100Mhz clock output in ref_der_clk_out 5GHz VCO/50 = 100MHz */
+	regmap_field_write(sp->cmn_plllc_clk1outdiv, 0x2e);
+
+	/* Un-lock Partition 2 : 8000h to 9FFFh */
+	writel(0x68EF3490, ioremap(0x00109008, 0x4)); /* LOCK2_KICK0 */
+	writel(0xD172BC5A, ioremap(0x0010900C, 0x4)); /* LOCK2_KICK1 */
+
+	/* Un-lock Partition 6 : 18000h to 19FFFh */
+	writel(0x68EF3490, ioremap(0x00119008, 0x4)); /* LOCK6_KICK0 */
+	writel(0xD172BC5A, ioremap(0x0011900C, 0x4)); /* LOCK6_KICK1 */
+
+	/* Enable ACSPCIe0 PAD 0 and 1 */
+	writel(0x01000000, ioremap(0x00118090, 0x4));
+	/* Enable ACSPCIe1 PAD 0 and 1 */
+	writel(0x01000000, ioremap(0x00118094, 0x4));
+
+	/* PCIE_REFCLK0_CLKSEL : EN + SERDES0_REF_DER_OUT_CLK */
+	writel(0x00000100, ioremap(0x00108070, 0x4));
+	/* PCIE_REFCLK1_CLKSEL : EN + SERDES1_REF_DER_OUT_CLK */
+	writel(0x00000101, ioremap(0x00108074, 0x4));
+	/* PCIE_REFCLK2_CLKSEL : EN + SERDES0_REF_DER_OUT_CLK */
+	writel(0x00000100, ioremap(0x00108078, 0x4));
+	/* PCIE_REFCLK3_CLKSEL : EN + SERDES1_REF_DER_OUT_CLK */
+	writel(0x00000101, ioremap(0x0010807C, 0x4));
+
 	pm_runtime_enable(dev);
 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
 	if (IS_ERR(phy_provider)) {
-- 
2.34.1

