aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can
diff options
context:
space:
mode:
authorMarc Kleine-Budde <mkl@pengutronix.de>2011-01-10 14:44:22 -0500
committerMarc Kleine-Budde <mkl@pengutronix.de>2011-01-24 08:56:37 -0500
commit3a5655a5b545e9647c3437473ee3d815fe1b9050 (patch)
tree5cadf4eaf9b3631b498a4ddfbee8c7458463b37c /drivers/net/can
parent9e0a2d1ca3de6e284e99ad5cae1ae33ecb74c479 (diff)
can: at91_can: make can_id of mailbox 0 configurable
Due to a chip bug (errata 50.2.6.3 & 50.3.5.3 in "AT91SAM9263 Preliminary 6249H-ATARM-27-Jul-09") the contents of mailbox 0 may be send under certain conditions (even if disabled or in rx mode). The workaround in the errata suggests not to use the mailbox and load it with an unused identifier. This patch implements the second part of the workaround. A sysfs entry "mb0_id" is introduced. While the interface is down it can be used to configure the can_id of mailbox 0. The default value id 0x7ff. In order to use an extended can_id add the CAN_EFF_FLAG (0x80000000U) to the can_id. Example: - standard id 0x7ff: echo 0x7ff > /sys/class/net/can0/mb0_id - extended id 0x1fffffff: echo 0x9fffffff > /sys/class/net/can0/mb0_id Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> Acked-by: Wolfgang Grandegger <wg@grandegger.com> Acked-by: Kurt Van Dijck <kurt.van.dijck@eia.be> For the Documentation-part: Acked-by: Wolfram Sang <w.sang@pengutronix.de>
Diffstat (limited to 'drivers/net/can')
-rw-r--r--drivers/net/can/at91_can.c90
1 files changed, 83 insertions, 7 deletions
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 16e45a51cbb..2532b963153 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -30,6 +30,7 @@
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/netdevice.h> 31#include <linux/netdevice.h>
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/rtnetlink.h>
33#include <linux/skbuff.h> 34#include <linux/skbuff.h>
34#include <linux/spinlock.h> 35#include <linux/spinlock.h>
35#include <linux/string.h> 36#include <linux/string.h>
@@ -169,6 +170,8 @@ struct at91_priv {
169 170
170 struct clk *clk; 171 struct clk *clk;
171 struct at91_can_data *pdata; 172 struct at91_can_data *pdata;
173
174 canid_t mb0_id;
172}; 175};
173 176
174static struct can_bittiming_const at91_bittiming_const = { 177static struct can_bittiming_const at91_bittiming_const = {
@@ -221,6 +224,18 @@ static inline void set_mb_mode(const struct at91_priv *priv, unsigned int mb,
221 set_mb_mode_prio(priv, mb, mode, 0); 224 set_mb_mode_prio(priv, mb, mode, 0);
222} 225}
223 226
227static inline u32 at91_can_id_to_reg_mid(canid_t can_id)
228{
229 u32 reg_mid;
230
231 if (can_id & CAN_EFF_FLAG)
232 reg_mid = (can_id & CAN_EFF_MASK) | AT91_MID_MIDE;
233 else
234 reg_mid = (can_id & CAN_SFF_MASK) << 18;
235
236 return reg_mid;
237}
238
224/* 239/*
225 * Swtich transceiver on or off 240 * Swtich transceiver on or off
226 */ 241 */
@@ -234,6 +249,7 @@ static void at91_setup_mailboxes(struct net_device *dev)
234{ 249{
235 struct at91_priv *priv = netdev_priv(dev); 250 struct at91_priv *priv = netdev_priv(dev);
236 unsigned int i; 251 unsigned int i;
252 u32 reg_mid;
237 253
238 /* 254 /*
239 * Due to a chip bug (errata 50.2.6.3 & 50.3.5.3) the first 255 * Due to a chip bug (errata 50.2.6.3 & 50.3.5.3) the first
@@ -242,8 +258,13 @@ static void at91_setup_mailboxes(struct net_device *dev)
242 * overwrite option. The overwrite flag indicates a FIFO 258 * overwrite option. The overwrite flag indicates a FIFO
243 * overflow. 259 * overflow.
244 */ 260 */
245 for (i = 0; i < AT91_MB_RX_FIRST; i++) 261 reg_mid = at91_can_id_to_reg_mid(priv->mb0_id);
262 for (i = 0; i < AT91_MB_RX_FIRST; i++) {
246 set_mb_mode(priv, i, AT91_MB_MODE_DISABLED); 263 set_mb_mode(priv, i, AT91_MB_MODE_DISABLED);
264 at91_write(priv, AT91_MID(i), reg_mid);
265 at91_write(priv, AT91_MCR(i), 0x0); /* clear dlc */
266 }
267
247 for (i = AT91_MB_RX_FIRST; i < AT91_MB_RX_LAST; i++) 268 for (i = AT91_MB_RX_FIRST; i < AT91_MB_RX_LAST; i++)
248 set_mb_mode(priv, i, AT91_MB_MODE_RX); 269 set_mb_mode(priv, i, AT91_MB_MODE_RX);
249 set_mb_mode(priv, AT91_MB_RX_LAST, AT91_MB_MODE_RX_OVRWR); 270 set_mb_mode(priv, AT91_MB_RX_LAST, AT91_MB_MODE_RX_OVRWR);
@@ -378,12 +399,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
378 netdev_err(dev, "BUG! TX buffer full when queue awake!\n"); 399 netdev_err(dev, "BUG! TX buffer full when queue awake!\n");
379 return NETDEV_TX_BUSY; 400 return NETDEV_TX_BUSY;
380 } 401 }
381 402 reg_mid = at91_can_id_to_reg_mid(cf->can_id);
382 if (cf->can_id & CAN_EFF_FLAG)
383 reg_mid = (cf->can_id & CAN_EFF_MASK) | AT91_MID_MIDE;
384 else
385 reg_mid = (cf->can_id & CAN_SFF_MASK) << 18;
386
387 reg_mcr = ((cf->can_id & CAN_RTR_FLAG) ? AT91_MCR_MRTR : 0) | 403 reg_mcr = ((cf->can_id & CAN_RTR_FLAG) ? AT91_MCR_MRTR : 0) |
388 (cf->can_dlc << 16) | AT91_MCR_MTCR; 404 (cf->can_dlc << 16) | AT91_MCR_MTCR;
389 405
@@ -1047,6 +1063,64 @@ static const struct net_device_ops at91_netdev_ops = {
1047 .ndo_start_xmit = at91_start_xmit, 1063 .ndo_start_xmit = at91_start_xmit,
1048}; 1064};
1049 1065
1066static ssize_t at91_sysfs_show_mb0_id(struct device *dev,
1067 struct device_attribute *attr, char *buf)
1068{
1069 struct at91_priv *priv = netdev_priv(to_net_dev(dev));
1070
1071 if (priv->mb0_id & CAN_EFF_FLAG)
1072 return snprintf(buf, PAGE_SIZE, "0x%08x\n", priv->mb0_id);
1073 else
1074 return snprintf(buf, PAGE_SIZE, "0x%03x\n", priv->mb0_id);
1075}
1076
1077static ssize_t at91_sysfs_set_mb0_id(struct device *dev,
1078 struct device_attribute *attr, const char *buf, size_t count)
1079{
1080 struct net_device *ndev = to_net_dev(dev);
1081 struct at91_priv *priv = netdev_priv(ndev);
1082 unsigned long can_id;
1083 ssize_t ret;
1084 int err;
1085
1086 rtnl_lock();
1087
1088 if (ndev->flags & IFF_UP) {
1089 ret = -EBUSY;
1090 goto out;
1091 }
1092
1093 err = strict_strtoul(buf, 0, &can_id);
1094 if (err) {
1095 ret = err;
1096 goto out;
1097 }
1098
1099 if (can_id & CAN_EFF_FLAG)
1100 can_id &= CAN_EFF_MASK | CAN_EFF_FLAG;
1101 else
1102 can_id &= CAN_SFF_MASK;
1103
1104 priv->mb0_id = can_id;
1105 ret = count;
1106
1107 out:
1108 rtnl_unlock();
1109 return ret;
1110}
1111
1112static DEVICE_ATTR(mb0_id, S_IWUGO | S_IRUGO,
1113 at91_sysfs_show_mb0_id, at91_sysfs_set_mb0_id);
1114
1115static struct attribute *at91_sysfs_attrs[] = {
1116 &dev_attr_mb0_id.attr,
1117 NULL,
1118};
1119
1120static struct attribute_group at91_sysfs_attr_group = {
1121 .attrs = at91_sysfs_attrs,
1122};
1123
1050static int __devinit at91_can_probe(struct platform_device *pdev) 1124static int __devinit at91_can_probe(struct platform_device *pdev)
1051{ 1125{
1052 struct net_device *dev; 1126 struct net_device *dev;
@@ -1092,6 +1166,7 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
1092 dev->netdev_ops = &at91_netdev_ops; 1166 dev->netdev_ops = &at91_netdev_ops;
1093 dev->irq = irq; 1167 dev->irq = irq;
1094 dev->flags |= IFF_ECHO; 1168 dev->flags |= IFF_ECHO;
1169 dev->sysfs_groups[0] = &at91_sysfs_attr_group;
1095 1170
1096 priv = netdev_priv(dev); 1171 priv = netdev_priv(dev);
1097 priv->can.clock.freq = clk_get_rate(clk); 1172 priv->can.clock.freq = clk_get_rate(clk);
@@ -1103,6 +1178,7 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
1103 priv->dev = dev; 1178 priv->dev = dev;
1104 priv->clk = clk; 1179 priv->clk = clk;
1105 priv->pdata = pdev->dev.platform_data; 1180 priv->pdata = pdev->dev.platform_data;
1181 priv->mb0_id = 0x7ff;
1106 1182
1107 netif_napi_add(dev, &priv->napi, at91_poll, AT91_NAPI_WEIGHT); 1183 netif_napi_add(dev, &priv->napi, at91_poll, AT91_NAPI_WEIGHT);
1108 1184