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>
This commit is contained in:
commit
3d40e44361
|
@ -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>;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue