Эх сурвалжийг харах

Merge branch 'dsa-gpio-reset'

Andrew Lunn says:

====================
DSA: GPIO to reset switches

These two patches add support for using a GPIO to hard reset a switch
during reset.

v2:

Thanks to a clue from Neil Armstrong, i figured out how to convert the
gpio into a gpiod, while keeping the ACTIVE_LOW flag, so simplifiying
the set/reset code.

I have not included the Tested-by: from Phil Reid, since i made a lot
of changes.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
David S. Miller 9 жил өмнө
parent
commit
3d40e44361

+ 3 - 0
Documentation/devicetree/bindings/net/dsa/dsa.txt

@@ -31,6 +31,8 @@ A switch child node has the following optional property:
 			  switch. Must be set if the switch can not detect
 			  the presence and/or size of a connected EEPROM,
 			  otherwise optional.
+- reset-gpios		: phandle and specifier to a gpio line connected to
+			  reset pin of the switch chip.
 
 A switch may have multiple "port" children nodes
 
@@ -114,6 +116,7 @@ Example:
 			#size-cells = <0>;
 			reg = <17 1>;	/* MDIO address 17, switch 1 in tree */
 			mii-bus = <&mii_bus1>;
+			reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
 
 			switch1port0: port@0 {
 				reg = <0>;

+ 10 - 0
drivers/net/dsa/mv88e6xxx.c

@@ -19,6 +19,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/gpio/consumer.h>
 #include <linux/phy.h>
 #include <net/dsa.h>
 #include <net/switchdev.h>
@@ -2323,6 +2324,7 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
+	struct gpio_desc *gpiod = ds->pd->reset;
 	unsigned long timeout;
 	int ret;
 	int i;
@@ -2336,6 +2338,14 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
 	/* Wait for transmit queues to drain. */
 	usleep_range(2000, 4000);
 
+	/* If there is a gpio connected to the reset pin, toggle it */
+	if (gpiod) {
+		gpiod_set_value_cansleep(gpiod, 1);
+		usleep_range(10000, 20000);
+		gpiod_set_value_cansleep(gpiod, 0);
+		usleep_range(10000, 20000);
+	}
+
 	/* Reset the switch. Keep the PPU active if requested. The PPU
 	 * needs to be active to support indirect phy register access
 	 * through global registers 0x18 and 0x19.

+ 8 - 0
include/net/dsa.h

@@ -16,6 +16,7 @@
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 #include <linux/of.h>
+#include <linux/of_gpio.h>
 #include <linux/phy.h>
 #include <linux/phy_fixed.h>
 #include <linux/ethtool.h>
@@ -64,6 +65,13 @@ struct dsa_chip_data {
 	 * NULL if there is only one switch chip.
 	 */
 	s8		*rtable;
+
+	/*
+	 * A switch may have a GPIO line tied to its reset pin. Parse
+	 * this from the device tree, and use it before performing
+	 * switch soft reset.
+	 */
+	struct gpio_desc *reset;
 };
 
 struct dsa_platform_data {

+ 17 - 0
net/dsa/dsa.c

@@ -21,6 +21,7 @@
 #include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 #include <linux/of_net.h>
+#include <linux/of_gpio.h>
 #include <linux/sysfs.h>
 #include <linux/phy_fixed.h>
 #include "dsa_priv.h"
@@ -688,6 +689,9 @@ static int dsa_of_probe(struct device *dev)
 	const char *port_name;
 	int chip_index, port_index;
 	const unsigned int *sw_addr, *port_reg;
+	int gpio;
+	enum of_gpio_flags of_flags;
+	unsigned long flags;
 	u32 eeprom_len;
 	int ret;
 
@@ -766,6 +770,19 @@ static int dsa_of_probe(struct device *dev)
 			put_device(cd->host_dev);
 			cd->host_dev = &mdio_bus_switch->dev;
 		}
+		gpio = of_get_named_gpio_flags(child, "reset-gpios", 0,
+					       &of_flags);
+		if (gpio_is_valid(gpio)) {
+			flags = (of_flags == OF_GPIO_ACTIVE_LOW ?
+				 GPIOF_ACTIVE_LOW : 0);
+			ret = devm_gpio_request_one(dev, gpio, flags,
+						    "switch_reset");
+			if (ret)
+				goto out_free_chip;
+
+			cd->reset = gpio_to_desc(gpio);
+			gpiod_direction_output(cd->reset, 0);
+		}
 
 		for_each_available_child_of_node(child, port) {
 			port_reg = of_get_property(port, "reg", NULL);