[PATCH net-next 03/20] net: ethernet: qualcomm: Add qcom PPE driver

From: Luo Jie
Date: Wed Jan 10 2024 - 06:43:38 EST


This patch adds the base source files and Makefiles for the PPE driver,
platform driver and clock initialization routines.

The PPE(packet process engine) hardware block is available in Qualcomm
IPQ chipsets that support PPE architecture, such as IPQ9574 and IPQ5332.
The PPE includes integrated ethernet MAC and PCS(uniphy), which is used
to connect with external PHY devices by PCS. The PPE also includes various
packet processing offload capabilities such as routing and bridgng offload,
L2 switch capability, VLAN and tunnel processing offload.

Signed-off-by: Luo Jie <quic_luoj@xxxxxxxxxxx>
---
MAINTAINERS | 9 +
drivers/net/ethernet/qualcomm/Kconfig | 14 +
drivers/net/ethernet/qualcomm/Makefile | 1 +
drivers/net/ethernet/qualcomm/ppe/Makefile | 7 +
drivers/net/ethernet/qualcomm/ppe/ppe.c | 389 +++++++++++++++++++++
drivers/net/ethernet/qualcomm/ppe/ppe.h | 143 ++++++++
include/linux/soc/qcom/ppe.h | 28 ++
7 files changed, 591 insertions(+)
create mode 100644 drivers/net/ethernet/qualcomm/ppe/Makefile
create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe.c
create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe.h
create mode 100644 include/linux/soc/qcom/ppe.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 014ad90d0872..18413231d173 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17943,6 +17943,15 @@ S: Maintained
F: Documentation/devicetree/bindings/mtd/qcom,nandc.yaml
F: drivers/mtd/nand/raw/qcom_nandc.c

+QUALCOMM PPE DRIVER
+M: Luo Jie <quic_luoj@xxxxxxxxxxx>
+L: netdev@xxxxxxxxxxxxxxx
+S: Supported
+F: Documentation/devicetree/bindings/net/qcom,ppe.yaml
+F: Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst
+F: drivers/net/ethernet/qualcomm/ppe/
+F: include/linux/soc/qcom/ppe.h
+
QUALCOMM QSEECOM DRIVER
M: Maximilian Luz <luzmaximilian@xxxxxxxxx>
L: linux-arm-msm@xxxxxxxxxxxxxxx
diff --git a/drivers/net/ethernet/qualcomm/Kconfig b/drivers/net/ethernet/qualcomm/Kconfig
index 9210ff360fdc..fe826c508f64 100644
--- a/drivers/net/ethernet/qualcomm/Kconfig
+++ b/drivers/net/ethernet/qualcomm/Kconfig
@@ -61,6 +61,20 @@ config QCOM_EMAC
low power, Receive-Side Scaling (RSS), and IEEE 1588-2008
Precision Clock Synchronization Protocol.

+config QCOM_PPE
+ tristate "Qualcomm Technologies, Inc. PPE Ethernet support"
+ depends on HAS_IOMEM && OF
+ depends on COMMON_CLK
+ help
+ This driver supports the Qualcomm Technologies, Inc. packet
+ process engine(PPE) available with IPQ SoC. The PPE houses
+ the ethernet MACs and Ethernet DMA (EDMA) hardware blocks.
+ It also 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"

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 := qca_uart.o

obj-y += emac/

+obj-$(CONFIG_QCOM_PPE) += ppe/
obj-$(CONFIG_RMNET) += rmnet/
diff --git a/drivers/net/ethernet/qualcomm/ppe/Makefile b/drivers/net/ethernet/qualcomm/ppe/Makefile
new file mode 100644
index 000000000000..795aff6501e4
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Makefile for the Qualcomm SoCs built-in PPE device driver
+#
+
+obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o
+qcom-ppe-objs := 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..23f9de105062
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c
@@ -0,0 +1,389 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+/* PPE platform device probe, DTSI read and basic HW initialization functions
+ * such as BM, QM, TDM and scheduler configs.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/ppe.h>
+#include "ppe.h"
+
+static const char * const ppe_clock_name[PPE_CLK_MAX] = {
+ "cmn_ahb",
+ "cmn_sys",
+ "uniphy0_sys",
+ "uniphy1_sys",
+ "uniphy2_sys",
+ "uniphy0_ahb",
+ "uniphy1_ahb",
+ "uniphy2_ahb",
+ "gcc_nsscc",
+ "gcc_nssnoc_nsscc",
+ "gcc_nssnoc_snoc",
+ "gcc_nssnoc_snoc_1",
+ "gcc_im_sleep",
+ "nss_ppe",
+ "nss_ppe_cfg",
+ "nssnoc_ppe",
+ "nssnoc_ppe_cfg",
+ "nss_edma",
+ "nss_edma_cfg",
+ "nss_ppe_ipe",
+ "nss_ppe_btq",
+ "port1_mac",
+ "port2_mac",
+ "port3_mac",
+ "port4_mac",
+ "port5_mac",
+ "port6_mac",
+ "nss_port1_rx",
+ "nss_port1_tx",
+ "nss_port2_rx",
+ "nss_port2_tx",
+ "nss_port3_rx",
+ "nss_port3_tx",
+ "nss_port4_rx",
+ "nss_port4_tx",
+ "nss_port5_rx",
+ "nss_port5_tx",
+ "nss_port6_rx",
+ "nss_port6_tx",
+ "uniphy_port1_rx",
+ "uniphy_port1_tx",
+ "uniphy_port2_rx",
+ "uniphy_port2_tx",
+ "uniphy_port3_rx",
+ "uniphy_port3_tx",
+ "uniphy_port4_rx",
+ "uniphy_port4_tx",
+ "uniphy_port5_rx",
+ "uniphy_port5_tx",
+ "uniphy_port6_rx",
+ "uniphy_port6_tx",
+ "nss_port5_rx_clk_src",
+ "nss_port5_tx_clk_src",
+};
+
+static const char * const ppe_reset_name[PPE_RST_MAX] = {
+ "ppe",
+ "uniphy0_sys",
+ "uniphy1_sys",
+ "uniphy2_sys",
+ "uniphy0_ahb",
+ "uniphy1_ahb",
+ "uniphy2_ahb",
+ "uniphy0_xpcs",
+ "uniphy1_xpcs",
+ "uniphy2_xpcs",
+ "uniphy0_soft",
+ "uniphy1_soft",
+ "uniphy2_soft",
+ "uniphy_port1_dis",
+ "uniphy_port2_dis",
+ "uniphy_port3_dis",
+ "uniphy_port4_dis",
+ "uniphy_port1_rx",
+ "uniphy_port1_tx",
+ "uniphy_port2_rx",
+ "uniphy_port2_tx",
+ "nss_port1_rx",
+ "nss_port1_tx",
+ "nss_port2_rx",
+ "nss_port2_tx",
+ "nss_port1",
+ "nss_port2",
+ "nss_port3",
+ "nss_port4",
+ "nss_port5",
+ "nss_port6",
+ "nss_port1_mac",
+ "nss_port2_mac",
+ "nss_port3_mac",
+ "nss_port4_mac",
+ "nss_port5_mac",
+ "nss_port6_mac",
+};
+
+int ppe_type_get(struct ppe_device *ppe_dev)
+{
+ struct ppe_data *ppe_dev_priv = ppe_dev->ppe_priv;
+
+ if (!ppe_dev_priv)
+ return PPE_TYPE_MAX;
+
+ return ppe_dev_priv->ppe_type;
+}
+
+static int ppe_clock_set_enable(struct ppe_device *ppe_dev,
+ enum ppe_clk_id clk_id, unsigned long rate)
+{
+ struct ppe_data *ppe_dev_priv = ppe_dev->ppe_priv;
+
+ if (clk_id >= PPE_CLK_MAX)
+ return -EINVAL;
+
+ if (rate != 0)
+ clk_set_rate(ppe_dev_priv->clk[clk_id], rate);
+
+ return clk_prepare_enable(ppe_dev_priv->clk[clk_id]);
+}
+
+static int ppe_fix_clock_init(struct ppe_device *ppe_dev)
+{
+ unsigned long noc_rate, ppe_rate;
+ enum ppe_clk_id clk_id;
+ int ppe_type = ppe_type_get(ppe_dev);
+
+ switch (ppe_type) {
+ case PPE_TYPE_APPE:
+ noc_rate = 342857143;
+ ppe_rate = 353000000;
+ break;
+ case PPE_TYPE_MPPE:
+ noc_rate = 266660000;
+ ppe_rate = 200000000;
+ ppe_clock_set_enable(ppe_dev, PPE_IM_SLEEP_CLK, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ppe_clock_set_enable(ppe_dev, PPE_CMN_AHB_CLK, 0);
+ ppe_clock_set_enable(ppe_dev, PPE_CMN_SYS_CLK, 0);
+ ppe_clock_set_enable(ppe_dev, PPE_NSSCC_CLK, 100000000);
+ ppe_clock_set_enable(ppe_dev, PPE_NSSNOC_NSSCC_CLK, 100000000);
+
+ ppe_clock_set_enable(ppe_dev, PPE_NSSNOC_SNOC_CLK, noc_rate);
+ ppe_clock_set_enable(ppe_dev, PPE_NSSNOC_SNOC_1_CLK, noc_rate);
+
+ ppe_clock_set_enable(ppe_dev, PPE_UNIPHY0_SYS_CLK, 24000000);
+ ppe_clock_set_enable(ppe_dev, PPE_UNIPHY1_SYS_CLK, 24000000);
+ ppe_clock_set_enable(ppe_dev, PPE_UNIPHY0_AHB_CLK, 100000000);
+ ppe_clock_set_enable(ppe_dev, PPE_UNIPHY1_AHB_CLK, 100000000);
+
+ if (ppe_type == PPE_TYPE_APPE) {
+ ppe_clock_set_enable(ppe_dev, PPE_UNIPHY2_SYS_CLK, 24000000);
+ ppe_clock_set_enable(ppe_dev, PPE_UNIPHY2_AHB_CLK, 100000000);
+ }
+
+ ppe_clock_set_enable(ppe_dev, PPE_PORT1_MAC_CLK, ppe_rate);
+ ppe_clock_set_enable(ppe_dev, PPE_PORT2_MAC_CLK, ppe_rate);
+
+ if (ppe_type == PPE_TYPE_APPE) {
+ ppe_clock_set_enable(ppe_dev, PPE_PORT3_MAC_CLK, ppe_rate);
+ ppe_clock_set_enable(ppe_dev, PPE_PORT4_MAC_CLK, ppe_rate);
+ ppe_clock_set_enable(ppe_dev, PPE_PORT5_MAC_CLK, ppe_rate);
+ ppe_clock_set_enable(ppe_dev, PPE_PORT6_MAC_CLK, ppe_rate);
+ }
+
+ ppe_clock_set_enable(ppe_dev, PPE_PPE_CLK, ppe_rate);
+ ppe_clock_set_enable(ppe_dev, PPE_PPE_CFG_CLK, ppe_rate);
+ ppe_clock_set_enable(ppe_dev, PPE_NSSNOC_PPE_CLK, ppe_rate);
+ ppe_clock_set_enable(ppe_dev, PPE_NSSNOC_PPE_CFG_CLK, ppe_rate);
+ ppe_clock_set_enable(ppe_dev, PPE_EDMA_CLK, ppe_rate);
+ ppe_clock_set_enable(ppe_dev, PPE_EDMA_CFG_CLK, ppe_rate);
+ ppe_clock_set_enable(ppe_dev, PPE_PPE_IPE_CLK, ppe_rate);
+ ppe_clock_set_enable(ppe_dev, PPE_PPE_BTQ_CLK, ppe_rate);
+
+ /* Enable uniphy port clocks */
+ for (clk_id = PPE_NSS_PORT1_RX_CLK; clk_id <= PPE_UNIPHY_PORT6_TX_CLK; clk_id++)
+ ppe_clock_set_enable(ppe_dev, clk_id, 0);
+
+ return 0;
+}
+
+static int ppe_clock_config(struct platform_device *pdev)
+{
+ struct ppe_device *ppe_dev = platform_get_drvdata(pdev);
+ struct ppe_data *ppe_dev_priv = ppe_dev->ppe_priv;
+ int ret;
+
+ ret = ppe_fix_clock_init(ppe_dev);
+ if (ret)
+ return ret;
+
+ /* Reset PPE */
+ reset_control_assert(ppe_dev_priv->rst[PPE_RST_PPE_RST]);
+ fsleep(100000);
+ reset_control_deassert(ppe_dev_priv->rst[PPE_RST_PPE_RST]);
+ fsleep(100000);
+
+ /* Reset the ahb uniphy connected with the PHY chip */
+ if (ppe_type_get(ppe_dev) == PPE_TYPE_MPPE) {
+ reset_control_assert(ppe_dev_priv->rst[PPE_UNIPHY1_AHB_RST]);
+ fsleep(100000);
+ reset_control_deassert(ppe_dev_priv->rst[PPE_UNIPHY1_AHB_RST]);
+ fsleep(100000);
+ }
+
+ return 0;
+}
+
+bool ppe_is_probed(struct platform_device *pdev)
+{
+ struct ppe_device *ppe_dev = platform_get_drvdata(pdev);
+
+ return ppe_dev && ppe_dev->is_ppe_probed;
+}
+EXPORT_SYMBOL_GPL(ppe_is_probed);
+
+struct ppe_device *ppe_dev_get(struct platform_device *pdev)
+{
+ return platform_get_drvdata(pdev);
+}
+EXPORT_SYMBOL_GPL(ppe_dev_get);
+
+static const struct regmap_range ppe_readable_ranges[] = {
+ regmap_reg_range(0x0, 0x1FF), /* GLB */
+ 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 IV */
+ 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 CSR */
+ regmap_reg_range(0x1E0000, 0x1EFFFF), /* INGRESS PARSE CSR */
+ regmap_reg_range(0x200000, 0x2FFFFF), /* IPE L3 */
+ regmap_reg_range(0x300000, 0x3FFFFF), /* IPE TL */
+ regmap_reg_range(0x400000, 0x4FFFFF), /* TM */
+ 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 */
+};
+
+static const struct regmap_access_table ppe_reg_table = {
+ .yes_ranges = ppe_readable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(ppe_readable_ranges),
+};
+
+static const struct regmap_config ppe_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .rd_table = &ppe_reg_table,
+ .wr_table = &ppe_reg_table,
+ .max_register = 0x9FFFFF,
+ .fast_io = true,
+};
+
+static struct ppe_data *ppe_data_init(struct platform_device *pdev)
+{
+ struct ppe_data *ppe_dev_priv;
+ int ret;
+
+ ppe_dev_priv = devm_kzalloc(&pdev->dev, sizeof(*ppe_dev_priv), GFP_KERNEL);
+ if (!ppe_dev_priv)
+ return ERR_PTR(-ENOMEM);
+
+ if (of_device_is_compatible(pdev->dev.of_node, "qcom,ipq9574-ppe"))
+ ppe_dev_priv->ppe_type = PPE_TYPE_APPE;
+ else if (of_device_is_compatible(pdev->dev.of_node, "qcom,ipq5332-ppe"))
+ ppe_dev_priv->ppe_type = PPE_TYPE_MPPE;
+ else
+ return ERR_PTR(-EINVAL);
+
+ for (ret = 0; ret < PPE_CLK_MAX; ret++) {
+ ppe_dev_priv->clk[ret] = devm_clk_get_optional(&pdev->dev,
+ ppe_clock_name[ret]);
+
+ if (IS_ERR(ppe_dev_priv->clk[ret]))
+ dev_err(&pdev->dev, "Failed to get the clock: %s\n",
+ ppe_clock_name[ret]);
+ }
+
+ for (ret = 0; ret < PPE_RST_MAX; ret++) {
+ ppe_dev_priv->rst[ret] =
+ devm_reset_control_get_optional_exclusive(&pdev->dev,
+ ppe_reset_name[ret]);
+ if (IS_ERR(ppe_dev_priv->rst[ret]))
+ dev_err(&pdev->dev, "Failed to get the reset %s!\n",
+ ppe_reset_name[ret]);
+ }
+
+ return ppe_dev_priv;
+}
+
+static int qcom_ppe_probe(struct platform_device *pdev)
+{
+ struct ppe_device *ppe_dev;
+ void __iomem *base;
+ int ret;
+
+ ppe_dev = devm_kzalloc(&pdev->dev, sizeof(*ppe_dev), GFP_KERNEL);
+ if (!ppe_dev)
+ return -ENOMEM;
+
+ ppe_dev->dev = &pdev->dev;
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return dev_err_probe(&pdev->dev,
+ PTR_ERR(base),
+ "Fail to ioremap\n");
+
+ ppe_dev->regmap = devm_regmap_init_mmio(&pdev->dev, base, &ppe_regmap_config);
+ if (IS_ERR(ppe_dev->regmap))
+ return dev_err_probe(&pdev->dev,
+ PTR_ERR(ppe_dev->regmap),
+ "Fail to regmap\n");
+
+ ppe_dev->ppe_priv = ppe_data_init(pdev);
+ if (IS_ERR(ppe_dev->ppe_priv))
+ return dev_err_probe(&pdev->dev,
+ PTR_ERR(ppe_dev->ppe_priv),
+ "Fail to init ppe data\n");
+
+ platform_set_drvdata(pdev, ppe_dev);
+ ret = ppe_clock_config(pdev);
+ if (ret)
+ return dev_err_probe(&pdev->dev,
+ ret,
+ "ppe clock config failed\n");
+
+ ppe_dev->is_ppe_probed = true;
+ return 0;
+}
+
+static int qcom_ppe_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static const struct of_device_id qcom_ppe_of_match[] = {
+ { .compatible = "qcom,ipq9574-ppe", },
+ { .compatible = "qcom,ipq5332-ppe", },
+ {},
+};
+
+static struct platform_driver qcom_ppe_driver = {
+ .driver = {
+ .name = "qcom_ppe",
+ .owner = THIS_MODULE,
+ .of_match_table = qcom_ppe_of_match,
+ },
+ .probe = qcom_ppe_probe,
+ .remove = qcom_ppe_remove,
+};
+module_platform_driver(qcom_ppe_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, qcom_ppe_of_match);
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.h b/drivers/net/ethernet/qualcomm/ppe/ppe.h
new file mode 100644
index 000000000000..f54406a6feb7
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+/* PPE clock, reset and register read/write declarations. */
+
+#ifndef __PPE_H__
+#define __PPE_H__
+
+#include <linux/clk.h>
+#include <linux/reset.h>
+
+enum ppe_clk_id {
+ /* clocks for CMN PLL */
+ PPE_CMN_AHB_CLK,
+ PPE_CMN_SYS_CLK,
+ /* clocks for PPE integrated uniphy */
+ PPE_UNIPHY0_SYS_CLK,
+ PPE_UNIPHY1_SYS_CLK,
+ PPE_UNIPHY2_SYS_CLK,
+ PPE_UNIPHY0_AHB_CLK,
+ PPE_UNIPHY1_AHB_CLK,
+ PPE_UNIPHY2_AHB_CLK,
+ /* clocks for NSS NOC that is connected with PPE */
+ PPE_NSSCC_CLK,
+ PPE_NSSNOC_NSSCC_CLK,
+ PPE_NSSNOC_SNOC_CLK,
+ PPE_NSSNOC_SNOC_1_CLK,
+ /* clock for sleep that is needed for PPE reset */
+ PPE_IM_SLEEP_CLK,
+ /* clocks for PPE block */
+ PPE_PPE_CLK,
+ PPE_PPE_CFG_CLK,
+ PPE_NSSNOC_PPE_CLK,
+ PPE_NSSNOC_PPE_CFG_CLK,
+ /* clocks for EDMA to be enabled during the PPE initialization */
+ PPE_EDMA_CLK,
+ PPE_EDMA_CFG_CLK,
+ /* clocks for PPE IPE/BTQ modules */
+ PPE_PPE_IPE_CLK,
+ PPE_PPE_BTQ_CLK,
+ /* clocks for PPE integrated MAC */
+ PPE_PORT1_MAC_CLK,
+ PPE_PORT2_MAC_CLK,
+ PPE_PORT3_MAC_CLK,
+ PPE_PORT4_MAC_CLK,
+ PPE_PORT5_MAC_CLK,
+ PPE_PORT6_MAC_CLK,
+ /* clocks for PPE port */
+ PPE_NSS_PORT1_RX_CLK,
+ PPE_NSS_PORT1_TX_CLK,
+ PPE_NSS_PORT2_RX_CLK,
+ PPE_NSS_PORT2_TX_CLK,
+ PPE_NSS_PORT3_RX_CLK,
+ PPE_NSS_PORT3_TX_CLK,
+ PPE_NSS_PORT4_RX_CLK,
+ PPE_NSS_PORT4_TX_CLK,
+ PPE_NSS_PORT5_RX_CLK,
+ PPE_NSS_PORT5_TX_CLK,
+ PPE_NSS_PORT6_RX_CLK,
+ PPE_NSS_PORT6_TX_CLK,
+ /* clocks for PPE uniphy port */
+ PPE_UNIPHY_PORT1_RX_CLK,
+ PPE_UNIPHY_PORT1_TX_CLK,
+ PPE_UNIPHY_PORT2_RX_CLK,
+ PPE_UNIPHY_PORT2_TX_CLK,
+ PPE_UNIPHY_PORT3_RX_CLK,
+ PPE_UNIPHY_PORT3_TX_CLK,
+ PPE_UNIPHY_PORT4_RX_CLK,
+ PPE_UNIPHY_PORT4_TX_CLK,
+ PPE_UNIPHY_PORT5_RX_CLK,
+ PPE_UNIPHY_PORT5_TX_CLK,
+ PPE_UNIPHY_PORT6_RX_CLK,
+ PPE_UNIPHY_PORT6_TX_CLK,
+ /* source clock for PPE port5 */
+ PPE_NSS_PORT5_RX_CLK_SRC,
+ PPE_NSS_PORT5_TX_CLK_SRC,
+ PPE_CLK_MAX
+};
+
+enum ppe_rst_id {
+ /* reset for PPE block */
+ PPE_RST_PPE_RST,
+ /* resets for uniphy */
+ PPE_UNIPHY0_SYS_RST,
+ PPE_UNIPHY1_SYS_RST,
+ PPE_UNIPHY2_SYS_RST,
+ PPE_UNIPHY0_AHB_RST,
+ PPE_UNIPHY1_AHB_RST,
+ PPE_UNIPHY2_AHB_RST,
+ PPE_UNIPHY0_XPCS_RST,
+ PPE_UNIPHY1_XPCS_RST,
+ PPE_UNIPHY2_XPCS_RST,
+ PPE_UNIPHY0_SOFT_RST,
+ PPE_UNIPHY1_SOFT_RST,
+ PPE_UNIPHY2_SOFT_RST,
+ /* resets for uniphy port */
+ PPE_UNIPHY_PORT1_DIS,
+ PPE_UNIPHY_PORT2_DIS,
+ PPE_UNIPHY_PORT3_DIS,
+ PPE_UNIPHY_PORT4_DIS,
+ PPE_UNIPHY_PORT1_RX_RST,
+ PPE_UNIPHY_PORT1_TX_RST,
+ PPE_UNIPHY_PORT2_RX_RST,
+ PPE_UNIPHY_PORT2_TX_RST,
+ /* resets for PPE port */
+ PPE_NSS_PORT1_RX_RST,
+ PPE_NSS_PORT1_TX_RST,
+ PPE_NSS_PORT2_RX_RST,
+ PPE_NSS_PORT2_TX_RST,
+ PPE_NSS_PORT1_RST,
+ PPE_NSS_PORT2_RST,
+ PPE_NSS_PORT3_RST,
+ PPE_NSS_PORT4_RST,
+ PPE_NSS_PORT5_RST,
+ PPE_NSS_PORT6_RST,
+ /* resets for PPE MAC */
+ PPE_NSS_PORT1_MAC_RST,
+ PPE_NSS_PORT2_MAC_RST,
+ PPE_NSS_PORT3_MAC_RST,
+ PPE_NSS_PORT4_MAC_RST,
+ PPE_NSS_PORT5_MAC_RST,
+ PPE_NSS_PORT6_MAC_RST,
+ PPE_RST_MAX
+};
+
+/* Different PPE type used on the different IPQ SoC platform */
+enum {
+ PPE_TYPE_APPE,
+ PPE_TYPE_MPPE,
+ PPE_TYPE_MAX = 0xff,
+};
+
+/* PPE private data of different PPE type device */
+struct ppe_data {
+ int ppe_type;
+ struct clk *clk[PPE_CLK_MAX];
+ struct reset_control *rst[PPE_RST_MAX];
+};
+
+int ppe_type_get(struct ppe_device *ppe_dev);
+#endif
diff --git a/include/linux/soc/qcom/ppe.h b/include/linux/soc/qcom/ppe.h
new file mode 100644
index 000000000000..90566a8841b4
--- /dev/null
+++ b/include/linux/soc/qcom/ppe.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+/* PPE operations to be used by ethernet driver */
+
+#ifndef __QCOM_PPE_H__
+#define __QCOM_PPE_H__
+
+#include <linux/platform_device.h>
+
+/* PPE platform private data, which is used by external driver like
+ * Ethernet DMA driver.
+ */
+struct ppe_device {
+ struct device *dev;
+ struct regmap *regmap;
+ bool is_ppe_probed;
+ void *ppe_priv;
+};
+
+/* Function used to check PPE platform dirver is registered correctly or not. */
+bool ppe_is_probed(struct platform_device *pdev);
+
+/* Function used to get the PPE device */
+struct ppe_device *ppe_dev_get(struct platform_device *pdev);
+#endif
--
2.42.0