aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can
diff options
context:
space:
mode:
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 16e45a51cbb3..2532b9631538 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