diff options
author | Alexander Shiyan <shc_work@mail.ru> | 2013-08-19 07:39:19 -0400 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2013-08-21 03:28:29 -0400 |
commit | 1ddff7da0faecffdcdeab3d981fb8241453cea44 (patch) | |
tree | 7388e85b2a844917fe3103c47bdb044799fba95f | |
parent | 954c396756e3d31985f7bc6a414a988a4736a7d0 (diff) |
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: Haojian Zhuang <haojian.zhuang@gmail.com>
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r-- | arch/arm/mach-pxa/icontrol.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-pxa/zeus.c | 46 | ||||
-rw-r--r-- | drivers/net/can/mcp251x.c | 83 | ||||
-rw-r--r-- | include/linux/can/platform/mcp251x.h | 13 |
4 files changed, 69 insertions, 76 deletions
diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c index fe31bfcbb8df..c98511c5abd1 100644 --- a/arch/arm/mach-pxa/icontrol.c +++ b/arch/arm/mach-pxa/icontrol.c | |||
@@ -73,9 +73,6 @@ static struct pxa2xx_spi_chip mcp251x_chip_info4 = { | |||
73 | 73 | ||
74 | static struct mcp251x_platform_data mcp251x_info = { | 74 | static struct mcp251x_platform_data mcp251x_info = { |
75 | .oscillator_frequency = 16E6, | 75 | .oscillator_frequency = 16E6, |
76 | .board_specific_setup = NULL, | ||
77 | .power_enable = NULL, | ||
78 | .transceiver_enable = NULL | ||
79 | }; | 76 | }; |
80 | 77 | ||
81 | static struct spi_board_info mcp251x_board_info[] = { | 78 | static struct spi_board_info mcp251x_board_info[] = { |
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c index f5d436434566..04a0aea23873 100644 --- a/arch/arm/mach-pxa/zeus.c +++ b/arch/arm/mach-pxa/zeus.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/i2c/pca953x.h> | 29 | #include <linux/i2c/pca953x.h> |
30 | #include <linux/apm-emulation.h> | 30 | #include <linux/apm-emulation.h> |
31 | #include <linux/can/platform/mcp251x.h> | 31 | #include <linux/can/platform/mcp251x.h> |
32 | #include <linux/regulator/fixed.h> | ||
33 | #include <linux/regulator/machine.h> | ||
32 | 34 | ||
33 | #include <asm/mach-types.h> | 35 | #include <asm/mach-types.h> |
34 | #include <asm/suspend.h> | 36 | #include <asm/suspend.h> |
@@ -391,33 +393,34 @@ static struct pxa2xx_spi_master pxa2xx_spi_ssp3_master_info = { | |||
391 | }; | 393 | }; |
392 | 394 | ||
393 | /* CAN bus on SPI */ | 395 | /* CAN bus on SPI */ |
394 | static int zeus_mcp2515_setup(struct spi_device *sdev) | 396 | static struct regulator_consumer_supply can_regulator_consumer = |
395 | { | 397 | REGULATOR_SUPPLY("vdd", "spi3.0"); |
396 | int err; | ||
397 | |||
398 | err = gpio_request(ZEUS_CAN_SHDN_GPIO, "CAN shutdown"); | ||
399 | if (err) | ||
400 | return err; | ||
401 | 398 | ||
402 | err = gpio_direction_output(ZEUS_CAN_SHDN_GPIO, 1); | 399 | static struct regulator_init_data can_regulator_init_data = { |
403 | if (err) { | 400 | .constraints = { |
404 | gpio_free(ZEUS_CAN_SHDN_GPIO); | 401 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
405 | return err; | 402 | }, |
406 | } | 403 | .consumer_supplies = &can_regulator_consumer, |
404 | .num_consumer_supplies = 1, | ||
405 | }; | ||
407 | 406 | ||
408 | return 0; | 407 | static struct fixed_voltage_config can_regulator_pdata = { |
409 | } | 408 | .supply_name = "CAN_SHDN", |
409 | .microvolts = 3300000, | ||
410 | .gpio = ZEUS_CAN_SHDN_GPIO, | ||
411 | .init_data = &can_regulator_init_data, | ||
412 | }; | ||
410 | 413 | ||
411 | static int zeus_mcp2515_transceiver_enable(int enable) | 414 | static struct platform_device can_regulator_device = { |
412 | { | 415 | .name = "reg-fixed-volage", |
413 | gpio_set_value(ZEUS_CAN_SHDN_GPIO, !enable); | 416 | .id = -1, |
414 | return 0; | 417 | .dev = { |
415 | } | 418 | .platform_data = &can_regulator_pdata, |
419 | }, | ||
420 | }; | ||
416 | 421 | ||
417 | static struct mcp251x_platform_data zeus_mcp2515_pdata = { | 422 | static struct mcp251x_platform_data zeus_mcp2515_pdata = { |
418 | .oscillator_frequency = 16*1000*1000, | 423 | .oscillator_frequency = 16*1000*1000, |
419 | .board_specific_setup = zeus_mcp2515_setup, | ||
420 | .power_enable = zeus_mcp2515_transceiver_enable, | ||
421 | }; | 424 | }; |
422 | 425 | ||
423 | static struct spi_board_info zeus_spi_board_info[] = { | 426 | static struct spi_board_info zeus_spi_board_info[] = { |
@@ -516,6 +519,7 @@ static struct platform_device *zeus_devices[] __initdata = { | |||
516 | &zeus_leds_device, | 519 | &zeus_leds_device, |
517 | &zeus_pcmcia_device, | 520 | &zeus_pcmcia_device, |
518 | &zeus_max6369_device, | 521 | &zeus_max6369_device, |
522 | &can_regulator_device, | ||
519 | }; | 523 | }; |
520 | 524 | ||
521 | /* AC'97 */ | 525 | /* AC'97 */ |
diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 8cda23bf0614..d2c54888b211 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c | |||
@@ -37,9 +37,6 @@ | |||
37 | * | 37 | * |
38 | * static struct mcp251x_platform_data mcp251x_info = { | 38 | * static struct mcp251x_platform_data mcp251x_info = { |
39 | * .oscillator_frequency = 8000000, | 39 | * .oscillator_frequency = 8000000, |
40 | * .board_specific_setup = &mcp251x_setup, | ||
41 | * .power_enable = mcp251x_power_enable, | ||
42 | * .transceiver_enable = NULL, | ||
43 | * }; | 40 | * }; |
44 | * | 41 | * |
45 | * static struct spi_board_info spi_board_info[] = { | 42 | * static struct spi_board_info spi_board_info[] = { |
@@ -76,6 +73,7 @@ | |||
76 | #include <linux/slab.h> | 73 | #include <linux/slab.h> |
77 | #include <linux/spi/spi.h> | 74 | #include <linux/spi/spi.h> |
78 | #include <linux/uaccess.h> | 75 | #include <linux/uaccess.h> |
76 | #include <linux/regulator/consumer.h> | ||
79 | 77 | ||
80 | /* SPI interface instruction set */ | 78 | /* SPI interface instruction set */ |
81 | #define INSTRUCTION_WRITE 0x02 | 79 | #define INSTRUCTION_WRITE 0x02 |
@@ -264,6 +262,8 @@ struct mcp251x_priv { | |||
264 | #define AFTER_SUSPEND_POWER 4 | 262 | #define AFTER_SUSPEND_POWER 4 |
265 | #define AFTER_SUSPEND_RESTART 8 | 263 | #define AFTER_SUSPEND_RESTART 8 |
266 | int restart_tx; | 264 | int restart_tx; |
265 | struct regulator *power; | ||
266 | struct regulator *transceiver; | ||
267 | }; | 267 | }; |
268 | 268 | ||
269 | #define MCP251X_IS(_model) \ | 269 | #define MCP251X_IS(_model) \ |
@@ -667,16 +667,25 @@ static int mcp251x_hw_probe(struct spi_device *spi) | |||
667 | return (st1 == 0x80 && st2 == 0x07) ? 1 : 0; | 667 | return (st1 == 0x80 && st2 == 0x07) ? 1 : 0; |
668 | } | 668 | } |
669 | 669 | ||
670 | static int mcp251x_power_enable(struct regulator *reg, int enable) | ||
671 | { | ||
672 | if (IS_ERR(reg)) | ||
673 | return 0; | ||
674 | |||
675 | if (enable) | ||
676 | return regulator_enable(reg); | ||
677 | else | ||
678 | return regulator_disable(reg); | ||
679 | } | ||
680 | |||
670 | static void mcp251x_open_clean(struct net_device *net) | 681 | static void mcp251x_open_clean(struct net_device *net) |
671 | { | 682 | { |
672 | struct mcp251x_priv *priv = netdev_priv(net); | 683 | struct mcp251x_priv *priv = netdev_priv(net); |
673 | struct spi_device *spi = priv->spi; | 684 | struct spi_device *spi = priv->spi; |
674 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | ||
675 | 685 | ||
676 | free_irq(spi->irq, priv); | 686 | free_irq(spi->irq, priv); |
677 | mcp251x_hw_sleep(spi); | 687 | mcp251x_hw_sleep(spi); |
678 | if (pdata->transceiver_enable) | 688 | mcp251x_power_enable(priv->transceiver, 0); |
679 | pdata->transceiver_enable(0); | ||
680 | close_candev(net); | 689 | close_candev(net); |
681 | } | 690 | } |
682 | 691 | ||
@@ -684,7 +693,6 @@ static int mcp251x_stop(struct net_device *net) | |||
684 | { | 693 | { |
685 | struct mcp251x_priv *priv = netdev_priv(net); | 694 | struct mcp251x_priv *priv = netdev_priv(net); |
686 | struct spi_device *spi = priv->spi; | 695 | struct spi_device *spi = priv->spi; |
687 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | ||
688 | 696 | ||
689 | close_candev(net); | 697 | close_candev(net); |
690 | 698 | ||
@@ -704,8 +712,7 @@ static int mcp251x_stop(struct net_device *net) | |||
704 | 712 | ||
705 | mcp251x_hw_sleep(spi); | 713 | mcp251x_hw_sleep(spi); |
706 | 714 | ||
707 | if (pdata->transceiver_enable) | 715 | mcp251x_power_enable(priv->transceiver, 0); |
708 | pdata->transceiver_enable(0); | ||
709 | 716 | ||
710 | priv->can.state = CAN_STATE_STOPPED; | 717 | priv->can.state = CAN_STATE_STOPPED; |
711 | 718 | ||
@@ -939,8 +946,7 @@ static int mcp251x_open(struct net_device *net) | |||
939 | } | 946 | } |
940 | 947 | ||
941 | mutex_lock(&priv->mcp_lock); | 948 | mutex_lock(&priv->mcp_lock); |
942 | if (pdata->transceiver_enable) | 949 | mcp251x_power_enable(priv->transceiver, 1); |
943 | pdata->transceiver_enable(1); | ||
944 | 950 | ||
945 | priv->force_quit = 0; | 951 | priv->force_quit = 0; |
946 | priv->tx_skb = NULL; | 952 | priv->tx_skb = NULL; |
@@ -956,8 +962,7 @@ static int mcp251x_open(struct net_device *net) | |||
956 | flags, DEVICE_NAME, priv); | 962 | flags, DEVICE_NAME, priv); |
957 | if (ret) { | 963 | if (ret) { |
958 | dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq); | 964 | dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq); |
959 | if (pdata->transceiver_enable) | 965 | mcp251x_power_enable(priv->transceiver, 0); |
960 | pdata->transceiver_enable(0); | ||
961 | close_candev(net); | 966 | close_candev(net); |
962 | goto open_unlock; | 967 | goto open_unlock; |
963 | } | 968 | } |
@@ -1026,6 +1031,19 @@ static int mcp251x_can_probe(struct spi_device *spi) | |||
1026 | CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; | 1031 | CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; |
1027 | priv->model = spi_get_device_id(spi)->driver_data; | 1032 | priv->model = spi_get_device_id(spi)->driver_data; |
1028 | priv->net = net; | 1033 | priv->net = net; |
1034 | |||
1035 | priv->power = devm_regulator_get(&spi->dev, "vdd"); | ||
1036 | priv->transceiver = devm_regulator_get(&spi->dev, "xceiver"); | ||
1037 | if ((PTR_ERR(priv->power) == -EPROBE_DEFER) || | ||
1038 | (PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) { | ||
1039 | ret = -EPROBE_DEFER; | ||
1040 | goto error_power; | ||
1041 | } | ||
1042 | |||
1043 | ret = mcp251x_power_enable(priv->power, 1); | ||
1044 | if (ret) | ||
1045 | goto error_power; | ||
1046 | |||
1029 | spi_set_drvdata(spi, priv); | 1047 | spi_set_drvdata(spi, priv); |
1030 | 1048 | ||
1031 | priv->spi = spi; | 1049 | priv->spi = spi; |
@@ -1068,13 +1086,6 @@ static int mcp251x_can_probe(struct spi_device *spi) | |||
1068 | } | 1086 | } |
1069 | } | 1087 | } |
1070 | 1088 | ||
1071 | if (pdata->power_enable) | ||
1072 | pdata->power_enable(1); | ||
1073 | |||
1074 | /* Call out to platform specific setup */ | ||
1075 | if (pdata->board_specific_setup) | ||
1076 | pdata->board_specific_setup(spi); | ||
1077 | |||
1078 | SET_NETDEV_DEV(net, &spi->dev); | 1089 | SET_NETDEV_DEV(net, &spi->dev); |
1079 | 1090 | ||
1080 | /* Configure the SPI bus */ | 1091 | /* Configure the SPI bus */ |
@@ -1084,14 +1095,11 @@ static int mcp251x_can_probe(struct spi_device *spi) | |||
1084 | 1095 | ||
1085 | /* Here is OK to not lock the MCP, no one knows about it yet */ | 1096 | /* Here is OK to not lock the MCP, no one knows about it yet */ |
1086 | if (!mcp251x_hw_probe(spi)) { | 1097 | if (!mcp251x_hw_probe(spi)) { |
1087 | dev_info(&spi->dev, "Probe failed\n"); | 1098 | ret = -ENODEV; |
1088 | goto error_probe; | 1099 | goto error_probe; |
1089 | } | 1100 | } |
1090 | mcp251x_hw_sleep(spi); | 1101 | mcp251x_hw_sleep(spi); |
1091 | 1102 | ||
1092 | if (pdata->transceiver_enable) | ||
1093 | pdata->transceiver_enable(0); | ||
1094 | |||
1095 | ret = register_candev(net); | 1103 | ret = register_candev(net); |
1096 | if (ret) | 1104 | if (ret) |
1097 | goto error_probe; | 1105 | goto error_probe; |
@@ -1109,13 +1117,13 @@ error_rx_buf: | |||
1109 | if (!mcp251x_enable_dma) | 1117 | if (!mcp251x_enable_dma) |
1110 | kfree(priv->spi_tx_buf); | 1118 | kfree(priv->spi_tx_buf); |
1111 | error_tx_buf: | 1119 | error_tx_buf: |
1112 | free_candev(net); | ||
1113 | if (mcp251x_enable_dma) | 1120 | if (mcp251x_enable_dma) |
1114 | dma_free_coherent(&spi->dev, PAGE_SIZE, | 1121 | dma_free_coherent(&spi->dev, PAGE_SIZE, |
1115 | priv->spi_tx_buf, priv->spi_tx_dma); | 1122 | priv->spi_tx_buf, priv->spi_tx_dma); |
1123 | mcp251x_power_enable(priv->power, 0); | ||
1124 | error_power: | ||
1125 | free_candev(net); | ||
1116 | error_alloc: | 1126 | error_alloc: |
1117 | if (pdata->power_enable) | ||
1118 | pdata->power_enable(0); | ||
1119 | dev_err(&spi->dev, "probe failed\n"); | 1127 | dev_err(&spi->dev, "probe failed\n"); |
1120 | error_out: | 1128 | error_out: |
1121 | return ret; | 1129 | return ret; |
@@ -1123,12 +1131,10 @@ error_out: | |||
1123 | 1131 | ||
1124 | static int mcp251x_can_remove(struct spi_device *spi) | 1132 | static int mcp251x_can_remove(struct spi_device *spi) |
1125 | { | 1133 | { |
1126 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | ||
1127 | struct mcp251x_priv *priv = spi_get_drvdata(spi); | 1134 | struct mcp251x_priv *priv = spi_get_drvdata(spi); |
1128 | struct net_device *net = priv->net; | 1135 | struct net_device *net = priv->net; |
1129 | 1136 | ||
1130 | unregister_candev(net); | 1137 | unregister_candev(net); |
1131 | free_candev(net); | ||
1132 | 1138 | ||
1133 | if (mcp251x_enable_dma) { | 1139 | if (mcp251x_enable_dma) { |
1134 | dma_free_coherent(&spi->dev, PAGE_SIZE, | 1140 | dma_free_coherent(&spi->dev, PAGE_SIZE, |
@@ -1138,8 +1144,9 @@ static int mcp251x_can_remove(struct spi_device *spi) | |||
1138 | kfree(priv->spi_rx_buf); | 1144 | kfree(priv->spi_rx_buf); |
1139 | } | 1145 | } |
1140 | 1146 | ||
1141 | if (pdata->power_enable) | 1147 | mcp251x_power_enable(priv->power, 0); |
1142 | pdata->power_enable(0); | 1148 | |
1149 | free_candev(net); | ||
1143 | 1150 | ||
1144 | return 0; | 1151 | return 0; |
1145 | } | 1152 | } |
@@ -1149,7 +1156,6 @@ static int mcp251x_can_remove(struct spi_device *spi) | |||
1149 | static int mcp251x_can_suspend(struct device *dev) | 1156 | static int mcp251x_can_suspend(struct device *dev) |
1150 | { | 1157 | { |
1151 | struct spi_device *spi = to_spi_device(dev); | 1158 | struct spi_device *spi = to_spi_device(dev); |
1152 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | ||
1153 | struct mcp251x_priv *priv = spi_get_drvdata(spi); | 1159 | struct mcp251x_priv *priv = spi_get_drvdata(spi); |
1154 | struct net_device *net = priv->net; | 1160 | struct net_device *net = priv->net; |
1155 | 1161 | ||
@@ -1163,15 +1169,14 @@ static int mcp251x_can_suspend(struct device *dev) | |||
1163 | netif_device_detach(net); | 1169 | netif_device_detach(net); |
1164 | 1170 | ||
1165 | mcp251x_hw_sleep(spi); | 1171 | mcp251x_hw_sleep(spi); |
1166 | if (pdata->transceiver_enable) | 1172 | mcp251x_power_enable(priv->transceiver, 0); |
1167 | pdata->transceiver_enable(0); | ||
1168 | priv->after_suspend = AFTER_SUSPEND_UP; | 1173 | priv->after_suspend = AFTER_SUSPEND_UP; |
1169 | } else { | 1174 | } else { |
1170 | priv->after_suspend = AFTER_SUSPEND_DOWN; | 1175 | priv->after_suspend = AFTER_SUSPEND_DOWN; |
1171 | } | 1176 | } |
1172 | 1177 | ||
1173 | if (pdata->power_enable) { | 1178 | if (!IS_ERR(priv->power)) { |
1174 | pdata->power_enable(0); | 1179 | regulator_disable(priv->power); |
1175 | priv->after_suspend |= AFTER_SUSPEND_POWER; | 1180 | priv->after_suspend |= AFTER_SUSPEND_POWER; |
1176 | } | 1181 | } |
1177 | 1182 | ||
@@ -1181,16 +1186,14 @@ static int mcp251x_can_suspend(struct device *dev) | |||
1181 | static int mcp251x_can_resume(struct device *dev) | 1186 | static int mcp251x_can_resume(struct device *dev) |
1182 | { | 1187 | { |
1183 | struct spi_device *spi = to_spi_device(dev); | 1188 | struct spi_device *spi = to_spi_device(dev); |
1184 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | ||
1185 | struct mcp251x_priv *priv = spi_get_drvdata(spi); | 1189 | struct mcp251x_priv *priv = spi_get_drvdata(spi); |
1186 | 1190 | ||
1187 | if (priv->after_suspend & AFTER_SUSPEND_POWER) { | 1191 | if (priv->after_suspend & AFTER_SUSPEND_POWER) { |
1188 | pdata->power_enable(1); | 1192 | mcp251x_power_enable(priv->power, 1); |
1189 | queue_work(priv->wq, &priv->restart_work); | 1193 | queue_work(priv->wq, &priv->restart_work); |
1190 | } else { | 1194 | } else { |
1191 | if (priv->after_suspend & AFTER_SUSPEND_UP) { | 1195 | if (priv->after_suspend & AFTER_SUSPEND_UP) { |
1192 | if (pdata->transceiver_enable) | 1196 | mcp251x_power_enable(priv->transceiver, 1); |
1193 | pdata->transceiver_enable(1); | ||
1194 | queue_work(priv->wq, &priv->restart_work); | 1197 | queue_work(priv->wq, &priv->restart_work); |
1195 | } else { | 1198 | } else { |
1196 | priv->after_suspend = 0; | 1199 | priv->after_suspend = 0; |
diff --git a/include/linux/can/platform/mcp251x.h b/include/linux/can/platform/mcp251x.h index 089fe43211a4..8a2725676d8b 100644 --- a/include/linux/can/platform/mcp251x.h +++ b/include/linux/can/platform/mcp251x.h | |||
@@ -9,26 +9,15 @@ | |||
9 | 9 | ||
10 | #include <linux/spi/spi.h> | 10 | #include <linux/spi/spi.h> |
11 | 11 | ||
12 | /** | 12 | /* |
13 | * struct mcp251x_platform_data - MCP251X SPI CAN controller platform data | 13 | * struct mcp251x_platform_data - MCP251X SPI CAN controller platform data |
14 | * @oscillator_frequency: - oscillator frequency in Hz | 14 | * @oscillator_frequency: - oscillator frequency in Hz |
15 | * @irq_flags: - IRQF configuration flags | 15 | * @irq_flags: - IRQF configuration flags |
16 | * @board_specific_setup: - called before probing the chip (power,reset) | ||
17 | * @transceiver_enable: - called to power on/off the transceiver | ||
18 | * @power_enable: - called to power on/off the mcp *and* the | ||
19 | * transceiver | ||
20 | * | ||
21 | * Please note that you should define power_enable or transceiver_enable or | ||
22 | * none of them. Defining both of them is no use. | ||
23 | * | ||
24 | */ | 16 | */ |
25 | 17 | ||
26 | struct mcp251x_platform_data { | 18 | struct mcp251x_platform_data { |
27 | unsigned long oscillator_frequency; | 19 | unsigned long oscillator_frequency; |
28 | unsigned long irq_flags; | 20 | unsigned long irq_flags; |
29 | int (*board_specific_setup)(struct spi_device *spi); | ||
30 | int (*transceiver_enable)(int enable); | ||
31 | int (*power_enable) (int enable); | ||
32 | }; | 21 | }; |
33 | 22 | ||
34 | #endif /* __CAN_PLATFORM_MCP251X_H__ */ | 23 | #endif /* __CAN_PLATFORM_MCP251X_H__ */ |