[PATCH net-next v4 5/8] net: dsa: mv88e6xxx: Add helpers for 6352 LED blink and brightness

Andrew Lunn
2024-04-06T20:14:12Z

The 6352 family has two LEDs per port for ports 0-4. Ports 5 and 6
share a couple of LEDs. Add support functions to set the brightness,
i.e. on or off, and to make the LEDs blink at a fixed rate.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6xxx/port.c | 93 ++++++++++++++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx/port.h | 76 +++++++++++++++++++++++++++++++-
2 files changed, 168 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 5394a8cf7bf1..37315a4aa9cf 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -1723,3 +1723,96 @@ int mv88e6393x_port_set_policy(struct mv88e6xxx_chip *chip, int port,

return mv88e6393x_port_policy_write(chip, port, ptr, reg);
}
+
+/* Offset 0x16: LED Control Register */
+
+static int mv88e6352_port_led_write(struct mv88e6xxx_chip *chip, int port,
+ u16 pointer, u16 data)
+{
+ u16 reg = MV88E6352_PORT_LED_CTL_UPDATE | pointer | data;
+
+ return mv88e6xxx_port_write(chip, port, MV88E6352_PORT_LED_CTL, reg);
+}
+
+static int mv88e6352_port_led_read(struct mv88e6xxx_chip *chip, int port,
+ u16 pointer, u16 *data)
+{
+ int err;
+ u16 val;
+
+ err = mv88e6xxx_port_write(chip, port, MV88E6352_PORT_LED_CTL, pointer);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_port_read(chip, port, MV88E6352_PORT_LED_CTL, &val);
+ if (err)
+ return err;
+
+ *data = val & MV88E6352_PORT_LED_CTL_DATA_MASK;
+
+ return 0;
+}
+
+int mv88e6352_port_led_brightness_set(struct mv88e6xxx_chip *chip, int port,
+ u8 led, enum led_brightness value)
+{
+ int err;
+ u16 val;
+
+ if (port > 5)
+ return -EOPNOTSUPP;
+
+ err = mv88e6352_port_led_read(chip, port,
+ MV88E6352_PORT_LED_CTL_PTR_LED01,
+ &val);
+ if (err)
+ return err;
+
+ if (led == 0) {
+ val &= ~MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_MASK;
+ if (value)
+ val |= MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_ON;
+ else
+ val |= MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_OFF;
+ } else {
+ val &= ~MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_MASK;
+ if (value)
+ val |= MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_ON;
+ else
+ val |= MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_OFF;
+ }
+ return mv88e6352_port_led_write(chip, port,
+ MV88E6352_PORT_LED_CTL_PTR_LED01,
+ val);
+}
+
+int mv88e6352_port_led_blink_set(struct mv88e6xxx_chip *chip, int port, u8 led,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ int err;
+ u16 val;
+
+ if (port > 5)
+ return -EOPNOTSUPP;
+
+ /* Reset default is 84ms */
+ *delay_on = 84 / 2;
+ *delay_off = 84 / 2;
+ err = mv88e6352_port_led_read(chip, port,
+ MV88E6352_PORT_LED_CTL_PTR_LED01,
+ &val);
+ if (err)
+ return err;
+
+ if (led == 0) {
+ val &= ~MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_MASK;
+ val |= MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_BLINK;
+ } else {
+ val &= ~MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_MASK;
+ val |= MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_BLINK;
+ }
+ return mv88e6352_port_led_write(chip, port,
+ MV88E6352_PORT_LED_CTL_PTR_LED01,
+ val);
+}
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 86deeb347cbc..72556e4d154c 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -294,6 +294,76 @@
/* Offset 0x13: OutFiltered Counter */
#define MV88E6XXX_PORT_OUT_FILTERED 0x13

+/* Offset 0x16: LED Control */
+#define MV88E6352_PORT_LED_CTL 0x16
+#define MV88E6352_PORT_LED_CTL_UPDATE 0x8000
+#define MV88E6352_PORT_LED_CTL_PTR_LED01 0x0000
+#define MV88E6352_PORT_LED_CTL_PTR_STRETCH_BLINK 0x6000
+#define MV88E6352_PORT_LED_CTL_PTR_SPECIAL 0x7000
+#define MV88E6352_PORT_LED_CTL_DATA_MASK 0x03ff
+/* Ports 0-4 */
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_P2_SPECIAL 0x0000
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_10_100_ACT 0x0010
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_1000 0x0030
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_P1_SPECIAL 0x0040
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_10_1000_ACT 0x0060
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_10_1000 0x0070
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_ACT 0x0080
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_100 0x0090
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_100_ACT 0x00A0
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_10_100 0x00B0
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_PTP_ACT 0x00C0
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_BLINK 0x00D0
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_OFF 0x00E0
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_ON 0x00F0
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_MASK 0x00F0
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED1_LINK_ACT 0x0000
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_100_1000_ACT 0x0001
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_1000_ACT 0x0002
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_LINK_ACT 0x0003
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_P0_SPECIAL 0x0004
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_DUPLEX_COL 0x0006
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_10_1000_ACT 0x0007
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_LINK 0x0008
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_10 0x0009
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_10_ACT 0x000A
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_100_1000 0x000B
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_PTP_ACT 0x000C
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_BLINK 0x000D
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_OFF 0x000E
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_ON 0x000F
+#define MV88E6352_PORT_LED_CTL_DATA_LED01_LED0_MASK 0x000F
+
+/* Port 5 */
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_P6_ACT 0x0000
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_FIBER_1000_ACT 0x0010
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_FIBER_100_ACT 0x0020
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_FIBER 0x0030
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_P5_ACT 0x0040
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_P6_LINK 0x0050
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_P6_DUPLEX_COL 0x0060
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_P6_LINK_ACT 0x0070
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_P0_SPECIAL 0x0080
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_P1_SPECIAL 0x0090
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_P2_SPECIAL 0x00A0
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_P6_PTP_ACT 0x00C0
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_BLINK 0x00D0
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_OFF 0x00E0
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_ON 0x00F0
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED1_P5_LINK_ACT 0x0000
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED0_FIBER_100_ACT 0x0001
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED0_FIBER_1000_ACT 0x0002
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED0_P0_SPECIAL 0x0003
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED0_P1_SPECIAL 0x0004
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED0_P2_SPECIAL 0x0005
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED0_P5_DUPLEX_COL 0x0006
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED0_P5_LINK_ACT 0x0007
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED0_P6_LINK_ACT 0x0008
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED0_BLINK 0x000D
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED0_OFF 0x000E
+#define MV88E6352_PORT_LED_CTL_DATA5_LED01_LED0_ON 0x000F
+/* Port 6 does not have any LEDs */
+
/* Offset 0x18: IEEE Priority Mapping Table */
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE 0x18
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE 0x8000
@@ -459,5 +529,9 @@ int mv88e6xxx_port_hidden_write(struct mv88e6xxx_chip *chip, int block,
int mv88e6xxx_port_hidden_wait(struct mv88e6xxx_chip *chip);
int mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip *chip, int block, int port,
int reg, u16 *val);
-
+int mv88e6352_port_led_brightness_set(struct mv88e6xxx_chip *chip, int port,
+ u8 led, enum led_brightness value);
+int mv88e6352_port_led_blink_set(struct mv88e6xxx_chip *chip, int port, u8 led,
+ unsigned long *delay_on,
+ unsigned long *delay_off);
#endif /* _MV88E6XXX_PORT_H */

--
2.43.0