Commit 1ddff7da authored by Alexander Shiyan's avatar Alexander Shiyan Committed by Marc Kleine-Budde

can: mcp251x: Replace power callbacks with regulator API

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: default avatarHaojian Zhuang <haojian.zhuang@gmail.com>
Signed-off-by: default avatarAlexander Shiyan <shc_work@mail.ru>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 954c3967
...@@ -73,9 +73,6 @@ static struct pxa2xx_spi_chip mcp251x_chip_info4 = { ...@@ -73,9 +73,6 @@ static struct pxa2xx_spi_chip mcp251x_chip_info4 = {
static struct mcp251x_platform_data mcp251x_info = { static struct mcp251x_platform_data mcp251x_info = {
.oscillator_frequency = 16E6, .oscillator_frequency = 16E6,
.board_specific_setup = NULL,
.power_enable = NULL,
.transceiver_enable = NULL
}; };
static struct spi_board_info mcp251x_board_info[] = { static struct spi_board_info mcp251x_board_info[] = {
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include <linux/i2c/pca953x.h> #include <linux/i2c/pca953x.h>
#include <linux/apm-emulation.h> #include <linux/apm-emulation.h>
#include <linux/can/platform/mcp251x.h> #include <linux/can/platform/mcp251x.h>
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/suspend.h> #include <asm/suspend.h>
...@@ -391,33 +393,34 @@ static struct pxa2xx_spi_master pxa2xx_spi_ssp3_master_info = { ...@@ -391,33 +393,34 @@ static struct pxa2xx_spi_master pxa2xx_spi_ssp3_master_info = {
}; };
/* CAN bus on SPI */ /* CAN bus on SPI */
static int zeus_mcp2515_setup(struct spi_device *sdev) static struct regulator_consumer_supply can_regulator_consumer =
{ REGULATOR_SUPPLY("vdd", "spi3.0");
int err;
err = gpio_request(ZEUS_CAN_SHDN_GPIO, "CAN shutdown"); static struct regulator_init_data can_regulator_init_data = {
if (err) .constraints = {
return err; .valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
err = gpio_direction_output(ZEUS_CAN_SHDN_GPIO, 1); .consumer_supplies = &can_regulator_consumer,
if (err) { .num_consumer_supplies = 1,
gpio_free(ZEUS_CAN_SHDN_GPIO); };
return err;
}
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) static struct platform_device can_regulator_device = {
{ .name = "reg-fixed-volage",
gpio_set_value(ZEUS_CAN_SHDN_GPIO, !enable); .id = -1,
return 0; .dev = {
} .platform_data = &can_regulator_pdata,
},
};
static struct mcp251x_platform_data zeus_mcp2515_pdata = { static struct mcp251x_platform_data zeus_mcp2515_pdata = {
.oscillator_frequency = 16*1000*1000, .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[] = { static struct spi_board_info zeus_spi_board_info[] = {
...@@ -516,6 +519,7 @@ static struct platform_device *zeus_devices[] __initdata = { ...@@ -516,6 +519,7 @@ static struct platform_device *zeus_devices[] __initdata = {
&zeus_leds_device, &zeus_leds_device,
&zeus_pcmcia_device, &zeus_pcmcia_device,
&zeus_max6369_device, &zeus_max6369_device,
&can_regulator_device,
}; };
/* AC'97 */ /* AC'97 */
......
...@@ -37,9 +37,6 @@ ...@@ -37,9 +37,6 @@
* *
* static struct mcp251x_platform_data mcp251x_info = { * static struct mcp251x_platform_data mcp251x_info = {
* .oscillator_frequency = 8000000, * .oscillator_frequency = 8000000,
* .board_specific_setup = &mcp251x_setup,
* .power_enable = mcp251x_power_enable,
* .transceiver_enable = NULL,
* }; * };
* *
* static struct spi_board_info spi_board_info[] = { * static struct spi_board_info spi_board_info[] = {
...@@ -76,6 +73,7 @@ ...@@ -76,6 +73,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/regulator/consumer.h>
/* SPI interface instruction set */ /* SPI interface instruction set */
#define INSTRUCTION_WRITE 0x02 #define INSTRUCTION_WRITE 0x02
...@@ -264,6 +262,8 @@ struct mcp251x_priv { ...@@ -264,6 +262,8 @@ struct mcp251x_priv {
#define AFTER_SUSPEND_POWER 4 #define AFTER_SUSPEND_POWER 4
#define AFTER_SUSPEND_RESTART 8 #define AFTER_SUSPEND_RESTART 8
int restart_tx; int restart_tx;
struct regulator *power;
struct regulator *transceiver;
}; };
#define MCP251X_IS(_model) \ #define MCP251X_IS(_model) \
...@@ -667,16 +667,25 @@ static int mcp251x_hw_probe(struct spi_device *spi) ...@@ -667,16 +667,25 @@ static int mcp251x_hw_probe(struct spi_device *spi)
return (st1 == 0x80 && st2 == 0x07) ? 1 : 0; 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) static void mcp251x_open_clean(struct net_device *net)
{ {
struct mcp251x_priv *priv = netdev_priv(net); struct mcp251x_priv *priv = netdev_priv(net);
struct spi_device *spi = priv->spi; struct spi_device *spi = priv->spi;
struct mcp251x_platform_data *pdata = spi->dev.platform_data;
free_irq(spi->irq, priv); free_irq(spi->irq, priv);
mcp251x_hw_sleep(spi); mcp251x_hw_sleep(spi);
if (pdata->transceiver_enable) mcp251x_power_enable(priv->transceiver, 0);
pdata->transceiver_enable(0);
close_candev(net); close_candev(net);
} }
...@@ -684,7 +693,6 @@ static int mcp251x_stop(struct net_device *net) ...@@ -684,7 +693,6 @@ static int mcp251x_stop(struct net_device *net)
{ {
struct mcp251x_priv *priv = netdev_priv(net); struct mcp251x_priv *priv = netdev_priv(net);
struct spi_device *spi = priv->spi; struct spi_device *spi = priv->spi;
struct mcp251x_platform_data *pdata = spi->dev.platform_data;
close_candev(net); close_candev(net);
...@@ -704,8 +712,7 @@ static int mcp251x_stop(struct net_device *net) ...@@ -704,8 +712,7 @@ static int mcp251x_stop(struct net_device *net)
mcp251x_hw_sleep(spi); mcp251x_hw_sleep(spi);
if (pdata->transceiver_enable) mcp251x_power_enable(priv->transceiver, 0);
pdata->transceiver_enable(0);
priv->can.state = CAN_STATE_STOPPED; priv->can.state = CAN_STATE_STOPPED;
...@@ -939,8 +946,7 @@ static int mcp251x_open(struct net_device *net) ...@@ -939,8 +946,7 @@ static int mcp251x_open(struct net_device *net)
} }
mutex_lock(&priv->mcp_lock); mutex_lock(&priv->mcp_lock);
if (pdata->transceiver_enable) mcp251x_power_enable(priv->transceiver, 1);
pdata->transceiver_enable(1);
priv->force_quit = 0; priv->force_quit = 0;
priv->tx_skb = NULL; priv->tx_skb = NULL;
...@@ -956,8 +962,7 @@ static int mcp251x_open(struct net_device *net) ...@@ -956,8 +962,7 @@ static int mcp251x_open(struct net_device *net)
flags, DEVICE_NAME, priv); flags, DEVICE_NAME, priv);
if (ret) { if (ret) {
dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq); dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
if (pdata->transceiver_enable) mcp251x_power_enable(priv->transceiver, 0);
pdata->transceiver_enable(0);
close_candev(net); close_candev(net);
goto open_unlock; goto open_unlock;
} }
...@@ -1026,6 +1031,19 @@ static int mcp251x_can_probe(struct spi_device *spi) ...@@ -1026,6 +1031,19 @@ static int mcp251x_can_probe(struct spi_device *spi)
CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
priv->model = spi_get_device_id(spi)->driver_data; priv->model = spi_get_device_id(spi)->driver_data;
priv->net = net; 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); spi_set_drvdata(spi, priv);
priv->spi = spi; priv->spi = spi;
...@@ -1068,13 +1086,6 @@ static int mcp251x_can_probe(struct spi_device *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); SET_NETDEV_DEV(net, &spi->dev);
/* Configure the SPI bus */ /* Configure the SPI bus */
...@@ -1084,14 +1095,11 @@ static int mcp251x_can_probe(struct spi_device *spi) ...@@ -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 */ /* Here is OK to not lock the MCP, no one knows about it yet */
if (!mcp251x_hw_probe(spi)) { if (!mcp251x_hw_probe(spi)) {
dev_info(&spi->dev, "Probe failed\n"); ret = -ENODEV;
goto error_probe; goto error_probe;
} }
mcp251x_hw_sleep(spi); mcp251x_hw_sleep(spi);
if (pdata->transceiver_enable)
pdata->transceiver_enable(0);
ret = register_candev(net); ret = register_candev(net);
if (ret) if (ret)
goto error_probe; goto error_probe;
...@@ -1109,13 +1117,13 @@ static int mcp251x_can_probe(struct spi_device *spi) ...@@ -1109,13 +1117,13 @@ static int mcp251x_can_probe(struct spi_device *spi)
if (!mcp251x_enable_dma) if (!mcp251x_enable_dma)
kfree(priv->spi_tx_buf); kfree(priv->spi_tx_buf);
error_tx_buf: error_tx_buf:
free_candev(net);
if (mcp251x_enable_dma) if (mcp251x_enable_dma)
dma_free_coherent(&spi->dev, PAGE_SIZE, dma_free_coherent(&spi->dev, PAGE_SIZE,
priv->spi_tx_buf, priv->spi_tx_dma); priv->spi_tx_buf, priv->spi_tx_dma);
mcp251x_power_enable(priv->power, 0);
error_power:
free_candev(net);
error_alloc: error_alloc:
if (pdata->power_enable)
pdata->power_enable(0);
dev_err(&spi->dev, "probe failed\n"); dev_err(&spi->dev, "probe failed\n");
error_out: error_out:
return ret; return ret;
...@@ -1123,12 +1131,10 @@ static int mcp251x_can_probe(struct spi_device *spi) ...@@ -1123,12 +1131,10 @@ static int mcp251x_can_probe(struct spi_device *spi)
static int mcp251x_can_remove(struct spi_device *spi) 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 mcp251x_priv *priv = spi_get_drvdata(spi);
struct net_device *net = priv->net; struct net_device *net = priv->net;
unregister_candev(net); unregister_candev(net);
free_candev(net);
if (mcp251x_enable_dma) { if (mcp251x_enable_dma) {
dma_free_coherent(&spi->dev, PAGE_SIZE, dma_free_coherent(&spi->dev, PAGE_SIZE,
...@@ -1138,8 +1144,9 @@ static int mcp251x_can_remove(struct spi_device *spi) ...@@ -1138,8 +1144,9 @@ static int mcp251x_can_remove(struct spi_device *spi)
kfree(priv->spi_rx_buf); kfree(priv->spi_rx_buf);
} }
if (pdata->power_enable) mcp251x_power_enable(priv->power, 0);
pdata->power_enable(0);
free_candev(net);
return 0; return 0;
} }
...@@ -1149,7 +1156,6 @@ static int mcp251x_can_remove(struct spi_device *spi) ...@@ -1149,7 +1156,6 @@ static int mcp251x_can_remove(struct spi_device *spi)
static int mcp251x_can_suspend(struct device *dev) static int mcp251x_can_suspend(struct device *dev)
{ {
struct spi_device *spi = to_spi_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 mcp251x_priv *priv = spi_get_drvdata(spi);
struct net_device *net = priv->net; struct net_device *net = priv->net;
...@@ -1163,15 +1169,14 @@ static int mcp251x_can_suspend(struct device *dev) ...@@ -1163,15 +1169,14 @@ static int mcp251x_can_suspend(struct device *dev)
netif_device_detach(net); netif_device_detach(net);
mcp251x_hw_sleep(spi); mcp251x_hw_sleep(spi);
if (pdata->transceiver_enable) mcp251x_power_enable(priv->transceiver, 0);
pdata->transceiver_enable(0);
priv->after_suspend = AFTER_SUSPEND_UP; priv->after_suspend = AFTER_SUSPEND_UP;
} else { } else {
priv->after_suspend = AFTER_SUSPEND_DOWN; priv->after_suspend = AFTER_SUSPEND_DOWN;
} }
if (pdata->power_enable) { if (!IS_ERR(priv->power)) {
pdata->power_enable(0); regulator_disable(priv->power);
priv->after_suspend |= AFTER_SUSPEND_POWER; priv->after_suspend |= AFTER_SUSPEND_POWER;
} }
...@@ -1181,16 +1186,14 @@ static int mcp251x_can_suspend(struct device *dev) ...@@ -1181,16 +1186,14 @@ static int mcp251x_can_suspend(struct device *dev)
static int mcp251x_can_resume(struct device *dev) static int mcp251x_can_resume(struct device *dev)
{ {
struct spi_device *spi = to_spi_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 mcp251x_priv *priv = spi_get_drvdata(spi);
if (priv->after_suspend & AFTER_SUSPEND_POWER) { if (priv->after_suspend & AFTER_SUSPEND_POWER) {
pdata->power_enable(1); mcp251x_power_enable(priv->power, 1);
queue_work(priv->wq, &priv->restart_work); queue_work(priv->wq, &priv->restart_work);
} else { } else {
if (priv->after_suspend & AFTER_SUSPEND_UP) { if (priv->after_suspend & AFTER_SUSPEND_UP) {
if (pdata->transceiver_enable) mcp251x_power_enable(priv->transceiver, 1);
pdata->transceiver_enable(1);
queue_work(priv->wq, &priv->restart_work); queue_work(priv->wq, &priv->restart_work);
} else { } else {
priv->after_suspend = 0; priv->after_suspend = 0;
......
...@@ -9,26 +9,15 @@ ...@@ -9,26 +9,15 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
/** /*
* struct mcp251x_platform_data - MCP251X SPI CAN controller platform data * struct mcp251x_platform_data - MCP251X SPI CAN controller platform data
* @oscillator_frequency: - oscillator frequency in Hz * @oscillator_frequency: - oscillator frequency in Hz
* @irq_flags: - IRQF configuration flags * @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 { struct mcp251x_platform_data {
unsigned long oscillator_frequency; unsigned long oscillator_frequency;
unsigned long irq_flags; 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__ */ #endif /* __CAN_PLATFORM_MCP251X_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment