diff options
Diffstat (limited to 'drivers/net/ethernet/smsc/smc91x.c')
-rw-r--r-- | drivers/net/ethernet/smsc/smc91x.c | 78 |
1 files changed, 70 insertions, 8 deletions
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 5e94d00b96b3..6cc3cf6f17c8 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c | |||
@@ -81,6 +81,7 @@ static const char version[] = | |||
81 | #include <linux/workqueue.h> | 81 | #include <linux/workqueue.h> |
82 | #include <linux/of.h> | 82 | #include <linux/of.h> |
83 | #include <linux/of_device.h> | 83 | #include <linux/of_device.h> |
84 | #include <linux/of_gpio.h> | ||
84 | 85 | ||
85 | #include <linux/netdevice.h> | 86 | #include <linux/netdevice.h> |
86 | #include <linux/etherdevice.h> | 87 | #include <linux/etherdevice.h> |
@@ -2188,6 +2189,41 @@ static const struct of_device_id smc91x_match[] = { | |||
2188 | {}, | 2189 | {}, |
2189 | }; | 2190 | }; |
2190 | MODULE_DEVICE_TABLE(of, smc91x_match); | 2191 | MODULE_DEVICE_TABLE(of, smc91x_match); |
2192 | |||
2193 | /** | ||
2194 | * of_try_set_control_gpio - configure a gpio if it exists | ||
2195 | */ | ||
2196 | static int try_toggle_control_gpio(struct device *dev, | ||
2197 | struct gpio_desc **desc, | ||
2198 | const char *name, int index, | ||
2199 | int value, unsigned int nsdelay) | ||
2200 | { | ||
2201 | struct gpio_desc *gpio = *desc; | ||
2202 | int res; | ||
2203 | |||
2204 | gpio = devm_gpiod_get_index(dev, name, index); | ||
2205 | if (IS_ERR(gpio)) { | ||
2206 | if (PTR_ERR(gpio) == -ENOENT) { | ||
2207 | *desc = NULL; | ||
2208 | return 0; | ||
2209 | } | ||
2210 | |||
2211 | return PTR_ERR(gpio); | ||
2212 | } | ||
2213 | res = gpiod_direction_output(gpio, !value); | ||
2214 | if (res) { | ||
2215 | dev_err(dev, "unable to toggle gpio %s: %i\n", name, res); | ||
2216 | devm_gpiod_put(dev, gpio); | ||
2217 | gpio = NULL; | ||
2218 | return res; | ||
2219 | } | ||
2220 | if (nsdelay) | ||
2221 | usleep_range(nsdelay, 2 * nsdelay); | ||
2222 | gpiod_set_value_cansleep(gpio, value); | ||
2223 | *desc = gpio; | ||
2224 | |||
2225 | return 0; | ||
2226 | } | ||
2191 | #endif | 2227 | #endif |
2192 | 2228 | ||
2193 | /* | 2229 | /* |
@@ -2207,9 +2243,10 @@ static int smc_drv_probe(struct platform_device *pdev) | |||
2207 | const struct of_device_id *match = NULL; | 2243 | const struct of_device_id *match = NULL; |
2208 | struct smc_local *lp; | 2244 | struct smc_local *lp; |
2209 | struct net_device *ndev; | 2245 | struct net_device *ndev; |
2210 | struct resource *res, *ires; | 2246 | struct resource *res; |
2211 | unsigned int __iomem *addr; | 2247 | unsigned int __iomem *addr; |
2212 | unsigned long irq_flags = SMC_IRQ_FLAGS; | 2248 | unsigned long irq_flags = SMC_IRQ_FLAGS; |
2249 | unsigned long irq_resflags; | ||
2213 | int ret; | 2250 | int ret; |
2214 | 2251 | ||
2215 | ndev = alloc_etherdev(sizeof(struct smc_local)); | 2252 | ndev = alloc_etherdev(sizeof(struct smc_local)); |
@@ -2237,6 +2274,28 @@ static int smc_drv_probe(struct platform_device *pdev) | |||
2237 | struct device_node *np = pdev->dev.of_node; | 2274 | struct device_node *np = pdev->dev.of_node; |
2238 | u32 val; | 2275 | u32 val; |
2239 | 2276 | ||
2277 | /* Optional pwrdwn GPIO configured? */ | ||
2278 | ret = try_toggle_control_gpio(&pdev->dev, &lp->power_gpio, | ||
2279 | "power", 0, 0, 100); | ||
2280 | if (ret) | ||
2281 | return ret; | ||
2282 | |||
2283 | /* | ||
2284 | * Optional reset GPIO configured? Minimum 100 ns reset needed | ||
2285 | * according to LAN91C96 datasheet page 14. | ||
2286 | */ | ||
2287 | ret = try_toggle_control_gpio(&pdev->dev, &lp->reset_gpio, | ||
2288 | "reset", 0, 0, 100); | ||
2289 | if (ret) | ||
2290 | return ret; | ||
2291 | |||
2292 | /* | ||
2293 | * Need to wait for optional EEPROM to load, max 750 us according | ||
2294 | * to LAN91C96 datasheet page 55. | ||
2295 | */ | ||
2296 | if (lp->reset_gpio) | ||
2297 | usleep_range(750, 1000); | ||
2298 | |||
2240 | /* Combination of IO widths supported, default to 16-bit */ | 2299 | /* Combination of IO widths supported, default to 16-bit */ |
2241 | if (!of_property_read_u32(np, "reg-io-width", &val)) { | 2300 | if (!of_property_read_u32(np, "reg-io-width", &val)) { |
2242 | if (val & 1) | 2301 | if (val & 1) |
@@ -2279,16 +2338,19 @@ static int smc_drv_probe(struct platform_device *pdev) | |||
2279 | goto out_free_netdev; | 2338 | goto out_free_netdev; |
2280 | } | 2339 | } |
2281 | 2340 | ||
2282 | ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 2341 | ndev->irq = platform_get_irq(pdev, 0); |
2283 | if (!ires) { | 2342 | if (ndev->irq <= 0) { |
2284 | ret = -ENODEV; | 2343 | ret = -ENODEV; |
2285 | goto out_release_io; | 2344 | goto out_release_io; |
2286 | } | 2345 | } |
2287 | 2346 | /* | |
2288 | ndev->irq = ires->start; | 2347 | * If this platform does not specify any special irqflags, or if |
2289 | 2348 | * the resource supplies a trigger, override the irqflags with | |
2290 | if (irq_flags == -1 || ires->flags & IRQF_TRIGGER_MASK) | 2349 | * the trigger flags from the resource. |
2291 | irq_flags = ires->flags & IRQF_TRIGGER_MASK; | 2350 | */ |
2351 | irq_resflags = irqd_get_trigger_type(irq_get_irq_data(ndev->irq)); | ||
2352 | if (irq_flags == -1 || irq_resflags & IRQF_TRIGGER_MASK) | ||
2353 | irq_flags = irq_resflags & IRQF_TRIGGER_MASK; | ||
2292 | 2354 | ||
2293 | ret = smc_request_attrib(pdev, ndev); | 2355 | ret = smc_request_attrib(pdev, ndev); |
2294 | if (ret) | 2356 | if (ret) |