]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
net: smc91x: Fix gpios for device tree based booting
authorTony Lindgren <tony@atomide.com>
Thu, 30 Oct 2014 16:59:27 +0000 (09:59 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 31 Oct 2014 19:54:18 +0000 (15:54 -0400)
With legacy booting, the platform init code was taking care of
the configuring of GPIOs. With device tree based booting, things
may or may not work depending what bootloader has configured or
if the legacy platform code gets called.

Let's add support for the pwrdn and reset GPIOs to the smc91x
driver to fix the issues of smc91x not working properly when
booted in device tree mode.

And let's change n900 to use these settings as some versions
of the bootloader do not configure things properly causing
errors.

Reported-by: Kevin Hilman <khilman@linaro.org>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Documentation/devicetree/bindings/net/smsc-lan91c111.txt
arch/arm/boot/dts/omap3-n900.dts
arch/arm/mach-omap2/pdata-quirks.c
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/smsc/smc91x.h

index 0f8487b888221e6344dec76afd6a8ffa44242306..e77e167593db2aa585ca1afbb48e4fbac0287384 100644 (file)
@@ -11,3 +11,5 @@ Optional properties:
   are supported on the device.  Valid value for SMSC LAN91c111 are
   1, 2 or 4.  If it's omitted or invalid, the size would be 2 meaning
   16-bit access only.
+- power-gpios: GPIO to control the PWRDWN pin
+- reset-gpios: GPIO to control the RESET pin
index 9b0494a8ab454f21b67060416b698ed10d710f64..286bbf620c77c94a1d42a7adda034d05484a7760 100644 (file)
                bank-width = <2>;
                pinctrl-names = "default";
                pinctrl-0 = <&ethernet_pins>;
+               power-gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;     /* gpio86 */
+               reset-gpios = <&gpio6 4 GPIO_ACTIVE_HIGH>;      /* gpio164 */
                gpmc,device-width = <2>;
                gpmc,sync-clk-ps = <0>;
                gpmc,cs-on-ns = <0>;
index c95346c948297fcb14f5f6a5dd33d71b7247166a..cec9d6c6442c80b03d3d6954c2c3feb65a62176f 100644 (file)
@@ -252,9 +252,6 @@ static void __init nokia_n900_legacy_init(void)
                platform_device_register(&omap3_rom_rng_device);
 
        }
-
-       /* Only on some development boards */
-       gpio_request_one(164, GPIOF_OUT_INIT_LOW, "smc91x reset");
 }
 
 static void __init omap3_tao3530_legacy_init(void)
index 5e94d00b96b301d9dc9cd09a17943520b96e8b52..2c62208077fe7a442aa1b5340e0e614d3b247c21 100644 (file)
@@ -81,6 +81,7 @@ static const char version[] =
 #include <linux/workqueue.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -2188,6 +2189,41 @@ static const struct of_device_id smc91x_match[] = {
        {},
 };
 MODULE_DEVICE_TABLE(of, smc91x_match);
+
+/**
+ * of_try_set_control_gpio - configure a gpio if it exists
+ */
+static int try_toggle_control_gpio(struct device *dev,
+                                  struct gpio_desc **desc,
+                                  const char *name, int index,
+                                  int value, unsigned int nsdelay)
+{
+       struct gpio_desc *gpio = *desc;
+       int res;
+
+       gpio = devm_gpiod_get_index(dev, name, index);
+       if (IS_ERR(gpio)) {
+               if (PTR_ERR(gpio) == -ENOENT) {
+                       *desc = NULL;
+                       return 0;
+               }
+
+               return PTR_ERR(gpio);
+       }
+       res = gpiod_direction_output(gpio, !value);
+       if (res) {
+               dev_err(dev, "unable to toggle gpio %s: %i\n", name, res);
+               devm_gpiod_put(dev, gpio);
+               gpio = NULL;
+               return res;
+       }
+       if (nsdelay)
+               usleep_range(nsdelay, 2 * nsdelay);
+       gpiod_set_value_cansleep(gpio, value);
+       *desc = gpio;
+
+       return 0;
+}
 #endif
 
 /*
@@ -2237,6 +2273,28 @@ static int smc_drv_probe(struct platform_device *pdev)
                struct device_node *np = pdev->dev.of_node;
                u32 val;
 
+               /* Optional pwrdwn GPIO configured? */
+               ret = try_toggle_control_gpio(&pdev->dev, &lp->power_gpio,
+                                             "power", 0, 0, 100);
+               if (ret)
+                       return ret;
+
+               /*
+                * Optional reset GPIO configured? Minimum 100 ns reset needed
+                * according to LAN91C96 datasheet page 14.
+                */
+               ret = try_toggle_control_gpio(&pdev->dev, &lp->reset_gpio,
+                                             "reset", 0, 0, 100);
+               if (ret)
+                       return ret;
+
+               /*
+                * Need to wait for optional EEPROM to load, max 750 us according
+                * to LAN91C96 datasheet page 55.
+                */
+               if (lp->reset_gpio)
+                       usleep_range(750, 1000);
+
                /* Combination of IO widths supported, default to 16-bit */
                if (!of_property_read_u32(np, "reg-io-width", &val)) {
                        if (val & 1)
index 47dce918eb0f49741a9dec7ae3cee68354fb7a0a..2a38dacbbd27fba4f153790117cb10102dadd6e6 100644 (file)
@@ -298,6 +298,9 @@ struct smc_local {
        struct sk_buff *pending_tx_skb;
        struct tasklet_struct tx_task;
 
+       struct gpio_desc *power_gpio;
+       struct gpio_desc *reset_gpio;
+
        /* version/revision of the SMC91x chip */
        int     version;