1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2024 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
3
4#include <linux/dsa/ksz_common.h>
5#include <net/dsa.h>
6#include <net/dscp.h>
7#include <net/ieee8021q.h>
8
9#include "ksz_common.h"
10#include "ksz_dcb.h"
11#include "ksz8.h"
12
13#define KSZ8_REG_PORT_1_CTRL_0			0x10
14#define KSZ8_PORT_DIFFSERV_ENABLE		BIT(6)
15#define KSZ8_PORT_802_1P_ENABLE			BIT(5)
16#define KSZ8_PORT_BASED_PRIO_M			GENMASK(4, 3)
17
18#define KSZ88X3_REG_TOS_DSCP_CTRL		0x60
19#define KSZ8765_REG_TOS_DSCP_CTRL		0x90
20
21#define KSZ9477_REG_SW_MAC_TOS_CTRL		0x033e
22#define KSZ9477_SW_TOS_DSCP_REMAP		BIT(0)
23#define KSZ9477_SW_TOS_DSCP_DEFAULT_PRIO_M	GENMASK(5, 3)
24
25#define KSZ9477_REG_DIFFSERV_PRIO_MAP		0x0340
26
27#define KSZ9477_REG_PORT_MRI_PRIO_CTRL		0x0801
28#define KSZ9477_PORT_HIGHEST_PRIO		BIT(7)
29#define KSZ9477_PORT_OR_PRIO			BIT(6)
30#define KSZ9477_PORT_MAC_PRIO_ENABLE		BIT(4)
31#define KSZ9477_PORT_VLAN_PRIO_ENABLE		BIT(3)
32#define KSZ9477_PORT_802_1P_PRIO_ENABLE		BIT(2)
33#define KSZ9477_PORT_DIFFSERV_PRIO_ENABLE	BIT(1)
34#define KSZ9477_PORT_ACL_PRIO_ENABLE		BIT(0)
35
36#define KSZ9477_REG_PORT_MRI_MAC_CTRL		0x0802
37#define KSZ9477_PORT_BASED_PRIO_M		GENMASK(2, 0)
38
39struct ksz_apptrust_map {
40	u8 apptrust;
41	u8 bit;
42};
43
44static const struct ksz_apptrust_map ksz8_apptrust_map_to_bit[] = {
45	{ DCB_APP_SEL_PCP, KSZ8_PORT_802_1P_ENABLE },
46	{ IEEE_8021QAZ_APP_SEL_DSCP, KSZ8_PORT_DIFFSERV_ENABLE },
47};
48
49static const struct ksz_apptrust_map ksz9477_apptrust_map_to_bit[] = {
50	{ DCB_APP_SEL_PCP, KSZ9477_PORT_802_1P_PRIO_ENABLE },
51	{ IEEE_8021QAZ_APP_SEL_DSCP, KSZ9477_PORT_DIFFSERV_PRIO_ENABLE },
52};
53
54/* ksz_supported_apptrust[] - Supported apptrust selectors and Priority Order
55 *			      of Internal Priority Map (IPM) sources.
56 *
57 * This array defines the apptrust selectors supported by the hardware, where
58 * the index within the array indicates the priority of the selector - lower
59 * indices correspond to higher priority. This fixed priority scheme is due to
60 * the hardware's design, which does not support configurable priority among
61 * different priority sources.
62 *
63 * The priority sources, including Tail Tag, ACL, VLAN PCP and DSCP are ordered
64 * by the hardware's fixed logic, as detailed below. The order reflects a
65 * non-configurable precedence where certain types of priority information
66 * override others:
67 *
68 * 1. Tail Tag - Highest priority, overrides ACL, VLAN PCP, and DSCP priorities.
69 * 2. ACL - Overrides VLAN PCP and DSCP priorities.
70 * 3. VLAN PCP - Overrides DSCP priority.
71 * 4. DSCP - Lowest priority, does not override any other priority source.
72 *
73 * In this context, the array's lower index (higher priority) for
74 * 'DCB_APP_SEL_PCP' suggests its relative priority over
75 * 'IEEE_8021QAZ_APP_SEL_DSCP' within the system's fixed priority scheme.
76 *
77 * DCB_APP_SEL_PCP - Priority Code Point selector
78 * IEEE_8021QAZ_APP_SEL_DSCP - Differentiated Services Code Point selector
79 */
80static const u8 ksz_supported_apptrust[] = {
81	DCB_APP_SEL_PCP,
82	IEEE_8021QAZ_APP_SEL_DSCP,
83};
84
85static const char * const ksz_supported_apptrust_variants[] = {
86	"empty", "dscp", "pcp", "dscp pcp"
87};
88
89static void ksz_get_default_port_prio_reg(struct ksz_device *dev, int *reg,
90					  u8 *mask, int *shift)
91{
92	if (is_ksz8(dev)) {
93		*reg = KSZ8_REG_PORT_1_CTRL_0;
94		*mask = KSZ8_PORT_BASED_PRIO_M;
95		*shift = __bf_shf(KSZ8_PORT_BASED_PRIO_M);
96	} else {
97		*reg = KSZ9477_REG_PORT_MRI_MAC_CTRL;
98		*mask = KSZ9477_PORT_BASED_PRIO_M;
99		*shift = __bf_shf(KSZ9477_PORT_BASED_PRIO_M);
100	}
101}
102
103/**
104 * ksz_get_dscp_prio_reg - Retrieves the DSCP-to-priority-mapping register
105 * @dev: Pointer to the KSZ switch device structure
106 * @reg: Pointer to the register address to be set
107 * @per_reg: Pointer to the number of DSCP values per register
108 * @mask: Pointer to the mask to be set
109 *
110 * This function retrieves the DSCP to priority mapping register, the number of
111 * DSCP values per register, and the mask to be set.
112 */
113static void ksz_get_dscp_prio_reg(struct ksz_device *dev, int *reg,
114				  int *per_reg, u8 *mask)
115{
116	if (ksz_is_ksz87xx(dev)) {
117		*reg = KSZ8765_REG_TOS_DSCP_CTRL;
118		*per_reg = 4;
119		*mask = GENMASK(1, 0);
120	} else if (ksz_is_ksz88x3(dev)) {
121		*reg = KSZ88X3_REG_TOS_DSCP_CTRL;
122		*per_reg = 4;
123		*mask = GENMASK(1, 0);
124	} else {
125		*reg = KSZ9477_REG_DIFFSERV_PRIO_MAP;
126		*per_reg = 2;
127		*mask = GENMASK(2, 0);
128	}
129}
130
131/**
132 * ksz_get_apptrust_map_and_reg - Retrieves the apptrust map and register
133 * @dev: Pointer to the KSZ switch device structure
134 * @map: Pointer to the apptrust map to be set
135 * @reg: Pointer to the register address to be set
136 * @mask: Pointer to the mask to be set
137 *
138 * This function retrieves the apptrust map and register address for the
139 * apptrust configuration.
140 */
141static void ksz_get_apptrust_map_and_reg(struct ksz_device *dev,
142					 const struct ksz_apptrust_map **map,
143					 int *reg, u8 *mask)
144{
145	if (is_ksz8(dev)) {
146		*map = ksz8_apptrust_map_to_bit;
147		*reg = KSZ8_REG_PORT_1_CTRL_0;
148		*mask = KSZ8_PORT_DIFFSERV_ENABLE | KSZ8_PORT_802_1P_ENABLE;
149	} else {
150		*map = ksz9477_apptrust_map_to_bit;
151		*reg = KSZ9477_REG_PORT_MRI_PRIO_CTRL;
152		*mask = KSZ9477_PORT_802_1P_PRIO_ENABLE |
153			KSZ9477_PORT_DIFFSERV_PRIO_ENABLE;
154	}
155}
156
157/**
158 * ksz_port_get_default_prio - Retrieves the default priority for a port on a
159 *			       KSZ switch
160 * @ds: Pointer to the DSA switch structure
161 * @port: Port number from which to get the default priority
162 *
163 * This function fetches the default priority for the specified port on a KSZ
164 * switch.
165 *
166 * Return: The default priority of the port on success, or a negative error
167 * code on failure.
168 */
169int ksz_port_get_default_prio(struct dsa_switch *ds, int port)
170{
171	struct ksz_device *dev = ds->priv;
172	int ret, reg, shift;
173	u8 data, mask;
174
175	ksz_get_default_port_prio_reg(dev, &reg, &mask, &shift);
176
177	ret = ksz_pread8(dev, port, reg, &data);
178	if (ret)
179		return ret;
180
181	return (data & mask) >> shift;
182}
183
184/**
185 * ksz88x3_port_set_default_prio_quirks - Quirks for default priority
186 * @dev: Pointer to the KSZ switch device structure
187 * @port: Port number for which to set the default priority
188 * @prio: Priority value to set
189 *
190 * This function implements quirks for setting the default priority on KSZ88x3
191 * devices. On Port 2, no other priority providers are working
192 * except of PCP. So, configuring default priority on Port 2 is not possible.
193 * On Port 1, it is not possible to configure port priority if PCP
194 * apptrust on Port 2 is disabled. Since we disable multiple queues on the
195 * switch to disable PCP on Port 2, we need to ensure that the default priority
196 * configuration on Port 1 is in agreement with the configuration on Port 2.
197 *
198 * Return: 0 on success, or a negative error code on failure
199 */
200static int ksz88x3_port_set_default_prio_quirks(struct ksz_device *dev, int port,
201						u8 prio)
202{
203	if (!prio)
204		return 0;
205
206	if (port == KSZ_PORT_2) {
207		dev_err(dev->dev, "Port priority configuration is not working on Port 2\n");
208		return -EINVAL;
209	} else if (port == KSZ_PORT_1) {
210		u8 port2_data;
211		int ret;
212
213		ret = ksz_pread8(dev, KSZ_PORT_2, KSZ8_REG_PORT_1_CTRL_0,
214				 &port2_data);
215		if (ret)
216			return ret;
217
218		if (!(port2_data & KSZ8_PORT_802_1P_ENABLE)) {
219			dev_err(dev->dev, "Not possible to configure port priority on Port 1 if PCP apptrust on Port 2 is disabled\n");
220			return -EINVAL;
221		}
222	}
223
224	return 0;
225}
226
227/**
228 * ksz_port_set_default_prio - Sets the default priority for a port on a KSZ
229 *			       switch
230 * @ds: Pointer to the DSA switch structure
231 * @port: Port number for which to set the default priority
232 * @prio: Priority value to set
233 *
234 * This function sets the default priority for the specified port on a KSZ
235 * switch.
236 *
237 * Return: 0 on success, or a negative error code on failure.
238 */
239int ksz_port_set_default_prio(struct dsa_switch *ds, int port, u8 prio)
240{
241	struct ksz_device *dev = ds->priv;
242	int reg, shift, ret;
243	u8 mask;
244
245	if (prio >= dev->info->num_ipms)
246		return -EINVAL;
247
248	if (ksz_is_ksz88x3(dev)) {
249		ret = ksz88x3_port_set_default_prio_quirks(dev, port, prio);
250		if (ret)
251			return ret;
252	}
253
254	ksz_get_default_port_prio_reg(dev, &reg, &mask, &shift);
255
256	return ksz_prmw8(dev, port, reg, mask, (prio << shift) & mask);
257}
258
259/**
260 * ksz_port_get_dscp_prio - Retrieves the priority for a DSCP value on a KSZ
261 *			    switch
262 * @ds: Pointer to the DSA switch structure
263 * @port: Port number for which to get the priority
264 * @dscp: DSCP value for which to get the priority
265 *
266 * This function fetches the priority value from switch global DSCP-to-priorty
267 * mapping table for the specified DSCP value.
268 *
269 * Return: The priority value for the DSCP on success, or a negative error
270 * code on failure.
271 */
272int ksz_port_get_dscp_prio(struct dsa_switch *ds, int port, u8 dscp)
273{
274	struct ksz_device *dev = ds->priv;
275	int reg, per_reg, ret, shift;
276	u8 data, mask;
277
278	ksz_get_dscp_prio_reg(dev, &reg, &per_reg, &mask);
279
280	/* If DSCP remapping is disabled, DSCP bits 3-5 are used as Internal
281	 * Priority Map (IPM)
282	 */
283	if (!is_ksz8(dev)) {
284		ret = ksz_read8(dev, KSZ9477_REG_SW_MAC_TOS_CTRL, &data);
285		if (ret)
286			return ret;
287
288		/* If DSCP remapping is disabled, DSCP bits 3-5 are used as
289		 * Internal Priority Map (IPM)
290		 */
291		if (!(data & KSZ9477_SW_TOS_DSCP_REMAP))
292			return FIELD_GET(KSZ9477_SW_TOS_DSCP_DEFAULT_PRIO_M,
293					 dscp);
294	}
295
296	/* In case DSCP remapping is enabled, we need to write the DSCP to
297	 * priority mapping table.
298	 */
299	reg += dscp / per_reg;
300	ret = ksz_read8(dev, reg, &data);
301	if (ret)
302		return ret;
303
304	shift = (dscp % per_reg) * (8 / per_reg);
305
306	return (data >> shift) & mask;
307}
308
309/**
310 * ksz_set_global_dscp_entry - Sets the global DSCP-to-priority mapping entry
311 * @dev: Pointer to the KSZ switch device structure
312 * @dscp: DSCP value for which to set the priority
313 * @ipm: Priority value to set
314 *
315 * This function sets the global DSCP-to-priority mapping entry for the
316 * specified DSCP value.
317 *
318 * Return: 0 on success, or a negative error code on failure.
319 */
320static int ksz_set_global_dscp_entry(struct ksz_device *dev, u8 dscp, u8 ipm)
321{
322	int reg, per_reg, shift;
323	u8 mask;
324
325	ksz_get_dscp_prio_reg(dev, &reg, &per_reg, &mask);
326
327	shift = (dscp % per_reg) * (8 / per_reg);
328
329	return ksz_rmw8(dev, reg + (dscp / per_reg), mask << shift,
330			ipm << shift);
331}
332
333/**
334 * ksz_init_global_dscp_map - Initializes the global DSCP-to-priority mapping
335 * @dev: Pointer to the KSZ switch device structure
336 *
337 * This function initializes the global DSCP-to-priority mapping table for the
338 * switch.
339 *
340 * Return: 0 on success, or a negative error code on failure
341 */
342static int ksz_init_global_dscp_map(struct ksz_device *dev)
343{
344	int ret, dscp;
345
346	/* On KSZ9xxx variants, DSCP remapping is disabled by default.
347	 * Enable to have, predictable and reproducible behavior across
348	 * different devices.
349	 */
350	if (!is_ksz8(dev)) {
351		ret = ksz_rmw8(dev, KSZ9477_REG_SW_MAC_TOS_CTRL,
352			       KSZ9477_SW_TOS_DSCP_REMAP,
353			       KSZ9477_SW_TOS_DSCP_REMAP);
354		if (ret)
355			return ret;
356	}
357
358	for (dscp = 0; dscp < DSCP_MAX; dscp++) {
359		int ipm, tt;
360
361		/* Map DSCP to Traffic Type, which is corresponding to the
362		 * Internal Priority Map (IPM) in the switch.
363		 */
364		if (!is_ksz8(dev)) {
365			ipm = ietf_dscp_to_ieee8021q_tt(dscp);
366		} else {
367			/* On KSZ8xxx variants we do not have IPM to queue
368			 * remapping table. We need to convert DSCP to Traffic
369			 * Type and then to queue.
370			 */
371			tt = ietf_dscp_to_ieee8021q_tt(dscp);
372			if (tt < 0)
373				return tt;
374
375			ipm = ieee8021q_tt_to_tc(tt, dev->info->num_tx_queues);
376		}
377
378		if (ipm < 0)
379			return ipm;
380
381		ret = ksz_set_global_dscp_entry(dev, dscp, ipm);
382	}
383
384	return 0;
385}
386
387/**
388 * ksz_port_add_dscp_prio - Adds a DSCP-to-priority mapping entry for a port on
389 *			    a KSZ switch.
390 * @ds: Pointer to the DSA switch structure
391 * @port: Port number for which to add the DSCP-to-priority mapping entry
392 * @dscp: DSCP value for which to add the priority
393 * @prio: Priority value to set
394 *
395 * Return: 0 on success, or a negative error code on failure
396 */
397int ksz_port_add_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, u8 prio)
398{
399	struct ksz_device *dev = ds->priv;
400
401	if (prio >= dev->info->num_ipms)
402		return -ERANGE;
403
404	return ksz_set_global_dscp_entry(dev, dscp, prio);
405}
406
407/**
408 * ksz_port_del_dscp_prio - Deletes a DSCP-to-priority mapping entry for a port
409 *			    on a KSZ switch.
410 * @ds: Pointer to the DSA switch structure
411 * @port: Port number for which to delete the DSCP-to-priority mapping entry
412 * @dscp: DSCP value for which to delete the priority
413 * @prio: Priority value to delete
414 *
415 * Return: 0 on success, or a negative error code on failure
416 */
417int ksz_port_del_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, u8 prio)
418{
419	struct ksz_device *dev = ds->priv;
420	int ipm;
421
422	if (ksz_port_get_dscp_prio(ds, port, dscp) != prio)
423		return 0;
424
425	if (is_ksz8(dev)) {
426		ipm = ieee8021q_tt_to_tc(IEEE8021Q_TT_BE,
427					 dev->info->num_tx_queues);
428		if (ipm < 0)
429			return ipm;
430	} else {
431		ipm = IEEE8021Q_TT_BE;
432	}
433
434	return ksz_set_global_dscp_entry(dev, dscp, ipm);
435}
436
437/**
438 * ksz_apptrust_error - Prints an error message for an invalid apptrust selector
439 * @dev: Pointer to the KSZ switch device structure
440 *
441 * This function prints an error message when an invalid apptrust selector is
442 * provided.
443 */
444static void ksz_apptrust_error(struct ksz_device *dev)
445{
446	char supported_apptrust_variants[64];
447	int i;
448
449	supported_apptrust_variants[0] = '\0';
450	for (i = 0; i < ARRAY_SIZE(ksz_supported_apptrust_variants); i++) {
451		if (i > 0)
452			strlcat(supported_apptrust_variants, ", ",
453				sizeof(supported_apptrust_variants));
454		strlcat(supported_apptrust_variants,
455			ksz_supported_apptrust_variants[i],
456			sizeof(supported_apptrust_variants));
457	}
458
459	dev_err(dev->dev, "Invalid apptrust selector or priority order. Supported: %s\n",
460		supported_apptrust_variants);
461}
462
463/**
464 * ksz_port_set_apptrust_validate - Validates the apptrust selectors
465 * @dev: Pointer to the KSZ switch device structure
466 * @port: Port number for which to set the apptrust selectors
467 * @sel: Array of apptrust selectors to validate
468 * @nsel: Number of apptrust selectors in the array
469 *
470 * This function validates the apptrust selectors provided and ensures that
471 * they are in the correct order.
472 *
473 * This family of switches supports two apptrust selectors: DCB_APP_SEL_PCP and
474 * IEEE_8021QAZ_APP_SEL_DSCP. The priority order of the selectors is fixed and
475 * cannot be changed. The order is as follows:
476 * 1. DCB_APP_SEL_PCP - Priority Code Point selector (highest priority)
477 * 2. IEEE_8021QAZ_APP_SEL_DSCP - Differentiated Services Code Point selector
478 *   (lowest priority)
479 *
480 * Return: 0 on success, or a negative error code on failure
481 */
482static int ksz_port_set_apptrust_validate(struct ksz_device *dev, int port,
483					  const u8 *sel, int nsel)
484{
485	int i, j, found;
486	int j_prev = 0;
487
488	/* Iterate through the requested selectors */
489	for (i = 0; i < nsel; i++) {
490		found = 0;
491
492		/* Check if the current selector is supported by the hardware */
493		for (j = 0; j < sizeof(ksz_supported_apptrust); j++) {
494			if (sel[i] != ksz_supported_apptrust[j])
495				continue;
496
497			found = 1;
498
499			/* Ensure that no higher priority selector (lower index)
500			 * precedes a lower priority one
501			 */
502			if (i > 0 && j <= j_prev)
503				goto err_sel_not_vaild;
504
505			j_prev = j;
506			break;
507		}
508
509		if (!found)
510			goto err_sel_not_vaild;
511	}
512
513	return 0;
514
515err_sel_not_vaild:
516	ksz_apptrust_error(dev);
517
518	return -EINVAL;
519}
520
521/**
522 * ksz88x3_port1_apptrust_quirk - Quirk for apptrust configuration on Port 1
523 *				  of KSZ88x3 devices
524 * @dev: Pointer to the KSZ switch device structure
525 * @port: Port number for which to set the apptrust selectors
526 * @reg: Register address for the apptrust configuration
527 * @port1_data: Data to set for the apptrust configuration
528 *
529 * This function implements a quirk for apptrust configuration on Port 1 of
530 * KSZ88x3 devices. It ensures that apptrust configuration on Port 1 is not
531 * possible if PCP apptrust on Port 2 is disabled. This is because the Port 2
532 * seems to be permanently hardwired to PCP classification, so we need to
533 * do Port 1 configuration always in agreement with Port 2 configuration.
534 *
535 * Return: 0 on success, or a negative error code on failure
536 */
537static int ksz88x3_port1_apptrust_quirk(struct ksz_device *dev, int port,
538					int reg, u8 port1_data)
539{
540	u8 port2_data;
541	int ret;
542
543	/* If no apptrust is requested for Port 1, no need to care about Port 2
544	 * configuration.
545	 */
546	if (!(port1_data & (KSZ8_PORT_802_1P_ENABLE | KSZ8_PORT_DIFFSERV_ENABLE)))
547		return 0;
548
549	/* We got request to enable any apptrust on Port 1. To make it possible,
550	 * we need to enable multiple queues on the switch. If we enable
551	 * multiqueue support, PCP classification on Port 2 will be
552	 * automatically activated by HW.
553	 */
554	ret = ksz_pread8(dev, KSZ_PORT_2, reg, &port2_data);
555	if (ret)
556		return ret;
557
558	/* If KSZ8_PORT_802_1P_ENABLE bit is set on Port 2, the driver showed
559	 * the interest in PCP classification on Port 2. In this case,
560	 * multiqueue support is enabled and we can enable any apptrust on
561	 * Port 1.
562	 * If KSZ8_PORT_802_1P_ENABLE bit is not set on Port 2, the PCP
563	 * classification on Port 2 is still active, but the driver disabled
564	 * multiqueue support and made frame prioritization inactive for
565	 * all ports. In this case, we can't enable any apptrust on Port 1.
566	 */
567	if (!(port2_data & KSZ8_PORT_802_1P_ENABLE)) {
568		dev_err(dev->dev, "Not possible to enable any apptrust on Port 1 if PCP apptrust on Port 2 is disabled\n");
569		return -EINVAL;
570	}
571
572	return 0;
573}
574
575/**
576 * ksz88x3_port2_apptrust_quirk - Quirk for apptrust configuration on Port 2
577 *				  of KSZ88x3 devices
578 * @dev: Pointer to the KSZ switch device structure
579 * @port: Port number for which to set the apptrust selectors
580 * @reg: Register address for the apptrust configuration
581 * @port2_data: Data to set for the apptrust configuration
582 *
583 * This function implements a quirk for apptrust configuration on Port 2 of
584 * KSZ88x3 devices. It ensures that DSCP apptrust is not working on Port 2 and
585 * that it is not possible to disable PCP on Port 2. The only way to disable PCP
586 * on Port 2 is to disable multiple queues on the switch.
587 *
588 * Return: 0 on success, or a negative error code on failure
589 */
590static int ksz88x3_port2_apptrust_quirk(struct ksz_device *dev, int port,
591					int reg, u8 port2_data)
592{
593	struct dsa_switch *ds = dev->ds;
594	u8 port1_data;
595	int ret;
596
597	/* First validate Port 2 configuration. DiffServ/DSCP is not working
598	 * on this port.
599	 */
600	if (port2_data & KSZ8_PORT_DIFFSERV_ENABLE) {
601		dev_err(dev->dev, "DSCP apptrust is not working on Port 2\n");
602		return -EINVAL;
603	}
604
605	/* If PCP support is requested, we need to enable all queues on the
606	 * switch to make PCP priority working on Port 2.
607	 */
608	if (port2_data & KSZ8_PORT_802_1P_ENABLE)
609		return ksz8_all_queues_split(dev, dev->info->num_tx_queues);
610
611	/* We got request to disable PCP priority on Port 2.
612	 * Now, we need to compare Port 2 configuration with Port 1
613	 * configuration.
614	 */
615	ret = ksz_pread8(dev, KSZ_PORT_1, reg, &port1_data);
616	if (ret)
617		return ret;
618
619	/* If Port 1 has any apptrust enabled, we can't disable multiple queues
620	 * on the switch, so we can't disable PCP on Port 2.
621	 */
622	if (port1_data & (KSZ8_PORT_802_1P_ENABLE | KSZ8_PORT_DIFFSERV_ENABLE)) {
623		dev_err(dev->dev, "Not possible to disable PCP on Port 2 if any apptrust is enabled on Port 1\n");
624		return -EINVAL;
625	}
626
627	/* Now we need to ensure that default priority on Port 1 is set to 0
628	 * otherwise we can't disable multiqueue support on the switch.
629	 */
630	ret = ksz_port_get_default_prio(ds, KSZ_PORT_1);
631	if (ret < 0) {
632		return ret;
633	} else if (ret) {
634		dev_err(dev->dev, "Not possible to disable PCP on Port 2 if non zero default priority is set on Port 1\n");
635		return -EINVAL;
636	}
637
638	/* Port 1 has no apptrust or default priority set and we got request to
639	 * disable PCP on Port 2. We can disable multiqueue support to disable
640	 * PCP on Port 2.
641	 */
642	return ksz8_all_queues_split(dev, 1);
643}
644
645/**
646 * ksz88x3_port_apptrust_quirk - Quirk for apptrust configuration on KSZ88x3
647 *			       devices
648 * @dev: Pointer to the KSZ switch device structure
649 * @port: Port number for which to set the apptrust selectors
650 * @reg: Register address for the apptrust configuration
651 * @data: Data to set for the apptrust configuration
652 *
653 * This function implements a quirk for apptrust configuration on KSZ88x3
654 * devices. It ensures that apptrust configuration on Port 1 and
655 * Port 2 is done in agreement with each other.
656 *
657 * Return: 0 on success, or a negative error code on failure
658 */
659static int ksz88x3_port_apptrust_quirk(struct ksz_device *dev, int port,
660				       int reg, u8 data)
661{
662	if (port == KSZ_PORT_1)
663		return ksz88x3_port1_apptrust_quirk(dev, port, reg, data);
664	else if (port == KSZ_PORT_2)
665		return ksz88x3_port2_apptrust_quirk(dev, port, reg, data);
666
667	return 0;
668}
669
670/**
671 * ksz_port_set_apptrust - Sets the apptrust selectors for a port on a KSZ
672 *			   switch
673 * @ds: Pointer to the DSA switch structure
674 * @port: Port number for which to set the apptrust selectors
675 * @sel: Array of apptrust selectors to set
676 * @nsel: Number of apptrust selectors in the array
677 *
678 * This function sets the apptrust selectors for the specified port on a KSZ
679 * switch.
680 *
681 * Return: 0 on success, or a negative error code on failure
682 */
683int ksz_port_set_apptrust(struct dsa_switch *ds, int port,
684			  const u8 *sel, int nsel)
685{
686	const struct ksz_apptrust_map *map;
687	struct ksz_device *dev = ds->priv;
688	int reg, i, ret;
689	u8 data = 0;
690	u8 mask;
691
692	ret = ksz_port_set_apptrust_validate(dev, port, sel, nsel);
693	if (ret)
694		return ret;
695
696	ksz_get_apptrust_map_and_reg(dev, &map, &reg, &mask);
697
698	for (i = 0; i < nsel; i++) {
699		int j;
700
701		for (j = 0; j < ARRAY_SIZE(ksz_supported_apptrust); j++) {
702			if (sel[i] != ksz_supported_apptrust[j])
703				continue;
704
705			data |= map[j].bit;
706			break;
707		}
708	}
709
710	if (ksz_is_ksz88x3(dev)) {
711		ret = ksz88x3_port_apptrust_quirk(dev, port, reg, data);
712		if (ret)
713			return ret;
714	}
715
716	return ksz_prmw8(dev, port, reg, mask, data);
717}
718
719/**
720 * ksz_port_get_apptrust - Retrieves the apptrust selectors for a port on a KSZ
721 *			   switch
722 * @ds: Pointer to the DSA switch structure
723 * @port: Port number for which to get the apptrust selectors
724 * @sel: Array to store the apptrust selectors
725 * @nsel: Number of apptrust selectors in the array
726 *
727 * This function fetches the apptrust selectors for the specified port on a KSZ
728 * switch.
729 *
730 * Return: 0 on success, or a negative error code on failure
731 */
732int ksz_port_get_apptrust(struct dsa_switch *ds, int port, u8 *sel, int *nsel)
733{
734	const struct ksz_apptrust_map *map;
735	struct ksz_device *dev = ds->priv;
736	int reg, i, ret;
737	u8 data;
738	u8 mask;
739
740	ksz_get_apptrust_map_and_reg(dev, &map, &reg, &mask);
741
742	ret = ksz_pread8(dev, port, reg, &data);
743	if (ret)
744		return ret;
745
746	*nsel = 0;
747	for (i = 0; i < ARRAY_SIZE(ksz_supported_apptrust); i++) {
748		if (data & map[i].bit)
749			sel[(*nsel)++] = ksz_supported_apptrust[i];
750	}
751
752	return 0;
753}
754
755/**
756 * ksz_dcb_init_port - Initializes the DCB configuration for a port on a KSZ
757 * @dev: Pointer to the KSZ switch device structure
758 * @port: Port number for which to initialize the DCB configuration
759 *
760 * This function initializes the DCB configuration for the specified port on a
761 * KSZ switch. Particular DCB configuration is set for the port, including the
762 * default priority and apptrust selectors.
763 * The default priority is set to Best Effort, and the apptrust selectors are
764 * set to all supported selectors.
765 *
766 * Return: 0 on success, or a negative error code on failure
767 */
768int ksz_dcb_init_port(struct ksz_device *dev, int port)
769{
770	const u8 ksz_default_apptrust[] = { DCB_APP_SEL_PCP };
771	int ret, ipm;
772
773	if (is_ksz8(dev)) {
774		ipm = ieee8021q_tt_to_tc(IEEE8021Q_TT_BE,
775					 dev->info->num_tx_queues);
776		if (ipm < 0)
777			return ipm;
778	} else {
779		ipm = IEEE8021Q_TT_BE;
780	}
781
782	/* Set the default priority for the port to Best Effort */
783	ret = ksz_port_set_default_prio(dev->ds, port, ipm);
784	if (ret)
785		return ret;
786
787	return ksz_port_set_apptrust(dev->ds, port, ksz_default_apptrust,
788				     ARRAY_SIZE(ksz_default_apptrust));
789}
790
791/**
792 * ksz_dcb_init - Initializes the DCB configuration for a KSZ switch
793 * @dev: Pointer to the KSZ switch device structure
794 *
795 * This function initializes the DCB configuration for a KSZ switch. The global
796 * DSCP-to-priority mapping table is initialized.
797 *
798 * Return: 0 on success, or a negative error code on failure
799 */
800int ksz_dcb_init(struct ksz_device *dev)
801{
802	int ret;
803
804	ret = ksz_init_global_dscp_map(dev);
805	if (ret)
806		return ret;
807
808	/* Enable 802.1p priority control on Port 2 during switch initialization.
809	 * This setup is critical for the apptrust functionality on Port 1, which
810	 * relies on the priority settings of Port 2. Note: Port 1 is naturally
811	 * configured before Port 2, necessitating this configuration order.
812	 */
813	if (ksz_is_ksz88x3(dev))
814		return ksz_prmw8(dev, KSZ_PORT_2, KSZ8_REG_PORT_1_CTRL_0,
815				 KSZ8_PORT_802_1P_ENABLE,
816				 KSZ8_PORT_802_1P_ENABLE);
817
818	return 0;
819}
820