diff mbox series

[RFC,2/2] pci: j721e: Enable reference clock output from serdes

Message ID 20230905114816.2993628-3-a-verma1@ti.com
State New
Headers show
Series Enable PCIe1 on J7AHP | expand

Commit Message

Achal Verma Sept. 5, 2023, 11:48 a.m. UTC
PCIe1 in J7AHP EVM has EP side connector reference clock connection from
serdes named SOC_SERDES0_REFCLK(PCIE_REFCLK_OUT) unlike PCIe0 which has
reference clock connection from on-board serdes. To enable this reference
clock out, ACSPCIE clock buffer pads have to be enabled.

This change enables ACSPCIE clock buffer pads and select clock source for
reference clock output.

Signed-off-by: Achal Verma <a-verma1@ti.com>
---
 .../pci/controller/cadence/pci-j721e-host.c   | 96 +++++++++++++++++++
 1 file changed, 96 insertions(+)

Comments

Bjorn Helgaas Sept. 5, 2023, 4:27 p.m. UTC | #1
Previous j721e subject line history is like this:

  c86f4bd6008e ("PCI: j721e: Convert to platform remove callback returning void")
  053ca37c87af ("PCI: j721e: Initialize pcie->cdns_pcie before using it")
  19e863828acf ("PCI: j721e: Drop redundant struct device *")
  72de208f2bda ("PCI: j721e: Drop pointless of_device_get_match_data() cast")
  496bb18483cc ("PCI: j721e: Fix j721e_pcie_probe() error path")
  c8a375a8e15a ("PCI: j721e: Add PCIe support for AM64")

Match capitalization style, i.e., "PCI: " instead of "pci: "

On Tue, Sep 05, 2023 at 05:18:16PM +0530, Achal Verma wrote:
> PCIe1 in J7AHP EVM has EP side connector reference clock connection from
> serdes named SOC_SERDES0_REFCLK(PCIE_REFCLK_OUT) unlike PCIe0 which has
> reference clock connection from on-board serdes. To enable this reference
> clock out, ACSPCIE clock buffer pads have to be enabled.
> 
> This change enables ACSPCIE clock buffer pads and select clock source for
> reference clock output.

s/This change enables/Enable/
s/and select/and selects/

> +static int j721e_enable_acspcie(struct j721e_pcie *pcie)
> +{
> +	struct device *dev = pcie->cdns_pcie->dev;
> +	struct device_node *node = dev->of_node;
> +	struct of_phandle_args args;
> +	unsigned int lock2_kick0_offset, lock2_kick1_offset;
> +	unsigned int acspcie_pad_offset, refclk_clksel_offset;
> +	unsigned int refclk_clksel_source;
> +	struct regmap *syscon;
> +	u32 val = 0, mask = 0;

Looks like these initializations are unnecessary?

> +	syscon = syscon_regmap_lookup_by_phandle(node, "ti,syscon-pcie-refclk-out");

Looks like this and the of_parse_phandle_with_fixed_args() below don't
fit in 80 columns like the rest of the file.

> +	ret = of_parse_phandle_with_fixed_args(node, "ti,syscon-pcie-refclk-out", 5,
> +						0, &args);

> +	/* Enable ACSPCIe PADS  */

Spurious extra space at end of comment.

> +	/*
> +	 * Enable ACSPCIe clock buffer to source out reference clock for EP
> +	 */

Looks like it could be a single-line comment, e.g.,

  /* Enable ACSPCIe clock buffer to source out reference clock for EP */
diff mbox series

Patch

diff --git a/drivers/pci/controller/cadence/pci-j721e-host.c b/drivers/pci/controller/cadence/pci-j721e-host.c
index af47aa090159..106472920f68 100644
--- a/drivers/pci/controller/cadence/pci-j721e-host.c
+++ b/drivers/pci/controller/cadence/pci-j721e-host.c
@@ -10,10 +10,21 @@ 
 #include <linux/gpio/consumer.h>
 #include <linux/delay.h>
 #include <linux/of_device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 
 #include "pcie-cadence.h"
 #include "pci-j721e.h"
 
+#define CTRL_MMR_LOCK2_MASK		0xFFFFFFFF
+#define CTRL_MMR_LOCK2_KICK0_UNLOCK_VAL	0x68EF3490
+#define CTRL_MMR_LOCK2_KICK1_UNLOCK_VAL	0xD172BC5A
+#define CTRL_MMR_LOCK_KICK_LOCK_VAL	0xFFFFFFFF
+#define CTRL_MMR_ACSPCIE_PAD_MASK	0xFFFFFFFF
+#define CTRL_MMR_ACSPCIE_PAD_EN		0x01000000
+#define PCIE_REFCLK_CLKSEL_OUT_EN	BIT(8)
+#define PCIE_REFCLK_CLKSEL_MASK	GENMASK(1, 0)
+
 static int cdns_ti_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
 				    int where, int size, u32 *value)
 {
@@ -79,6 +90,84 @@  static const struct of_device_id of_j721e_pcie_host_match[] = {
 };
 MODULE_DEVICE_TABLE(of, of_j721e_pcie_host_match);
 
+static int j721e_enable_acspcie(struct j721e_pcie *pcie)
+{
+	struct device *dev = pcie->cdns_pcie->dev;
+	struct device_node *node = dev->of_node;
+	struct of_phandle_args args;
+	unsigned int lock2_kick0_offset, lock2_kick1_offset;
+	unsigned int acspcie_pad_offset, refclk_clksel_offset;
+	unsigned int refclk_clksel_source;
+	struct regmap *syscon;
+	u32 val = 0, mask = 0;
+	int ret;
+
+	/*
+	 * If property ti,syscon-pcie-refclk-out exists, believe PCIe connector
+	 * requires PCIe ref clock from Serdes, so enable ACSPCIE pads and mux
+	 * to source out PCIe ref clock else ref clock has to be supplied from
+	 * on-board clock generator.
+	 */
+	syscon = syscon_regmap_lookup_by_phandle(node, "ti,syscon-pcie-refclk-out");
+	if (IS_ERR(syscon))
+		return 0;
+
+	ret = of_parse_phandle_with_fixed_args(node, "ti,syscon-pcie-refclk-out", 5,
+						0, &args);
+	if (ret) {
+		dev_err(dev, "Failed to read ti,syscon-pcie-refclk-out property\n");
+		return ret;
+	}
+
+	lock2_kick0_offset = args.args[0];
+	lock2_kick1_offset = args.args[1];
+	acspcie_pad_offset = args.args[2];
+	refclk_clksel_offset = args.args[3];
+	refclk_clksel_source = args.args[4];
+
+	/* Un-lock Partition 2 : 8000h to 9FFFh */
+	mask = CTRL_MMR_LOCK2_MASK;
+	val = CTRL_MMR_LOCK2_KICK0_UNLOCK_VAL;
+	ret = regmap_update_bits(syscon, lock2_kick0_offset, mask, val);
+	if (ret)
+		goto err;
+
+	val = CTRL_MMR_LOCK2_KICK1_UNLOCK_VAL;
+	ret = regmap_update_bits(syscon, lock2_kick1_offset, mask, val);
+	if (ret)
+		goto err;
+
+	/* Enable ACSPCIe PADS  */
+	mask = CTRL_MMR_ACSPCIE_PAD_MASK;
+	val = CTRL_MMR_ACSPCIE_PAD_EN;
+	ret = regmap_update_bits(syscon, acspcie_pad_offset, mask, val);
+	if (ret)
+		goto err;
+
+	/* PCIE_REFCLKx_CLKSEL : EN + ref_clk_source */
+	mask = PCIE_REFCLK_CLKSEL_OUT_EN | PCIE_REFCLK_CLKSEL_MASK;
+	val = PCIE_REFCLK_CLKSEL_OUT_EN | refclk_clksel_source;
+	ret = regmap_update_bits(syscon, refclk_clksel_offset, mask, val);
+	if (ret)
+		goto err;
+
+	/* Re-lock Partition 2 : 8000h to 9FFFh */
+	mask = CTRL_MMR_LOCK_KICK_LOCK_VAL;
+	val = CTRL_MMR_LOCK_KICK_LOCK_VAL;
+	ret = regmap_update_bits(syscon, lock2_kick0_offset, mask, val);
+	if (ret)
+		goto err;
+
+	ret = regmap_update_bits(syscon, lock2_kick1_offset, mask, val);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	dev_err(dev, "Failed to enable ref clock out\n");
+	return ret;
+}
+
 static int j721e_pcie_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -121,6 +210,13 @@  static int j721e_pcie_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	/*
+	 * Enable ACSPCIe clock buffer to source out reference clock for EP
+	 */
+	ret = j721e_enable_acspcie(pcie);
+	if (ret < 0)
+		return ret;
+
 	pcie->perst_gpiod = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
 	if (IS_ERR(pcie->perst_gpiod)) {
 		ret = PTR_ERR(pcie->perst_gpiod);