ks8851: Add GPIO and regulator support

Allow the ks8851 driver to configure regulators and GPIOs
specified as platform data or in device tree.

Change-Id: I806f7c22ba4b75eb26720704968cdec9cd7796c8
Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
Signed-off-by: Stepan Moskovchenko <stepanm@codeaurora.org>
(cherry picked from commit c990b2faa3ce0b4f2361630a687abdedee4241a9)

Signed-off-by: Sudhir Sharma <sudsha@codeaurora.org>
This commit is contained in:
Stepan Moskovchenko
2012-08-22 18:45:44 -07:00
committed by Stephen Boyd
parent 62774a2a5f
commit af33ebe883

View File

@@ -23,8 +23,13 @@
#include <linux/crc32.h>
#include <linux/mii.h>
#include <linux/eeprom_93cx6.h>
#include <linux/ks8851.h>
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#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,