So it is possible to change the default behaviour of the switch LEDs.
Signed-off-by: Hubert Feurstein <[email protected]>
---
drivers/net/dsa/mv88e6xxx/chip.c | 52 ++++++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx/chip.h | 2 ++
drivers/net/dsa/mv88e6xxx/port.c | 13 ++++++++
drivers/net/dsa/mv88e6xxx/port.h | 10 ++++++
4 files changed, 77 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 85638b868d8e..e5a11454e1e0 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1985,6 +1985,52 @@ static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip)
return mv88e6xxx_software_reset(chip);
}
+static void mv88e6xxx_led_control_init(struct mv88e6xxx_chip *chip,
+ const struct device_node *np)
+{
+ struct device_node *ports, *port;
+ struct mv88e6xxx_port *chip_port;
+ u32 led_control, reg;
+ int err;
+
+ if (!np)
+ return;
+
+ /* Read LED Control register value from device-tree */
+ ports = of_get_child_by_name(np, "ports");
+ if (!ports)
+ return;
+
+ for_each_available_child_of_node(ports, port) {
+ err = of_property_read_u32(port, "reg", ®);
+ if (err || reg >= ARRAY_SIZE(chip->ports))
+ break;
+
+ err = of_property_read_u32(port, "marvell,led-control",
+ &led_control);
+ if (!err) {
+ chip_port = &chip->ports[reg];
+ chip_port->led_control = led_control |
+ MV88E6XXX_LED_CONTROL_VALID;
+ dev_dbg(chip->dev, "LED control value for port%d = 0x%02x\n",
+ reg, led_control);
+ }
+ }
+
+ of_node_put(ports);
+}
+
+static int mv88e6xxx_led_control_setup(struct mv88e6xxx_chip *chip, int port)
+{
+ u16 led_control = chip->ports[port].led_control;
+
+ if ((led_control & MV88E6XXX_LED_CONTROL_VALID) == 0)
+ return 0;
+
+ led_control &= ~MV88E6XXX_LED_CONTROL_VALID;
+ return mv88e6xxx_port_set_led_control(chip, port, led_control);
+}
+
static int mv88e6xxx_set_port_mode(struct mv88e6xxx_chip *chip, int port,
enum mv88e6xxx_frame_mode frame,
enum mv88e6xxx_egress_mode egress, u16 etype)
@@ -2120,6 +2166,11 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
chip->ports[port].chip = chip;
chip->ports[port].port = port;
+ /* Setup LED Control before link-up or link-unforce */
+ err = mv88e6xxx_led_control_setup(chip, port);
+ if (err)
+ return err;
+
/* MAC Forcing register: don't force link, speed, duplex or flow control
* state to any particular values on physical ports, but force the CPU
* port and all DSA ports to their maximum bandwidth and full duplex.
@@ -4851,6 +4902,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
goto out;
mv88e6xxx_phy_init(chip);
+ mv88e6xxx_led_control_init(chip, np);
if (chip->info->ops->get_eeprom) {
if (np)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 64872251e479..1bb775855d62 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -24,6 +24,7 @@
#define MV88E6XXX_MAX_PVT_PORTS 16
#define MV88E6XXX_MAX_GPIO 16
+#define MV88E6XXX_LED_CONTROL_VALID 0x8000
enum mv88e6xxx_egress_mode {
MV88E6XXX_EGRESS_MODE_UNMODIFIED,
@@ -194,6 +195,7 @@ struct mv88e6xxx_port {
u64 vtu_member_violation;
u64 vtu_miss_violation;
u8 cmode;
+ u16 led_control;
int serdes_irq;
};
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 04309ef0a1cc..111bb686b764 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -1183,6 +1183,19 @@ 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 mv88e6xxx_port_set_led_control(struct mv88e6xxx_chip *chip, int port,
+ u16 led_control)
+{
+ led_control &= MV88E6XXX_PORT_LED_CONTROL_DATA_MASK;
+ led_control |= MV88E6XXX_PORT_LED_CONTROL_POINTER_CONTROL_LED01
+ | MV88E6XXX_PORT_LED_CONTROL_UPDATE;
+
+ return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_LED_CONTROL,
+ led_control);
+}
+
/* 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 141df2988cd1..5aacbccf81e3 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -239,6 +239,14 @@
/* Offset 0x13: OutFiltered Counter */
#define MV88E6XXX_PORT_OUT_FILTERED 0x13
+/* Offset 0x16: LED Control Register */
+#define MV88E6XXX_PORT_LED_CONTROL 0x16
+#define MV88E6XXX_PORT_LED_CONTROL_DATA_MASK 0x07ff
+#define MV88E6XXX_PORT_LED_CONTROL_UPDATE 0x8000
+#define MV88E6XXX_PORT_LED_CONTROL_POINTER_CONTROL_LED01 0x0000
+#define MV88E6XXX_PORT_LED_CONTROL_POINTER_STRECH_BLINK_RATE 0x6000
+#define MV88E6XXX_PORT_LED_CONTROL_POINTER_CONTROL_SPECIAL 0x7000
+
/* Offset 0x18: IEEE Priority Mapping Table */
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE 0x18
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE 0x8000
@@ -323,6 +331,8 @@ int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
bool unicast, bool multicast);
int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
u16 etype);
+int mv88e6xxx_port_set_led_control(struct mv88e6xxx_chip *chip, int port,
+ u16 led_control);
int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
bool message_port);
int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port,
--
2.22.0
With this property it is possible to change the default behaviour of
the switch LEDs.
Signed-off-by: Hubert Feurstein <[email protected]>
---
Documentation/devicetree/bindings/net/dsa/marvell.txt | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/dsa/marvell.txt b/Documentation/devicetree/bindings/net/dsa/marvell.txt
index 30c11fea491b..5e094e37c76d 100644
--- a/Documentation/devicetree/bindings/net/dsa/marvell.txt
+++ b/Documentation/devicetree/bindings/net/dsa/marvell.txt
@@ -46,6 +46,16 @@ Optional properties:
- mdio? : Container of PHYs and devices on the external MDIO
bus. The node must contains a compatible string of
"marvell,mv88e6xxx-mdio-external"
+- marvell,led-control : The register value for the LED control register (
+ Control for LED 0 & 1). This property can be defined
+ per port. Example:
+ ports {
+ port@0 {
+ [...]
+ marvell,led-control = <0x11>
+ };
+ [...]
+ }
Example:
--
2.22.0
On Tue, Jul 30, 2019 at 12:14:50PM +0200, Hubert Feurstein wrote:
> So it is possible to change the default behaviour of the switch LEDs.
Sorry, but this is not going to be accepted. There is an ongoing
discussion about PHY LEDs and how they should be configured. Switch
LEDs are no different from PHY LEDs. So they should use the same basic
concept.
Please take a look at the discussion around:
[RFC] dt-bindings: net: phy: Add subnode for LED configuration
Marvell designers have made this more difficult than it should be by
moving the registers out of the PHY address space and into the switch
address space. So we are going to have to implement this code twice
:-(
Andrew
Am Di., 30. Juli 2019 um 16:09 Uhr schrieb Andrew Lunn <[email protected]>:
[...]
> Sorry, but this is not going to be accepted. There is an ongoing
> discussion about PHY LEDs and how they should be configured. Switch
> LEDs are no different from PHY LEDs. So they should use the same basic
> concept.
>
> Please take a look at the discussion around:
>
> [RFC] dt-bindings: net: phy: Add subnode for LED configuration
>
> Marvell designers have made this more difficult than it should be by
> moving the registers out of the PHY address space and into the switch
> address space. So we are going to have to implement this code twice
> :-(
Ok, good to know. I'll wait for the first implementation and take it
as a reference.
Hubert