@@ -4,4 +4,4 @@
#
obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o
-qcom-ppe-objs := ppe.o
+qcom-ppe-objs := ppe.o ppe_ops.o
@@ -15,8 +15,13 @@
#include <linux/soc/qcom/ppe.h>
#include "ppe.h"
#include "ppe_regs.h"
+#include "ppe_ops.h"
#define PPE_SCHEDULER_PORT_NUM 8
+#define PPE_SCHEDULER_L0_NUM 300
+#define PPE_SCHEDULER_L1_NUM 64
+#define PPE_SP_PRIORITY_NUM 8
+
static const char * const ppe_clock_name[PPE_CLK_MAX] = {
"cmn_ahb",
"cmn_sys",
@@ -794,17 +799,202 @@ static int of_parse_ppe_scheduler_resource(struct ppe_device *ppe_dev,
return 0;
}
+static int of_parse_ppe_scheduler_group_config(struct ppe_device *ppe_dev,
+ struct device_node *group_node,
+ int port,
+ const char *node_name,
+ const char *loop_name)
+{
+ struct ppe_qos_scheduler_cfg qos_cfg;
+ const struct ppe_queue_ops *ppe_queue_ops;
+ const __be32 *paddr;
+ int ret, len, i, node_id, level, node_max;
+ u32 tmp_cfg[5], pri_loop, max_pri;
+
+ ppe_queue_ops = ppe_queue_config_ops_get();
+ if (!ppe_queue_ops->queue_scheduler_set)
+ return -EINVAL;
+
+ /* The value of the property node_name can be single value
+ * or array value.
+ *
+ * If the array value is defined, the property loop_name should not
+ * be specified.
+ *
+ * If the single value is defined, the queue ID will be added in the
+ * loop value defined by the loop_name.
+ */
+ paddr = of_get_property(group_node, node_name, &len);
+ if (!paddr)
+ return dev_err_probe(ppe_dev->dev, -ENODEV,
+ "Fail to get queue %s of port %d\n",
+ node_name, port);
+
+ len /= sizeof(u32);
+
+ /* There are two levels scheduler configs, the level 0 scheduler
+ * config is configured on the queue, the level 1 scheduler is
+ * configured on the flow that is from the output of level 0
+ * scheduler.
+ */
+ if (!strcmp(node_name, "qcom,flow")) {
+ level = 1;
+ node_max = PPE_SCHEDULER_L1_NUM;
+ } else {
+ level = 0;
+ node_max = PPE_SCHEDULER_L0_NUM;
+ }
+
+ if (of_property_read_u32_array(group_node, "qcom,scheduler-config",
+ tmp_cfg, ARRAY_SIZE(tmp_cfg)))
+ return dev_err_probe(ppe_dev->dev, -ENODEV,
+ "Fail to get qcom,scheduler-config of port %d\n",
+ port);
+
+ if (of_property_read_u32(group_node, loop_name, &pri_loop)) {
+ for (i = 0; i < len; i++) {
+ node_id = be32_to_cpup(paddr + i);
+ if (node_id >= node_max)
+ return dev_err_probe(ppe_dev->dev, -EINVAL,
+ "Invalid node ID %d of port %d\n",
+ node_id, port);
+
+ memset(&qos_cfg, 0, sizeof(qos_cfg));
+
+ qos_cfg.sp_id = tmp_cfg[0];
+ qos_cfg.c_pri = tmp_cfg[1];
+ qos_cfg.c_drr_id = tmp_cfg[2];
+ qos_cfg.e_pri = tmp_cfg[3];
+ qos_cfg.e_drr_id = tmp_cfg[4];
+ qos_cfg.c_drr_wt = 1;
+ qos_cfg.e_drr_wt = 1;
+ ret = ppe_queue_ops->queue_scheduler_set(ppe_dev,
+ node_id,
+ level,
+ port,
+ qos_cfg);
+ if (ret)
+ return dev_err_probe(ppe_dev->dev, ret,
+ "scheduler set fail on node ID %d\n",
+ node_id);
+ }
+ } else {
+ /* Only one base node ID allowed to loop. */
+ if (len != 1)
+ return dev_err_probe(ppe_dev->dev, -EINVAL,
+ "Multiple node ID defined to loop for port %d\n",
+ port);
+
+ /* Property qcom,drr-max-priority is optional for loop,
+ * if not defined, the default value PPE_SP_PRIORITY_NUM
+ * is used.
+ */
+ max_pri = PPE_SP_PRIORITY_NUM;
+ of_property_read_u32(group_node, "qcom,drr-max-priority", &max_pri);
+
+ node_id = be32_to_cpup(paddr);
+ if (node_id >= node_max)
+ return dev_err_probe(ppe_dev->dev, -EINVAL,
+ "Invalid node ID %d defined to loop for port %d\n",
+ node_id, port);
+
+ for (i = 0; i < pri_loop; i++) {
+ memset(&qos_cfg, 0, sizeof(qos_cfg));
+
+ qos_cfg.sp_id = tmp_cfg[0] + i / max_pri;
+ qos_cfg.c_pri = tmp_cfg[1] + i % max_pri;
+ qos_cfg.c_drr_id = tmp_cfg[2] + i;
+ qos_cfg.e_pri = tmp_cfg[3] + i % max_pri;
+ qos_cfg.e_drr_id = tmp_cfg[4] + i;
+ qos_cfg.c_drr_wt = 1;
+ qos_cfg.e_drr_wt = 1;
+ ret = ppe_queue_ops->queue_scheduler_set(ppe_dev,
+ node_id + i,
+ level,
+ port,
+ qos_cfg);
+ if (ret)
+ return dev_err_probe(ppe_dev->dev, ret,
+ "scheduler set fail on node ID %d\n",
+ node_id + i);
+ }
+ }
+
+ return 0;
+}
+
+static int of_parse_ppe_scheduler_config(struct ppe_device *ppe_dev,
+ struct device_node *port_node)
+{
+ struct device_node *scheduler_node, *child;
+ int port, ret;
+
+ if (of_property_read_u32(port_node, "port-id", &port))
+ return dev_err_probe(ppe_dev->dev, -ENODEV,
+ "Fail to get port-id of l0scheduler\n");
+
+ scheduler_node = of_get_child_by_name(port_node, "l0scheduler");
+ if (!scheduler_node)
+ return dev_err_probe(ppe_dev->dev, -ENODEV,
+ "Fail to get l0scheduler config\n");
+
+ for_each_available_child_of_node(scheduler_node, child) {
+ ret = of_parse_ppe_scheduler_group_config(ppe_dev, child, port,
+ "qcom,ucast-queue",
+ "qcom,ucast-loop-priority");
+ if (ret)
+ return ret;
+
+ ret = of_parse_ppe_scheduler_group_config(ppe_dev, child, port,
+ "qcom,mcast-queue",
+ "qcom,mcast-loop-priority");
+ if (ret)
+ return ret;
+ }
+
+ scheduler_node = of_get_child_by_name(port_node, "l1scheduler");
+ if (!scheduler_node)
+ return dev_err_probe(ppe_dev->dev, -ENODEV,
+ "Fail to get l1scheduler config\n");
+
+ for_each_available_child_of_node(scheduler_node, child) {
+ ret = of_parse_ppe_scheduler_group_config(ppe_dev, child, port,
+ "qcom,flow",
+ "qcom,flow-loop-priority");
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
static int of_parse_ppe_scheduler(struct ppe_device *ppe_dev,
struct device_node *ppe_node)
{
- struct device_node *scheduler_node;
+ struct device_node *scheduler_node, *port_node;
+ int ret;
scheduler_node = of_get_child_by_name(ppe_node, "port-scheduler-resource");
if (!scheduler_node)
return dev_err_probe(ppe_dev->dev, -ENODEV,
"port-scheduler-resource is not defined\n");
- return of_parse_ppe_scheduler_resource(ppe_dev, scheduler_node);
+ ret = of_parse_ppe_scheduler_resource(ppe_dev, scheduler_node);
+ if (ret)
+ return ret;
+
+ scheduler_node = of_get_child_by_name(ppe_node, "port-scheduler-config");
+ if (!scheduler_node)
+ return dev_err_probe(ppe_dev->dev, -ENODEV,
+ "port-scheduler-config is not defined\n");
+
+ for_each_available_child_of_node(scheduler_node, port_node) {
+ ret = of_parse_ppe_scheduler_config(ppe_dev, port_node);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
}
static int of_parse_ppe_config(struct ppe_device *ppe_dev,
new file mode 100644
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+/* Low level PPE operations made available to higher level network drivers
+ * such as ethernet or QoS drivers.
+ */
+
+#include <linux/soc/qcom/ppe.h>
+#include "ppe_ops.h"
+#include "ppe_regs.h"
+#include "ppe.h"
+
+static int ppe_scheduler_l0_queue_map_set(struct ppe_device *ppe_dev,
+ int node_id, int port,
+ struct ppe_qos_scheduler_cfg scheduler_cfg)
+{
+ u32 val, index;
+
+ if (node_id >= PPE_L0_FLOW_MAP_TBL_NUM)
+ return -EINVAL;
+
+ val = FIELD_PREP(PPE_L0_FLOW_MAP_TBL_SP_ID, scheduler_cfg.sp_id) |
+ FIELD_PREP(PPE_L0_FLOW_MAP_TBL_C_PRI, scheduler_cfg.c_pri) |
+ FIELD_PREP(PPE_L0_FLOW_MAP_TBL_E_PRI, scheduler_cfg.e_pri) |
+ FIELD_PREP(PPE_L0_FLOW_MAP_TBL_C_DRR_WT, scheduler_cfg.c_drr_wt) |
+ FIELD_PREP(PPE_L0_FLOW_MAP_TBL_E_DRR_WT, scheduler_cfg.e_drr_wt);
+ index = PPE_L0_FLOW_MAP_TBL + node_id * PPE_L0_FLOW_MAP_TBL_INC;
+ ppe_write(ppe_dev, index, val);
+
+ val = FIELD_PREP(PPE_L0_C_SP_CFG_TBL_DRR_ID, scheduler_cfg.c_drr_id) |
+ FIELD_PREP(PPE_L0_C_SP_CFG_TBL_DRR_CREDIT_UNIT, scheduler_cfg.c_drr_unit);
+ index = PPE_L0_C_SP_CFG_TBL +
+ (scheduler_cfg.sp_id * 8 + scheduler_cfg.c_pri) * PPE_L0_C_SP_CFG_TBL_INC;
+ ppe_write(ppe_dev, index, val);
+
+ val = FIELD_PREP(PPE_L0_E_SP_CFG_TBL_DRR_ID, scheduler_cfg.e_drr_id) |
+ FIELD_PREP(PPE_L0_E_SP_CFG_TBL_DRR_CREDIT_UNIT, scheduler_cfg.e_drr_unit);
+ index = PPE_L0_E_SP_CFG_TBL +
+ (scheduler_cfg.sp_id * 8 + scheduler_cfg.e_pri) * PPE_L0_E_SP_CFG_TBL_INC;
+ ppe_write(ppe_dev, index, val);
+
+ val = FIELD_PREP(PPE_L0_FLOW_PORT_MAP_TBL_PORT_NUM, port);
+ index = PPE_L0_FLOW_PORT_MAP_TBL + node_id * PPE_L0_FLOW_PORT_MAP_TBL_INC;
+ ppe_write(ppe_dev, index, val);
+
+ index = PPE_L0_COMP_CFG_TBL + node_id * PPE_L0_COMP_CFG_TBL_INC;
+ return ppe_mask(ppe_dev, index, PPE_L0_COMP_CFG_TBL_DRR_METER_LEN,
+ FIELD_PREP(PPE_L0_COMP_CFG_TBL_DRR_METER_LEN,
+ scheduler_cfg.drr_frame_mode));
+}
+
+static int ppe_scheduler_l0_queue_map_get(struct ppe_device *ppe_dev,
+ int node_id, int *port,
+ struct ppe_qos_scheduler_cfg *scheduler_cfg)
+{
+ u32 val, index;
+
+ if (node_id >= PPE_L0_FLOW_MAP_TBL_NUM)
+ return -EINVAL;
+
+ index = PPE_L0_FLOW_MAP_TBL + node_id * PPE_L0_FLOW_MAP_TBL_INC;
+ ppe_read(ppe_dev, index, &val);
+ scheduler_cfg->sp_id = FIELD_GET(PPE_L0_FLOW_MAP_TBL_SP_ID, val);
+ scheduler_cfg->c_pri = FIELD_GET(PPE_L0_FLOW_MAP_TBL_C_PRI, val);
+ scheduler_cfg->e_pri = FIELD_GET(PPE_L0_FLOW_MAP_TBL_E_PRI, val);
+ scheduler_cfg->c_drr_wt = FIELD_GET(PPE_L0_FLOW_MAP_TBL_C_DRR_WT, val);
+ scheduler_cfg->e_drr_wt = FIELD_GET(PPE_L0_FLOW_MAP_TBL_E_DRR_WT, val);
+
+ index = PPE_L0_C_SP_CFG_TBL +
+ (scheduler_cfg->sp_id * 8 + scheduler_cfg->c_pri) * PPE_L0_C_SP_CFG_TBL_INC;
+ ppe_read(ppe_dev, index, &val);
+ scheduler_cfg->c_drr_id = FIELD_GET(PPE_L0_C_SP_CFG_TBL_DRR_ID, val);
+ scheduler_cfg->c_drr_unit = FIELD_GET(PPE_L0_C_SP_CFG_TBL_DRR_CREDIT_UNIT, val);
+
+ index = PPE_L0_E_SP_CFG_TBL +
+ (scheduler_cfg->sp_id * 8 + scheduler_cfg->e_pri) * PPE_L0_E_SP_CFG_TBL_INC;
+ ppe_read(ppe_dev, index, &val);
+ scheduler_cfg->e_drr_id = FIELD_GET(PPE_L0_E_SP_CFG_TBL_DRR_ID, val);
+ scheduler_cfg->e_drr_unit = FIELD_GET(PPE_L0_E_SP_CFG_TBL_DRR_CREDIT_UNIT, val);
+
+ index = PPE_L0_FLOW_PORT_MAP_TBL + node_id * PPE_L0_FLOW_PORT_MAP_TBL_INC;
+ ppe_read(ppe_dev, index, &val);
+ *port = FIELD_GET(PPE_L0_FLOW_PORT_MAP_TBL_PORT_NUM, val);
+
+ index = PPE_L0_COMP_CFG_TBL + node_id * PPE_L0_COMP_CFG_TBL_INC;
+ ppe_read(ppe_dev, index, &val);
+ scheduler_cfg->drr_frame_mode = FIELD_GET(PPE_L0_COMP_CFG_TBL_DRR_METER_LEN, val);
+
+ return 0;
+}
+
+static int ppe_scheduler_l1_queue_map_set(struct ppe_device *ppe_dev,
+ int node_id, int port,
+ struct ppe_qos_scheduler_cfg scheduler_cfg)
+{
+ u32 val, index;
+
+ if (node_id >= PPE_L1_FLOW_MAP_TBL_NUM)
+ return -EINVAL;
+
+ val = FIELD_PREP(PPE_L1_FLOW_MAP_TBL_SP_ID, scheduler_cfg.sp_id) |
+ FIELD_PREP(PPE_L1_FLOW_MAP_TBL_C_PRI, scheduler_cfg.c_pri) |
+ FIELD_PREP(PPE_L1_FLOW_MAP_TBL_E_PRI, scheduler_cfg.e_pri) |
+ FIELD_PREP(PPE_L1_FLOW_MAP_TBL_C_DRR_WT, scheduler_cfg.c_drr_wt) |
+ FIELD_PREP(PPE_L1_FLOW_MAP_TBL_E_DRR_WT, scheduler_cfg.e_drr_wt);
+ index = PPE_L1_FLOW_MAP_TBL + node_id * PPE_L1_FLOW_MAP_TBL_INC;
+ ppe_write(ppe_dev, index, val);
+
+ val = FIELD_PREP(PPE_L1_C_SP_CFG_TBL_DRR_ID, scheduler_cfg.c_drr_id) |
+ FIELD_PREP(PPE_L1_C_SP_CFG_TBL_DRR_CREDIT_UNIT, scheduler_cfg.c_drr_unit);
+ index = PPE_L1_C_SP_CFG_TBL +
+ (scheduler_cfg.sp_id * 8 + scheduler_cfg.c_pri) * PPE_L1_C_SP_CFG_TBL_INC;
+ ppe_write(ppe_dev, index, val);
+
+ val = FIELD_PREP(PPE_L1_E_SP_CFG_TBL_DRR_ID, scheduler_cfg.e_drr_id) |
+ FIELD_PREP(PPE_L1_E_SP_CFG_TBL_DRR_CREDIT_UNIT, scheduler_cfg.e_drr_unit);
+ index = PPE_L1_E_SP_CFG_TBL +
+ (scheduler_cfg.sp_id * 8 + scheduler_cfg.e_pri) * PPE_L1_E_SP_CFG_TBL_INC;
+ ppe_write(ppe_dev, index, val);
+
+ val = FIELD_PREP(PPE_L1_FLOW_PORT_MAP_TBL_PORT_NUM, port);
+ index = PPE_L1_FLOW_PORT_MAP_TBL + node_id * PPE_L1_FLOW_PORT_MAP_TBL_INC;
+ ppe_write(ppe_dev, index, val);
+
+ index = PPE_L1_COMP_CFG_TBL + node_id * PPE_L1_COMP_CFG_TBL_INC;
+ return ppe_mask(ppe_dev, index, PPE_L1_COMP_CFG_TBL_DRR_METER_LEN,
+ FIELD_PREP(PPE_L1_COMP_CFG_TBL_DRR_METER_LEN,
+ scheduler_cfg.drr_frame_mode));
+}
+
+static int ppe_scheduler_l1_queue_map_get(struct ppe_device *ppe_dev,
+ int node_id, int *port,
+ struct ppe_qos_scheduler_cfg *scheduler_cfg)
+{
+ u32 val, index;
+
+ if (node_id >= PPE_L1_FLOW_MAP_TBL_NUM)
+ return -EINVAL;
+
+ index = PPE_L1_FLOW_MAP_TBL + node_id * PPE_L1_FLOW_MAP_TBL_INC;
+ ppe_read(ppe_dev, index, &val);
+ scheduler_cfg->sp_id = FIELD_GET(PPE_L1_FLOW_MAP_TBL_SP_ID, val);
+ scheduler_cfg->c_pri = FIELD_GET(PPE_L1_FLOW_MAP_TBL_C_PRI, val);
+ scheduler_cfg->e_pri = FIELD_GET(PPE_L1_FLOW_MAP_TBL_E_PRI, val);
+ scheduler_cfg->c_drr_wt = FIELD_GET(PPE_L1_FLOW_MAP_TBL_C_DRR_WT, val);
+ scheduler_cfg->e_drr_wt = FIELD_GET(PPE_L1_FLOW_MAP_TBL_E_DRR_WT, val);
+
+ index = PPE_L1_C_SP_CFG_TBL +
+ (scheduler_cfg->sp_id * 8 + scheduler_cfg->c_pri) * PPE_L1_C_SP_CFG_TBL_INC;
+ ppe_read(ppe_dev, index, &val);
+ scheduler_cfg->c_drr_id = FIELD_GET(PPE_L1_C_SP_CFG_TBL_DRR_ID, val);
+ scheduler_cfg->c_drr_unit = FIELD_GET(PPE_L1_C_SP_CFG_TBL_DRR_CREDIT_UNIT, val);
+
+ index = PPE_L1_E_SP_CFG_TBL +
+ (scheduler_cfg->sp_id * 8 + scheduler_cfg->e_pri) * PPE_L1_E_SP_CFG_TBL_INC;
+ ppe_read(ppe_dev, index, &val);
+ scheduler_cfg->e_drr_id = FIELD_GET(PPE_L1_E_SP_CFG_TBL_DRR_ID, val);
+ scheduler_cfg->e_drr_unit = FIELD_GET(PPE_L1_E_SP_CFG_TBL_DRR_CREDIT_UNIT, val);
+
+ index = PPE_L1_FLOW_PORT_MAP_TBL + node_id * PPE_L1_FLOW_PORT_MAP_TBL_INC;
+ ppe_read(ppe_dev, index, &val);
+ *port = FIELD_GET(PPE_L1_FLOW_PORT_MAP_TBL_PORT_NUM, val);
+
+ index = PPE_L1_COMP_CFG_TBL + node_id * PPE_L1_COMP_CFG_TBL_INC;
+ ppe_read(ppe_dev, index, &val);
+ scheduler_cfg->drr_frame_mode = FIELD_GET(PPE_L1_COMP_CFG_TBL_DRR_METER_LEN, val);
+
+ return 0;
+}
+
+static int ppe_queue_scheduler_set(struct ppe_device *ppe_dev,
+ int node_id, int level, int port,
+ struct ppe_qos_scheduler_cfg scheduler_cfg)
+{
+ if (level == 0)
+ return ppe_scheduler_l0_queue_map_set(ppe_dev, node_id, port, scheduler_cfg);
+ else if (level == 1)
+ return ppe_scheduler_l1_queue_map_set(ppe_dev, node_id, port, scheduler_cfg);
+ else
+ return -EINVAL;
+}
+
+static int ppe_queue_scheduler_get(struct ppe_device *ppe_dev,
+ int node_id, int level, int *port,
+ struct ppe_qos_scheduler_cfg *scheduler_cfg)
+{
+ if (level == 0)
+ return ppe_scheduler_l0_queue_map_get(ppe_dev, node_id, port, scheduler_cfg);
+ else if (level == 1)
+ return ppe_scheduler_l1_queue_map_get(ppe_dev, node_id, port, scheduler_cfg);
+ else
+ return -EINVAL;
+}
+
+static const struct ppe_queue_ops qcom_ppe_queue_config_ops = {
+ .queue_scheduler_set = ppe_queue_scheduler_set,
+ .queue_scheduler_get = ppe_queue_scheduler_get,
+};
+
+const struct ppe_queue_ops *ppe_queue_config_ops_get(void)
+{
+ return &qcom_ppe_queue_config_ops;
+}
+EXPORT_SYMBOL_GPL(ppe_queue_config_ops_get);
new file mode 100644
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+/* Low level PPE operations to be used by higher level network drivers
+ * such as ethernet or QoS drivers.
+ */
+
+#ifndef __PPE_OPS_H__
+#define __PPE_OPS_H__
+
+/* PPE hardware QoS configurations used to dispatch the packet passed
+ * through PPE, the scheduler supports DRR(deficit round robin with the
+ * weight) and SP(strict priority).
+ */
+struct ppe_qos_scheduler_cfg {
+ int sp_id;
+ int e_pri;
+ int c_pri;
+ int c_drr_id;
+ int e_drr_id;
+ int e_drr_wt;
+ int c_drr_wt;
+ int c_drr_unit;
+ int e_drr_unit;
+ int drr_frame_mode;
+};
+
+/* The operations are used to configure the PPE queue related resource */
+struct ppe_queue_ops {
+ int (*queue_scheduler_set)(struct ppe_device *ppe_dev,
+ int node_id,
+ int level,
+ int port,
+ struct ppe_qos_scheduler_cfg scheduler_cfg);
+ int (*queue_scheduler_get)(struct ppe_device *ppe_dev,
+ int node_id,
+ int level,
+ int *port,
+ struct ppe_qos_scheduler_cfg *scheduler_cfg);
+};
+
+const struct ppe_queue_ops *ppe_queue_config_ops_get(void);
+#endif
@@ -31,11 +31,75 @@
#define PPE_PSCH_TDM_DEPTH_CFG_INC 4
#define PPE_PSCH_TDM_DEPTH_CFG_TDM_DEPTH GENMASK(7, 0)
+#define PPE_L0_FLOW_MAP_TBL 0x402000
+#define PPE_L0_FLOW_MAP_TBL_NUM 300
+#define PPE_L0_FLOW_MAP_TBL_INC 0x10
+#define PPE_L0_FLOW_MAP_TBL_SP_ID GENMASK(5, 0)
+#define PPE_L0_FLOW_MAP_TBL_C_PRI GENMASK(8, 6)
+#define PPE_L0_FLOW_MAP_TBL_E_PRI GENMASK(11, 9)
+#define PPE_L0_FLOW_MAP_TBL_C_DRR_WT GENMASK(21, 12)
+#define PPE_L0_FLOW_MAP_TBL_E_DRR_WT GENMASK(31, 22)
+
+#define PPE_L0_C_SP_CFG_TBL 0x404000
+#define PPE_L0_C_SP_CFG_TBL_NUM 512
+#define PPE_L0_C_SP_CFG_TBL_INC 0x10
+#define PPE_L0_C_SP_CFG_TBL_DRR_ID GENMASK(7, 0)
+#define PPE_L0_C_SP_CFG_TBL_DRR_CREDIT_UNIT BIT(8)
+
+#define PPE_L0_E_SP_CFG_TBL 0x406000
+#define PPE_L0_E_SP_CFG_TBL_NUM 512
+#define PPE_L0_E_SP_CFG_TBL_INC 0x10
+#define PPE_L0_E_SP_CFG_TBL_DRR_ID GENMASK(7, 0)
+#define PPE_L0_E_SP_CFG_TBL_DRR_CREDIT_UNIT BIT(8)
+
+#define PPE_L0_FLOW_PORT_MAP_TBL 0x408000
+#define PPE_L0_FLOW_PORT_MAP_TBL_NUM 300
+#define PPE_L0_FLOW_PORT_MAP_TBL_INC 0x10
+#define PPE_L0_FLOW_PORT_MAP_TBL_PORT_NUM GENMASK(3, 0)
+
+#define PPE_L0_COMP_CFG_TBL 0x428000
+#define PPE_L0_COMP_CFG_TBL_NUM 300
+#define PPE_L0_COMP_CFG_TBL_INC 0x10
+#define PPE_L0_COMP_CFG_TBL_SHAPER_METER_LEN GENMASK(1, 0)
+#define PPE_L0_COMP_CFG_TBL_DRR_METER_LEN GENMASK(3, 2)
+
#define PPE_DEQ_OPR_TBL 0x430000
#define PPE_DEQ_OPR_TBL_NUM 300
#define PPE_DEQ_OPR_TBL_INC 0x10
#define PPE_ENQ_OPR_TBL_DEQ_DISABLE BIT(0)
+#define PPE_L1_FLOW_MAP_TBL 0x440000
+#define PPE_L1_FLOW_MAP_TBL_NUM 64
+#define PPE_L1_FLOW_MAP_TBL_INC 0x10
+#define PPE_L1_FLOW_MAP_TBL_SP_ID GENMASK(3, 0)
+#define PPE_L1_FLOW_MAP_TBL_C_PRI GENMASK(6, 4)
+#define PPE_L1_FLOW_MAP_TBL_E_PRI GENMASK(9, 7)
+#define PPE_L1_FLOW_MAP_TBL_C_DRR_WT GENMASK(19, 10)
+#define PPE_L1_FLOW_MAP_TBL_E_DRR_WT GENMASK(29, 20)
+
+#define PPE_L1_C_SP_CFG_TBL 0x442000
+#define PPE_L1_C_SP_CFG_TBL_NUM 64
+#define PPE_L1_C_SP_CFG_TBL_INC 0x10
+#define PPE_L1_C_SP_CFG_TBL_DRR_ID GENMASK(5, 0)
+#define PPE_L1_C_SP_CFG_TBL_DRR_CREDIT_UNIT BIT(6)
+
+#define PPE_L1_E_SP_CFG_TBL 0x444000
+#define PPE_L1_E_SP_CFG_TBL_NUM 64
+#define PPE_L1_E_SP_CFG_TBL_INC 0x10
+#define PPE_L1_E_SP_CFG_TBL_DRR_ID GENMASK(5, 0)
+#define PPE_L1_E_SP_CFG_TBL_DRR_CREDIT_UNIT BIT(6)
+
+#define PPE_L1_FLOW_PORT_MAP_TBL 0x446000
+#define PPE_L1_FLOW_PORT_MAP_TBL_NUM 64
+#define PPE_L1_FLOW_PORT_MAP_TBL_INC 0x10
+#define PPE_L1_FLOW_PORT_MAP_TBL_PORT_NUM GENMASK(3, 0)
+
+#define PPE_L1_COMP_CFG_TBL 0x46a000
+#define PPE_L1_COMP_CFG_TBL_NUM 64
+#define PPE_L1_COMP_CFG_TBL_INC 0x10
+#define PPE_L1_COMP_CFG_TBL_SHAPER_METER_LEN GENMASK(1, 0)
+#define PPE_L1_COMP_CFG_TBL_DRR_METER_LEN GENMASK(3, 2)
+
#define PPE_PSCH_TDM_CFG_TBL 0x47a000
#define PPE_PSCH_TDM_CFG_TBL_NUM 128
#define PPE_PSCH_TDM_CFG_TBL_INC 0x10