1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /* Microsemi Ocelot Switch driver
4 * Copyright (c) 2019 Microsemi Corporation
7 #include <soc/mscc/ocelot.h>
8 #include "ocelot_police.h"
10 enum mscc_qos_rate_mode
{
11 MSCC_QOS_RATE_MODE_DISABLED
, /* Policer/shaper disabled */
12 MSCC_QOS_RATE_MODE_LINE
, /* Measure line rate in kbps incl. IPG */
13 MSCC_QOS_RATE_MODE_DATA
, /* Measures data rate in kbps excl. IPG */
14 MSCC_QOS_RATE_MODE_FRAME
, /* Measures frame rate in fps */
15 __MSCC_QOS_RATE_MODE_END
,
16 NUM_MSCC_QOS_RATE_MODE
= __MSCC_QOS_RATE_MODE_END
,
17 MSCC_QOS_RATE_MODE_MAX
= __MSCC_QOS_RATE_MODE_END
- 1,
20 /* Types for ANA:POL[0-192]:POL_MODE_CFG.FRM_MODE */
21 #define POL_MODE_LINERATE 0 /* Incl IPG. Unit: 33 1/3 kbps, 4096 bytes */
22 #define POL_MODE_DATARATE 1 /* Excl IPG. Unit: 33 1/3 kbps, 4096 bytes */
23 #define POL_MODE_FRMRATE_HI 2 /* Unit: 33 1/3 fps, 32.8 frames */
24 #define POL_MODE_FRMRATE_LO 3 /* Unit: 1/3 fps, 0.3 frames */
27 #define POL_IX_PORT 0 /* 0-11 : Port policers */
28 #define POL_IX_QUEUE 32 /* 32-127 : Queue policers */
30 /* Default policer order */
31 #define POL_ORDER 0x1d3 /* Ocelot policer order: Serial (QoS -> Port -> VCAP) */
33 struct qos_policer_conf
{
34 enum mscc_qos_rate_mode mode
;
35 bool dlb
; /* Enable DLB (dual leaky bucket mode */
36 bool cf
; /* Coupling flag (ignored in SLB mode) */
37 u32 cir
; /* CIR in kbps/fps (ignored in SLB mode) */
38 u32 cbs
; /* CBS in bytes/frames (ignored in SLB mode) */
39 u32 pir
; /* PIR in kbps/fps */
40 u32 pbs
; /* PBS in bytes/frames */
41 u8 ipg
; /* Size of IPG when MSCC_QOS_RATE_MODE_LINE is chosen */
44 static int qos_policer_conf_set(struct ocelot
*ocelot
, int port
, u32 pol_ix
,
45 struct qos_policer_conf
*conf
)
47 u32 cf
= 0, cir_ena
= 0, frm_mode
= POL_MODE_LINERATE
;
48 u32 cir
= 0, cbs
= 0, pir
= 0, pbs
= 0;
49 bool cir_discard
= 0, pir_discard
= 0;
50 u32 pbs_max
= 0, cbs_max
= 0;
58 case MSCC_QOS_RATE_MODE_LINE
:
59 case MSCC_QOS_RATE_MODE_DATA
:
60 if (conf
->mode
== MSCC_QOS_RATE_MODE_LINE
) {
61 frm_mode
= POL_MODE_LINERATE
;
62 ipg
= min_t(u8
, GENMASK(4, 0), conf
->ipg
);
64 frm_mode
= POL_MODE_DATARATE
;
70 if (cir
== 0 && cbs
== 0) {
71 /* Discard cir frames */
74 cir
= DIV_ROUND_UP(cir
, 100);
75 cir
*= 3; /* 33 1/3 kbps */
76 cbs
= DIV_ROUND_UP(cbs
, 4096);
77 cbs
= (cbs
? cbs
: 1); /* No zero burst size */
78 cbs_max
= 60; /* Limit burst size */
84 if (pir
== 0 && pbs
== 0) {
85 /* Discard PIR frames */
88 pir
= DIV_ROUND_UP(pir
, 100);
89 pir
*= 3; /* 33 1/3 kbps */
90 pbs
= DIV_ROUND_UP(pbs
, 4096);
91 pbs
= (pbs
? pbs
: 1); /* No zero burst size */
92 pbs_max
= 60; /* Limit burst size */
95 case MSCC_QOS_RATE_MODE_FRAME
:
97 frm_mode
= POL_MODE_FRMRATE_HI
;
98 pir
= DIV_ROUND_UP(pir
, 100);
99 pir
*= 3; /* 33 1/3 fps */
100 pbs
= (pbs
* 10) / 328; /* 32.8 frames */
101 pbs
= (pbs
? pbs
: 1); /* No zero burst size */
102 pbs_max
= GENMASK(6, 0); /* Limit burst size */
104 frm_mode
= POL_MODE_FRMRATE_LO
;
105 if (pir
== 0 && pbs
== 0) {
106 /* Discard all frames */
110 pir
*= 3; /* 1/3 fps */
111 pbs
= (pbs
* 10) / 3; /* 0.3 frames */
112 pbs
= (pbs
? pbs
: 1); /* No zero burst size */
113 pbs_max
= 61; /* Limit burst size */
117 default: /* MSCC_QOS_RATE_MODE_DISABLED */
118 /* Disable policer using maximum rate and zero burst */
119 pir
= GENMASK(15, 0);
125 if (pir
> GENMASK(15, 0)) {
126 dev_err(ocelot
->dev
, "Invalid pir for port %d: %u (max %lu)\n",
127 port
, pir
, GENMASK(15, 0));
131 if (cir
> GENMASK(15, 0)) {
132 dev_err(ocelot
->dev
, "Invalid cir for port %d: %u (max %lu)\n",
133 port
, cir
, GENMASK(15, 0));
138 dev_err(ocelot
->dev
, "Invalid pbs for port %d: %u (max %u)\n",
144 dev_err(ocelot
->dev
, "Invalid cbs for port %d: %u (max %u)\n",
149 value
= (ANA_POL_MODE_CFG_IPG_SIZE(ipg
) |
150 ANA_POL_MODE_CFG_FRM_MODE(frm_mode
) |
151 (cf
? ANA_POL_MODE_CFG_DLB_COUPLED
: 0) |
152 (cir_ena
? ANA_POL_MODE_CFG_CIR_ENA
: 0) |
153 ANA_POL_MODE_CFG_OVERSHOOT_ENA
);
155 ocelot_write_gix(ocelot
, value
, ANA_POL_MODE_CFG
, pol_ix
);
157 ocelot_write_gix(ocelot
,
158 ANA_POL_PIR_CFG_PIR_RATE(pir
) |
159 ANA_POL_PIR_CFG_PIR_BURST(pbs
),
160 ANA_POL_PIR_CFG
, pol_ix
);
162 ocelot_write_gix(ocelot
,
163 (pir_discard
? GENMASK(22, 0) : 0),
164 ANA_POL_PIR_STATE
, pol_ix
);
166 ocelot_write_gix(ocelot
,
167 ANA_POL_CIR_CFG_CIR_RATE(cir
) |
168 ANA_POL_CIR_CFG_CIR_BURST(cbs
),
169 ANA_POL_CIR_CFG
, pol_ix
);
171 ocelot_write_gix(ocelot
,
172 (cir_discard
? GENMASK(22, 0) : 0),
173 ANA_POL_CIR_STATE
, pol_ix
);
178 int ocelot_port_policer_add(struct ocelot
*ocelot
, int port
,
179 struct ocelot_policer
*pol
)
181 struct qos_policer_conf pp
= { 0 };
187 pp
.mode
= MSCC_QOS_RATE_MODE_DATA
;
191 dev_dbg(ocelot
->dev
, "%s: port %u pir %u kbps, pbs %u bytes\n",
192 __func__
, port
, pp
.pir
, pp
.pbs
);
194 err
= qos_policer_conf_set(ocelot
, port
, POL_IX_PORT
+ port
, &pp
);
198 ocelot_rmw_gix(ocelot
,
199 ANA_PORT_POL_CFG_PORT_POL_ENA
|
200 ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER
),
201 ANA_PORT_POL_CFG_PORT_POL_ENA
|
202 ANA_PORT_POL_CFG_POL_ORDER_M
,
203 ANA_PORT_POL_CFG
, port
);
207 EXPORT_SYMBOL(ocelot_port_policer_add
);
209 int ocelot_port_policer_del(struct ocelot
*ocelot
, int port
)
211 struct qos_policer_conf pp
= { 0 };
214 dev_dbg(ocelot
->dev
, "%s: port %u\n", __func__
, port
);
216 pp
.mode
= MSCC_QOS_RATE_MODE_DISABLED
;
218 err
= qos_policer_conf_set(ocelot
, port
, POL_IX_PORT
+ port
, &pp
);
222 ocelot_rmw_gix(ocelot
,
223 ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER
),
224 ANA_PORT_POL_CFG_PORT_POL_ENA
|
225 ANA_PORT_POL_CFG_POL_ORDER_M
,
226 ANA_PORT_POL_CFG
, port
);
230 EXPORT_SYMBOL(ocelot_port_policer_del
);
232 int ocelot_ace_policer_add(struct ocelot
*ocelot
, u32 pol_ix
,
233 struct ocelot_policer
*pol
)
235 struct qos_policer_conf pp
= { 0 };
240 pp
.mode
= MSCC_QOS_RATE_MODE_DATA
;
244 return qos_policer_conf_set(ocelot
, 0, pol_ix
, &pp
);
247 int ocelot_ace_policer_del(struct ocelot
*ocelot
, u32 pol_ix
)
249 struct qos_policer_conf pp
= { 0 };
251 pp
.mode
= MSCC_QOS_RATE_MODE_DISABLED
;
253 return qos_policer_conf_set(ocelot
, 0, pol_ix
, &pp
);