diff options
Diffstat (limited to 'drivers/net/ethernet/micrel/ks8851.c')
-rw-r--r-- | drivers/net/ethernet/micrel/ks8851.c | 87 |
1 files changed, 67 insertions, 20 deletions
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index e0c92e0e5e1d..66d4ab703f45 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -26,6 +26,8 @@ #include <linux/regulator/consumer.h> #include <linux/spi/spi.h> +#include <linux/gpio.h> +#include <linux/of_gpio.h> #include "ks8851.h" @@ -85,6 +87,8 @@ union ks8851_tx_hdr { * @eeprom_size: Companion eeprom size in Bytes, 0 if no eeprom * @eeprom: 93CX6 EEPROM state for accessing on-board EEPROM. * @vdd_reg: Optional regulator supplying the chip + * @vdd_io: Optional digital power supply for IO + * @gpio: Optional reset_n gpio * * The @lock ensures that the chip is protected when certain operations are * in progress. When the read or write packet transfer is in progress, most @@ -133,6 +137,8 @@ struct ks8851_net { struct eeprom_93cx6 eeprom; struct regulator *vdd_reg; + struct regulator *vdd_io; + int gpio; }; static int msg_enable; @@ -1404,6 +1410,7 @@ static int ks8851_probe(struct spi_device *spi) struct ks8851_net *ks; int ret; unsigned cider; + int gpio; ndev = alloc_etherdev(sizeof(struct ks8851_net)); if (!ndev) @@ -1417,20 +1424,53 @@ static int ks8851_probe(struct spi_device *spi) ks->spidev = spi; ks->tx_space = 6144; - ks->vdd_reg = regulator_get_optional(&spi->dev, "vdd"); - if (IS_ERR(ks->vdd_reg)) { - ret = PTR_ERR(ks->vdd_reg); - if (ret == -EPROBE_DEFER) - goto err_reg; - } else { - ret = regulator_enable(ks->vdd_reg); + gpio = of_get_named_gpio_flags(spi->dev.of_node, "reset-gpios", + 0, NULL); + if (gpio == -EPROBE_DEFER) { + ret = gpio; + goto err_gpio; + } + + ks->gpio = gpio; + if (gpio_is_valid(gpio)) { + ret = devm_gpio_request_one(&spi->dev, gpio, + GPIOF_OUT_INIT_LOW, "ks8851_rst_n"); if (ret) { - dev_err(&spi->dev, "regulator enable fail: %d\n", - ret); - goto err_reg_en; + dev_err(&spi->dev, "reset gpio request failed\n"); + goto err_gpio; } } + ks->vdd_io = devm_regulator_get(&spi->dev, "vdd-io"); + if (IS_ERR(ks->vdd_io)) { + ret = PTR_ERR(ks->vdd_io); + goto err_reg_io; + } + + ret = regulator_enable(ks->vdd_io); + if (ret) { + dev_err(&spi->dev, "regulator vdd_io enable fail: %d\n", + ret); + goto err_reg_io; + } + + ks->vdd_reg = devm_regulator_get(&spi->dev, "vdd"); + if (IS_ERR(ks->vdd_reg)) { + ret = PTR_ERR(ks->vdd_reg); + goto err_reg; + } + + ret = regulator_enable(ks->vdd_reg); + if (ret) { + dev_err(&spi->dev, "regulator vdd enable fail: %d\n", + ret); + goto err_reg; + } + + if (gpio_is_valid(gpio)) { + usleep_range(10000, 11000); + gpio_set_value(gpio, 1); + } mutex_init(&ks->lock); spin_lock_init(&ks->statelock); @@ -1471,7 +1511,7 @@ static int ks8851_probe(struct spi_device *spi) skb_queue_head_init(&ks->txq); - SET_ETHTOOL_OPS(ndev, &ks8851_ethtool_ops); + ndev->ethtool_ops = &ks8851_ethtool_ops; SET_NETDEV_DEV(ndev, &spi->dev); spi_set_drvdata(spi, ks); @@ -1527,13 +1567,14 @@ err_netdev: free_irq(ndev->irq, ks); err_irq: + if (gpio_is_valid(gpio)) + gpio_set_value(gpio, 0); err_id: - if (!IS_ERR(ks->vdd_reg)) - regulator_disable(ks->vdd_reg); -err_reg_en: - if (!IS_ERR(ks->vdd_reg)) - regulator_put(ks->vdd_reg); + regulator_disable(ks->vdd_reg); err_reg: + regulator_disable(ks->vdd_io); +err_reg_io: +err_gpio: free_netdev(ndev); return ret; } @@ -1547,18 +1588,24 @@ static int ks8851_remove(struct spi_device *spi) unregister_netdev(priv->netdev); free_irq(spi->irq, priv); - if (!IS_ERR(priv->vdd_reg)) { - regulator_disable(priv->vdd_reg); - regulator_put(priv->vdd_reg); - } + if (gpio_is_valid(priv->gpio)) + gpio_set_value(priv->gpio, 0); + regulator_disable(priv->vdd_reg); + regulator_disable(priv->vdd_io); free_netdev(priv->netdev); return 0; } +static const 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, .pm = &ks8851_pm_ops, }, |