diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index 5e313e9a252..a80735490cb 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -23,8 +23,13 @@ #include #include #include +#include #include +#include +#include +#include +#include #include "ks8851.h" @@ -131,6 +136,10 @@ struct ks8851_net { struct spi_transfer spi_xfer1; struct spi_transfer spi_xfer2[2]; + struct regulator *vdd_io; + struct regulator *vdd_phy; + int rst_gpio; + struct eeprom_93cx6 eeprom; }; @@ -1415,6 +1424,66 @@ static int ks8851_resume(struct spi_device *spi) #define ks8851_resume NULL #endif +static int __devinit ks8851_init_hw(struct spi_device *spi, + struct ks8851_net *ks) +{ + struct ks8851_pdata *pdata = spi->dev.platform_data; + struct device_node *dnode = spi->dev.of_node; + enum of_gpio_flags flags; + int ret; + + ks->rst_gpio = -ENODEV; + + if (dnode) + ks->rst_gpio = of_get_named_gpio_flags(dnode, "rst-gpio", + 0, &flags); + else if (pdata) + ks->rst_gpio = pdata->rst_gpio; + + if (gpio_is_valid(ks->rst_gpio)) { + ret = gpio_request(ks->rst_gpio, "ks8851_rst"); + if (ret) { + pr_err("ks8851 gpio_request failed: %d\n", ret); + return ret; + } + + /* Make sure the chip is in reset state */ + gpio_direction_output(ks->rst_gpio, 0); + } + + ks->vdd_io = regulator_get(&spi->dev, "vdd-io"); + + if (IS_ERR(ks->vdd_io)) { + ret = PTR_ERR(ks->vdd_io); + goto fail_gpio; + } + + ks->vdd_phy = regulator_get(&spi->dev, "vdd-phy"); + + if (IS_ERR(ks->vdd_phy)) { + regulator_put(ks->vdd_io); + ret = PTR_ERR(ks->vdd_phy); + goto fail_gpio; + } + + regulator_enable(ks->vdd_io); + regulator_enable(ks->vdd_phy); + + /* Wait for atleast 10ms after turning on regulator */ + usleep_range(10000, 11000); + + if (gpio_is_valid(ks->rst_gpio)) + gpio_direction_output(ks->rst_gpio, 1); + + return 0; + +fail_gpio: + if (gpio_is_valid(ks->rst_gpio)) + gpio_free(ks->rst_gpio); + + return ret; +} + static int __devinit ks8851_probe(struct spi_device *spi) { struct net_device *ndev; @@ -1430,6 +1499,10 @@ static int __devinit ks8851_probe(struct spi_device *spi) ks = netdev_priv(ndev); + ret = ks8851_init_hw(spi, ks); + if (ret) + goto err_init; + ks->netdev = ndev; ks->spidev = spi; ks->tx_space = 6144; @@ -1530,6 +1603,20 @@ err_netdev: err_id: err_irq: + if (gpio_is_valid(ks->rst_gpio)) + gpio_free(ks->rst_gpio); + + if (!IS_ERR(ks->vdd_io)) { + regulator_disable(ks->vdd_io); + regulator_put(ks->vdd_io); + } + + if (!IS_ERR(ks->vdd_phy)) { + regulator_disable(ks->vdd_phy); + regulator_put(ks->vdd_phy); + } + +err_init: free_netdev(ndev); return ret; } @@ -1541,6 +1628,19 @@ static int __devexit ks8851_remove(struct spi_device *spi) if (netif_msg_drv(priv)) dev_info(&spi->dev, "remove\n"); + if (gpio_is_valid(priv->rst_gpio)) + gpio_free(priv->rst_gpio); + + if (!IS_ERR(priv->vdd_io)) { + regulator_disable(priv->vdd_io); + regulator_put(priv->vdd_io); + } + + if (!IS_ERR(priv->vdd_phy)) { + regulator_disable(priv->vdd_phy); + regulator_put(priv->vdd_phy); + } + unregister_netdev(priv->netdev); free_irq(spi->irq, priv); free_netdev(priv->netdev); @@ -1548,9 +1648,17 @@ static int __devexit ks8851_remove(struct spi_device *spi) return 0; } +static struct of_device_id ks8851_match_table[] = { + { + .compatible = "micrel,ks8851", + }, + {} +}; + static struct spi_driver ks8851_driver = { .driver = { .name = "ks8851", + .of_match_table = ks8851_match_table, .owner = THIS_MODULE, }, .probe = ks8851_probe,