Commit 8197ec49 authored by John Madieu's avatar John Madieu Committed by Manivannan Sadhasivam
Browse files

PCI: rzg3s-host: Add support for RZ/G3E PCIe controller



Add support for the PCIe controller found in RZ/G3E SoCs to the existing
RZ/G3S PCIe host controller driver. The RZ/G3E PCIe controller is similar
to the RZ/G3S, with the following key differences:

 - Supports PCIe Gen3 (8.0 GT/s) link speeds alongside Gen2 (5.0 GT/s)
 - Uses a different reset control mechanism via AXI registers instead
   of the Linux reset framework
 - Requires specific SYSC configuration for link state control and
   Root Complex mode selection

Signed-off-by: default avatarJohn Madieu <john.madieu.xa@bp.renesas.com>
[mani: added a readl_relaxed() before fsleep() to flush previous write]
Signed-off-by: default avatarManivannan Sadhasivam <mani@kernel.org>
Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> # RZ/V2N EVK
Tested-by: default avatarClaudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Reviewed-by: default avatarClaudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Link: https://patch.msgid.link/20260306143423.19562-13-john.madieu.xa@bp.renesas.com
parent 5e9a5af5
Loading
Loading
Loading
Loading
+93 −0
Original line number Diff line number Diff line
@@ -111,6 +111,15 @@
#define RZG3S_PCI_PERM_CFG_HWINIT_EN		BIT(2)
#define RZG3S_PCI_PERM_PIPE_PHY_REG_EN		BIT(1)

#define RZG3S_PCI_RESET				0x310
#define RZG3S_PCI_RESET_RST_OUT_B		BIT(6)
#define RZG3S_PCI_RESET_RST_PS_B		BIT(5)
#define RZG3S_PCI_RESET_RST_LOAD_B		BIT(4)
#define RZG3S_PCI_RESET_RST_CFG_B		BIT(3)
#define RZG3S_PCI_RESET_RST_RSM_B		BIT(2)
#define RZG3S_PCI_RESET_RST_GP_B		BIT(1)
#define RZG3S_PCI_RESET_RST_B			BIT(0)

#define RZG3S_PCI_MSIRE(id)			(0x600 + (id) * 0x10)
#define RZG3S_PCI_MSIRE_ENA			BIT(0)

@@ -183,10 +192,14 @@ struct rzg3s_sysc_function {
/**
 * enum rzg3s_sysc_func_id - System controller function IDs
 * @RZG3S_SYSC_FUNC_ID_RST_RSM_B: RST_RSM_B SYSC function ID
 * @RZG3S_SYSC_FUNC_ID_L1_ALLOW: L1 allow SYSC function ID
 * @RZG3S_SYSC_FUNC_ID_MODE: Mode SYSC function ID
 * @RZG3S_SYSC_FUNC_ID_MAX: Max SYSC function ID
 */
enum rzg3s_sysc_func_id {
	RZG3S_SYSC_FUNC_ID_RST_RSM_B,
	RZG3S_SYSC_FUNC_ID_L1_ALLOW,
	RZG3S_SYSC_FUNC_ID_MODE,
	RZG3S_SYSC_FUNC_ID_MAX,
};

@@ -1151,6 +1164,45 @@ static int rzg3s_pcie_config_deinit(struct rzg3s_pcie_host *host)
					 host->cfg_resets);
}

static void rzg3e_pcie_config_pre_init(struct rzg3s_pcie_host *host)
{
	u32 mask = RZG3S_PCI_RESET_RST_LOAD_B | RZG3S_PCI_RESET_RST_CFG_B;

	/* De-assert LOAD_B and CFG_B */
	rzg3s_pcie_update_bits(host->axi, RZG3S_PCI_RESET, mask, mask);
}

static int rzg3e_pcie_config_deinit(struct rzg3s_pcie_host *host)
{
	writel_relaxed(0, host->axi + RZG3S_PCI_RESET);
	return 0;
}

static int rzg3e_pcie_config_post_init(struct rzg3s_pcie_host *host)
{
	u32 mask = RZG3S_PCI_RESET_RST_PS_B | RZG3S_PCI_RESET_RST_GP_B |
		   RZG3S_PCI_RESET_RST_B;

	/* De-assert PS_B, GP_B, RST_B */
	rzg3s_pcie_update_bits(host->axi, RZG3S_PCI_RESET, mask, mask);

	/* Flush deassert */
	readl_relaxed(host->axi + RZG3S_PCI_RESET);

	/*
	 * According to the RZ/G3E HW manual (Rev.1.15, Table 6.6-130
	 * Initialization Procedure (RC)), hardware requires >= 500us delay
	 * before final reset deassert.
	 */
	fsleep(500);

	/* De-assert OUT_B and RSM_B */
	mask = RZG3S_PCI_RESET_RST_OUT_B | RZG3S_PCI_RESET_RST_RSM_B;
	rzg3s_pcie_update_bits(host->axi, RZG3S_PCI_RESET, mask, mask);

	return 0;
}

static void rzg3s_pcie_irq_init(struct rzg3s_pcie_host *host)
{
	/*
@@ -1312,6 +1364,12 @@ static int rzg3s_pcie_host_init(struct rzg3s_pcie_host *host)
	if (ret)
		goto config_deinit;

	/* Enable ASPM L1 transition for SoCs that use it */
	ret = rzg3s_sysc_config_func(host->sysc,
				     RZG3S_SYSC_FUNC_ID_L1_ALLOW, 1);
	if (ret)
		goto config_deinit_and_refclk;

	/* Initialize the interrupts */
	rzg3s_pcie_irq_init(host);

@@ -1659,6 +1717,11 @@ static int rzg3s_pcie_probe(struct platform_device *pdev)
		goto port_refclk_put;
	}

	/* Put controller in RC mode */
	ret = rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_MODE, 1);
	if (ret)
		goto port_refclk_put;

	ret = rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 1);
	if (ret)
		goto port_refclk_put;
@@ -1769,6 +1832,10 @@ static int rzg3s_pcie_resume_noirq(struct device *dev)
	struct rzg3s_sysc *sysc = host->sysc;
	int ret;

	ret = rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_MODE, 1);
	if (ret)
		return ret;

	ret = rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 1);
	if (ret)
		return ret;
@@ -1833,11 +1900,37 @@ static const struct rzg3s_pcie_soc_data rzg3s_soc_data = {
	},
};

static const char * const rzg3e_soc_power_resets[] = { "aresetn" };

static const struct rzg3s_pcie_soc_data rzg3e_soc_data = {
	.power_resets = rzg3e_soc_power_resets,
	.num_power_resets = ARRAY_SIZE(rzg3e_soc_power_resets),
	.config_pre_init = rzg3e_pcie_config_pre_init,
	.config_post_init = rzg3e_pcie_config_post_init,
	.config_deinit = rzg3e_pcie_config_deinit,
	.sysc_info = {
		.functions = {
			[RZG3S_SYSC_FUNC_ID_L1_ALLOW] = {
				.offset = 0x1020,
				.mask = BIT(0),
			},
			[RZG3S_SYSC_FUNC_ID_MODE] = {
				.offset = 0x1024,
				.mask = BIT(0),
			},
		},
	},
};

static const struct of_device_id rzg3s_pcie_of_match[] = {
	{
		.compatible = "renesas,r9a08g045-pcie",
		.data = &rzg3s_soc_data,
	},
	{
		.compatible = "renesas,r9a09g047-pcie",
		.data = &rzg3e_soc_data,
	},
	{}
};