From nobody Sat Oct 4 22:37:49 2025 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1FCCC2EB5A7; Tue, 12 Aug 2025 14:11:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755007876; cv=none; b=fg6wSJxXftGsjQ4wbZMpiBKtX7fOD1wyZDKNv59DMdUVw20aJNYKGeWP++gi4IzdI62nEUqdDSjvYKesoSDWSBGGARCMuhRr8RoaWxxWn7PWxVy7pZKUcZqWoX+S0aJYOJ2LlRJR9H7nCGUHTCQI+H+xkJElhUAyN8TdjxvDG5A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755007876; c=relaxed/simple; bh=ybeuExx2SAFT5NOfRhjwNkMjV2oOtGWgq55ZNGm+7mw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=c6ZN5mmVbs/zDmopeeDXiJ5Ar+Pm347Vs/HPQWTmLFo+nlmB/Psc0HTWJWWbIQqncxSOe87lIjxRVJLlCDUwjRAF0doAAaI4rCzkwKaQNaa54banMzwKsc7UYZmDWAzf4Ft9HcBrhY0FL7sMzwrnOXA+4ggke2r53NRa+MXq3DM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=AuxmQcqO; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="AuxmQcqO" Received: from pps.filterd (m0279866.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 57CAvhx2021043; Tue, 12 Aug 2025 14:11:02 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= PnIHUTPdCMNFjtRzi6XgCuGSecGkhYEvLxRQISc/Vz8=; b=AuxmQcqOXu1IYiFw /bZLxFD6SzUTgm44bTtaIY2c1SKSOViY3Ioje/wcabkb5/zagANvpEPo9cnwh+mj YLSpQ8qKp5yoqO40J3Fa2SvwxL+L5ZVU6dmOOGBrEtPe+hTzAeNzoEpnqdaClEFl /3UP2yZz+hVoNMqxbad96h4TDWzeSaqZp2FTh/7Dof0lKbrV0Mi96NaDQS+uAkUP QNurAzlHSatjds3DBFKYO2d/Od20VJqwTIboMMfcgnEeay+cFgXEQ9/x5NYpR4W9 BVaZtI99JeDRZxENIQFZGIi4gQjLgwK2CkpcdV5k3fim8TBBUUiBQdlHD8fX4RK+ KyW8hg== Received: from nasanppmta04.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 48ffq6m8d9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 12 Aug 2025 14:11:02 +0000 (GMT) Received: from nasanex01b.na.qualcomm.com (nasanex01b.na.qualcomm.com [10.46.141.250]) by NASANPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 57CEB2I5025062 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 12 Aug 2025 14:11:02 GMT Received: from nsssdc-sh01-lnx.ap.qualcomm.com (10.80.80.8) by nasanex01b.na.qualcomm.com (10.46.141.250) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.10; Tue, 12 Aug 2025 07:10:56 -0700 From: Luo Jie Date: Tue, 12 Aug 2025 22:10:27 +0800 Subject: [PATCH net-next v7 03/14] net: ethernet: qualcomm: Add PPE driver for IPQ9574 SoC Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20250812-qcom_ipq_ppe-v7-3-789404bdbc9a@quicinc.com> References: <20250812-qcom_ipq_ppe-v7-0-789404bdbc9a@quicinc.com> In-Reply-To: <20250812-qcom_ipq_ppe-v7-0-789404bdbc9a@quicinc.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lei Wei , Suruchi Agarwal , Pavithra R , "Simon Horman" , Jonathan Corbet , Kees Cook , "Gustavo A. R. Silva" , "Philipp Zabel" CC: , , , , , , , , Luo Jie X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1755007841; l=10919; i=quic_luoj@quicinc.com; s=20250209; h=from:subject:message-id; bh=ybeuExx2SAFT5NOfRhjwNkMjV2oOtGWgq55ZNGm+7mw=; b=3jY9HAMib/TJfyj3ZoiK/NawmXB8yArd5mQcfSixGYZ1TGQDhg7AL6765Q5HzefjhoIDrh2KL DgEO3V+xXCxADSusikNt03au+wxwdYIVawAucfhGs2iLh5X5VTMuueb X-Developer-Key: i=quic_luoj@quicinc.com; a=ed25519; pk=pzwy8bU5tJZ5UKGTv28n+QOuktaWuriznGmriA9Qkfc= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nasanex01b.na.qualcomm.com (10.46.141.250) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwODExMDA3NSBTYWx0ZWRfX6StmBFMwVM0V MmBpbtE7Xa2TlHKP8GdL1xKTO0BtsjojKhhFGBkf+JsIHB091eH9KJXD0XWheinmGNzYPdi+7R6 rXbhjRlnQKxJbF1URvMlaGkjqF98Zf9Z0lZTLhD+0I4EpshuRPt0XdKwxfLqG3TfUyU8EGZXwol AJWFU85M6RYc82RGpC6utdVrm/62YDZC+gBJ9N/OYDkAyfV7QY2DMZhzQkftmNTpxHMiuG0k2UM 7BrnLpsose9tUAEi3/PIRjiVqSafVZvqgJlSHOXLOe0v8FPcQNDuqWFrZdt/bFlLu965z++AlvJ r8iR2xGbBEMKUpolpjlOUuCb0FXhoJvmPQCUuYCqlNhnkkN6CwY9tM8Fq0KWWVu6JSX75jLbol2 5bb6VJpd X-Authority-Analysis: v=2.4 cv=TLZFS0la c=1 sm=1 tr=0 ts=689b4b76 cx=c_pps a=JYp8KDb2vCoCEuGobkYCKw==:117 a=JYp8KDb2vCoCEuGobkYCKw==:17 a=GEpy-HfZoHoA:10 a=IkcTkHD0fZMA:10 a=2OwXVqhp2XgA:10 a=COk6AnOGAAAA:8 a=f-HWf9TQXBEveYD7iK4A:9 a=QEXdDO2ut3YA:10 a=TjNXssC_j7lpFel5tvFf:22 X-Proofpoint-GUID: dBeRe1MvozNh4qGd67gb2CBGHQxIjvkW X-Proofpoint-ORIG-GUID: dBeRe1MvozNh4qGd67gb2CBGHQxIjvkW X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.1.9,FMLib:17.12.80.40 definitions=2025-08-12_07,2025-08-11_01,2025-03-28_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 phishscore=0 malwarescore=0 spamscore=0 priorityscore=1501 bulkscore=0 adultscore=0 impostorscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2507300000 definitions=main-2508110075 The PPE (Packet Process Engine) hardware block is available on Qualcomm IPQ SoC that support PPE architecture, such as IPQ9574. The PPE in IPQ9574 includes six integrated ethernet MAC for 6 PPE ports, buffer management, queue management and scheduler functions. The MACs can connect with the external PHY or switch devices using the UNIPHY PCS block available in the SoC. The PPE also includes various packet processing offload capabilities such as L3 routing and L2 bridging, VLAN and tunnel processing offload. It also includes Ethernet DMA function for transferring packets between ARM cores and PPE ethernet ports. This patch adds the base source files and Makefiles for the PPE driver such as platform driver registration, clock initialization, and PPE reset routines. Signed-off-by: Luo Jie --- drivers/net/ethernet/qualcomm/Kconfig | 15 ++ drivers/net/ethernet/qualcomm/Makefile | 1 + drivers/net/ethernet/qualcomm/ppe/Makefile | 7 + drivers/net/ethernet/qualcomm/ppe/ppe.c | 223 +++++++++++++++++++++++++= ++++ drivers/net/ethernet/qualcomm/ppe/ppe.h | 36 +++++ 5 files changed, 282 insertions(+) diff --git a/drivers/net/ethernet/qualcomm/Kconfig b/drivers/net/ethernet/q= ualcomm/Kconfig index a4434eb38950..6e56b022fc2d 100644 --- a/drivers/net/ethernet/qualcomm/Kconfig +++ b/drivers/net/ethernet/qualcomm/Kconfig @@ -60,6 +60,21 @@ config QCOM_EMAC low power, Receive-Side Scaling (RSS), and IEEE 1588-2008 Precision Clock Synchronization Protocol. =20 +config QCOM_PPE + tristate "Qualcomm Technologies, Inc. PPE Ethernet support" + depends on HAS_IOMEM && OF + depends on COMMON_CLK + select REGMAP_MMIO + help + This driver supports the Qualcomm Technologies, Inc. packet + process engine (PPE) available with IPQ SoC. The PPE includes + the ethernet MACs, Ethernet DMA (EDMA) and switch core that + supports L3 flow offload, L2 switch function, RSS and tunnel + offload. + + To compile this driver as a module, choose M here. The module + will be called qcom-ppe. + source "drivers/net/ethernet/qualcomm/rmnet/Kconfig" =20 endif # NET_VENDOR_QUALCOMM diff --git a/drivers/net/ethernet/qualcomm/Makefile b/drivers/net/ethernet/= qualcomm/Makefile index 9250976dd884..166a59aea363 100644 --- a/drivers/net/ethernet/qualcomm/Makefile +++ b/drivers/net/ethernet/qualcomm/Makefile @@ -11,4 +11,5 @@ qcauart-objs :=3D qca_uart.o =20 obj-y +=3D emac/ =20 +obj-$(CONFIG_QCOM_PPE) +=3D ppe/ obj-$(CONFIG_RMNET) +=3D rmnet/ diff --git a/drivers/net/ethernet/qualcomm/ppe/Makefile b/drivers/net/ether= net/qualcomm/ppe/Makefile new file mode 100644 index 000000000000..63d50d3b4f2e --- /dev/null +++ b/drivers/net/ethernet/qualcomm/ppe/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Makefile for the device driver of PPE (Packet Process Engine) in IPQ SoC +# + +obj-$(CONFIG_QCOM_PPE) +=3D qcom-ppe.o +qcom-ppe-objs :=3D ppe.o diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.c b/drivers/net/ethernet= /qualcomm/ppe/ppe.c new file mode 100644 index 000000000000..3aacb8eddbae --- /dev/null +++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/* PPE platform device probe, DTSI parser and PPE clock initializations. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ppe.h" + +#define PPE_PORT_MAX 8 +#define PPE_CLK_RATE 353000000 + +/* ICC clocks for enabling PPE device. The avg_bw and peak_bw with value 0 + * will be updated by the clock rate of PPE. + */ +static const struct icc_bulk_data ppe_icc_data[] =3D { + { + .name =3D "ppe", + .avg_bw =3D 0, + .peak_bw =3D 0, + }, + { + .name =3D "ppe_cfg", + .avg_bw =3D 0, + .peak_bw =3D 0, + }, + { + .name =3D "qos_gen", + .avg_bw =3D 6000, + .peak_bw =3D 6000, + }, + { + .name =3D "timeout_ref", + .avg_bw =3D 6000, + .peak_bw =3D 6000, + }, + { + .name =3D "nssnoc_memnoc", + .avg_bw =3D 533333, + .peak_bw =3D 533333, + }, + { + .name =3D "memnoc_nssnoc", + .avg_bw =3D 533333, + .peak_bw =3D 533333, + }, + { + .name =3D "memnoc_nssnoc_1", + .avg_bw =3D 533333, + .peak_bw =3D 533333, + }, +}; + +static const struct regmap_range ppe_readable_ranges[] =3D { + regmap_reg_range(0x0, 0x1ff), /* Global */ + regmap_reg_range(0x400, 0x5ff), /* LPI CSR */ + regmap_reg_range(0x1000, 0x11ff), /* GMAC0 */ + regmap_reg_range(0x1200, 0x13ff), /* GMAC1 */ + regmap_reg_range(0x1400, 0x15ff), /* GMAC2 */ + regmap_reg_range(0x1600, 0x17ff), /* GMAC3 */ + regmap_reg_range(0x1800, 0x19ff), /* GMAC4 */ + regmap_reg_range(0x1a00, 0x1bff), /* GMAC5 */ + regmap_reg_range(0xb000, 0xefff), /* PRX CSR */ + regmap_reg_range(0xf000, 0x1efff), /* IPE */ + regmap_reg_range(0x20000, 0x5ffff), /* PTX CSR */ + regmap_reg_range(0x60000, 0x9ffff), /* IPE L2 CSR */ + regmap_reg_range(0xb0000, 0xeffff), /* IPO CSR */ + regmap_reg_range(0x100000, 0x17ffff), /* IPE PC */ + regmap_reg_range(0x180000, 0x1bffff), /* PRE IPO CSR */ + regmap_reg_range(0x1d0000, 0x1dffff), /* Tunnel parser */ + regmap_reg_range(0x1e0000, 0x1effff), /* Ingress parse */ + regmap_reg_range(0x200000, 0x2fffff), /* IPE L3 */ + regmap_reg_range(0x300000, 0x3fffff), /* IPE tunnel */ + regmap_reg_range(0x400000, 0x4fffff), /* Scheduler */ + regmap_reg_range(0x500000, 0x503fff), /* XGMAC0 */ + regmap_reg_range(0x504000, 0x507fff), /* XGMAC1 */ + regmap_reg_range(0x508000, 0x50bfff), /* XGMAC2 */ + regmap_reg_range(0x50c000, 0x50ffff), /* XGMAC3 */ + regmap_reg_range(0x510000, 0x513fff), /* XGMAC4 */ + regmap_reg_range(0x514000, 0x517fff), /* XGMAC5 */ + regmap_reg_range(0x600000, 0x6fffff), /* BM */ + regmap_reg_range(0x800000, 0x9fffff), /* QM */ + regmap_reg_range(0xb00000, 0xbef800), /* EDMA */ +}; + +static const struct regmap_access_table ppe_reg_table =3D { + .yes_ranges =3D ppe_readable_ranges, + .n_yes_ranges =3D ARRAY_SIZE(ppe_readable_ranges), +}; + +static const struct regmap_config regmap_config_ipq9574 =3D { + .reg_bits =3D 32, + .reg_stride =3D 4, + .val_bits =3D 32, + .rd_table =3D &ppe_reg_table, + .wr_table =3D &ppe_reg_table, + .max_register =3D 0xbef800, + .fast_io =3D true, +}; + +static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev) +{ + unsigned long ppe_rate =3D ppe_dev->clk_rate; + struct device *dev =3D ppe_dev->dev; + struct reset_control *rstc; + struct clk_bulk_data *clks; + struct clk *clk; + int ret, i; + + for (i =3D 0; i < ppe_dev->num_icc_paths; i++) { + ppe_dev->icc_paths[i].name =3D ppe_icc_data[i].name; + ppe_dev->icc_paths[i].avg_bw =3D ppe_icc_data[i].avg_bw ? : + Bps_to_icc(ppe_rate); + + /* PPE does not have an explicit peak bandwidth requirement, + * so set the peak bandwidth to be equal to the average + * bandwidth. + */ + ppe_dev->icc_paths[i].peak_bw =3D ppe_icc_data[i].peak_bw ? : + Bps_to_icc(ppe_rate); + } + + ret =3D devm_of_icc_bulk_get(dev, ppe_dev->num_icc_paths, + ppe_dev->icc_paths); + if (ret) + return ret; + + ret =3D icc_bulk_set_bw(ppe_dev->num_icc_paths, ppe_dev->icc_paths); + if (ret) + return ret; + + /* The PPE clocks have a common parent clock. Setting the clock + * rate of "ppe" ensures the clock rate of all PPE clocks is + * configured to the same rate. + */ + clk =3D devm_clk_get(dev, "ppe"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + ret =3D clk_set_rate(clk, ppe_rate); + if (ret) + return ret; + + ret =3D devm_clk_bulk_get_all_enabled(dev, &clks); + if (ret < 0) + return ret; + + /* Reset the PPE. */ + rstc =3D devm_reset_control_get_exclusive(dev, NULL); + if (IS_ERR(rstc)) + return PTR_ERR(rstc); + + ret =3D reset_control_assert(rstc); + if (ret) + return ret; + + /* The delay 10 ms of assert is necessary for resetting PPE. */ + usleep_range(10000, 11000); + + return reset_control_deassert(rstc); +} + +static int qcom_ppe_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct ppe_device *ppe_dev; + void __iomem *base; + int ret, num_icc; + + num_icc =3D ARRAY_SIZE(ppe_icc_data); + ppe_dev =3D devm_kzalloc(dev, struct_size(ppe_dev, icc_paths, num_icc), + GFP_KERNEL); + if (!ppe_dev) + return -ENOMEM; + + base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), "PPE ioremap failed\n"); + + ppe_dev->regmap =3D devm_regmap_init_mmio(dev, base, ®map_config_ipq95= 74); + if (IS_ERR(ppe_dev->regmap)) + return dev_err_probe(dev, PTR_ERR(ppe_dev->regmap), + "PPE initialize regmap failed\n"); + ppe_dev->dev =3D dev; + ppe_dev->clk_rate =3D PPE_CLK_RATE; + ppe_dev->num_ports =3D PPE_PORT_MAX; + ppe_dev->num_icc_paths =3D num_icc; + + ret =3D ppe_clock_init_and_reset(ppe_dev); + if (ret) + return dev_err_probe(dev, ret, "PPE clock config failed\n"); + + platform_set_drvdata(pdev, ppe_dev); + + return 0; +} + +static const struct of_device_id qcom_ppe_of_match[] =3D { + { .compatible =3D "qcom,ipq9574-ppe" }, + {} +}; +MODULE_DEVICE_TABLE(of, qcom_ppe_of_match); + +static struct platform_driver qcom_ppe_driver =3D { + .driver =3D { + .name =3D "qcom_ppe", + .of_match_table =3D qcom_ppe_of_match, + }, + .probe =3D qcom_ppe_probe, +}; +module_platform_driver(qcom_ppe_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Qualcomm Technologies, Inc. IPQ PPE driver"); diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.h b/drivers/net/ethernet= /qualcomm/ppe/ppe.h new file mode 100644 index 000000000000..779f39c9f098 --- /dev/null +++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __PPE_H__ +#define __PPE_H__ + +#include +#include + +struct device; +struct regmap; + +/** + * struct ppe_device - PPE device private data. + * @dev: PPE device structure. + * @regmap: PPE register map. + * @clk_rate: PPE clock rate. + * @num_ports: Number of PPE ports. + * @num_icc_paths: Number of interconnect paths. + * @icc_paths: Interconnect path array. + * + * PPE device is the instance of PPE hardware, which is used to + * configure PPE packet process modules such as BM (buffer management), + * QM (queue management), and scheduler. + */ +struct ppe_device { + struct device *dev; + struct regmap *regmap; + unsigned long clk_rate; + unsigned int num_ports; + unsigned int num_icc_paths; + struct icc_bulk_data icc_paths[] __counted_by(num_icc_paths); +}; +#endif --=20 2.34.1