[PATCH net-next 1/4] net: ethernet: qualcomm: ppe: Select hardware configuration by SoC
flat view
WARM2d
From: Til Kaiser <hidden>
Date: 2026-10-05 15:36:09
Also in:
linux-arm-msm, linux-devicetree, linux-doc, lkml
Subsystem:
networking drivers, qualcomm ppe driver, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Luo Jie, Linus Torvalds
The PPE driver hardcodes IPQ9574 parameters: the PPE clock rate, interconnect paths, port count, buffer limits and scheduler arbitration tables. Other SoCs with the same PPE architecture need different values. Move these into per-SoC platform match data, and collect the buffer manager (BM), queue manager (QM) and scheduler tables in a new struct ppe_soc_config that is passed to the hardware initialization code. The IPQ9574 values are unchanged; no functional change intended. The IPQ9574 scheduler resource table has nine entries, with the reserved pool at index 8. Select that final entry for port ID num_ports, preserving the IPQ9574 lookup while allowing a smaller port count on other SoCs. Rename regmap_config_ipq9574 to ppe_reg_config for the shared PPE register layout. Signed-off-by: Til Kaiser <redacted> --- drivers/net/ethernet/qualcomm/ppe/ppe.c | 48 ++++++++++----- .../net/ethernet/qualcomm/ppe/ppe_config.c | 58 +++++++++++++------ .../net/ethernet/qualcomm/ppe/ppe_config.h | 34 ++++++++++- 3 files changed, 106 insertions(+), 34 deletions(-)
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.c b/drivers/net/ethernet/qualcomm/ppe/ppe.c
index 3c301e609d3e..0ef72c20364b 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c@@ -11,6 +11,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/regmap.h> #include <linux/reset.h>
@@ -18,13 +19,15 @@ #include "ppe_config.h" #include "ppe_debugfs.h" -#define PPE_PORT_MAX 8 -#define PPE_CLK_RATE 353000000 +struct ppe_plat_data { + const struct ppe_soc_config *soc_cfg; + const struct icc_bulk_data *icc_data; + unsigned long ppe_clk_rate; + unsigned int num_icc, num_ports; +}; -/* 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[] = { +/* IPQ9574 interconnect paths. Zero bandwidths use the PPE clock rate. */ +static const struct icc_bulk_data ipq9574_icc_data[] = { { .name = "ppe", .avg_bw = 0,
@@ -62,6 +65,15 @@ static const struct icc_bulk_data ppe_icc_data[] = { }, }; +static const struct ppe_plat_data ipq9574_ppe_data = { + .soc_cfg = &ipq9574_soc_config, + .icc_data = ipq9574_icc_data, + .ppe_clk_rate = 353000000, + .num_icc = ARRAY_SIZE(ipq9574_icc_data), + .num_ports = 8, +}; + +/* PPE register access ranges. */ static const struct regmap_range ppe_readable_ranges[] = { regmap_reg_range(0x0, 0x1ff), /* Global */ regmap_reg_range(0x400, 0x5ff), /* LPI CSR */
@@ -99,7 +111,7 @@ static const struct regmap_access_table ppe_reg_table = { .n_yes_ranges = ARRAY_SIZE(ppe_readable_ranges), }; -static const struct regmap_config regmap_config_ipq9574 = { +static const struct regmap_config ppe_reg_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32,
@@ -108,7 +120,8 @@ static const struct regmap_config regmap_config_ipq9574 = { .max_register = 0xbef800, }; -static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev) +static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev, + const struct icc_bulk_data *ppe_icc_data) { unsigned long ppe_rate = ppe_dev->clk_rate; struct device *dev = ppe_dev->dev;
@@ -172,12 +185,17 @@ static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev) static int qcom_ppe_probe(struct platform_device *pdev) { + const struct ppe_plat_data *plat_data; struct device *dev = &pdev->dev; struct ppe_device *ppe_dev; void __iomem *base; int ret, num_icc; - num_icc = ARRAY_SIZE(ppe_icc_data); + plat_data = device_get_match_data(dev); + if (!plat_data) + return -EINVAL; + + num_icc = plat_data->num_icc; ppe_dev = devm_kzalloc(dev, struct_size(ppe_dev, icc_paths, num_icc), GFP_KERNEL); if (!ppe_dev)
@@ -187,20 +205,20 @@ 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, &ppe_reg_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->clk_rate = plat_data->ppe_clk_rate; + ppe_dev->num_ports = plat_data->num_ports; ppe_dev->num_icc_paths = num_icc; - ret = ppe_clock_init_and_reset(ppe_dev); + ret = ppe_clock_init_and_reset(ppe_dev, plat_data->icc_data); if (ret) return dev_err_probe(dev, ret, "PPE clock config failed\n"); - ret = ppe_hw_config(ppe_dev); + ret = ppe_hw_config(ppe_dev, plat_data->soc_cfg); if (ret) return dev_err_probe(dev, ret, "PPE HW config failed\n");
@@ -219,7 +237,7 @@ static void qcom_ppe_remove(struct platform_device *pdev) } static const struct of_device_id qcom_ppe_of_match[] = { - { .compatible = "qcom,ipq9574-ppe" }, + { .compatible = "qcom,ipq9574-ppe", .data = &ipq9574_ppe_data }, {} }; MODULE_DEVICE_TABLE(of, qcom_ppe_of_match);
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
index 125b73be92b1..65ac6c0841d5 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c@@ -835,6 +835,19 @@ static const struct ppe_port_schedule_resource ppe_scheduler_res[] = { }, }; +const struct ppe_soc_config ipq9574_soc_config = { + .bm_group_config = ipq9574_ppe_bm_group_config, + .bm_port_config = ipq9574_ppe_bm_port_config, + .bm_port_config_cnt = ARRAY_SIZE(ipq9574_ppe_bm_port_config), + .qm_group_config = ipq9574_ppe_qm_group_config, + .qm_queue_config = ipq9574_ppe_qm_queue_config, + .qm_queue_config_cnt = ARRAY_SIZE(ipq9574_ppe_qm_queue_config), + .sch_bm_config = ipq9574_ppe_sch_bm_config, + .sch_bm_config_cnt = ARRAY_SIZE(ipq9574_ppe_sch_bm_config), + .sch_qm_config = ipq9574_ppe_sch_qm_config, + .sch_qm_config_cnt = ARRAY_SIZE(ipq9574_ppe_sch_qm_config), +}; + /* Set the PPE queue level scheduler configuration. */ static int ppe_scheduler_l0_queue_map_set(struct ppe_device *ppe_dev, int node_id, int port,
@@ -1080,7 +1093,12 @@ int ppe_port_resource_get(struct ppe_device *ppe_dev, int port, if (port > ppe_dev->num_ports) return -EINVAL; - res = ppe_scheduler_res[port]; + /* Port ID num_ports selects the reserved pool in the final entry. */ + if (port == ppe_dev->num_ports) + res = ppe_scheduler_res[ARRAY_SIZE(ppe_scheduler_res) - 1]; + else + res = ppe_scheduler_res[port]; + switch (type) { case PPE_RES_UCAST: *res_start = res.ucastq_start;
@@ -1427,7 +1445,8 @@ static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, } /* Configure the buffer threshold for the port flow control function. */ -static int ppe_config_bm(struct ppe_device *ppe_dev) +static int ppe_config_bm(struct ppe_device *ppe_dev, + const struct ppe_soc_config *soc_cfg) { const struct ppe_bm_port_config *port_cfg; unsigned int i, bm_port_id, port_cfg_cnt;
@@ -1440,7 +1459,7 @@ static int ppe_config_bm(struct ppe_device *ppe_dev) */ reg = PPE_BM_SHARED_GROUP_CFG_ADDR; val = FIELD_PREP(PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT, - ipq9574_ppe_bm_group_config); + soc_cfg->bm_group_config); ret = regmap_update_bits(ppe_dev->regmap, reg, PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT, val);
@@ -1448,8 +1467,8 @@ static int ppe_config_bm(struct ppe_device *ppe_dev) goto bm_config_fail; /* Configure buffer thresholds for the BM ports. */ - port_cfg = ipq9574_ppe_bm_port_config; - port_cfg_cnt = ARRAY_SIZE(ipq9574_ppe_bm_port_config); + port_cfg = soc_cfg->bm_port_config; + port_cfg_cnt = soc_cfg->bm_port_config_cnt; for (i = 0; i < port_cfg_cnt; i++) { for (bm_port_id = port_cfg[i].port_id_start; bm_port_id <= port_cfg[i].port_id_end; bm_port_id++) {
@@ -1470,7 +1489,8 @@ static int ppe_config_bm(struct ppe_device *ppe_dev) /* Configure PPE hardware queue depth, which is decided by the threshold * of queue. */ -static int ppe_config_qm(struct ppe_device *ppe_dev) +static int ppe_config_qm(struct ppe_device *ppe_dev, + const struct ppe_soc_config *soc_cfg) { const struct ppe_qm_queue_config *queue_cfg; int ret, i, queue_id, queue_cfg_count;
@@ -1485,15 +1505,15 @@ static int ppe_config_qm(struct ppe_device *ppe_dev) if (ret) goto qm_config_fail; - PPE_AC_GRP_SET_BUF_LIMIT(group_cfg, ipq9574_ppe_qm_group_config); + PPE_AC_GRP_SET_BUF_LIMIT(group_cfg, soc_cfg->qm_group_config); ret = regmap_bulk_write(ppe_dev->regmap, reg, group_cfg, ARRAY_SIZE(group_cfg)); if (ret) goto qm_config_fail; - queue_cfg = ipq9574_ppe_qm_queue_config; - queue_cfg_count = ARRAY_SIZE(ipq9574_ppe_qm_queue_config); + queue_cfg = soc_cfg->qm_queue_config; + queue_cfg_count = soc_cfg->qm_queue_config_cnt; for (i = 0; i < queue_cfg_count; i++) { queue_id = queue_cfg[i].queue_start;
@@ -1625,7 +1645,8 @@ static int ppe_node_scheduler_config(struct ppe_device *ppe_dev, /* Initialize scheduler settings for PPE buffer utilization and dispatching * packet on PPE queue. */ -static int ppe_config_scheduler(struct ppe_device *ppe_dev) +static int ppe_config_scheduler(struct ppe_device *ppe_dev, + const struct ppe_soc_config *soc_cfg) { const struct ppe_scheduler_port_config *port_cfg; const struct ppe_scheduler_qm_config *qm_cfg;
@@ -1633,8 +1654,8 @@ static int ppe_config_scheduler(struct ppe_device *ppe_dev) int ret, i, count; u32 val, reg; - count = ARRAY_SIZE(ipq9574_ppe_sch_bm_config); - bm_cfg = ipq9574_ppe_sch_bm_config; + count = soc_cfg->sch_bm_config_cnt; + bm_cfg = soc_cfg->sch_bm_config; /* Configure the depth of BM scheduler entries. */ val = FIELD_PREP(PPE_BM_SCH_CTRL_SCH_DEPTH, count);
@@ -1664,8 +1685,8 @@ static int ppe_config_scheduler(struct ppe_device *ppe_dev) goto sch_config_fail; } - count = ARRAY_SIZE(ipq9574_ppe_sch_qm_config); - qm_cfg = ipq9574_ppe_sch_qm_config; + count = soc_cfg->sch_qm_config_cnt; + qm_cfg = soc_cfg->sch_qm_config; /* Configure the depth of QM scheduler entries. */ val = FIELD_PREP(PPE_PSCH_SCH_DEPTH_CFG_SCH_DEPTH, count);
@@ -1995,19 +2016,20 @@ static int ppe_bridge_init(struct ppe_device *ppe_dev) return 0; } -int ppe_hw_config(struct ppe_device *ppe_dev) +int ppe_hw_config(struct ppe_device *ppe_dev, + const struct ppe_soc_config *soc_cfg) { int ret; - ret = ppe_config_bm(ppe_dev); + ret = ppe_config_bm(ppe_dev, soc_cfg); if (ret) return ret; - ret = ppe_config_qm(ppe_dev); + ret = ppe_config_qm(ppe_dev, soc_cfg); if (ret) return ret; - ret = ppe_config_scheduler(ppe_dev); + ret = ppe_config_scheduler(ppe_dev, soc_cfg); if (ret) return ret;
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
index 60493e51e0a4..0dafab264743 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h@@ -287,7 +287,39 @@ struct ppe_rss_hash_cfg { u8 hash_fin_outer[PPE_RSS_HASH_TUPLES]; }; -int ppe_hw_config(struct ppe_device *ppe_dev); +/** + * struct ppe_soc_config - SoC-specific PPE hardware configuration. + * @bm_group_config: Buffer Management (BM) group configuration. + * @bm_port_config: Pointer to the BM port configuration array. + * @bm_port_config_cnt: Number of entries in the BM port configuration array. + * @qm_group_config: Queue Management (QM) group configuration. + * @qm_queue_config: Pointer to the QM queue configuration array. + * @qm_queue_config_cnt: Number of entries in the QM queue configuration array. + * @sch_bm_config: Pointer to the BM scheduler arbitration array. + * @sch_bm_config_cnt: Number of entries in the BM scheduler arbitration array. + * @sch_qm_config: Pointer to the QM scheduler arbitration array. + * @sch_qm_config_cnt: Number of entries in the QM scheduler arbitration array. + */ +struct ppe_soc_config { + int bm_group_config; + const struct ppe_bm_port_config *bm_port_config; + unsigned int bm_port_config_cnt; + + int qm_group_config; + const struct ppe_qm_queue_config *qm_queue_config; + unsigned int qm_queue_config_cnt; + + const struct ppe_scheduler_bm_config *sch_bm_config; + unsigned int sch_bm_config_cnt; + + const struct ppe_scheduler_qm_config *sch_qm_config; + unsigned int sch_qm_config_cnt; +}; + +extern const struct ppe_soc_config ipq9574_soc_config; + +int ppe_hw_config(struct ppe_device *ppe_dev, + const struct ppe_soc_config *soc_cfg); int ppe_queue_scheduler_set(struct ppe_device *ppe_dev, int node_id, bool flow_level, int port, struct ppe_scheduler_cfg scheduler_cfg);
--
2.56.0