All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hubert Feurstein <h.feurstein@gmail.com>
To: netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Hubert Feurstein <h.feurstein@gmail.com>,
	Andrew Lunn <andrew@lunn.ch>,
	Vivien Didelot <vivien.didelot@gmail.com>,
	Florian Fainelli <f.fainelli@gmail.com>,
	"David S. Miller" <davem@davemloft.net>
Subject: [PATCH 1/2] net: dsa: mv88e6xxx: add support to setup led-control register through device-tree
Date: Tue, 30 Jul 2019 12:14:50 +0200	[thread overview]
Message-ID: <20190730101451.845-1-h.feurstein@gmail.com> (raw)

So it is possible to change the default behaviour of the switch LEDs.

Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com>
---
 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", &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


             reply	other threads:[~2019-07-30 10:15 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-30 10:14 Hubert Feurstein [this message]
2019-07-30 10:14 ` [PATCH 2/2] dt-bindings: net: dsa: marvell: add property "marvell,led-control" Hubert Feurstein
2019-07-30 14:09 ` [PATCH 1/2] net: dsa: mv88e6xxx: add support to setup led-control register through device-tree Andrew Lunn
2019-07-30 15:50   ` Hubert Feurstein

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190730101451.845-1-h.feurstein@gmail.com \
    --to=h.feurstein@gmail.com \
    --cc=andrew@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=f.fainelli@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=vivien.didelot@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.