diff options
author | Alexander Shiyan <shc_work@mail.ru> | 2013-12-21 00:01:41 -0500 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2013-12-21 09:04:24 -0500 |
commit | 66606aafd8cd6cffbefa463b27e1f16e793e40a9 (patch) | |
tree | d4b9c8e4d0fdfe8fb99306a73747d287f0e34985 /drivers/net/can | |
parent | c0ebbdd6b57949775d428f00b8696a4078f86ac4 (diff) |
can: mcp251x: Add device tree support
This patch adds Device Tree support to the Microchip MCP251X driver.
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can')
-rw-r--r-- | drivers/net/can/mcp251x.c | 99 |
1 files changed, 74 insertions, 25 deletions
diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 88d3877b6277..cdb9808d12db 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <linux/can/dev.h> | 58 | #include <linux/can/dev.h> |
59 | #include <linux/can/led.h> | 59 | #include <linux/can/led.h> |
60 | #include <linux/can/platform/mcp251x.h> | 60 | #include <linux/can/platform/mcp251x.h> |
61 | #include <linux/clk.h> | ||
61 | #include <linux/completion.h> | 62 | #include <linux/completion.h> |
62 | #include <linux/delay.h> | 63 | #include <linux/delay.h> |
63 | #include <linux/device.h> | 64 | #include <linux/device.h> |
@@ -68,6 +69,8 @@ | |||
68 | #include <linux/kernel.h> | 69 | #include <linux/kernel.h> |
69 | #include <linux/module.h> | 70 | #include <linux/module.h> |
70 | #include <linux/netdevice.h> | 71 | #include <linux/netdevice.h> |
72 | #include <linux/of.h> | ||
73 | #include <linux/of_device.h> | ||
71 | #include <linux/platform_device.h> | 74 | #include <linux/platform_device.h> |
72 | #include <linux/slab.h> | 75 | #include <linux/slab.h> |
73 | #include <linux/spi/spi.h> | 76 | #include <linux/spi/spi.h> |
@@ -263,6 +266,7 @@ struct mcp251x_priv { | |||
263 | int restart_tx; | 266 | int restart_tx; |
264 | struct regulator *power; | 267 | struct regulator *power; |
265 | struct regulator *transceiver; | 268 | struct regulator *transceiver; |
269 | struct clk *clk; | ||
266 | }; | 270 | }; |
267 | 271 | ||
268 | #define MCP251X_IS(_model) \ | 272 | #define MCP251X_IS(_model) \ |
@@ -994,22 +998,65 @@ static const struct net_device_ops mcp251x_netdev_ops = { | |||
994 | .ndo_start_xmit = mcp251x_hard_start_xmit, | 998 | .ndo_start_xmit = mcp251x_hard_start_xmit, |
995 | }; | 999 | }; |
996 | 1000 | ||
1001 | static const struct of_device_id mcp251x_of_match[] = { | ||
1002 | { | ||
1003 | .compatible = "microchip,mcp2510", | ||
1004 | .data = (void *)CAN_MCP251X_MCP2510, | ||
1005 | }, | ||
1006 | { | ||
1007 | .compatible = "microchip,mcp2515", | ||
1008 | .data = (void *)CAN_MCP251X_MCP2515, | ||
1009 | }, | ||
1010 | { } | ||
1011 | }; | ||
1012 | MODULE_DEVICE_TABLE(of, mcp251x_of_match); | ||
1013 | |||
1014 | static const struct spi_device_id mcp251x_id_table[] = { | ||
1015 | { | ||
1016 | .name = "mcp2510", | ||
1017 | .driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2510, | ||
1018 | }, | ||
1019 | { | ||
1020 | .name = "mcp2515", | ||
1021 | .driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2515, | ||
1022 | }, | ||
1023 | { } | ||
1024 | }; | ||
1025 | MODULE_DEVICE_TABLE(spi, mcp251x_id_table); | ||
1026 | |||
997 | static int mcp251x_can_probe(struct spi_device *spi) | 1027 | static int mcp251x_can_probe(struct spi_device *spi) |
998 | { | 1028 | { |
1029 | const struct of_device_id *of_id = of_match_device(mcp251x_of_match, | ||
1030 | &spi->dev); | ||
1031 | struct mcp251x_platform_data *pdata = dev_get_platdata(&spi->dev); | ||
999 | struct net_device *net; | 1032 | struct net_device *net; |
1000 | struct mcp251x_priv *priv; | 1033 | struct mcp251x_priv *priv; |
1001 | struct mcp251x_platform_data *pdata = dev_get_platdata(&spi->dev); | 1034 | int freq, ret = -ENODEV; |
1002 | int ret = -ENODEV; | 1035 | struct clk *clk; |
1036 | |||
1037 | clk = devm_clk_get(&spi->dev, NULL); | ||
1038 | if (IS_ERR(clk)) { | ||
1039 | if (pdata) | ||
1040 | freq = pdata->oscillator_frequency; | ||
1041 | else | ||
1042 | return PTR_ERR(clk); | ||
1043 | } else { | ||
1044 | freq = clk_get_rate(clk); | ||
1045 | } | ||
1003 | 1046 | ||
1004 | if (!pdata) | 1047 | /* Sanity check */ |
1005 | /* Platform data is required for osc freq */ | 1048 | if (freq < 1000000 || freq > 25000000) |
1006 | goto error_out; | 1049 | return -ERANGE; |
1007 | 1050 | ||
1008 | /* Allocate can/net device */ | 1051 | /* Allocate can/net device */ |
1009 | net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX); | 1052 | net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX); |
1010 | if (!net) { | 1053 | if (!net) |
1011 | ret = -ENOMEM; | 1054 | return -ENOMEM; |
1012 | goto error_alloc; | 1055 | |
1056 | if (!IS_ERR(clk)) { | ||
1057 | ret = clk_prepare_enable(clk); | ||
1058 | if (ret) | ||
1059 | goto out_free; | ||
1013 | } | 1060 | } |
1014 | 1061 | ||
1015 | net->netdev_ops = &mcp251x_netdev_ops; | 1062 | net->netdev_ops = &mcp251x_netdev_ops; |
@@ -1018,23 +1065,27 @@ static int mcp251x_can_probe(struct spi_device *spi) | |||
1018 | priv = netdev_priv(net); | 1065 | priv = netdev_priv(net); |
1019 | priv->can.bittiming_const = &mcp251x_bittiming_const; | 1066 | priv->can.bittiming_const = &mcp251x_bittiming_const; |
1020 | priv->can.do_set_mode = mcp251x_do_set_mode; | 1067 | priv->can.do_set_mode = mcp251x_do_set_mode; |
1021 | priv->can.clock.freq = pdata->oscillator_frequency / 2; | 1068 | priv->can.clock.freq = freq / 2; |
1022 | priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | | 1069 | priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | |
1023 | CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; | 1070 | CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; |
1024 | priv->model = spi_get_device_id(spi)->driver_data; | 1071 | if (of_id) |
1072 | priv->model = (enum mcp251x_model)of_id->data; | ||
1073 | else | ||
1074 | priv->model = spi_get_device_id(spi)->driver_data; | ||
1025 | priv->net = net; | 1075 | priv->net = net; |
1076 | priv->clk = clk; | ||
1026 | 1077 | ||
1027 | priv->power = devm_regulator_get(&spi->dev, "vdd"); | 1078 | priv->power = devm_regulator_get(&spi->dev, "vdd"); |
1028 | priv->transceiver = devm_regulator_get(&spi->dev, "xceiver"); | 1079 | priv->transceiver = devm_regulator_get(&spi->dev, "xceiver"); |
1029 | if ((PTR_ERR(priv->power) == -EPROBE_DEFER) || | 1080 | if ((PTR_ERR(priv->power) == -EPROBE_DEFER) || |
1030 | (PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) { | 1081 | (PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) { |
1031 | ret = -EPROBE_DEFER; | 1082 | ret = -EPROBE_DEFER; |
1032 | goto error_power; | 1083 | goto out_clk; |
1033 | } | 1084 | } |
1034 | 1085 | ||
1035 | ret = mcp251x_power_enable(priv->power, 1); | 1086 | ret = mcp251x_power_enable(priv->power, 1); |
1036 | if (ret) | 1087 | if (ret) |
1037 | goto error_power; | 1088 | goto out_clk; |
1038 | 1089 | ||
1039 | spi_set_drvdata(spi, priv); | 1090 | spi_set_drvdata(spi, priv); |
1040 | 1091 | ||
@@ -1113,11 +1164,14 @@ error_probe: | |||
1113 | dma_free_coherent(&spi->dev, PAGE_SIZE, | 1164 | dma_free_coherent(&spi->dev, PAGE_SIZE, |
1114 | priv->spi_tx_buf, priv->spi_tx_dma); | 1165 | priv->spi_tx_buf, priv->spi_tx_dma); |
1115 | mcp251x_power_enable(priv->power, 0); | 1166 | mcp251x_power_enable(priv->power, 0); |
1116 | error_power: | 1167 | |
1168 | out_clk: | ||
1169 | if (!IS_ERR(clk)) | ||
1170 | clk_disable_unprepare(clk); | ||
1171 | |||
1172 | out_free: | ||
1117 | free_candev(net); | 1173 | free_candev(net); |
1118 | error_alloc: | 1174 | |
1119 | dev_err(&spi->dev, "probe failed\n"); | ||
1120 | error_out: | ||
1121 | return ret; | 1175 | return ret; |
1122 | } | 1176 | } |
1123 | 1177 | ||
@@ -1135,6 +1189,9 @@ static int mcp251x_can_remove(struct spi_device *spi) | |||
1135 | 1189 | ||
1136 | mcp251x_power_enable(priv->power, 0); | 1190 | mcp251x_power_enable(priv->power, 0); |
1137 | 1191 | ||
1192 | if (!IS_ERR(priv->clk)) | ||
1193 | clk_disable_unprepare(priv->clk); | ||
1194 | |||
1138 | free_candev(net); | 1195 | free_candev(net); |
1139 | 1196 | ||
1140 | return 0; | 1197 | return 0; |
@@ -1197,21 +1254,13 @@ static int mcp251x_can_resume(struct device *dev) | |||
1197 | static SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend, | 1254 | static SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend, |
1198 | mcp251x_can_resume); | 1255 | mcp251x_can_resume); |
1199 | 1256 | ||
1200 | static const struct spi_device_id mcp251x_id_table[] = { | ||
1201 | { "mcp2510", CAN_MCP251X_MCP2510 }, | ||
1202 | { "mcp2515", CAN_MCP251X_MCP2515 }, | ||
1203 | { }, | ||
1204 | }; | ||
1205 | |||
1206 | MODULE_DEVICE_TABLE(spi, mcp251x_id_table); | ||
1207 | |||
1208 | static struct spi_driver mcp251x_can_driver = { | 1257 | static struct spi_driver mcp251x_can_driver = { |
1209 | .driver = { | 1258 | .driver = { |
1210 | .name = DEVICE_NAME, | 1259 | .name = DEVICE_NAME, |
1211 | .owner = THIS_MODULE, | 1260 | .owner = THIS_MODULE, |
1261 | .of_match_table = mcp251x_of_match, | ||
1212 | .pm = &mcp251x_can_pm_ops, | 1262 | .pm = &mcp251x_can_pm_ops, |
1213 | }, | 1263 | }, |
1214 | |||
1215 | .id_table = mcp251x_id_table, | 1264 | .id_table = mcp251x_id_table, |
1216 | .probe = mcp251x_can_probe, | 1265 | .probe = mcp251x_can_probe, |
1217 | .remove = mcp251x_can_remove, | 1266 | .remove = mcp251x_can_remove, |