net: dsa: lantiq_gswip: store switch API version in priv

Store the switch API version in struct gswip_priv. As the hardware has
the 'major/minor' version bytes in the wrong order preventing numerical
comparisons the version to be stored in gswip_priv is constructed in
such a way that the REV field is the most significant byte and the MOD
field the least significant byte. Also provide a conveniance macro to
allow comparing the stored version of the hardware against the already
defined GSWIP_VERSION_* macros.

This is done in order to prepare supporting newer features such as 4096
VLANs and per-port configurable learning which are only available
starting from specific hardware versions.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/eddb51ae8d0b2046ca91906e93daad7be5af56d7.1755878232.git.daniel@makrotopia.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Daniel Golle 2025-08-22 17:12:21 +01:00 committed by Jakub Kicinski
parent 1ccc407285
commit 8a7576d220
2 changed files with 22 additions and 4 deletions

View File

@ -1907,6 +1907,16 @@ static int gswip_probe(struct platform_device *pdev)
mutex_init(&priv->pce_table_lock);
version = gswip_switch_r(priv, GSWIP_VERSION);
/* The hardware has the 'major/minor' version bytes in the wrong order
* preventing numerical comparisons. Construct a 16-bit unsigned integer
* having the REV field as most significant byte and the MOD field as
* least significant byte. This is effectively swapping the two bytes of
* the version variable, but other than using swab16 it doesn't affect
* the source variable.
*/
priv->version = GSWIP_VERSION_REV(version) << 8 |
GSWIP_VERSION_MOD(version);
np = dev->of_node;
switch (version) {
case GSWIP_VERSION_2_0:
@ -1955,8 +1965,7 @@ static int gswip_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv);
dev_info(dev, "probed GSWIP version %lx mod %lx\n",
(version & GSWIP_VERSION_REV_MASK) >> GSWIP_VERSION_REV_SHIFT,
(version & GSWIP_VERSION_MOD_MASK) >> GSWIP_VERSION_MOD_SHIFT);
GSWIP_VERSION_REV(version), GSWIP_VERSION_MOD(version));
return 0;
disable_switch:

View File

@ -7,6 +7,7 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/swab.h>
#include <net/dsa.h>
/* GSWIP MDIO Registers */
@ -85,14 +86,21 @@
#define GSWIP_SWRES_R1 BIT(1) /* GSWIP Software reset */
#define GSWIP_SWRES_R0 BIT(0) /* GSWIP Hardware reset */
#define GSWIP_VERSION 0x013
#define GSWIP_VERSION_REV_SHIFT 0
#define GSWIP_VERSION_REV_MASK GENMASK(7, 0)
#define GSWIP_VERSION_MOD_SHIFT 8
#define GSWIP_VERSION_MOD_MASK GENMASK(15, 8)
#define GSWIP_VERSION_REV(v) FIELD_GET(GSWIP_VERSION_REV_MASK, v)
#define GSWIP_VERSION_MOD(v) FIELD_GET(GSWIP_VERSION_MOD_MASK, v)
#define GSWIP_VERSION_2_0 0x100
#define GSWIP_VERSION_2_1 0x021
#define GSWIP_VERSION_2_2 0x122
#define GSWIP_VERSION_2_2_ETC 0x022
/* The hardware has the 'major/minor' version bytes in the wrong order
* preventing numerical comparisons. Swap the bytes of the 16-bit value
* to end up with REV being the most significant byte and MOD being the
* least significant byte, which then allows comparing it with the
* value stored in struct gswip_priv.
*/
#define GSWIP_VERSION_GE(priv, ver) ((priv)->version >= swab16(ver))
#define GSWIP_BM_RAM_VAL(x) (0x043 - (x))
#define GSWIP_BM_RAM_ADDR 0x044
@ -258,6 +266,7 @@ struct gswip_priv {
struct gswip_gphy_fw *gphy_fw;
u32 port_vlan_filter;
struct mutex pce_table_lock;
u16 version;
};
#endif /* __LANTIQ_GSWIP_H */