[PATCH net-next 05/11] net: ethernet: qualcomm: ppe: Add platform support for IPQ5424
From: Luo Jie
Date: Thu Oct 08 2026 - 10:57:49 EST
IPQ5424 integrates the same PPE switch core as IPQ9574, but has only 3
Ethernet ports plus the EDMA FIFO, without the EIP FIFO. The PPE clock runs
at 375 MHz instead of IPQ9574's 353 MHz, and IPQ5424 requires a different,
smaller set of interconnect paths. The register space of the unavailable
MAC3 to MAC5 must also not be accessed on IPQ5424.
Add the platform data per SoC to describe these differences, and add the
IPQ5424 compatible.
Signed-off-by: Luo Jie <jie.luo@xxxxxxxxxxxxxxxx>
---
drivers/net/ethernet/qualcomm/ppe/ppe.c | 132 ++++++++++++++++++++++++++++----
1 file changed, 116 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.c b/drivers/net/ethernet/qualcomm/ppe/ppe.c
index 3c301e609d3e..f71b673b6f97 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c
@@ -18,13 +18,34 @@
#include "ppe_config.h"
#include "ppe_debugfs.h"
-#define PPE_PORT_MAX 8
-#define PPE_CLK_RATE 353000000
+#define IPQ9574_PPE_CLK_RATE 353000000
+#define IPQ5424_PPE_CLK_RATE 375000000
+
+/* 6 physical ports, 1 EDMA FIFO and 1 EIP FIFO. */
+#define IPQ9574_PPE_PORT_MAX 8
+/* 3 physical ports and 1 EDMA FIFO. */
+#define IPQ5424_PPE_PORT_MAX 4
+
+/**
+ * struct ppe_of_data - PPE private data of IPQ SoC
+ * @ppe_rate: PPE clock rate
+ * @num_ports: Number of PPE ports
+ * @regmap_config: Regmap configuration
+ * @icc_paths: Interconnect paths per PPE type
+ * @num_icc_paths: Number of ICC paths
+ */
+struct ppe_of_data {
+ unsigned long ppe_rate;
+ int num_ports;
+ const struct regmap_config *regmap_config;
+ const struct icc_bulk_data *icc_paths;
+ int num_icc_paths;
+};
/* 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[] = {
+static const struct icc_bulk_data ipq9574_ppe_icc_data[] = {
{
.name = "ppe",
.avg_bw = 0,
@@ -62,6 +83,34 @@ static const struct icc_bulk_data ppe_icc_data[] = {
},
};
+static const struct icc_bulk_data ipq5424_ppe_icc_data[] = {
+ {
+ .name = "ppe",
+ .avg_bw = 0,
+ .peak_bw = 0,
+ },
+ {
+ .name = "ppe_cfg",
+ .avg_bw = 0,
+ .peak_bw = 0,
+ },
+ {
+ .name = "nssnoc_ce_axi",
+ .avg_bw = 0,
+ .peak_bw = 0,
+ },
+ {
+ .name = "nssnoc_ce_apb",
+ .avg_bw = 0,
+ .peak_bw = 0,
+ },
+ {
+ .name = "nssnoc_nss_csr",
+ .avg_bw = 100000,
+ .peak_bw = 100000,
+ },
+};
+
static const struct regmap_range ppe_readable_ranges[] = {
regmap_reg_range(0x0, 0x1ff), /* Global */
regmap_reg_range(0x400, 0x5ff), /* LPI CSR */
@@ -108,7 +157,36 @@ static const struct regmap_config regmap_config_ipq9574 = {
.max_register = 0xbef800,
};
-static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev)
+/* For IPQ5424, there are only three Ethernet ports, the register space of
+ * GMAC/XGMAC 3-5 is unavailable.
+ */
+static const struct regmap_range ppe_reserved_ranges_ipq5424[] = {
+ regmap_reg_range(0x1600, 0x17ff), /* GMAC3 */
+ regmap_reg_range(0x1800, 0x19ff), /* GMAC4 */
+ regmap_reg_range(0x1a00, 0x1bff), /* GMAC5 */
+ regmap_reg_range(0x50c000, 0x50ffff), /* XGMAC3 */
+ regmap_reg_range(0x510000, 0x513fff), /* XGMAC4 */
+ regmap_reg_range(0x514000, 0x517fff), /* XGMAC5 */
+};
+
+static const struct regmap_access_table ppe_reg_table_ipq5424 = {
+ .yes_ranges = ppe_readable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(ppe_readable_ranges),
+ .no_ranges = ppe_reserved_ranges_ipq5424,
+ .n_no_ranges = ARRAY_SIZE(ppe_reserved_ranges_ipq5424),
+};
+
+static const struct regmap_config regmap_config_ipq5424 = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .rd_table = &ppe_reg_table_ipq5424,
+ .wr_table = &ppe_reg_table_ipq5424,
+ .max_register = 0xbef800,
+};
+
+static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev,
+ const struct ppe_of_data *data)
{
unsigned long ppe_rate = ppe_dev->clk_rate;
struct device *dev = ppe_dev->dev;
@@ -118,15 +196,15 @@ static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev)
int ret, i;
for (i = 0; i < ppe_dev->num_icc_paths; i++) {
- ppe_dev->icc_paths[i].name = ppe_icc_data[i].name;
- ppe_dev->icc_paths[i].avg_bw = ppe_icc_data[i].avg_bw ? :
+ ppe_dev->icc_paths[i].name = data->icc_paths[i].name;
+ ppe_dev->icc_paths[i].avg_bw = data->icc_paths[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 = ppe_icc_data[i].peak_bw ? :
+ ppe_dev->icc_paths[i].peak_bw = data->icc_paths[i].peak_bw ? :
Bps_to_icc(ppe_rate);
}
@@ -173,12 +251,17 @@ static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev)
static int qcom_ppe_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ const struct ppe_of_data *data;
struct ppe_device *ppe_dev;
void __iomem *base;
- int ret, num_icc;
+ int ret;
+
+ data = of_device_get_match_data(dev);
+ if (!data)
+ return dev_err_probe(dev, -EINVAL, "PPE no match data provided\n");
- num_icc = ARRAY_SIZE(ppe_icc_data);
- ppe_dev = devm_kzalloc(dev, struct_size(ppe_dev, icc_paths, num_icc),
+ ppe_dev = devm_kzalloc(dev,
+ struct_size(ppe_dev, icc_paths, data->num_icc_paths),
GFP_KERNEL);
if (!ppe_dev)
return -ENOMEM;
@@ -187,16 +270,16 @@ static int qcom_ppe_probe(struct platform_device *pdev)
if (IS_ERR(base))
return dev_err_probe(dev, PTR_ERR(base), "PPE ioremap failed\n");
- ppe_dev->regmap = devm_regmap_init_mmio(dev, base, ®map_config_ipq9574);
+ ppe_dev->regmap = devm_regmap_init_mmio(dev, base, data->regmap_config);
if (IS_ERR(ppe_dev->regmap))
return dev_err_probe(dev, PTR_ERR(ppe_dev->regmap),
"PPE initialize regmap failed\n");
ppe_dev->dev = dev;
- ppe_dev->clk_rate = PPE_CLK_RATE;
- ppe_dev->num_ports = PPE_PORT_MAX;
- ppe_dev->num_icc_paths = num_icc;
+ ppe_dev->clk_rate = data->ppe_rate;
+ ppe_dev->num_ports = data->num_ports;
+ ppe_dev->num_icc_paths = data->num_icc_paths;
- ret = ppe_clock_init_and_reset(ppe_dev);
+ ret = ppe_clock_init_and_reset(ppe_dev, data);
if (ret)
return dev_err_probe(dev, ret, "PPE clock config failed\n");
@@ -218,8 +301,25 @@ static void qcom_ppe_remove(struct platform_device *pdev)
ppe_debugfs_teardown(ppe_dev);
}
+static const struct ppe_of_data ipq9574_data = {
+ .ppe_rate = IPQ9574_PPE_CLK_RATE,
+ .num_ports = IPQ9574_PPE_PORT_MAX,
+ .regmap_config = ®map_config_ipq9574,
+ .icc_paths = ipq9574_ppe_icc_data,
+ .num_icc_paths = ARRAY_SIZE(ipq9574_ppe_icc_data),
+};
+
+static const struct ppe_of_data ipq5424_data = {
+ .ppe_rate = IPQ5424_PPE_CLK_RATE,
+ .num_ports = IPQ5424_PPE_PORT_MAX,
+ .regmap_config = ®map_config_ipq5424,
+ .icc_paths = ipq5424_ppe_icc_data,
+ .num_icc_paths = ARRAY_SIZE(ipq5424_ppe_icc_data),
+};
+
static const struct of_device_id qcom_ppe_of_match[] = {
- { .compatible = "qcom,ipq9574-ppe" },
+ { .compatible = "qcom,ipq9574-ppe", .data = &ipq9574_data },
+ { .compatible = "qcom,ipq5424-ppe", .data = &ipq5424_data },
{}
};
MODULE_DEVICE_TABLE(of, qcom_ppe_of_match);
--
2.43.0