From nobody Mon Apr 6 20:00:42 2026 Received: from mail-wr1-f41.google.com (mail-wr1-f41.google.com [209.85.221.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 281763D75BC for ; Wed, 18 Mar 2026 12:45:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773837922; cv=none; b=mgDGjD2UEsEplqBYfH7yA1HaCtkoacyl2OMWyjEvIfxKKu67Jo8rByKUvw3zCIMXbykWmla+UN3LCGGAe1fdyNRL9ZIgWPSxETuMEyySu3GYOGjkIB0lGaeSMTJfk5r3dx49KKcOl9yt4vgjE7BTbMPl89/2YhslVoHb3Gno2dE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773837922; c=relaxed/simple; bh=RjHl7j/Lg5vZPB4YXi7xN2rOYCqftOPO41V9TjL/Piw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KPeXlbgWFSdpqbtiBVcLqU8N+9lYkxrybwTE4pBiM09uzygkgctmWmrM1UXizcHNICY68nGXTpQLJpgBqqyJqQ617whVNBgrt0dthT8upe/CecS+kh5zscPhPS7f3JLWn6xPeCbHUMJMA33HTaFemgSkAITF9zVTgpOvj3mIqnA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Lqmas3KB; arc=none smtp.client-ip=209.85.221.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Lqmas3KB" Received: by mail-wr1-f41.google.com with SMTP id ffacd0b85a97d-43a03cb1df9so6809654f8f.1 for ; Wed, 18 Mar 2026 05:45:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773837913; x=1774442713; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2beXNldnnMW0fC5Mifqd0YZdlJwrApukwctaOe5qsiI=; b=Lqmas3KBg/R7DZ50IkY6cNDr0fR+hTLq+KlfGmy0CfwFM08gZVoS2REHTMuZcylBAC wYq21G5yCkZQuiQl0WAO0FHBztcVExohLhT7RIeDGR93rSyqbrCaSBtYLqZJR99zwvo8 YPWsjBk8ze27yBeSiMKHeyjl3jWGQaGurz9pyfuANf8/MO6+jZiuy4996MyLAGD5+1pv 4GllsZ5VgoES7ZBcqpoafNtAvt22TjGFnL39jwakj+iXYSpvJMw5rR7e9E/4GgtuhuQz hfgPiVBiC9YOIT/ZYww0Dayxc/M1DsaLmbbQuU80vWutE+GETbi4vrXyaZpWQHl/k3NH Nk9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773837913; x=1774442713; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=2beXNldnnMW0fC5Mifqd0YZdlJwrApukwctaOe5qsiI=; b=kei61Mk/KrfaTdKF3FMkkFQjwYOk1AES6+Mdk4crR1lcmyqFNfHWPKY71icV8nk5Th 144ujacoGoS/mALlkasKUT4djcdUbqUrkwo6mdQra3OehC7vVutlDJ3Py0xOiXJTYWgj S5U4dxSOwTyu13NJmMRiKrH51Tbeulb5lMUEpVdrjsUo7ijmGvH4jZWfikp0E5p3CHcJ repfEtUV8MxJ1HSzlG4mtF7VS7ljjM5ufyue4lwigefVKbLCrMhSULVtrAghhUW0H69v DJNy1Gi+7TywsPVOklWNbC+K5q7lLToTaxtxEsLfn6Q6/+OIBEb91+8G/eTxAj0SipUY t6oQ== X-Forwarded-Encrypted: i=1; AJvYcCW1Qfel+ifLNG3CjL6Y2awQ31WezhEe7Qrvj+cCYnfzW0AzVUyAoP2jtoW4FdkrKesYDxE9uRkBHeesV4Y=@vger.kernel.org X-Gm-Message-State: AOJu0YzrnV6SlQ8yboRIKO9NvVI+r6s727dsnwjduUOxzL+bV3NaBSKe D6XWwrZzaib79tprEYNq+uN0IHukMzvW+aMP8029D6KbBII5V00XMaSL X-Gm-Gg: ATEYQzyB2FEjvPQ9KWRSL006V0XRYYJ/wKh5XNOnGaS0NtoX/Lt5tamGkoIJ9Be+v+1 aSYe5NqeDJ9iV0yvwFc2vWqAxVYlCArIpobpx7LLDY74syRk4FfIL9A54kUg9sj3M+XzwI7iW1g iPBEEK4iEe37vlk//H6h1H3Mr0ms8ddRYU5lHUvVggyur43Nlml95RG22b0dY1KXqQYV5ZqFa/H 2cdUYphX4gmfGcPMHS8Hi62cjGzKt37dmydC+IMy+BwO7AuWE6h5mU389wkHdZDqh0ZGz+GD1kS sMy771+n4gkwAVoNjXvHWOyNeqFVSRdxQ0WrIQP+MV9zKcEODo+MI5lbeuwVRJ8z4xcGwxGwHuX FHFZvtlZ8bF4TEMqT58mGVBC6SnLlgOeQyqwwCn7YsZ487fCle0ZYQrmAFbUtyGauv/BDS8n/Dr dumOUHBvWlzg3xIiC9Fcmd4j8X+K/LOm1KApEzYdApM3bbcQcgzf/Uhxb77MY8UQYHvVDQ9u+QD 60XGe2XRkelA7LbcemHP1U1W1TafvZfCjd+KDAWwhSqN+Q= X-Received: by 2002:a05:6000:26cc:b0:43b:4921:8745 with SMTP id ffacd0b85a97d-43b527aa3f5mr5799725f8f.21.1773837912986; Wed, 18 Mar 2026 05:45:12 -0700 (PDT) Received: from iku.example.org ([2a06:5906:61b:2d00:5f14:a98b:b4be:efbd]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-43b518985f6sm7888162f8f.25.2026.03.18.05.45.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 Mar 2026 05:45:12 -0700 (PDT) From: Prabhakar X-Google-Original-From: Prabhakar To: Claudiu Beznea , Bjorn Helgaas , Lorenzo Pieralisi , =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= , Manivannan Sadhasivam , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Philipp Zabel , Geert Uytterhoeven , Magnus Damm , Wolfram Sang Cc: John Madieu , linux-pci@vger.kernel.org, linux-renesas-soc@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Prabhakar , Biju Das , Fabrizio Castro , Lad Prabhakar Subject: [PATCH 5/5] PCI: rzg3s-host: Add support for RZ/V2H(P) SoC Date: Wed, 18 Mar 2026 12:44:50 +0000 Message-ID: <20260318124450.163471-6-prabhakar.mahadev-lad.rj@bp.renesas.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260318124450.163471-1-prabhakar.mahadev-lad.rj@bp.renesas.com> References: <20260318124450.163471-1-prabhakar.mahadev-lad.rj@bp.renesas.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Lad Prabhakar Add support for the RZ/V2H(P) SoC PCIe controller to the rzg3s-host driver. The RZ/V2H(P) SoC features two independent PCIe channels that share physical lanes. The hardware supports two configuration modes: single x4 mode where one controller uses all four lanes, or dual x2 mode where both controllers use two lanes each. Introduce configure_lanes() function pointer to configure the PCIe lanes based on the number of channels enabled. Implement rzv2h_pcie_configure_lanes() to detect the active PCIe channels at boot time and program the lane mode via the system controller using the new RZG3S_SYSC_FUNC_ID_LINK_MASTER function ID. Signed-off-by: Lad Prabhakar --- drivers/pci/controller/pcie-rzg3s-host.c | 142 +++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/control= ler/pcie-rzg3s-host.c index a629e861bbd0..d1bf1e750d9b 100644 --- a/drivers/pci/controller/pcie-rzg3s-host.c +++ b/drivers/pci/controller/pcie-rzg3s-host.c @@ -179,6 +179,16 @@ /* Timeouts experimentally determined */ #define RZG3S_REQ_ISSUE_TIMEOUT_US 2500 =20 +/** + * enum rzg3s_sysc_link_mode - PCIe link configuration modes + * @RZG3S_SYSC_LINK_MODE_SINGLE_X4: Single port with x4 lanes + * @RZG3S_SYSC_LINK_MODE_DUAL_X2: Dual ports with x2 lanes each + */ +enum rzg3s_sysc_link_mode { + RZG3S_SYSC_LINK_MODE_SINGLE_X4 =3D 1, + RZG3S_SYSC_LINK_MODE_DUAL_X2 =3D 3, +}; + /** * struct rzg3s_sysc_function - System Controller function descriptor * @offset: Register offset from the System Controller base address @@ -194,12 +204,14 @@ struct rzg3s_sysc_function { * @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_LINK_MASTER: Link master 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_LINK_MASTER, RZG3S_SYSC_FUNC_ID_MAX, }; =20 @@ -261,6 +273,7 @@ struct rzg3s_pcie_host; * @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 + * @setup_lanes: Callback for setting up the number of lanes * @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 @@ -268,17 +281,20 @@ struct rzg3s_pcie_host; * @sysc_info: System Controller info for each PCIe channel * @num_power_resets: number of power resets * @num_cfg_resets: number of configuration resets + * @num_channels: number of PCIe channels */ 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); + int (*setup_lanes)(struct rzg3s_pcie_host *host); const char * const *power_resets; const char * const *cfg_resets; struct rzg3s_sysc_info sysc_info[RZG3S_PCIE_CHANNEL_ID_MAX]; u8 num_power_resets; u8 num_cfg_resets; + u8 num_channels; }; =20 /** @@ -309,6 +325,7 @@ struct rzg3s_pcie_port { * @intx_irqs: INTx interrupts * @max_link_speed: maximum supported link speed * @channel_id: PCIe channel identifier, used for System Controller access + * @num_lanes: The number of lanes */ struct rzg3s_pcie_host { void __iomem *axi; @@ -325,6 +342,7 @@ struct rzg3s_pcie_host { int intx_irqs[PCI_NUM_INTX]; int max_link_speed; enum rzg3s_pcie_channel_id channel_id; + u8 num_lanes; }; =20 #define rzg3s_msi_to_host(_msi) container_of(_msi, struct rzg3s_pcie_host,= msi) @@ -1155,6 +1173,13 @@ static int rzg3s_pcie_config_init(struct rzg3s_pcie_= host *host) rzg3s_pcie_update_bits(host->pcie, PCI_CLASS_REVISION, mask, field_prep(mask, PCI_CLASS_BRIDGE_PCI_NORMAL)); =20 + if (host->num_lanes) { + rzg3s_pcie_update_bits(host->pcie + RZG3S_PCI_CFG_PCIEC, + PCI_EXP_LNKCAP, PCI_EXP_LNKCAP_MLW, + FIELD_PREP(PCI_EXP_LNKCAP_MLW, + host->num_lanes)); + } + /* Disable access control to the CFGU */ writel_relaxed(0, host->axi + RZG3S_PCI_PERM); =20 @@ -1687,6 +1712,63 @@ rzg3s_pcie_host_setup(struct rzg3s_pcie_host *host, return ret; } =20 +static int rzg3s_pcie_get_controller_id(struct rzg3s_pcie_host *host) +{ + struct device_node *np =3D host->dev->of_node; + u32 domain; + int ret; + + if (host->data->num_channels =3D=3D 1) + return 0; + + ret =3D of_property_read_u32(np, "linux,pci-domain", &domain); + if (ret) + return ret; + + if (domain >=3D host->data->num_channels) + return -EINVAL; + + host->channel_id =3D domain; + + return 0; +} + +static int rzv2h_pcie_setup_lanes(struct rzg3s_pcie_host *host) +{ + struct device_node *np =3D host->dev->of_node; + static u8 rzv2h_num_total_lanes; + u32 num_lanes; + int ret; + + ret =3D of_property_read_u32(np, "num-lanes", &num_lanes); + if (ret) + return ret; + + /* + * RZ/V2H(P) supports up to 4 lanes, but only in single x4 mode. + * Dual x2 mode is only supported with 2 total lanes. Validate + * the configuration to avoid conflicts with other host, if any. + */ + if (num_lanes !=3D 4 && num_lanes !=3D 2) + return -EINVAL; + + if (rzv2h_num_total_lanes =3D=3D 2 && num_lanes !=3D 2) + return -EINVAL; + + if (rzv2h_num_total_lanes =3D=3D 4) + return -EINVAL; + + rzv2h_num_total_lanes +=3D num_lanes; + + host->num_lanes =3D num_lanes; + + return rzg3s_sysc_config_func(host->sysc, + RZG3S_SYSC_FUNC_ID_LINK_MASTER, + num_lanes =3D=3D 2 ? + RZG3S_SYSC_LINK_MODE_DUAL_X2 : + RZG3S_SYSC_LINK_MODE_SINGLE_X4); +} + static int rzg3s_pcie_probe(struct platform_device *pdev) { struct pci_host_bridge *bridge; @@ -1711,6 +1793,10 @@ static int rzg3s_pcie_probe(struct platform_device *= pdev) if (!host->sysc) return -ENOMEM; =20 + ret =3D rzg3s_pcie_get_controller_id(host); + if (ret) + return ret; + sysc =3D host->sysc; sysc->info =3D &host->data->sysc_info[host->channel_id]; =20 @@ -1740,6 +1826,12 @@ static int rzg3s_pcie_probe(struct platform_device *= pdev) if (ret) goto port_refclk_put; =20 + if (host->data->setup_lanes) { + ret =3D host->data->setup_lanes(host); + if (ret) + goto sysc_signal_restore; + } + ret =3D rzg3s_pcie_resets_prepare_and_get(host); if (ret) goto sysc_signal_restore; @@ -1901,6 +1993,7 @@ static const struct rzg3s_pcie_soc_data rzg3s_soc_dat= a =3D { .num_power_resets =3D ARRAY_SIZE(rzg3s_soc_power_resets), .cfg_resets =3D rzg3s_soc_cfg_resets, .num_cfg_resets =3D ARRAY_SIZE(rzg3s_soc_cfg_resets), + .num_channels =3D 1, .config_post_init =3D rzg3s_pcie_config_post_init, .config_deinit =3D rzg3s_pcie_config_deinit, .init_phy =3D rzg3s_soc_pcie_init_phy, @@ -1921,6 +2014,7 @@ static const char * const rzg3e_soc_power_resets[] = =3D { "aresetn" }; static const struct rzg3s_pcie_soc_data rzg3e_soc_data =3D { .power_resets =3D rzg3e_soc_power_resets, .num_power_resets =3D ARRAY_SIZE(rzg3e_soc_power_resets), + .num_channels =3D 1, .config_pre_init =3D rzg3e_pcie_config_pre_init, .config_post_init =3D rzg3e_pcie_config_post_init, .config_deinit =3D rzg3e_pcie_config_deinit, @@ -1940,6 +2034,50 @@ static const struct rzg3s_pcie_soc_data rzg3e_soc_da= ta =3D { }, }; =20 +static const struct rzg3s_pcie_soc_data rzv2h_soc_data =3D { + .power_resets =3D rzg3e_soc_power_resets, + .num_power_resets =3D ARRAY_SIZE(rzg3e_soc_power_resets), + .num_channels =3D 2, + .config_pre_init =3D rzg3e_pcie_config_pre_init, + .config_post_init =3D rzg3e_pcie_config_post_init, + .config_deinit =3D rzg3e_pcie_config_deinit, + .setup_lanes =3D rzv2h_pcie_setup_lanes, + .sysc_info =3D { + [RZG3S_PCIE_CHANNEL_ID_0] =3D { + .functions =3D { + [RZG3S_SYSC_FUNC_ID_L1_ALLOW] =3D { + .offset =3D 0x1020, + .mask =3D BIT(0), + }, + [RZG3S_SYSC_FUNC_ID_MODE] =3D { + .offset =3D 0x1024, + .mask =3D BIT(0), + }, + [RZG3S_SYSC_FUNC_ID_LINK_MASTER] =3D { + .offset =3D 0x1060, + .mask =3D GENMASK(9, 8), + }, + }, + }, + [RZG3S_PCIE_CHANNEL_ID_1] =3D { + .functions =3D { + [RZG3S_SYSC_FUNC_ID_L1_ALLOW] =3D { + .offset =3D 0x1050, + .mask =3D BIT(0), + }, + [RZG3S_SYSC_FUNC_ID_MODE] =3D { + .offset =3D 0x1054, + .mask =3D BIT(0), + }, + [RZG3S_SYSC_FUNC_ID_LINK_MASTER] =3D { + .offset =3D 0x1060, + .mask =3D GENMASK(9, 8), + }, + }, + }, + }, +}; + static const struct of_device_id rzg3s_pcie_of_match[] =3D { { .compatible =3D "renesas,r9a08g045-pcie", @@ -1949,6 +2087,10 @@ static const struct of_device_id rzg3s_pcie_of_match= [] =3D { .compatible =3D "renesas,r9a09g047-pcie", .data =3D &rzg3e_soc_data, }, + { + .compatible =3D "renesas,r9a09g057-pcie", + .data =3D &rzv2h_soc_data, + }, {} }; =20 --=20 2.53.0