* [PATCH net-next 1/2] net: dsa: mv88e6xxx: Add LED infrastructure
2024-01-03 10:33 [PATCH net-next 0/2] net: dsa: mv88e6xxx: Add LED support for 6393X Tobias Waldekranz
@ 2024-01-03 10:33 ` Tobias Waldekranz
2024-01-03 14:09 ` Andrew Lunn
` (2 more replies)
2024-01-03 10:33 ` [PATCH net-next 2/2] net: dsa: mv88e6xxx: Add LED support for 6393X Tobias Waldekranz
1 sibling, 3 replies; 9+ messages in thread
From: Tobias Waldekranz @ 2024-01-03 10:33 UTC (permalink / raw)
To: davem, kuba; +Cc: andrew, f.fainelli, olteanv, netdev
Parse LEDs from DT and register them with the kernel, for chips that
support it. No actual implementations exist yet, they will be added in
upcoming commits.
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
drivers/net/dsa/mv88e6xxx/Makefile | 1 +
drivers/net/dsa/mv88e6xxx/chip.c | 5 +
drivers/net/dsa/mv88e6xxx/chip.h | 4 +
drivers/net/dsa/mv88e6xxx/leds.c | 195 +++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx/leds.h | 12 ++
5 files changed, 217 insertions(+)
create mode 100644 drivers/net/dsa/mv88e6xxx/leds.c
create mode 100644 drivers/net/dsa/mv88e6xxx/leds.h
diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile
index a9a9651187db..6720d9303914 100644
--- a/drivers/net/dsa/mv88e6xxx/Makefile
+++ b/drivers/net/dsa/mv88e6xxx/Makefile
@@ -9,6 +9,7 @@ mv88e6xxx-objs += global2.o
mv88e6xxx-objs += global2_avb.o
mv88e6xxx-objs += global2_scratch.o
mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o
+mv88e6xxx-objs += leds.o
mv88e6xxx-objs += pcs-6185.o
mv88e6xxx-objs += pcs-6352.o
mv88e6xxx-objs += pcs-639x.o
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 383b3c4d6f59..8fab16badc9e 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -37,6 +37,7 @@
#include "global1.h"
#include "global2.h"
#include "hwtstamp.h"
+#include "leds.h"
#include "phy.h"
#include "port.h"
#include "ptp.h"
@@ -4006,6 +4007,10 @@ static int mv88e6xxx_port_setup(struct dsa_switch *ds, int port)
struct mv88e6xxx_chip *chip = ds->priv;
int err;
+ err = mv88e6xxx_port_setup_leds(ds, port);
+ if (err)
+ return err;
+
if (chip->info->ops->pcs_ops &&
chip->info->ops->pcs_ops->pcs_init) {
err = chip->info->ops->pcs_ops->pcs_init(chip, port);
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 85eb293381a7..c229e3d6a265 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -206,6 +206,7 @@ struct mv88e6xxx_gpio_ops;
struct mv88e6xxx_avb_ops;
struct mv88e6xxx_ptp_ops;
struct mv88e6xxx_pcs_ops;
+struct mv88e6xxx_led_ops;
struct mv88e6xxx_irq {
u16 masked;
@@ -653,6 +654,9 @@ struct mv88e6xxx_ops {
/* Precision Time Protocol operations */
const struct mv88e6xxx_ptp_ops *ptp_ops;
+ /* LED operations */
+ const struct mv88e6xxx_led_ops *led_ops;
+
/* Phylink */
void (*phylink_get_caps)(struct mv88e6xxx_chip *chip, int port,
struct phylink_config *config);
diff --git a/drivers/net/dsa/mv88e6xxx/leds.c b/drivers/net/dsa/mv88e6xxx/leds.c
new file mode 100644
index 000000000000..1f331a632065
--- /dev/null
+++ b/drivers/net/dsa/mv88e6xxx/leds.c
@@ -0,0 +1,195 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <net/dsa.h>
+
+#include "chip.h"
+#include "port.h"
+
+struct mv88e6xxx_led {
+ struct mv88e6xxx_chip *chip;
+ int port;
+ u8 index;
+
+ struct led_classdev ldev;
+};
+
+struct mv88e6xxx_led_ops {
+ int (*brightness_set)(struct mv88e6xxx_led *led,
+ enum led_brightness brightness);
+ int (*blink_set)(struct mv88e6xxx_led *led,
+ unsigned long *delay_on, unsigned long *delay_off);
+ int (*hw_control_is_supported)(struct mv88e6xxx_led *led,
+ unsigned long flags);
+ int (*hw_control_set)(struct mv88e6xxx_led *led, unsigned long flags);
+ int (*hw_control_get)(struct mv88e6xxx_led *led, unsigned long *flags);
+};
+
+static int mv88e6xxx_led_brightness_set(struct led_classdev *ldev,
+ enum led_brightness brightness)
+{
+ const struct mv88e6xxx_led_ops *ops;
+ struct mv88e6xxx_led *led;
+
+ led = container_of(ldev, struct mv88e6xxx_led, ldev);
+ ops = led->chip->info->ops->led_ops;
+
+ if (!ops->brightness_set)
+ return -EOPNOTSUPP;
+
+ return ops->brightness_set(led, brightness);
+}
+
+static int mv88e6xxx_led_blink_set(struct led_classdev *ldev,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ const struct mv88e6xxx_led_ops *ops;
+ struct mv88e6xxx_led *led;
+
+ led = container_of(ldev, struct mv88e6xxx_led, ldev);
+ ops = led->chip->info->ops->led_ops;
+
+ if (!ops->blink_set)
+ return -EOPNOTSUPP;
+
+ return ops->blink_set(led, delay_on, delay_off);
+}
+
+static int mv88e6xxx_led_hw_control_is_supported(struct led_classdev *ldev,
+ unsigned long flags)
+{
+ const struct mv88e6xxx_led_ops *ops;
+ struct mv88e6xxx_led *led;
+
+ led = container_of(ldev, struct mv88e6xxx_led, ldev);
+ ops = led->chip->info->ops->led_ops;
+
+ if (!ops->hw_control_is_supported)
+ return -EOPNOTSUPP;
+
+ return ops->hw_control_is_supported(led, flags);
+}
+
+static int mv88e6xxx_led_hw_control_set(struct led_classdev *ldev,
+ unsigned long flags)
+{
+ const struct mv88e6xxx_led_ops *ops;
+ struct mv88e6xxx_led *led;
+
+ led = container_of(ldev, struct mv88e6xxx_led, ldev);
+ ops = led->chip->info->ops->led_ops;
+
+ if (!ops->hw_control_set)
+ return -EOPNOTSUPP;
+
+ return ops->hw_control_set(led, flags);
+}
+
+static int mv88e6xxx_led_hw_control_get(struct led_classdev *ldev,
+ unsigned long *flags)
+{
+ const struct mv88e6xxx_led_ops *ops;
+ struct mv88e6xxx_led *led;
+
+ led = container_of(ldev, struct mv88e6xxx_led, ldev);
+ ops = led->chip->info->ops->led_ops;
+
+ if (!ops->hw_control_get)
+ return -EOPNOTSUPP;
+
+ return ops->hw_control_get(led, flags);
+}
+
+static struct device *mv88e6xxx_led_hw_control_get_device(struct led_classdev *ldev)
+{
+ struct mv88e6xxx_led *led;
+ struct dsa_port *dp;
+
+ led = container_of(ldev, struct mv88e6xxx_led, ldev);
+ dp = dsa_to_port(led->chip->ds, led->port);
+
+ if (dp && dp->user)
+ return &dp->user->dev;
+
+ return NULL;
+}
+
+static int mv88e6xxx_port_setup_led(struct mv88e6xxx_chip *chip, int port,
+ struct device_node *np)
+{
+ struct led_init_data init_data = {};
+ struct mv88e6xxx_led *led;
+ char *devname;
+ u32 index;
+ int err;
+
+ err = of_property_read_u32(np, "reg", &index);
+ if (err)
+ return err;
+
+ if (index >= 2)
+ return -EINVAL;
+
+ led = devm_kzalloc(chip->dev, sizeof(*led), GFP_KERNEL);
+ if (!led)
+ return -ENOMEM;
+
+ *led = (struct mv88e6xxx_led) {
+ .chip = chip,
+ .port = port,
+ .index = index,
+
+ .ldev = {
+ .max_brightness = 1,
+ .brightness_set_blocking = mv88e6xxx_led_brightness_set,
+ .blink_set = mv88e6xxx_led_blink_set,
+
+#ifdef CONFIG_LEDS_TRIGGERS
+ .hw_control_trigger = "netdev",
+ .hw_control_get_device = mv88e6xxx_led_hw_control_get_device,
+
+ .hw_control_is_supported = mv88e6xxx_led_hw_control_is_supported,
+ .hw_control_set = mv88e6xxx_led_hw_control_set,
+ .hw_control_get = mv88e6xxx_led_hw_control_get,
+#endif
+ },
+ };
+
+ devname = devm_kasprintf(chip->dev, GFP_KERNEL, "%s.%d",
+ dev_name(chip->dev), port);
+ if (!devname)
+ return -ENOMEM;
+
+ init_data = (struct led_init_data) {
+ .fwnode = of_fwnode_handle(np),
+ .devname_mandatory = true,
+ .devicename = devname,
+ };
+
+ return devm_led_classdev_register_ext(chip->dev, &led->ldev, &init_data);
+}
+
+int mv88e6xxx_port_setup_leds(struct dsa_switch *ds, int port)
+{
+ struct dsa_port *dp = dsa_to_port(ds, port);
+ struct mv88e6xxx_chip *chip = ds->priv;
+ struct device_node *pnp, *np;
+ int err;
+
+ if (!chip->info->ops->led_ops)
+ return 0;
+
+ if (!dp->dn)
+ return 0;
+
+ pnp = of_get_child_by_name(dp->dn, "leds");
+ if (!pnp)
+ return 0;
+
+ for_each_available_child_of_node(pnp, np) {
+ err = mv88e6xxx_port_setup_led(chip, port, np);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/dsa/mv88e6xxx/leds.h b/drivers/net/dsa/mv88e6xxx/leds.h
new file mode 100644
index 000000000000..a99d7a5ebc6d
--- /dev/null
+++ b/drivers/net/dsa/mv88e6xxx/leds.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/* Marvell 88E6xxx Switch LED support. */
+
+#ifndef _MV88E6XXX_LEDS_H
+#define _MV88E6XXX_LEDS_H
+
+#include "chip.h"
+
+int mv88e6xxx_port_setup_leds(struct dsa_switch *ds, int port);
+
+#endif /* _MV88E6XXX_LEDS_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net-next 2/2] net: dsa: mv88e6xxx: Add LED support for 6393X
2024-01-03 10:33 [PATCH net-next 0/2] net: dsa: mv88e6xxx: Add LED support for 6393X Tobias Waldekranz
2024-01-03 10:33 ` [PATCH net-next 1/2] net: dsa: mv88e6xxx: Add LED infrastructure Tobias Waldekranz
@ 2024-01-03 10:33 ` Tobias Waldekranz
2024-01-04 3:16 ` kernel test robot
2024-01-04 22:01 ` kernel test robot
1 sibling, 2 replies; 9+ messages in thread
From: Tobias Waldekranz @ 2024-01-03 10:33 UTC (permalink / raw)
To: davem, kuba; +Cc: andrew, f.fainelli, olteanv, netdev
Trigger support:
- "none"
- "timer"
- "netdev"
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 1 +
drivers/net/dsa/mv88e6xxx/leds.c | 227 +++++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx/leds.h | 2 +
drivers/net/dsa/mv88e6xxx/port.c | 33 +++++
drivers/net/dsa/mv88e6xxx/port.h | 7 +
5 files changed, 270 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 8fab16badc9e..f43dc863999a 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -5495,6 +5495,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
.gpio_ops = &mv88e6352_gpio_ops,
.avb_ops = &mv88e6390_avb_ops,
.ptp_ops = &mv88e6352_ptp_ops,
+ .led_ops = &mv88e6393x_led_ops,
.phylink_get_caps = mv88e6393x_phylink_get_caps,
.pcs_ops = &mv88e6393x_pcs_ops,
};
diff --git a/drivers/net/dsa/mv88e6xxx/leds.c b/drivers/net/dsa/mv88e6xxx/leds.c
index 1f331a632065..f964b3a7a3e7 100644
--- a/drivers/net/dsa/mv88e6xxx/leds.c
+++ b/drivers/net/dsa/mv88e6xxx/leds.c
@@ -4,6 +4,13 @@
#include "chip.h"
#include "port.h"
+#define FLAG_ACT (BIT(TRIGGER_NETDEV_RX) | BIT(TRIGGER_NETDEV_TX))
+#define FLAG_LINK BIT(TRIGGER_NETDEV_LINK)
+#define FLAG_LINK_10 BIT(TRIGGER_NETDEV_LINK_10)
+#define FLAG_LINK_100 BIT(TRIGGER_NETDEV_LINK_100)
+#define FLAG_LINK_1G BIT(TRIGGER_NETDEV_LINK_1000)
+#define FLAG_FULL BIT(TRIGGER_NETDEV_FULL_DUPLEX)
+
struct mv88e6xxx_led {
struct mv88e6xxx_chip *chip;
int port;
@@ -23,6 +30,226 @@ struct mv88e6xxx_led_ops {
int (*hw_control_get)(struct mv88e6xxx_led *led, unsigned long *flags);
};
+enum mv88e6393x_led_mode {
+ MV88E6393X_LED_MODE_BLINK = 0xd,
+ MV88E6393X_LED_MODE_OFF = 0xe,
+ MV88E6393X_LED_MODE_ON = 0xf,
+
+ MV88E6393X_LED_MODES = 0x10
+};
+
+static const unsigned long mv88e6393x_led_map_p1_p8[2][MV88E6393X_LED_MODES] = {
+ {
+ [0x1] = FLAG_ACT | FLAG_LINK_100 | FLAG_LINK_1G,
+ [0x2] = FLAG_ACT | FLAG_LINK_1G,
+ [0x3] = FLAG_ACT | FLAG_LINK,
+ [0x6] = FLAG_FULL,
+ [0x7] = FLAG_ACT | FLAG_LINK_10 | FLAG_LINK_1G,
+ [0x8] = FLAG_LINK,
+ [0x9] = FLAG_LINK_10,
+ [0xa] = FLAG_ACT | FLAG_LINK_10,
+ [0xb] = FLAG_LINK_100 | FLAG_LINK_1G,
+ },
+ {
+ [0x1] = FLAG_ACT,
+ [0x2] = FLAG_ACT | FLAG_LINK_10 | FLAG_LINK_100,
+ [0x3] = FLAG_LINK_1G,
+ [0x5] = FLAG_ACT | FLAG_LINK,
+ [0x6] = FLAG_ACT | FLAG_LINK_10 | FLAG_LINK_1G,
+ [0x7] = FLAG_LINK_10 | FLAG_LINK_1G,
+ [0x9] = FLAG_LINK_100,
+ [0xa] = FLAG_ACT | FLAG_LINK_100,
+ [0xb] = FLAG_LINK_10 | FLAG_LINK_100,
+ }
+};
+
+static const unsigned long mv88e6393x_led_map_p9_p10[2][MV88E6393X_LED_MODES] = {
+ {
+ [0x1] = FLAG_ACT | FLAG_LINK,
+ },
+ {
+ [0x6] = FLAG_FULL,
+ [0x7] = FLAG_ACT | FLAG_LINK,
+ [0x8] = FLAG_LINK,
+ }
+};
+
+const unsigned long *mv88e6393x_led_map(struct mv88e6xxx_led *led)
+{
+ switch (led->port) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ return mv88e6393x_led_map_p1_p8[led->index];
+ case 9:
+ case 10:
+ return mv88e6393x_led_map_p9_p10[led->index];
+ }
+
+ return NULL;
+}
+
+static int mv88e6393x_led_flags_to_mode(struct mv88e6xxx_led *led, unsigned long flags)
+{
+ const unsigned long *map = mv88e6393x_led_map(led);
+ int i;
+
+ if (!map)
+ return -ENODEV;
+
+ if (!flags)
+ return MV88E6393X_LED_MODE_OFF;
+
+ for (i = 0; i < MV88E6393X_LED_MODES; i++) {
+ if (map[i] == flags)
+ return i;
+ }
+
+ return -EINVAL;
+}
+
+static int mv88e6393x_led_mode_to_flags(struct mv88e6xxx_led *led, u8 mode,
+ unsigned long *flags)
+{
+ const unsigned long *map = mv88e6393x_led_map(led);
+
+ if (!map)
+ return -ENODEV;
+
+ if (mode == MV88E6393X_LED_MODE_OFF) {
+ *flags = 0;
+ return 0;
+ }
+
+ if (map[mode]) {
+ *flags = map[mode];
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int mv88e6393x_led_set(struct mv88e6xxx_led *led, int mode)
+{
+ u16 ctrl;
+ int err;
+
+ if (mode < 0)
+ return mode;
+
+ mv88e6xxx_reg_lock(led->chip);
+
+ err = mv88e6393x_port_led_read(led->chip, led->port, 0, &ctrl);
+ if (err)
+ goto out;
+
+ switch (led->index) {
+ case 0:
+ ctrl &= ~0x0f;
+ ctrl |= mode;
+ break;
+ case 1:
+ ctrl &= ~0xf0;
+ ctrl |= mode << 4;
+ }
+
+ err = mv88e6393x_port_led_write(led->chip, led->port, 0, ctrl);
+out:
+ mv88e6xxx_reg_unlock(led->chip);
+ return err;
+}
+
+static int mv88e6393x_led_get(struct mv88e6xxx_led *led)
+{
+ u16 ctrl;
+ int err;
+
+ mv88e6xxx_reg_lock(led->chip);
+ err = mv88e6393x_port_led_read(led->chip, led->port, 0, &ctrl);
+ mv88e6xxx_reg_unlock(led->chip);
+ if (err)
+ return err;
+
+ switch (led->index) {
+ case 0:
+ return ctrl & 0xf;
+ case 1:
+ return (ctrl >> 4) & 0xf;
+ }
+
+ return -EINVAL;
+}
+
+static int mv88e6393x_led_brightness_set(struct mv88e6xxx_led *led,
+ enum led_brightness brightness)
+{
+ if (brightness == LED_OFF)
+ return mv88e6393x_led_set(led, MV88E6393X_LED_MODE_OFF);
+
+ return mv88e6393x_led_set(led, MV88E6393X_LED_MODE_ON);
+}
+
+static int mv88e6393x_led_blink_set(struct mv88e6xxx_led *led,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ int err;
+
+ /* Defer anything other than 50% duty cycles to software */
+ if (*delay_on != *delay_off)
+ return -EINVAL;
+
+ /* Reject values outside ~20% of our default rate (84ms) */
+ if (*delay_on && ((*delay_on < 30) || (*delay_on > 50)))
+ return -EINVAL;
+
+ err = mv88e6393x_led_set(led, MV88E6393X_LED_MODE_BLINK);
+ if (!err)
+ *delay_on = *delay_off = 42;
+
+ return err;
+}
+
+static int mv88e6393x_led_hw_control_is_supported(struct mv88e6xxx_led *led,
+ unsigned long flags)
+{
+ int mode = mv88e6393x_led_flags_to_mode(led, flags);
+
+ return (mode < 0) ? mode : 0;
+}
+
+static int mv88e6393x_led_hw_control_set(struct mv88e6xxx_led *led,
+ unsigned long flags)
+{
+ int mode = mv88e6393x_led_flags_to_mode(led, flags);
+
+ return mv88e6393x_led_set(led, mode);
+}
+
+static int mv88e6393x_led_hw_control_get(struct mv88e6xxx_led *led,
+ unsigned long *flags)
+{
+ int mode = mv88e6393x_led_get(led);
+
+ if (mode < 0)
+ return mode;
+
+ return mv88e6393x_led_mode_to_flags(led, mode, flags);
+}
+
+const struct mv88e6xxx_led_ops mv88e6393x_led_ops = {
+ .brightness_set = mv88e6393x_led_brightness_set,
+ .blink_set = mv88e6393x_led_blink_set,
+ .hw_control_is_supported = mv88e6393x_led_hw_control_is_supported,
+ .hw_control_set = mv88e6393x_led_hw_control_set,
+ .hw_control_get = mv88e6393x_led_hw_control_get,
+};
+
static int mv88e6xxx_led_brightness_set(struct led_classdev *ldev,
enum led_brightness brightness)
{
diff --git a/drivers/net/dsa/mv88e6xxx/leds.h b/drivers/net/dsa/mv88e6xxx/leds.h
index a99d7a5ebc6d..c7de16ce4dde 100644
--- a/drivers/net/dsa/mv88e6xxx/leds.h
+++ b/drivers/net/dsa/mv88e6xxx/leds.h
@@ -7,6 +7,8 @@
#include "chip.h"
+extern const struct mv88e6xxx_led_ops mv88e6393x_led_ops;
+
int mv88e6xxx_port_setup_leds(struct dsa_switch *ds, int port);
#endif /* _MV88E6XXX_LEDS_H */
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 5394a8cf7bf1..66073a1ef260 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -1539,6 +1539,39 @@ int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ETH_TYPE, etype);
}
+/* Offset 0x16: LED Control Register */
+
+int mv88e6393x_port_led_write(struct mv88e6xxx_chip *chip, int port,
+ unsigned int pointer, u16 data)
+{
+ u16 cmd = BIT(15) | ((pointer & 0x7) << 12) | (data & 0x7ff);
+ int err;
+
+ err = mv88e6xxx_port_write(chip, port, MV88E6393X_PORT_LED_CONTROL, cmd);
+ if (err)
+ return err;
+
+ return mv88e6xxx_port_wait_bit(chip, port, MV88E6393X_PORT_LED_CONTROL, 15, 0);
+}
+
+int mv88e6393x_port_led_read(struct mv88e6xxx_chip *chip, int port,
+ unsigned int pointer, u16 *data)
+{
+ u16 cmd = (pointer & 0x7) << 12;
+ int err;
+
+ err = mv88e6xxx_port_write(chip, port, MV88E6393X_PORT_LED_CONTROL, cmd);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_port_read(chip, port, MV88E6393X_PORT_LED_CONTROL, &cmd);
+ if (err)
+ return err;
+
+ *data = cmd & 0x7ff;
+ return 0;
+}
+
/* Offset 0x18: Port IEEE Priority Remapping Registers [0-3]
* Offset 0x19: Port IEEE Priority Remapping Registers [4-7]
*/
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 86deeb347cbc..3605a59d1399 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -294,6 +294,9 @@
/* Offset 0x13: OutFiltered Counter */
#define MV88E6XXX_PORT_OUT_FILTERED 0x13
+/* Offset 0x16: LED Control Register */
+#define MV88E6393X_PORT_LED_CONTROL 0x16
+
/* Offset 0x18: IEEE Priority Mapping Table */
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE 0x18
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE 0x8000
@@ -410,6 +413,10 @@ int mv88e6393x_port_set_policy(struct mv88e6xxx_chip *chip, int port,
enum mv88e6xxx_policy_action action);
int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
u16 etype);
+int mv88e6393x_port_led_write(struct mv88e6xxx_chip *chip, int port,
+ unsigned int pointer, u16 data);
+int mv88e6393x_port_led_read(struct mv88e6xxx_chip *chip, int port,
+ unsigned int pointer, u16 *data);
int mv88e6393x_set_egress_port(struct mv88e6xxx_chip *chip,
enum mv88e6xxx_egress_direction direction,
int port);
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread