Commit b274423c authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/controller/rzg3s-host'

- Assert (not deassert) resets in probe error path (John Madieu)

- Assert resets in suspend path in reverse order they were deasserted
  during probe (John Madieu)

- Rework inbound window algorithm to prevent mapping more than intended
  region and enforce alignment on size, to prepare for RZ/G3E support (John
  Madieu)

- Fix renesas,r9a08g045s33-pcie 'serr_cor' typo and convert properties from
  'description' to 'const' for better validation (John Madieu)

- Add RZ/G3E to DT binding and to driver (John Madieu)

* pci/controller/rzg3s-host:
  PCI: rzg3s-host: Add support for RZ/G3E PCIe controller
  PCI: rzg3s-host: Add PCIe Gen3 (8.0 GT/s) link speed support
  PCI: rzg3s-host: Explicitly set class code for RZ/G3E compatibility
  PCI: rzg3s-host: Add SoC-specific configuration and initialization callbacks
  PCI: rzg3s-host: Make configuration reset lines optional
  PCI: rzg3s-host: Make SYSC register offsets SoC-specific
  dt-bindings: PCI: renesas,r9a08g045s33-pcie: Document RZ/G3E SoC
  dt-bindings: PCI: renesas,r9a08g045s33-pcie: Fix naming properties
  PCI: rzg3s-host: Rework inbound window algorithm for supporting RZ/G3E SoC
  PCI: rzg3s-host: Reorder reset assertion during suspend
  PCI: rzg3s-host: Fix reset handling in probe error path

# Conflicts:
#	drivers/pci/controller/pcie-rzg3s-host.c
parents d096bd7d 8197ec49
Loading
Loading
Loading
Loading
+91 −30
Original line number Diff line number Diff line
@@ -10,17 +10,21 @@ maintainers:
  - Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

description:
  Renesas RZ/G3S PCIe host controller complies with PCIe Base Specification
  4.0 and supports up to 5 GT/s (Gen2).
  Renesas RZ/G3{E,S} PCIe host controllers comply with PCIe
  Base Specification 4.0 and support up to 5 GT/s (Gen2) for RZ/G3S and
  up to 8 GT/s (Gen3) for RZ/G3E.

properties:
  compatible:
    const: renesas,r9a08g045-pcie # RZ/G3S
    enum:
      - renesas,r9a08g045-pcie # RZ/G3S
      - renesas,r9a09g047-pcie # RZ/G3E

  reg:
    maxItems: 1

  interrupts:
    minItems: 16
    items:
      - description: System error interrupt
      - description: System error on correctable error interrupt
@@ -38,39 +42,55 @@ properties:
      - description: PCIe event interrupt
      - description: Message interrupt
      - description: All interrupts
      - description: Link equalization request interrupt
      - description: Turn off event interrupt
      - description: PMU power off interrupt
      - description: D3 event function 0 interrupt
      - description: D3 event function 1 interrupt
      - description: Configuration PMCSR write clear function 0 interrupt
      - description: Configuration PMCSR write clear function 1 interrupt

  interrupt-names:
    minItems: 16
    items:
      - description: serr
      - description: ser_cor
      - description: serr_nonfatal
      - description: serr_fatal
      - description: axi_err
      - description: inta
      - description: intb
      - description: intc
      - description: intd
      - description: msi
      - description: link_bandwidth
      - description: pm_pme
      - description: dma
      - description: pcie_evt
      - description: msg
      - description: all
      - const: serr
      - const: serr_cor
      - const: serr_nonfatal
      - const: serr_fatal
      - const: axi_err
      - const: inta
      - const: intb
      - const: intc
      - const: intd
      - const: msi
      - const: link_bandwidth
      - const: pm_pme
      - const: dma
      - const: pcie_evt
      - const: msg
      - const: all
      - const: link_equalization_request
      - const: turn_off_event
      - const: pmu_poweroff
      - const: d3_event_f0
      - const: d3_event_f1
      - const: cfg_pmcsr_writeclear_f0
      - const: cfg_pmcsr_writeclear_f1

  interrupt-controller: true

  clocks:
    items:
      - description: System clock
      - description: PM control clock
      - description: PM control clock or clock for L1 substate handling

  clock-names:
    items:
      - description: aclk
      - description: pm
      - const: aclk
      - enum: [pm, pmu]

  resets:
    minItems: 1
    items:
      - description: AXI2PCIe Bridge reset
      - description: Data link layer/transaction layer reset
@@ -81,14 +101,15 @@ properties:
      - description: Configuration register reset

  reset-names:
    minItems: 1
    items:
      - description: aresetn
      - description: rst_b
      - description: rst_gp_b
      - description: rst_ps_b
      - description: rst_rsm_b
      - description: rst_cfg_b
      - description: rst_load_b
      - const: aresetn
      - const: rst_b
      - const: rst_gp_b
      - const: rst_ps_b
      - const: rst_rsm_b
      - const: rst_cfg_b
      - const: rst_load_b

  power-domains:
    maxItems: 1
@@ -128,7 +149,9 @@ patternProperties:
        const: 0x1912

      device-id:
        const: 0x0033
        enum:
          - 0x0033
          - 0x0039

      clocks:
        items:
@@ -167,6 +190,44 @@ required:

allOf:
  - $ref: /schemas/pci/pci-host-bridge.yaml#
  - if:
      properties:
        compatible:
          contains:
            const: renesas,r9a08g045-pcie
    then:
      properties:
        interrupts:
          maxItems: 16
        interrupt-names:
          maxItems: 16
        clock-names:
          items:
            - const: aclk
            - const: pm
        resets:
          minItems: 7
        reset-names:
          minItems: 7
  - if:
      properties:
        compatible:
          contains:
            const: renesas,r9a09g047-pcie
    then:
      properties:
        interrupts:
          minItems: 23
        interrupt-names:
          minItems: 23
        clock-names:
          items:
            - const: aclk
            - const: pmu
        resets:
          maxItems: 1
        reset-names:
          maxItems: 1

unevaluatedProperties: false

+285 −80
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)

@@ -159,10 +168,6 @@

#define RZG3S_PCI_CFG_PCIEC			0x60

/* System controller registers */
#define RZG3S_SYS_PCIE_RST_RSM_B		0xd74
#define RZG3S_SYS_PCIE_RST_RSM_B_MASK		BIT(0)

/* Maximum number of windows */
#define RZG3S_MAX_WINDOWS			8

@@ -174,6 +179,48 @@
/* Timeouts experimentally determined */
#define RZG3S_REQ_ISSUE_TIMEOUT_US		2500

/**
 * struct rzg3s_sysc_function - System Controller function descriptor
 * @offset: Register offset from the System Controller base address
 * @mask: Bit mask for the function within the register
 */
struct rzg3s_sysc_function {
	u32 offset;
	u32 mask;
};

/**
 * 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,
};

/**
 * struct rzg3s_sysc_info - RZ/G3S System Controller info
 * @functions: SYSC function descriptors array
 */
struct rzg3s_sysc_info {
	const struct rzg3s_sysc_function functions[RZG3S_SYSC_FUNC_ID_MAX];
};

/**
 * struct rzg3s_sysc - RZ/G3S System Controller descriptor
 * @regmap: System controller regmap
 * @info: System controller info
 */
struct rzg3s_sysc {
	struct regmap *regmap;
	const struct rzg3s_sysc_info *info;
};

/**
 * struct rzg3s_pcie_msi - RZ/G3S PCIe MSI data structure
 * @domain: IRQ domain
@@ -199,17 +246,25 @@ struct rzg3s_pcie_host;
/**
 * struct rzg3s_pcie_soc_data - SoC specific data
 * @init_phy: PHY initialization function
 * @config_pre_init: Optional callback for SoC-specific pre-configuration
 * @config_post_init: Callback for SoC-specific post-configuration
 * @config_deinit: Callback for SoC-specific de-initialization
 * @power_resets: array with the resets that need to be de-asserted after
 *                power-on
 * @cfg_resets: array with the resets that need to be de-asserted after
 *              configuration
 * @sysc_info: SYSC info
 * @num_power_resets: number of power resets
 * @num_cfg_resets: number of configuration resets
 */
struct rzg3s_pcie_soc_data {
	int (*init_phy)(struct rzg3s_pcie_host *host);
	void (*config_pre_init)(struct rzg3s_pcie_host *host);
	int (*config_post_init)(struct rzg3s_pcie_host *host);
	int (*config_deinit)(struct rzg3s_pcie_host *host);
	const char * const *power_resets;
	const char * const *cfg_resets;
	struct rzg3s_sysc_info sysc_info;
	u8 num_power_resets;
	u8 num_cfg_resets;
};
@@ -233,7 +288,7 @@ struct rzg3s_pcie_port {
 * @dev: struct device
 * @power_resets: reset control signals that should be set after power up
 * @cfg_resets: reset control signals that should be set after configuration
 * @sysc: SYSC regmap
 * @sysc: SYSC descriptor
 * @intx_domain: INTx IRQ domain
 * @data: SoC specific data
 * @msi: MSI data structure
@@ -248,7 +303,7 @@ struct rzg3s_pcie_host {
	struct device *dev;
	struct reset_control_bulk_data *power_resets;
	struct reset_control_bulk_data *cfg_resets;
	struct regmap *sysc;
	struct rzg3s_sysc *sysc;
	struct irq_domain *intx_domain;
	const struct rzg3s_pcie_soc_data *data;
	struct rzg3s_pcie_msi msi;
@@ -260,6 +315,23 @@ struct rzg3s_pcie_host {

#define rzg3s_msi_to_host(_msi)	container_of(_msi, struct rzg3s_pcie_host, msi)

static int rzg3s_sysc_config_func(struct rzg3s_sysc *sysc,
				  enum rzg3s_sysc_func_id fid, u32 val)
{
	const struct rzg3s_sysc_info *info = sysc->info;
	const struct rzg3s_sysc_function *functions = info->functions;

	if (fid >= RZG3S_SYSC_FUNC_ID_MAX)
		return -EINVAL;

	if (!functions[fid].mask)
		return 0;

	return regmap_update_bits(sysc->regmap, functions[fid].offset,
				  functions[fid].mask,
				  field_prep(functions[fid].mask, val));
}

static void rzg3s_pcie_update_bits(void __iomem *base, u32 offset, u32 mask,
				   u32 val)
{
@@ -945,8 +1017,9 @@ static int rzg3s_pcie_set_max_link_speed(struct rzg3s_pcie_host *host)
{
	u32 remote_supported_link_speeds, max_supported_link_speeds;
	u32 cs2, tmp, pcie_cap = RZG3S_PCI_CFG_PCIEC;
	u32 cur_link_speed, link_speed;
	u32 cur_link_speed, link_speed, hw_max_speed;
	u8 ltssm_state_l0 = 0xc;
	u32 lnkcap;
	int ret;
	u16 ls;

@@ -966,7 +1039,22 @@ static int rzg3s_pcie_set_max_link_speed(struct rzg3s_pcie_host *host)
	ls = readw_relaxed(host->pcie + pcie_cap + PCI_EXP_LNKSTA);
	cs2 = readl_relaxed(host->axi + RZG3S_PCI_PCSTAT2);

	switch (pcie_get_link_speed(host->max_link_speed)) {
	/* Read hardware supported link speed from Link Capabilities Register */
	lnkcap = readl_relaxed(host->pcie + pcie_cap + PCI_EXP_LNKCAP);
	hw_max_speed = FIELD_GET(PCI_EXP_LNKCAP_SLS, lnkcap);

	/*
	 * Use DT max-link-speed only as a limit. If specified and lower
	 * than hardware capability, cap to that value.
	 */
	if (host->max_link_speed > 0 && host->max_link_speed < hw_max_speed)
		hw_max_speed = host->max_link_speed;

	switch (pcie_get_link_speed(hw_max_speed)) {
	case PCIE_SPEED_8_0GT:
		max_supported_link_speeds = GENMASK(PCI_EXP_LNKSTA_CLS_8_0GB - 1, 0);
		link_speed = PCI_EXP_LNKCTL2_TLS_8_0GT;
		break;
	case PCIE_SPEED_5_0GT:
		max_supported_link_speeds = GENMASK(PCI_EXP_LNKSTA_CLS_5_0GB - 1, 0);
		link_speed = PCI_EXP_LNKCTL2_TLS_5_0GT;
@@ -982,10 +1070,10 @@ static int rzg3s_pcie_set_max_link_speed(struct rzg3s_pcie_host *host)
	remote_supported_link_speeds &= max_supported_link_speeds;

	/*
	 * Return if max link speed is already set or the connected device
	 * Return if target link speed is already set or the connected device
	 * doesn't support it.
	 */
	if (cur_link_speed == host->max_link_speed ||
	if (cur_link_speed == hw_max_speed ||
	    remote_supported_link_speeds != max_supported_link_speeds)
		return 0;

@@ -1022,6 +1110,7 @@ static int rzg3s_pcie_set_max_link_speed(struct rzg3s_pcie_host *host)
static int rzg3s_pcie_config_init(struct rzg3s_pcie_host *host)
{
	struct pci_host_bridge *bridge = pci_host_bridge_from_priv(host);
	u32 mask = GENMASK(31, 8);
	struct resource_entry *ft;
	struct resource *bus;
	u8 subordinate_bus;
@@ -1045,6 +1134,13 @@ static int rzg3s_pcie_config_init(struct rzg3s_pcie_host *host)
	writel_relaxed(0xffffffff, host->pcie + RZG3S_PCI_CFG_BARMSK00L);
	writel_relaxed(0xffffffff, host->pcie + RZG3S_PCI_CFG_BARMSK00U);

	/*
	 * Explicitly program class code. RZ/G3E requires this configuration.
	 * Harmless for RZ/G3S where this matches the hardware default.
	 */
	rzg3s_pcie_update_bits(host->pcie, PCI_CLASS_REVISION, mask,
			       field_prep(mask, PCI_CLASS_BRIDGE_PCI_NORMAL));

	/* Disable access control to the CFGU */
	writel_relaxed(0, host->axi + RZG3S_PCI_PERM);

@@ -1056,6 +1152,57 @@ static int rzg3s_pcie_config_init(struct rzg3s_pcie_host *host)
	return 0;
}

static int rzg3s_pcie_config_post_init(struct rzg3s_pcie_host *host)
{
	return reset_control_bulk_deassert(host->data->num_cfg_resets,
					   host->cfg_resets);
}

static int rzg3s_pcie_config_deinit(struct rzg3s_pcie_host *host)
{
	return reset_control_bulk_assert(host->data->num_cfg_resets,
					 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)
{
	/*
@@ -1135,7 +1282,7 @@ static int rzg3s_pcie_resets_prepare_and_get(struct rzg3s_pcie_host *host)
	if (ret)
		return ret;

	return devm_reset_control_bulk_get_exclusive(host->dev,
	return devm_reset_control_bulk_get_optional_exclusive(host->dev,
							      data->num_cfg_resets,
							      host->cfg_resets);
}
@@ -1204,22 +1351,32 @@ static int rzg3s_pcie_host_init(struct rzg3s_pcie_host *host)
	u32 val;
	int ret;

	/* SoC-specific pre-configuration */
	if (host->data->config_pre_init)
		host->data->config_pre_init(host);

	/* Initialize the PCIe related registers */
	ret = rzg3s_pcie_config_init(host);
	if (ret)
		return ret;
		goto config_deinit;

	ret = rzg3s_pcie_host_init_port(host);
	if (ret)
		return 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);

	ret = reset_control_bulk_deassert(host->data->num_cfg_resets,
					  host->cfg_resets);
	/* SoC-specific post-configuration */
	ret = host->data->config_post_init(host);
	if (ret)
		goto disable_port_refclk;
		goto config_deinit_and_refclk;

	/* Wait for link up */
	ret = readl_poll_timeout(host->axi + RZG3S_PCI_PCSTAT1, val,
@@ -1228,18 +1385,20 @@ static int rzg3s_pcie_host_init(struct rzg3s_pcie_host *host)
				 PCIE_LINK_WAIT_SLEEP_MS * MILLI *
				 PCIE_LINK_WAIT_MAX_RETRIES);
	if (ret)
		goto cfg_resets_deassert;
		goto config_deinit_post;

	val = readl_relaxed(host->axi + RZG3S_PCI_PCSTAT2);
	dev_info(host->dev, "PCIe link status [0x%x]\n", val);

	return 0;

cfg_resets_deassert:
	reset_control_bulk_assert(host->data->num_cfg_resets,
				  host->cfg_resets);
disable_port_refclk:
config_deinit_post:
	host->data->config_deinit(host);
config_deinit_and_refclk:
	clk_disable_unprepare(host->port.refclk);
config_deinit:
	if (host->data->config_pre_init)
		host->data->config_deinit(host);
	return ret;
}

@@ -1271,50 +1430,55 @@ static int rzg3s_pcie_set_inbound_windows(struct rzg3s_pcie_host *host,
	u64 pci_addr = entry->res->start - entry->offset;
	u64 cpu_addr = entry->res->start;
	u64 cpu_end = entry->res->end;
	u64 size_id = 0;
	int id = *index;
	u64 size;

	while (cpu_addr < cpu_end) {
	/*
	 * According to the RZ/G3S HW manual (Rev.1.10, section 34.6.6.7) and
	 * RZ/G3E HW manual (Rev.1.15, section 6.6.7.6):
	 * - Each window must be a single memory size of power of two
	 * - Mask registers must be set to (2^N - 1)
	 * - Bit carry must not occur when adding base and mask registers,
	 *   meaning the base address must be aligned to the window size
	 *
	 * Split non-power-of-2 regions into multiple windows to satisfy
	 * these constraints without over-mapping.
	 */
	while (cpu_addr <= cpu_end) {
		u64 remaining_size = cpu_end - cpu_addr + 1;
		u64 align_limit;

		if (id >= RZG3S_MAX_WINDOWS)
			return dev_err_probe(host->dev, -ENOSPC,
					     "Failed to map inbound window for resource (%s)\n",
					     entry->res->name);

		size = resource_size(entry->res) - size_id;
		/* Start with largest power-of-two that fits in remaining size */
		size = 1ULL << __fls(remaining_size);

		/*
		 * According to the RZ/G3S HW manual (Rev.1.10,
		 * section 34.3.1.71 AXI Window Mask (Lower) Registers) the min
		 * size is 4K.
		 * The "no bit carry" rule requires base addresses to be
		 * aligned to the window size. Find the maximum window size
		 * that both addresses can support based on their natural
		 * alignment (lowest set bit).
		 */
		size = max(size, SZ_4K);
		align_limit = min(cpu_addr ? (1ULL << __ffs(cpu_addr)) : ~0ULL,
				  pci_addr ? (1ULL << __ffs(pci_addr)) : ~0ULL);

		/*
		 * According the RZ/G3S HW manual (Rev.1.10, sections:
		 * - 34.3.1.69 AXI Window Base (Lower) Registers
		 * - 34.3.1.71 AXI Window Mask (Lower) Registers
		 * - 34.3.1.73 AXI Destination (Lower) Registers)
		 * the CPU addr, PCIe addr, size should be 4K aligned and be a
		 * power of 2.
		 */
		size = ALIGN(size, SZ_4K);
		size = roundup_pow_of_two(size);

		cpu_addr = ALIGN(cpu_addr, SZ_4K);
		pci_addr = ALIGN(pci_addr, SZ_4K);
		size = min(size, align_limit);

		/*
		 * According to the RZ/G3S HW manual (Rev.1.10, section
		 * 34.3.1.71 AXI Window Mask (Lower) Registers) HW expects first
		 * 12 LSB bits to be 0xfff. Subtract 1 from size for this.
		 * Minimum window size is 4KB.
		 * See RZ/G3S HW manual (Rev.1.10, section 34.3.1.71) and
		 * RZ/G3E HW manual (Rev.1.15, section 6.6.4.1.3.(74)).
		 */
		size = max(size, SZ_4K);

		rzg3s_pcie_set_inbound_window(host, cpu_addr, pci_addr,
					      size - 1, id);

		pci_addr += size;
		cpu_addr += size;
		size_id = size;
		id++;
	}
	*index = id;
@@ -1517,6 +1681,7 @@ static int rzg3s_pcie_probe(struct platform_device *pdev)
	struct device_node *sysc_np __free(device_node) =
		of_parse_phandle(np, "renesas,sysc", 0);
	struct rzg3s_pcie_host *host;
	struct rzg3s_sysc *sysc;
	int ret;

	bridge = devm_pci_alloc_host_bridge(dev, sizeof(*host));
@@ -1528,28 +1693,36 @@ static int rzg3s_pcie_probe(struct platform_device *pdev)
	host->data = device_get_match_data(dev);
	platform_set_drvdata(pdev, host);

	host->sysc = devm_kzalloc(dev, sizeof(*host->sysc), GFP_KERNEL);
	if (!host->sysc)
		return -ENOMEM;

	sysc = host->sysc;
	sysc->info = &host->data->sysc_info;

	host->axi = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(host->axi))
		return PTR_ERR(host->axi);
	host->pcie = host->axi + RZG3S_PCI_CFG_BASE;

	host->max_link_speed = of_pci_get_max_link_speed(np);
	if (host->max_link_speed < 0)
		host->max_link_speed = 2;

	ret = rzg3s_pcie_host_parse_port(host);
	if (ret)
		return ret;

	host->sysc = syscon_node_to_regmap(sysc_np);
	if (IS_ERR(host->sysc)) {
		ret = PTR_ERR(host->sysc);
	sysc->regmap = syscon_node_to_regmap(sysc_np);
	if (IS_ERR(sysc->regmap)) {
		ret = PTR_ERR(sysc->regmap);
		goto port_refclk_put;
	}

	ret = regmap_update_bits(host->sysc, RZG3S_SYS_PCIE_RST_RSM_B,
				 RZG3S_SYS_PCIE_RST_RSM_B_MASK,
				 FIELD_PREP(RZG3S_SYS_PCIE_RST_RSM_B_MASK, 1));
	/* 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;

@@ -1589,8 +1762,7 @@ static int rzg3s_pcie_probe(struct platform_device *pdev)

host_probe_teardown:
	rzg3s_pcie_teardown_irqdomain(host);
	reset_control_bulk_deassert(host->data->num_cfg_resets,
				    host->cfg_resets);
	host->data->config_deinit(host);
rpm_put:
	pm_runtime_put_sync(dev);
rpm_disable:
@@ -1602,9 +1774,7 @@ static int rzg3s_pcie_probe(struct platform_device *pdev)
	 * SYSC RST_RSM_B signal need to be asserted before turning off the
	 * power to the PHY.
	 */
	regmap_update_bits(host->sysc, RZG3S_SYS_PCIE_RST_RSM_B,
			   RZG3S_SYS_PCIE_RST_RSM_B_MASK,
			   FIELD_PREP(RZG3S_SYS_PCIE_RST_RSM_B_MASK, 0));
	rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0);
port_refclk_put:
	clk_put(host->port.refclk);

@@ -1616,7 +1786,7 @@ static int rzg3s_pcie_suspend_noirq(struct device *dev)
	struct rzg3s_pcie_host *host = dev_get_drvdata(dev);
	const struct rzg3s_pcie_soc_data *data = host->data;
	struct rzg3s_pcie_port *port = &host->port;
	struct regmap *sysc = host->sysc;
	struct rzg3s_sysc *sysc = host->sysc;
	int ret;

	ret = pm_runtime_put_sync(dev);
@@ -1625,31 +1795,30 @@ static int rzg3s_pcie_suspend_noirq(struct device *dev)

	clk_disable_unprepare(port->refclk);

	ret = reset_control_bulk_assert(data->num_power_resets,
					host->power_resets);
	/* SoC-specific de-initialization */
	ret = data->config_deinit(host);
	if (ret)
		goto refclk_restore;

	ret = reset_control_bulk_assert(data->num_cfg_resets,
					host->cfg_resets);
	ret = reset_control_bulk_assert(data->num_power_resets,
					host->power_resets);
	if (ret)
		goto power_resets_restore;
		goto config_reinit;

	ret = regmap_update_bits(sysc, RZG3S_SYS_PCIE_RST_RSM_B,
				 RZG3S_SYS_PCIE_RST_RSM_B_MASK,
				 FIELD_PREP(RZG3S_SYS_PCIE_RST_RSM_B_MASK, 0));
	ret = rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0);
	if (ret)
		goto cfg_resets_restore;
		goto power_resets_restore;

	return 0;

	/* Restore the previous state if any error happens */
cfg_resets_restore:
	reset_control_bulk_deassert(data->num_cfg_resets,
				    host->cfg_resets);
power_resets_restore:
	reset_control_bulk_deassert(data->num_power_resets,
				    host->power_resets);
config_reinit:
	if (data->config_pre_init)
		data->config_pre_init(host);
	data->config_post_init(host);
refclk_restore:
	clk_prepare_enable(port->refclk);
	pm_runtime_resume_and_get(dev);
@@ -1660,12 +1829,14 @@ static int rzg3s_pcie_resume_noirq(struct device *dev)
{
	struct rzg3s_pcie_host *host = dev_get_drvdata(dev);
	const struct rzg3s_pcie_soc_data *data = host->data;
	struct regmap *sysc = host->sysc;
	struct rzg3s_sysc *sysc = host->sysc;
	int ret;

	ret = regmap_update_bits(sysc, RZG3S_SYS_PCIE_RST_RSM_B,
				 RZG3S_SYS_PCIE_RST_RSM_B_MASK,
				 FIELD_PREP(RZG3S_SYS_PCIE_RST_RSM_B_MASK, 1));
	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;

@@ -1694,9 +1865,7 @@ static int rzg3s_pcie_resume_noirq(struct device *dev)
	reset_control_bulk_assert(data->num_power_resets,
				  host->power_resets);
assert_rst_rsm_b:
	regmap_update_bits(sysc, RZG3S_SYS_PCIE_RST_RSM_B,
			   RZG3S_SYS_PCIE_RST_RSM_B_MASK,
			   FIELD_PREP(RZG3S_SYS_PCIE_RST_RSM_B_MASK, 0));
	rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0);
	return ret;
}

@@ -1718,7 +1887,39 @@ static const struct rzg3s_pcie_soc_data rzg3s_soc_data = {
	.num_power_resets = ARRAY_SIZE(rzg3s_soc_power_resets),
	.cfg_resets = rzg3s_soc_cfg_resets,
	.num_cfg_resets = ARRAY_SIZE(rzg3s_soc_cfg_resets),
	.config_post_init = rzg3s_pcie_config_post_init,
	.config_deinit = rzg3s_pcie_config_deinit,
	.init_phy = rzg3s_soc_pcie_init_phy,
	.sysc_info = {
		.functions = {
			[RZG3S_SYSC_FUNC_ID_RST_RSM_B] = {
				.offset = 0xd74,
				.mask = BIT(0),
			},
		},
	},
};

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[] = {
@@ -1726,6 +1927,10 @@ 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,
	},
	{}
};