can: mcp251x: Replace power callbacks with regulator API
authorAlexander Shiyan <shc_work@mail.ru>
Mon, 19 Aug 2013 11:39:19 +0000 (15:39 +0400)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Wed, 21 Aug 2013 07:28:29 +0000 (09:28 +0200)
This patch replaces power callbacks to the regulator API. To improve
the readability of the code, helper for the regulator enable/disable
was added.

Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com>
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
arch/arm/mach-pxa/icontrol.c
arch/arm/mach-pxa/zeus.c
drivers/net/can/mcp251x.c
include/linux/can/platform/mcp251x.h

index fe31bfc..c98511c 100644 (file)
@@ -73,9 +73,6 @@ static struct pxa2xx_spi_chip mcp251x_chip_info4 = {
 
 static struct mcp251x_platform_data mcp251x_info = {
        .oscillator_frequency = 16E6,
-       .board_specific_setup = NULL,
-       .power_enable         = NULL,
-       .transceiver_enable   = NULL
 };
 
 static struct spi_board_info mcp251x_board_info[] = {
index f5d4364..04a0aea 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/i2c/pca953x.h>
 #include <linux/apm-emulation.h>
 #include <linux/can/platform/mcp251x.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
 
 #include <asm/mach-types.h>
 #include <asm/suspend.h>
@@ -391,33 +393,34 @@ static struct pxa2xx_spi_master pxa2xx_spi_ssp3_master_info = {
 };
 
 /* CAN bus on SPI */
-static int zeus_mcp2515_setup(struct spi_device *sdev)
-{
-       int err;
-
-       err = gpio_request(ZEUS_CAN_SHDN_GPIO, "CAN shutdown");
-       if (err)
-               return err;
+static struct regulator_consumer_supply can_regulator_consumer =
+       REGULATOR_SUPPLY("vdd", "spi3.0");
 
-       err = gpio_direction_output(ZEUS_CAN_SHDN_GPIO, 1);
-       if (err) {
-               gpio_free(ZEUS_CAN_SHDN_GPIO);
-               return err;
-       }
+static struct regulator_init_data can_regulator_init_data = {
+       .constraints    = {
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .consumer_supplies      = &can_regulator_consumer,
+       .num_consumer_supplies  = 1,
+};
 
-       return 0;
-}
+static struct fixed_voltage_config can_regulator_pdata = {
+       .supply_name    = "CAN_SHDN",
+       .microvolts     = 3300000,
+       .gpio           = ZEUS_CAN_SHDN_GPIO,
+       .init_data      = &can_regulator_init_data,
+};
 
-static int zeus_mcp2515_transceiver_enable(int enable)
-{
-       gpio_set_value(ZEUS_CAN_SHDN_GPIO, !enable);
-       return 0;
-}
+static struct platform_device can_regulator_device = {
+       .name   = "reg-fixed-volage",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &can_regulator_pdata,
+       },
+};
 
 static struct mcp251x_platform_data zeus_mcp2515_pdata = {
        .oscillator_frequency   = 16*1000*1000,
-       .board_specific_setup   = zeus_mcp2515_setup,
-       .power_enable           = zeus_mcp2515_transceiver_enable,
 };
 
 static struct spi_board_info zeus_spi_board_info[] = {
@@ -516,6 +519,7 @@ static struct platform_device *zeus_devices[] __initdata = {
        &zeus_leds_device,
        &zeus_pcmcia_device,
        &zeus_max6369_device,
+       &can_regulator_device,
 };
 
 /* AC'97 */
index 8cda23b..d2c5488 100644 (file)
@@ -37,9 +37,6 @@
  *
  * static struct mcp251x_platform_data mcp251x_info = {
  *         .oscillator_frequency = 8000000,
- *         .board_specific_setup = &mcp251x_setup,
- *         .power_enable = mcp251x_power_enable,
- *         .transceiver_enable = NULL,
  * };
  *
  * static struct spi_board_info spi_board_info[] = {
@@ -76,6 +73,7 @@
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
 #include <linux/uaccess.h>
+#include <linux/regulator/consumer.h>
 
 /* SPI interface instruction set */
 #define INSTRUCTION_WRITE      0x02
@@ -264,6 +262,8 @@ struct mcp251x_priv {
 #define AFTER_SUSPEND_POWER 4
 #define AFTER_SUSPEND_RESTART 8
        int restart_tx;
+       struct regulator *power;
+       struct regulator *transceiver;
 };
 
 #define MCP251X_IS(_model) \
@@ -667,16 +667,25 @@ static int mcp251x_hw_probe(struct spi_device *spi)
        return (st1 == 0x80 && st2 == 0x07) ? 1 : 0;
 }
 
+static int mcp251x_power_enable(struct regulator *reg, int enable)
+{
+       if (IS_ERR(reg))
+               return 0;
+
+       if (enable)
+               return regulator_enable(reg);
+       else
+               return regulator_disable(reg);
+}
+
 static void mcp251x_open_clean(struct net_device *net)
 {
        struct mcp251x_priv *priv = netdev_priv(net);
        struct spi_device *spi = priv->spi;
-       struct mcp251x_platform_data *pdata = spi->dev.platform_data;
 
        free_irq(spi->irq, priv);
        mcp251x_hw_sleep(spi);
-       if (pdata->transceiver_enable)
-               pdata->transceiver_enable(0);
+       mcp251x_power_enable(priv->transceiver, 0);
        close_candev(net);
 }
 
@@ -684,7 +693,6 @@ static int mcp251x_stop(struct net_device *net)
 {
        struct mcp251x_priv *priv = netdev_priv(net);
        struct spi_device *spi = priv->spi;
-       struct mcp251x_platform_data *pdata = spi->dev.platform_data;
 
        close_candev(net);
 
@@ -704,8 +712,7 @@ static int mcp251x_stop(struct net_device *net)
 
        mcp251x_hw_sleep(spi);
 
-       if (pdata->transceiver_enable)
-               pdata->transceiver_enable(0);
+       mcp251x_power_enable(priv->transceiver, 0);
 
        priv->can.state = CAN_STATE_STOPPED;
 
@@ -939,8 +946,7 @@ static int mcp251x_open(struct net_device *net)
        }
 
        mutex_lock(&priv->mcp_lock);
-       if (pdata->transceiver_enable)
-               pdata->transceiver_enable(1);
+       mcp251x_power_enable(priv->transceiver, 1);
 
        priv->force_quit = 0;
        priv->tx_skb = NULL;
@@ -956,8 +962,7 @@ static int mcp251x_open(struct net_device *net)
                                   flags, DEVICE_NAME, priv);
        if (ret) {
                dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
-               if (pdata->transceiver_enable)
-                       pdata->transceiver_enable(0);
+               mcp251x_power_enable(priv->transceiver, 0);
                close_candev(net);
                goto open_unlock;
        }
@@ -1026,6 +1031,19 @@ static int mcp251x_can_probe(struct spi_device *spi)
                CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
        priv->model = spi_get_device_id(spi)->driver_data;
        priv->net = net;
+
+       priv->power = devm_regulator_get(&spi->dev, "vdd");
+       priv->transceiver = devm_regulator_get(&spi->dev, "xceiver");
+       if ((PTR_ERR(priv->power) == -EPROBE_DEFER) ||
+           (PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) {
+               ret = -EPROBE_DEFER;
+               goto error_power;
+       }
+
+       ret = mcp251x_power_enable(priv->power, 1);
+       if (ret)
+               goto error_power;
+
        spi_set_drvdata(spi, priv);
 
        priv->spi = spi;
@@ -1068,13 +1086,6 @@ static int mcp251x_can_probe(struct spi_device *spi)
                }
        }
 
-       if (pdata->power_enable)
-               pdata->power_enable(1);
-
-       /* Call out to platform specific setup */
-       if (pdata->board_specific_setup)
-               pdata->board_specific_setup(spi);
-
        SET_NETDEV_DEV(net, &spi->dev);
 
        /* Configure the SPI bus */
@@ -1084,14 +1095,11 @@ static int mcp251x_can_probe(struct spi_device *spi)
 
        /* Here is OK to not lock the MCP, no one knows about it yet */
        if (!mcp251x_hw_probe(spi)) {
-               dev_info(&spi->dev, "Probe failed\n");
+               ret = -ENODEV;
                goto error_probe;
        }
        mcp251x_hw_sleep(spi);
 
-       if (pdata->transceiver_enable)
-               pdata->transceiver_enable(0);
-
        ret = register_candev(net);
        if (ret)
                goto error_probe;
@@ -1109,13 +1117,13 @@ error_rx_buf:
        if (!mcp251x_enable_dma)
                kfree(priv->spi_tx_buf);
 error_tx_buf:
-       free_candev(net);
        if (mcp251x_enable_dma)
                dma_free_coherent(&spi->dev, PAGE_SIZE,
                                  priv->spi_tx_buf, priv->spi_tx_dma);
+       mcp251x_power_enable(priv->power, 0);
+error_power:
+       free_candev(net);
 error_alloc:
-       if (pdata->power_enable)
-               pdata->power_enable(0);
        dev_err(&spi->dev, "probe failed\n");
 error_out:
        return ret;
@@ -1123,12 +1131,10 @@ error_out:
 
 static int mcp251x_can_remove(struct spi_device *spi)
 {
-       struct mcp251x_platform_data *pdata = spi->dev.platform_data;
        struct mcp251x_priv *priv = spi_get_drvdata(spi);
        struct net_device *net = priv->net;
 
        unregister_candev(net);
-       free_candev(net);
 
        if (mcp251x_enable_dma) {
                dma_free_coherent(&spi->dev, PAGE_SIZE,
@@ -1138,8 +1144,9 @@ static int mcp251x_can_remove(struct spi_device *spi)
                kfree(priv->spi_rx_buf);
        }
 
-       if (pdata->power_enable)
-               pdata->power_enable(0);
+       mcp251x_power_enable(priv->power, 0);
+
+       free_candev(net);
 
        return 0;
 }
@@ -1149,7 +1156,6 @@ static int mcp251x_can_remove(struct spi_device *spi)
 static int mcp251x_can_suspend(struct device *dev)
 {
        struct spi_device *spi = to_spi_device(dev);
-       struct mcp251x_platform_data *pdata = spi->dev.platform_data;
        struct mcp251x_priv *priv = spi_get_drvdata(spi);
        struct net_device *net = priv->net;
 
@@ -1163,15 +1169,14 @@ static int mcp251x_can_suspend(struct device *dev)
                netif_device_detach(net);
 
                mcp251x_hw_sleep(spi);
-               if (pdata->transceiver_enable)
-                       pdata->transceiver_enable(0);
+               mcp251x_power_enable(priv->transceiver, 0);
                priv->after_suspend = AFTER_SUSPEND_UP;
        } else {
                priv->after_suspend = AFTER_SUSPEND_DOWN;
        }
 
-       if (pdata->power_enable) {
-               pdata->power_enable(0);
+       if (!IS_ERR(priv->power)) {
+               regulator_disable(priv->power);
                priv->after_suspend |= AFTER_SUSPEND_POWER;
        }
 
@@ -1181,16 +1186,14 @@ static int mcp251x_can_suspend(struct device *dev)
 static int mcp251x_can_resume(struct device *dev)
 {
        struct spi_device *spi = to_spi_device(dev);
-       struct mcp251x_platform_data *pdata = spi->dev.platform_data;
        struct mcp251x_priv *priv = spi_get_drvdata(spi);
 
        if (priv->after_suspend & AFTER_SUSPEND_POWER) {
-               pdata->power_enable(1);
+               mcp251x_power_enable(priv->power, 1);
                queue_work(priv->wq, &priv->restart_work);
        } else {
                if (priv->after_suspend & AFTER_SUSPEND_UP) {
-                       if (pdata->transceiver_enable)
-                               pdata->transceiver_enable(1);
+                       mcp251x_power_enable(priv->transceiver, 1);
                        queue_work(priv->wq, &priv->restart_work);
                } else {
                        priv->after_suspend = 0;
index 089fe43..8a27256 100644 (file)
@@ -9,26 +9,15 @@
 
 #include <linux/spi/spi.h>
 
-/**
+/*
  * struct mcp251x_platform_data - MCP251X SPI CAN controller platform data
  * @oscillator_frequency:       - oscillator frequency in Hz
  * @irq_flags:                  - IRQF configuration flags
- * @board_specific_setup:       - called before probing the chip (power,reset)
- * @transceiver_enable:         - called to power on/off the transceiver
- * @power_enable:               - called to power on/off the mcp *and* the
- *                                transceiver
- *
- * Please note that you should define power_enable or transceiver_enable or
- * none of them. Defining both of them is no use.
- *
  */
 
 struct mcp251x_platform_data {
        unsigned long oscillator_frequency;
        unsigned long irq_flags;
-       int (*board_specific_setup)(struct spi_device *spi);
-       int (*transceiver_enable)(int enable);
-       int (*power_enable) (int enable);
 };
 
 #endif /* __CAN_PLATFORM_MCP251X_H__ */