aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can/flexcan.c
diff options
context:
space:
mode:
authorHui Wang <jason77.wang@gmail.com>2012-06-28 04:21:35 -0400
committerMarc Kleine-Budde <mkl@pengutronix.de>2012-07-03 03:33:00 -0400
commit30c1e672044d98e5c4cff5fcbdb34b55a2df0c0f (patch)
tree6b12a4975cb050ecc7eda4273a26d58ee92cb5bd /drivers/net/can/flexcan.c
parentafc016d8360ceb19a1f37bf6579d5850d47d582d (diff)
can: flexcan: add hardware controller version support
At least in the i.MX series, the flexcan contrller divides into ver_3 and ver_10, current driver is for ver_3 controller. i.MX6 has ver_10 controller, it has more reigsters than ver_3 has. The rxfgmask (Rx FIFO Global Mask) register is one of the new added. Its reset value is 0xffffffff, this means ID Filter Table must be checked when receive a packet, but the driver is designed to accept everything during the chip start, we need to clear this register to follow this design. Use the data entry of the struct of_device_id to point chip specific info, we can set hardware version for each platform. Cc: linux-can@vger.kernel.org Cc: Marc Kleine-Budde <mkl@pengutronix.de> Cc: Wolfgang Grandegger <wg@grandegger.com> Cc: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Hui Wang <jason77.wang@gmail.com> [mkl: add id_table support] Tested-by: Hui Wang <jason77.wang@gmail.com> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can/flexcan.c')
-rw-r--r--drivers/net/can/flexcan.c60
1 files changed, 52 insertions, 8 deletions
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index b429b3f3fa7f..81324a11a50f 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -34,6 +34,7 @@
34#include <linux/list.h> 34#include <linux/list.h>
35#include <linux/module.h> 35#include <linux/module.h>
36#include <linux/of.h> 36#include <linux/of.h>
37#include <linux/of_device.h>
37#include <linux/platform_device.h> 38#include <linux/platform_device.h>
38#include <linux/pinctrl/consumer.h> 39#include <linux/pinctrl/consumer.h>
39 40
@@ -165,10 +166,21 @@ struct flexcan_regs {
165 u32 imask1; /* 0x28 */ 166 u32 imask1; /* 0x28 */
166 u32 iflag2; /* 0x2c */ 167 u32 iflag2; /* 0x2c */
167 u32 iflag1; /* 0x30 */ 168 u32 iflag1; /* 0x30 */
168 u32 _reserved2[19]; 169 u32 crl2; /* 0x34 */
170 u32 esr2; /* 0x38 */
171 u32 imeur; /* 0x3c */
172 u32 lrfr; /* 0x40 */
173 u32 crcr; /* 0x44 */
174 u32 rxfgmask; /* 0x48 */
175 u32 rxfir; /* 0x4c */
176 u32 _reserved3[12];
169 struct flexcan_mb cantxfg[64]; 177 struct flexcan_mb cantxfg[64];
170}; 178};
171 179
180struct flexcan_devtype_data {
181 u32 hw_ver; /* hardware controller version */
182};
183
172struct flexcan_priv { 184struct flexcan_priv {
173 struct can_priv can; 185 struct can_priv can;
174 struct net_device *dev; 186 struct net_device *dev;
@@ -180,6 +192,15 @@ struct flexcan_priv {
180 192
181 struct clk *clk; 193 struct clk *clk;
182 struct flexcan_platform_data *pdata; 194 struct flexcan_platform_data *pdata;
195 struct flexcan_devtype_data *devtype_data;
196};
197
198static struct flexcan_devtype_data fsl_p1010_devtype_data = {
199 .hw_ver = 3,
200};
201
202static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
203 .hw_ver = 10,
183}; 204};
184 205
185static struct can_bittiming_const flexcan_bittiming_const = { 206static struct can_bittiming_const flexcan_bittiming_const = {
@@ -750,6 +771,9 @@ static int flexcan_chip_start(struct net_device *dev)
750 flexcan_write(0x0, &regs->rx14mask); 771 flexcan_write(0x0, &regs->rx14mask);
751 flexcan_write(0x0, &regs->rx15mask); 772 flexcan_write(0x0, &regs->rx15mask);
752 773
774 if (priv->devtype_data->hw_ver >= 10)
775 flexcan_write(0x0, &regs->rxfgmask);
776
753 flexcan_transceiver_switch(priv, 1); 777 flexcan_transceiver_switch(priv, 1);
754 778
755 /* synchronize with the can bus */ 779 /* synchronize with the can bus */
@@ -922,8 +946,21 @@ static void __devexit unregister_flexcandev(struct net_device *dev)
922 unregister_candev(dev); 946 unregister_candev(dev);
923} 947}
924 948
949static const struct of_device_id flexcan_of_match[] = {
950 { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, },
951 { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
952 { /* sentinel */ },
953};
954
955static const struct platform_device_id flexcan_id_table[] = {
956 { .name = "flexcan", .driver_data = (kernel_ulong_t)&fsl_p1010_devtype_data, },
957 { /* sentinel */ },
958};
959
925static int __devinit flexcan_probe(struct platform_device *pdev) 960static int __devinit flexcan_probe(struct platform_device *pdev)
926{ 961{
962 const struct of_device_id *of_id;
963 struct flexcan_devtype_data *devtype_data;
927 struct net_device *dev; 964 struct net_device *dev;
928 struct flexcan_priv *priv; 965 struct flexcan_priv *priv;
929 struct resource *mem; 966 struct resource *mem;
@@ -977,6 +1014,17 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
977 goto failed_alloc; 1014 goto failed_alloc;
978 } 1015 }
979 1016
1017 of_id = of_match_device(flexcan_of_match, &pdev->dev);
1018 if (of_id) {
1019 devtype_data = of_id->data;
1020 } else if (pdev->id_entry->driver_data) {
1021 devtype_data = (struct flexcan_devtype_data *)
1022 pdev->id_entry->driver_data;
1023 } else {
1024 err = -ENODEV;
1025 goto failed_devtype;
1026 }
1027
980 dev->netdev_ops = &flexcan_netdev_ops; 1028 dev->netdev_ops = &flexcan_netdev_ops;
981 dev->irq = irq; 1029 dev->irq = irq;
982 dev->flags |= IFF_ECHO; 1030 dev->flags |= IFF_ECHO;
@@ -993,6 +1041,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
993 priv->dev = dev; 1041 priv->dev = dev;
994 priv->clk = clk; 1042 priv->clk = clk;
995 priv->pdata = pdev->dev.platform_data; 1043 priv->pdata = pdev->dev.platform_data;
1044 priv->devtype_data = devtype_data;
996 1045
997 netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT); 1046 netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT);
998 1047
@@ -1011,6 +1060,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
1011 return 0; 1060 return 0;
1012 1061
1013 failed_register: 1062 failed_register:
1063 failed_devtype:
1014 free_candev(dev); 1064 free_candev(dev);
1015 failed_alloc: 1065 failed_alloc:
1016 iounmap(base); 1066 iounmap(base);
@@ -1044,13 +1094,6 @@ static int __devexit flexcan_remove(struct platform_device *pdev)
1044 return 0; 1094 return 0;
1045} 1095}
1046 1096
1047static struct of_device_id flexcan_of_match[] = {
1048 {
1049 .compatible = "fsl,p1010-flexcan",
1050 },
1051 {},
1052};
1053
1054#ifdef CONFIG_PM 1097#ifdef CONFIG_PM
1055static int flexcan_suspend(struct platform_device *pdev, pm_message_t state) 1098static int flexcan_suspend(struct platform_device *pdev, pm_message_t state)
1056{ 1099{
@@ -1097,6 +1140,7 @@ static struct platform_driver flexcan_driver = {
1097 .remove = __devexit_p(flexcan_remove), 1140 .remove = __devexit_p(flexcan_remove),
1098 .suspend = flexcan_suspend, 1141 .suspend = flexcan_suspend,
1099 .resume = flexcan_resume, 1142 .resume = flexcan_resume,
1143 .id_table = flexcan_id_table,
1100}; 1144};
1101 1145
1102module_platform_driver(flexcan_driver); 1146module_platform_driver(flexcan_driver);