aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can
diff options
context:
space:
mode:
authorWolfram Sang <w.sang@pengutronix.de>2009-11-13 01:14:52 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-13 23:47:03 -0500
commitafa17a500a3667f66df450100538d06769529bba (patch)
treed3e134c679b2ee54733eeced15a99b62548ebf93 /drivers/net/can
parent888801357f240daee5d310327867d834bc05183b (diff)
net/can: add driver for mscan family & mpc52xx_mscan
Taken from socketcan-svn, fixed remaining todos, cleaned up, tested with a phyCORE-MPC5200B-IO and a custom board. Signed-off-by: Wolfram Sang <w.sang@pengutronix.de> Cc: Wolfgang Grandegger <wg@grandegger.com> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: David Miller <davem@davemloft.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/can')
-rw-r--r--drivers/net/can/Kconfig19
-rw-r--r--drivers/net/can/Makefile1
-rw-r--r--drivers/net/can/mscan/Makefile5
-rw-r--r--drivers/net/can/mscan/mpc52xx_can.c279
-rw-r--r--drivers/net/can/mscan/mscan.c699
-rw-r--r--drivers/net/can/mscan/mscan.h262
6 files changed, 1265 insertions, 0 deletions
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index b819cc2a429e..c16e6ff139d0 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -108,6 +108,25 @@ config CAN_MCP251X
108 ---help--- 108 ---help---
109 Driver for the Microchip MCP251x SPI CAN controllers. 109 Driver for the Microchip MCP251x SPI CAN controllers.
110 110
111config CAN_MSCAN
112 depends on CAN_DEV && (PPC || M68K || M68KNOMMU)
113 tristate "Support for Freescale MSCAN based chips"
114 ---help---
115 The Motorola Scalable Controller Area Network (MSCAN) definition
116 is based on the MSCAN12 definition which is the specific
117 implementation of the Motorola Scalable CAN concept targeted for
118 the Motorola MC68HC12 Microcontroller Family.
119
120config CAN_MPC52XX
121 tristate "Freescale MPC5xxx onboard CAN controller"
122 depends on CAN_MSCAN && PPC_MPC52xx
123 ---help---
124 If you say yes here you get support for Freescale's MPC52xx
125 onboard dualCAN controller.
126
127 This driver can also be built as a module. If so, the module
128 will be called mpc5xxx_can.
129
111config CAN_DEBUG_DEVICES 130config CAN_DEBUG_DEVICES
112 bool "CAN devices debugging messages" 131 bool "CAN devices debugging messages"
113 depends on CAN 132 depends on CAN
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 14891817ea5b..56899fef1c6a 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -10,6 +10,7 @@ can-dev-y := dev.o
10obj-y += usb/ 10obj-y += usb/
11 11
12obj-$(CONFIG_CAN_SJA1000) += sja1000/ 12obj-$(CONFIG_CAN_SJA1000) += sja1000/
13obj-$(CONFIG_CAN_MSCAN) += mscan/
13obj-$(CONFIG_CAN_AT91) += at91_can.o 14obj-$(CONFIG_CAN_AT91) += at91_can.o
14obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o 15obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o
15obj-$(CONFIG_CAN_MCP251X) += mcp251x.o 16obj-$(CONFIG_CAN_MCP251X) += mcp251x.o
diff --git a/drivers/net/can/mscan/Makefile b/drivers/net/can/mscan/Makefile
new file mode 100644
index 000000000000..2bd9f04c7908
--- /dev/null
+++ b/drivers/net/can/mscan/Makefile
@@ -0,0 +1,5 @@
1
2obj-$(CONFIG_CAN_MPC52XX) += mscan-mpc52xx.o
3mscan-mpc52xx-objs := mscan.o mpc52xx_can.o
4
5ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/mscan/mpc52xx_can.c b/drivers/net/can/mscan/mpc52xx_can.c
new file mode 100644
index 000000000000..4707a82f1ae0
--- /dev/null
+++ b/drivers/net/can/mscan/mpc52xx_can.c
@@ -0,0 +1,279 @@
1/*
2 * CAN bus driver for the Freescale MPC5xxx embedded CPU.
3 *
4 * Copyright (C) 2004-2005 Andrey Volkov <avolkov@varma-el.com>,
5 * Varma Electronics Oy
6 * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
7 * Copyright (C) 2009 Wolfram Sang, Pengutronix <w.sang@pengutronix.de>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the version 2 of the GNU General Public License
11 * as published by the Free Software Foundation
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/interrupt.h>
26#include <linux/platform_device.h>
27#include <linux/netdevice.h>
28#include <linux/can.h>
29#include <linux/can/dev.h>
30#include <linux/of_platform.h>
31#include <sysdev/fsl_soc.h>
32#include <linux/io.h>
33#include <asm/mpc52xx.h>
34
35#include "mscan.h"
36
37
38#define DRV_NAME "mpc5xxx_can"
39
40static struct of_device_id mpc52xx_cdm_ids[] __devinitdata = {
41 { .compatible = "fsl,mpc5200-cdm", },
42 { .compatible = "fsl,mpc5200b-cdm", },
43 {}
44};
45
46/*
47 * Get the frequency of the external oscillator clock connected
48 * to the SYS_XTAL_IN pin, or return 0 if it cannot be determined.
49 */
50static unsigned int __devinit mpc52xx_can_xtal_freq(struct of_device *of)
51{
52 struct mpc52xx_cdm __iomem *cdm;
53 struct device_node *np_cdm;
54 unsigned int freq;
55 u32 val;
56
57 freq = mpc5xxx_get_bus_frequency(of->node);
58 if (!freq)
59 return 0;
60
61 /*
62 * Determine SYS_XTAL_IN frequency from the clock domain settings
63 */
64 np_cdm = of_find_matching_node(NULL, mpc52xx_cdm_ids);
65 if (!np_cdm) {
66 dev_err(&of->dev, "can't get clock node!\n");
67 return 0;
68 }
69 cdm = of_iomap(np_cdm, 0);
70 of_node_put(np_cdm);
71
72 if (in_8(&cdm->ipb_clk_sel) & 0x1)
73 freq *= 2;
74 val = in_be32(&cdm->rstcfg);
75 if (val & (1 << 5))
76 freq *= 8;
77 else
78 freq *= 4;
79 if (val & (1 << 6))
80 freq /= 12;
81 else
82 freq /= 16;
83
84 iounmap(cdm);
85
86 return freq;
87}
88
89/*
90 * Get frequency of the MSCAN clock source
91 *
92 * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock (IP_CLK)
93 * can be selected. According to the MPC5200 user's manual, the oscillator
94 * clock is the better choice as it has less jitter but due to a hardware
95 * bug, it can not be selected for the old MPC5200 Rev. A chips.
96 */
97
98static unsigned int __devinit mpc52xx_can_clock_freq(struct of_device *of,
99 int clock_src)
100{
101 unsigned int pvr;
102
103 pvr = mfspr(SPRN_PVR);
104
105 if (clock_src == MSCAN_CLKSRC_BUS || pvr == 0x80822011)
106 return mpc5xxx_get_bus_frequency(of->node);
107
108 return mpc52xx_can_xtal_freq(of);
109}
110
111static int __devinit mpc5xxx_can_probe(struct of_device *ofdev,
112 const struct of_device_id *id)
113{
114 struct device_node *np = ofdev->node;
115 struct net_device *dev;
116 struct mscan_priv *priv;
117 void __iomem *base;
118 const char *clk_src;
119 int err, irq, clock_src;
120
121 base = of_iomap(ofdev->node, 0);
122 if (!base) {
123 dev_err(&ofdev->dev, "couldn't ioremap\n");
124 err = -ENOMEM;
125 goto exit_release_mem;
126 }
127
128 irq = irq_of_parse_and_map(np, 0);
129 if (!irq) {
130 dev_err(&ofdev->dev, "no irq found\n");
131 err = -ENODEV;
132 goto exit_unmap_mem;
133 }
134
135 dev = alloc_mscandev();
136 if (!dev) {
137 err = -ENOMEM;
138 goto exit_dispose_irq;
139 }
140
141 priv = netdev_priv(dev);
142 priv->reg_base = base;
143 dev->irq = irq;
144
145 /*
146 * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock
147 * (IP_CLK) can be selected as MSCAN clock source. According to
148 * the MPC5200 user's manual, the oscillator clock is the better
149 * choice as it has less jitter. For this reason, it is selected
150 * by default.
151 */
152 clk_src = of_get_property(np, "fsl,mscan-clk-src", NULL);
153 if (clk_src && strcmp(clk_src, "ip") == 0)
154 clock_src = MSCAN_CLKSRC_BUS;
155 else
156 clock_src = MSCAN_CLKSRC_XTAL;
157 priv->can.clock.freq = mpc52xx_can_clock_freq(ofdev, clock_src);
158 if (!priv->can.clock.freq) {
159 dev_err(&ofdev->dev, "couldn't get MSCAN clock frequency\n");
160 err = -ENODEV;
161 goto exit_free_mscan;
162 }
163
164 SET_NETDEV_DEV(dev, &ofdev->dev);
165
166 err = register_mscandev(dev, clock_src);
167 if (err) {
168 dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
169 DRV_NAME, err);
170 goto exit_free_mscan;
171 }
172
173 dev_set_drvdata(&ofdev->dev, dev);
174
175 dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n",
176 priv->reg_base, dev->irq, priv->can.clock.freq);
177
178 return 0;
179
180exit_free_mscan:
181 free_candev(dev);
182exit_dispose_irq:
183 irq_dispose_mapping(irq);
184exit_unmap_mem:
185 iounmap(base);
186exit_release_mem:
187 return err;
188}
189
190static int __devexit mpc5xxx_can_remove(struct of_device *ofdev)
191{
192 struct net_device *dev = dev_get_drvdata(&ofdev->dev);
193 struct mscan_priv *priv = netdev_priv(dev);
194
195 dev_set_drvdata(&ofdev->dev, NULL);
196
197 unregister_mscandev(dev);
198 iounmap(priv->reg_base);
199 irq_dispose_mapping(dev->irq);
200 free_candev(dev);
201
202 return 0;
203}
204
205#ifdef CONFIG_PM
206static struct mscan_regs saved_regs;
207static int mpc5xxx_can_suspend(struct of_device *ofdev, pm_message_t state)
208{
209 struct net_device *dev = dev_get_drvdata(&ofdev->dev);
210 struct mscan_priv *priv = netdev_priv(dev);
211 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
212
213 _memcpy_fromio(&saved_regs, regs, sizeof(*regs));
214
215 return 0;
216}
217
218static int mpc5xxx_can_resume(struct of_device *ofdev)
219{
220 struct net_device *dev = dev_get_drvdata(&ofdev->dev);
221 struct mscan_priv *priv = netdev_priv(dev);
222 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
223
224 regs->canctl0 |= MSCAN_INITRQ;
225 while ((regs->canctl1 & MSCAN_INITAK) == 0)
226 udelay(10);
227
228 regs->canctl1 = saved_regs.canctl1;
229 regs->canbtr0 = saved_regs.canbtr0;
230 regs->canbtr1 = saved_regs.canbtr1;
231 regs->canidac = saved_regs.canidac;
232
233 /* restore masks, buffers etc. */
234 _memcpy_toio(&regs->canidar1_0, (void *)&saved_regs.canidar1_0,
235 sizeof(*regs) - offsetof(struct mscan_regs, canidar1_0));
236
237 regs->canctl0 &= ~MSCAN_INITRQ;
238 regs->cantbsel = saved_regs.cantbsel;
239 regs->canrier = saved_regs.canrier;
240 regs->cantier = saved_regs.cantier;
241 regs->canctl0 = saved_regs.canctl0;
242
243 return 0;
244}
245#endif
246
247static struct of_device_id __devinitdata mpc5xxx_can_table[] = {
248 {.compatible = "fsl,mpc5200-mscan"},
249 {.compatible = "fsl,mpc5200b-mscan"},
250 {},
251};
252
253static struct of_platform_driver mpc5xxx_can_driver = {
254 .owner = THIS_MODULE,
255 .name = "mpc5xxx_can",
256 .probe = mpc5xxx_can_probe,
257 .remove = __devexit_p(mpc5xxx_can_remove),
258#ifdef CONFIG_PM
259 .suspend = mpc5xxx_can_suspend,
260 .resume = mpc5xxx_can_resume,
261#endif
262 .match_table = mpc5xxx_can_table,
263};
264
265static int __init mpc5xxx_can_init(void)
266{
267 return of_register_platform_driver(&mpc5xxx_can_driver);
268}
269module_init(mpc5xxx_can_init);
270
271static void __exit mpc5xxx_can_exit(void)
272{
273 return of_unregister_platform_driver(&mpc5xxx_can_driver);
274};
275module_exit(mpc5xxx_can_exit);
276
277MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
278MODULE_DESCRIPTION("Freescale MPC5200 CAN driver");
279MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
new file mode 100644
index 000000000000..49542cab9df4
--- /dev/null
+++ b/drivers/net/can/mscan/mscan.c
@@ -0,0 +1,699 @@
1/*
2 * CAN bus driver for the alone generic (as possible as) MSCAN controller.
3 *
4 * Copyright (C) 2005-2006 Andrey Volkov <avolkov@varma-el.com>,
5 * Varma Electronics Oy
6 * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
7 * Copytight (C) 2008-2009 Pengutronix <kernel@pengutronix.de>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the version 2 of the GNU General Public License
11 * as published by the Free Software Foundation
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/interrupt.h>
26#include <linux/delay.h>
27#include <linux/netdevice.h>
28#include <linux/if_arp.h>
29#include <linux/if_ether.h>
30#include <linux/list.h>
31#include <linux/can.h>
32#include <linux/can/dev.h>
33#include <linux/can/error.h>
34#include <linux/io.h>
35
36#include "mscan.h"
37
38#define MSCAN_NORMAL_MODE 0
39#define MSCAN_SLEEP_MODE MSCAN_SLPRQ
40#define MSCAN_INIT_MODE (MSCAN_INITRQ | MSCAN_SLPRQ)
41#define MSCAN_POWEROFF_MODE (MSCAN_CSWAI | MSCAN_SLPRQ)
42#define MSCAN_SET_MODE_RETRIES 255
43#define MSCAN_ECHO_SKB_MAX 3
44
45#define BTR0_BRP_MASK 0x3f
46#define BTR0_SJW_SHIFT 6
47#define BTR0_SJW_MASK (0x3 << BTR0_SJW_SHIFT)
48
49#define BTR1_TSEG1_MASK 0xf
50#define BTR1_TSEG2_SHIFT 4
51#define BTR1_TSEG2_MASK (0x7 << BTR1_TSEG2_SHIFT)
52#define BTR1_SAM_SHIFT 7
53
54#define BTR0_SET_BRP(brp) (((brp) - 1) & BTR0_BRP_MASK)
55#define BTR0_SET_SJW(sjw) ((((sjw) - 1) << BTR0_SJW_SHIFT) & \
56 BTR0_SJW_MASK)
57
58#define BTR1_SET_TSEG1(tseg1) (((tseg1) - 1) & BTR1_TSEG1_MASK)
59#define BTR1_SET_TSEG2(tseg2) ((((tseg2) - 1) << BTR1_TSEG2_SHIFT) & \
60 BTR1_TSEG2_MASK)
61#define BTR1_SET_SAM(sam) ((sam) ? 1 << BTR1_SAM_SHIFT : 0)
62
63static struct can_bittiming_const mscan_bittiming_const = {
64 .name = "mscan",
65 .tseg1_min = 4,
66 .tseg1_max = 16,
67 .tseg2_min = 2,
68 .tseg2_max = 8,
69 .sjw_max = 4,
70 .brp_min = 1,
71 .brp_max = 64,
72 .brp_inc = 1,
73};
74
75struct mscan_state {
76 u8 mode;
77 u8 canrier;
78 u8 cantier;
79};
80
81#define F_RX_PROGRESS 0
82#define F_TX_PROGRESS 1
83#define F_TX_WAIT_ALL 2
84
85static enum can_state state_map[] = {
86 CAN_STATE_ERROR_ACTIVE,
87 CAN_STATE_ERROR_WARNING,
88 CAN_STATE_ERROR_PASSIVE,
89 CAN_STATE_BUS_OFF
90};
91
92static int mscan_set_mode(struct net_device *dev, u8 mode)
93{
94 struct mscan_priv *priv = netdev_priv(dev);
95 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
96 int ret = 0;
97 int i;
98 u8 canctl1;
99
100 if (mode != MSCAN_NORMAL_MODE) {
101
102 if (priv->tx_active) {
103 /* Abort transfers before going to sleep */#
104 out_8(&regs->cantarq, priv->tx_active);
105 /* Suppress TX done interrupts */
106 out_8(&regs->cantier, 0);
107 }
108
109 canctl1 = in_8(&regs->canctl1);
110 if ((mode & MSCAN_SLPRQ) && (canctl1 & MSCAN_SLPAK) == 0) {
111 out_8(&regs->canctl0,
112 in_8(&regs->canctl0) | MSCAN_SLPRQ);
113 for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
114 if (in_8(&regs->canctl1) & MSCAN_SLPAK)
115 break;
116 udelay(100);
117 }
118 /*
119 * The mscan controller will fail to enter sleep mode,
120 * while there are irregular activities on bus, like
121 * somebody keeps retransmitting. This behavior is
122 * undocumented and seems to differ between mscan built
123 * in mpc5200b and mpc5200. We proceed in that case,
124 * since otherwise the slprq will be kept set and the
125 * controller will get stuck. NOTE: INITRQ or CSWAI
126 * will abort all active transmit actions, if still
127 * any, at once.
128 */
129 if (i >= MSCAN_SET_MODE_RETRIES)
130 dev_dbg(dev->dev.parent,
131 "device failed to enter sleep mode. "
132 "We proceed anyhow.\n");
133 else
134 priv->can.state = CAN_STATE_SLEEPING;
135 }
136
137 if ((mode & MSCAN_INITRQ) && (canctl1 & MSCAN_INITAK) == 0) {
138 out_8(&regs->canctl0,
139 in_8(&regs->canctl0) | MSCAN_INITRQ);
140 for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
141 if (in_8(&regs->canctl1) & MSCAN_INITAK)
142 break;
143 }
144 if (i >= MSCAN_SET_MODE_RETRIES)
145 ret = -ENODEV;
146 }
147 if (!ret)
148 priv->can.state = CAN_STATE_STOPPED;
149
150 if (mode & MSCAN_CSWAI)
151 out_8(&regs->canctl0,
152 in_8(&regs->canctl0) | MSCAN_CSWAI);
153
154 } else {
155 canctl1 = in_8(&regs->canctl1);
156 if (canctl1 & (MSCAN_SLPAK | MSCAN_INITAK)) {
157 out_8(&regs->canctl0, in_8(&regs->canctl0) &
158 ~(MSCAN_SLPRQ | MSCAN_INITRQ));
159 for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
160 canctl1 = in_8(&regs->canctl1);
161 if (!(canctl1 & (MSCAN_INITAK | MSCAN_SLPAK)))
162 break;
163 }
164 if (i >= MSCAN_SET_MODE_RETRIES)
165 ret = -ENODEV;
166 else
167 priv->can.state = CAN_STATE_ERROR_ACTIVE;
168 }
169 }
170 return ret;
171}
172
173static int mscan_start(struct net_device *dev)
174{
175 struct mscan_priv *priv = netdev_priv(dev);
176 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
177 u8 canrflg;
178 int err;
179
180 out_8(&regs->canrier, 0);
181
182 INIT_LIST_HEAD(&priv->tx_head);
183 priv->prev_buf_id = 0;
184 priv->cur_pri = 0;
185 priv->tx_active = 0;
186 priv->shadow_canrier = 0;
187 priv->flags = 0;
188
189 err = mscan_set_mode(dev, MSCAN_NORMAL_MODE);
190 if (err)
191 return err;
192
193 canrflg = in_8(&regs->canrflg);
194 priv->shadow_statflg = canrflg & MSCAN_STAT_MSK;
195 priv->can.state = state_map[max(MSCAN_STATE_RX(canrflg),
196 MSCAN_STATE_TX(canrflg))];
197 out_8(&regs->cantier, 0);
198
199 /* Enable receive interrupts. */
200 out_8(&regs->canrier, MSCAN_OVRIE | MSCAN_RXFIE | MSCAN_CSCIE |
201 MSCAN_RSTATE1 | MSCAN_RSTATE0 | MSCAN_TSTATE1 | MSCAN_TSTATE0);
202
203 return 0;
204}
205
206static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
207{
208 struct can_frame *frame = (struct can_frame *)skb->data;
209 struct mscan_priv *priv = netdev_priv(dev);
210 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
211 int i, rtr, buf_id;
212 u32 can_id;
213
214 if (frame->can_dlc > 8)
215 return -EINVAL;
216
217 out_8(&regs->cantier, 0);
218
219 i = ~priv->tx_active & MSCAN_TXE;
220 buf_id = ffs(i) - 1;
221 switch (hweight8(i)) {
222 case 0:
223 netif_stop_queue(dev);
224 dev_err(dev->dev.parent, "Tx Ring full when queue awake!\n");
225 return NETDEV_TX_BUSY;
226 case 1:
227 /*
228 * if buf_id < 3, then current frame will be send out of order,
229 * since buffer with lower id have higher priority (hell..)
230 */
231 netif_stop_queue(dev);
232 case 2:
233 if (buf_id < priv->prev_buf_id) {
234 priv->cur_pri++;
235 if (priv->cur_pri == 0xff) {
236 set_bit(F_TX_WAIT_ALL, &priv->flags);
237 netif_stop_queue(dev);
238 }
239 }
240 set_bit(F_TX_PROGRESS, &priv->flags);
241 break;
242 }
243 priv->prev_buf_id = buf_id;
244 out_8(&regs->cantbsel, i);
245
246 rtr = frame->can_id & CAN_RTR_FLAG;
247
248 if (frame->can_id & CAN_EFF_FLAG) {
249 can_id = (frame->can_id & CAN_EFF_MASK) << 1;
250 if (rtr)
251 can_id |= 1;
252 out_be16(&regs->tx.idr3_2, can_id);
253
254 can_id >>= 16;
255 can_id = (can_id & 0x7) | ((can_id << 2) & 0xffe0) | (3 << 3);
256 } else {
257 can_id = (frame->can_id & CAN_SFF_MASK) << 5;
258 if (rtr)
259 can_id |= 1 << 4;
260 }
261 out_be16(&regs->tx.idr1_0, can_id);
262
263 if (!rtr) {
264 void __iomem *data = &regs->tx.dsr1_0;
265 u16 *payload = (u16 *) frame->data;
266 /* It is safe to write into dsr[dlc+1] */
267 for (i = 0; i < (frame->can_dlc + 1) / 2; i++) {
268 out_be16(data, *payload++);
269 data += 2 + _MSCAN_RESERVED_DSR_SIZE;
270 }
271 }
272
273 out_8(&regs->tx.dlr, frame->can_dlc);
274 out_8(&regs->tx.tbpr, priv->cur_pri);
275
276 /* Start transmission. */
277 out_8(&regs->cantflg, 1 << buf_id);
278
279 if (!test_bit(F_TX_PROGRESS, &priv->flags))
280 dev->trans_start = jiffies;
281
282 list_add_tail(&priv->tx_queue[buf_id].list, &priv->tx_head);
283
284 can_put_echo_skb(skb, dev, buf_id);
285
286 /* Enable interrupt. */
287 priv->tx_active |= 1 << buf_id;
288 out_8(&regs->cantier, priv->tx_active);
289
290 return NETDEV_TX_OK;
291}
292
293/* This function returns the old state to see where we came from */
294static enum can_state check_set_state(struct net_device *dev, u8 canrflg)
295{
296 struct mscan_priv *priv = netdev_priv(dev);
297 enum can_state state, old_state = priv->can.state;
298
299 if (canrflg & MSCAN_CSCIF && old_state <= CAN_STATE_BUS_OFF) {
300 state = state_map[max(MSCAN_STATE_RX(canrflg),
301 MSCAN_STATE_TX(canrflg))];
302 priv->can.state = state;
303 }
304 return old_state;
305}
306
307static void mscan_get_rx_frame(struct net_device *dev, struct can_frame *frame)
308{
309 struct mscan_priv *priv = netdev_priv(dev);
310 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
311 u32 can_id;
312 int i;
313
314 can_id = in_be16(&regs->rx.idr1_0);
315 if (can_id & (1 << 3)) {
316 frame->can_id = CAN_EFF_FLAG;
317 can_id = ((can_id << 16) | in_be16(&regs->rx.idr3_2));
318 can_id = ((can_id & 0xffe00000) |
319 ((can_id & 0x7ffff) << 2)) >> 2;
320 } else {
321 can_id >>= 4;
322 frame->can_id = 0;
323 }
324
325 frame->can_id |= can_id >> 1;
326 if (can_id & 1)
327 frame->can_id |= CAN_RTR_FLAG;
328 frame->can_dlc = in_8(&regs->rx.dlr) & 0xf;
329
330 if (!(frame->can_id & CAN_RTR_FLAG)) {
331 void __iomem *data = &regs->rx.dsr1_0;
332 u16 *payload = (u16 *) frame->data;
333 for (i = 0; i < (frame->can_dlc + 1) / 2; i++) {
334 *payload++ = in_be16(data);
335 data += 2 + _MSCAN_RESERVED_DSR_SIZE;
336 }
337 }
338
339 out_8(&regs->canrflg, MSCAN_RXF);
340}
341
342static void mscan_get_err_frame(struct net_device *dev, struct can_frame *frame,
343 u8 canrflg)
344{
345 struct mscan_priv *priv = netdev_priv(dev);
346 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
347 struct net_device_stats *stats = &dev->stats;
348 enum can_state old_state;
349
350 dev_dbg(dev->dev.parent, "error interrupt (canrflg=%#x)\n", canrflg);
351 frame->can_id = CAN_ERR_FLAG;
352
353 if (canrflg & MSCAN_OVRIF) {
354 frame->can_id |= CAN_ERR_CRTL;
355 frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
356 stats->rx_over_errors++;
357 stats->rx_errors++;
358 } else
359 frame->data[1] = 0;
360
361 old_state = check_set_state(dev, canrflg);
362 /* State changed */
363 if (old_state != priv->can.state) {
364 switch (priv->can.state) {
365 case CAN_STATE_ERROR_WARNING:
366 frame->can_id |= CAN_ERR_CRTL;
367 priv->can.can_stats.error_warning++;
368 if ((priv->shadow_statflg & MSCAN_RSTAT_MSK) <
369 (canrflg & MSCAN_RSTAT_MSK))
370 frame->data[1] |= CAN_ERR_CRTL_RX_WARNING;
371
372 if ((priv->shadow_statflg & MSCAN_TSTAT_MSK) <
373 (canrflg & MSCAN_TSTAT_MSK))
374 frame->data[1] |= CAN_ERR_CRTL_TX_WARNING;
375 break;
376 case CAN_STATE_ERROR_PASSIVE:
377 frame->can_id |= CAN_ERR_CRTL;
378 priv->can.can_stats.error_passive++;
379 frame->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
380 break;
381 case CAN_STATE_BUS_OFF:
382 frame->can_id |= CAN_ERR_BUSOFF;
383 /*
384 * The MSCAN on the MPC5200 does recover from bus-off
385 * automatically. To avoid that we stop the chip doing
386 * a light-weight stop (we are in irq-context).
387 */
388 out_8(&regs->cantier, 0);
389 out_8(&regs->canrier, 0);
390 out_8(&regs->canctl0, in_8(&regs->canctl0) |
391 MSCAN_SLPRQ | MSCAN_INITRQ);
392 can_bus_off(dev);
393 break;
394 default:
395 break;
396 }
397 }
398 priv->shadow_statflg = canrflg & MSCAN_STAT_MSK;
399 frame->can_dlc = CAN_ERR_DLC;
400 out_8(&regs->canrflg, MSCAN_ERR_IF);
401}
402
403static int mscan_rx_poll(struct napi_struct *napi, int quota)
404{
405 struct mscan_priv *priv = container_of(napi, struct mscan_priv, napi);
406 struct net_device *dev = napi->dev;
407 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
408 struct net_device_stats *stats = &dev->stats;
409 int npackets = 0;
410 int ret = 1;
411 struct sk_buff *skb;
412 struct can_frame *frame;
413 u8 canrflg;
414
415 while (npackets < quota && ((canrflg = in_8(&regs->canrflg)) &
416 (MSCAN_RXF | MSCAN_ERR_IF))) {
417
418 skb = alloc_can_skb(dev, &frame);
419 if (!skb) {
420 if (printk_ratelimit())
421 dev_notice(dev->dev.parent, "packet dropped\n");
422 stats->rx_dropped++;
423 out_8(&regs->canrflg, canrflg);
424 continue;
425 }
426
427 if (canrflg & MSCAN_RXF)
428 mscan_get_rx_frame(dev, frame);
429 else if (canrflg & MSCAN_ERR_IF)
430 mscan_get_err_frame(dev, frame, canrflg);
431
432 stats->rx_packets++;
433 stats->rx_bytes += frame->can_dlc;
434 npackets++;
435 netif_receive_skb(skb);
436 }
437
438 if (!(in_8(&regs->canrflg) & (MSCAN_RXF | MSCAN_ERR_IF))) {
439 napi_complete(&priv->napi);
440 clear_bit(F_RX_PROGRESS, &priv->flags);
441 if (priv->can.state < CAN_STATE_BUS_OFF)
442 out_8(&regs->canrier, priv->shadow_canrier);
443 ret = 0;
444 }
445 return ret;
446}
447
448static irqreturn_t mscan_isr(int irq, void *dev_id)
449{
450 struct net_device *dev = (struct net_device *)dev_id;
451 struct mscan_priv *priv = netdev_priv(dev);
452 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
453 struct net_device_stats *stats = &dev->stats;
454 u8 cantier, cantflg, canrflg;
455 irqreturn_t ret = IRQ_NONE;
456
457 cantier = in_8(&regs->cantier) & MSCAN_TXE;
458 cantflg = in_8(&regs->cantflg) & cantier;
459
460 if (cantier && cantflg) {
461
462 struct list_head *tmp, *pos;
463
464 list_for_each_safe(pos, tmp, &priv->tx_head) {
465 struct tx_queue_entry *entry =
466 list_entry(pos, struct tx_queue_entry, list);
467 u8 mask = entry->mask;
468
469 if (!(cantflg & mask))
470 continue;
471
472 out_8(&regs->cantbsel, mask);
473 stats->tx_bytes += in_8(&regs->tx.dlr);
474 stats->tx_packets++;
475 can_get_echo_skb(dev, entry->id);
476 priv->tx_active &= ~mask;
477 list_del(pos);
478 }
479
480 if (list_empty(&priv->tx_head)) {
481 clear_bit(F_TX_WAIT_ALL, &priv->flags);
482 clear_bit(F_TX_PROGRESS, &priv->flags);
483 priv->cur_pri = 0;
484 } else
485 dev->trans_start = jiffies;
486
487 if (!test_bit(F_TX_WAIT_ALL, &priv->flags))
488 netif_wake_queue(dev);
489
490 out_8(&regs->cantier, priv->tx_active);
491 ret = IRQ_HANDLED;
492 }
493
494 canrflg = in_8(&regs->canrflg);
495 if ((canrflg & ~MSCAN_STAT_MSK) &&
496 !test_and_set_bit(F_RX_PROGRESS, &priv->flags)) {
497 if (canrflg & ~MSCAN_STAT_MSK) {
498 priv->shadow_canrier = in_8(&regs->canrier);
499 out_8(&regs->canrier, 0);
500 napi_schedule(&priv->napi);
501 ret = IRQ_HANDLED;
502 } else
503 clear_bit(F_RX_PROGRESS, &priv->flags);
504 }
505 return ret;
506}
507
508static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)
509{
510
511 struct mscan_priv *priv = netdev_priv(dev);
512 int ret = 0;
513
514 if (!priv->open_time)
515 return -EINVAL;
516
517 switch (mode) {
518 case CAN_MODE_SLEEP:
519 case CAN_MODE_STOP:
520 netif_stop_queue(dev);
521 mscan_set_mode(dev,
522 (mode ==
523 CAN_MODE_STOP) ? MSCAN_INIT_MODE :
524 MSCAN_SLEEP_MODE);
525 break;
526 case CAN_MODE_START:
527 if (priv->can.state <= CAN_STATE_BUS_OFF)
528 mscan_set_mode(dev, MSCAN_INIT_MODE);
529 ret = mscan_start(dev);
530 if (ret)
531 break;
532 if (netif_queue_stopped(dev))
533 netif_wake_queue(dev);
534 break;
535
536 default:
537 ret = -EOPNOTSUPP;
538 break;
539 }
540 return ret;
541}
542
543static int mscan_do_set_bittiming(struct net_device *dev)
544{
545 struct mscan_priv *priv = netdev_priv(dev);
546 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
547 struct can_bittiming *bt = &priv->can.bittiming;
548 u8 btr0, btr1;
549
550 btr0 = BTR0_SET_BRP(bt->brp) | BTR0_SET_SJW(bt->sjw);
551 btr1 = (BTR1_SET_TSEG1(bt->prop_seg + bt->phase_seg1) |
552 BTR1_SET_TSEG2(bt->phase_seg2) |
553 BTR1_SET_SAM(priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES));
554
555 dev_info(dev->dev.parent, "setting BTR0=0x%02x BTR1=0x%02x\n",
556 btr0, btr1);
557
558 out_8(&regs->canbtr0, btr0);
559 out_8(&regs->canbtr1, btr1);
560
561 return 0;
562}
563
564static int mscan_open(struct net_device *dev)
565{
566 int ret;
567 struct mscan_priv *priv = netdev_priv(dev);
568 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
569
570 /* common open */
571 ret = open_candev(dev);
572 if (ret)
573 return ret;
574
575 napi_enable(&priv->napi);
576
577 ret = request_irq(dev->irq, mscan_isr, 0, dev->name, dev);
578 if (ret < 0) {
579 napi_disable(&priv->napi);
580 printk(KERN_ERR "%s - failed to attach interrupt\n",
581 dev->name);
582 return ret;
583 }
584
585 priv->open_time = jiffies;
586
587 out_8(&regs->canctl1, in_8(&regs->canctl1) & ~MSCAN_LISTEN);
588
589 ret = mscan_start(dev);
590 if (ret)
591 return ret;
592
593 netif_start_queue(dev);
594
595 return 0;
596}
597
598static int mscan_close(struct net_device *dev)
599{
600 struct mscan_priv *priv = netdev_priv(dev);
601 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
602
603 netif_stop_queue(dev);
604 napi_disable(&priv->napi);
605
606 out_8(&regs->cantier, 0);
607 out_8(&regs->canrier, 0);
608 mscan_set_mode(dev, MSCAN_INIT_MODE);
609 close_candev(dev);
610 free_irq(dev->irq, dev);
611 priv->open_time = 0;
612
613 return 0;
614}
615
616static const struct net_device_ops mscan_netdev_ops = {
617 .ndo_open = mscan_open,
618 .ndo_stop = mscan_close,
619 .ndo_start_xmit = mscan_start_xmit,
620};
621
622int register_mscandev(struct net_device *dev, int clock_src)
623{
624 struct mscan_priv *priv = netdev_priv(dev);
625 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
626 u8 ctl1;
627
628 ctl1 = in_8(&regs->canctl1);
629 if (clock_src)
630 ctl1 |= MSCAN_CLKSRC;
631 else
632 ctl1 &= ~MSCAN_CLKSRC;
633
634 ctl1 |= MSCAN_CANE;
635 out_8(&regs->canctl1, ctl1);
636 udelay(100);
637
638 /* acceptance mask/acceptance code (accept everything) */
639 out_be16(&regs->canidar1_0, 0);
640 out_be16(&regs->canidar3_2, 0);
641 out_be16(&regs->canidar5_4, 0);
642 out_be16(&regs->canidar7_6, 0);
643
644 out_be16(&regs->canidmr1_0, 0xffff);
645 out_be16(&regs->canidmr3_2, 0xffff);
646 out_be16(&regs->canidmr5_4, 0xffff);
647 out_be16(&regs->canidmr7_6, 0xffff);
648 /* Two 32 bit Acceptance Filters */
649 out_8(&regs->canidac, MSCAN_AF_32BIT);
650
651 mscan_set_mode(dev, MSCAN_INIT_MODE);
652
653 return register_candev(dev);
654}
655EXPORT_SYMBOL_GPL(register_mscandev);
656
657void unregister_mscandev(struct net_device *dev)
658{
659 struct mscan_priv *priv = netdev_priv(dev);
660 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
661 mscan_set_mode(dev, MSCAN_INIT_MODE);
662 out_8(&regs->canctl1, in_8(&regs->canctl1) & ~MSCAN_CANE);
663 unregister_candev(dev);
664}
665EXPORT_SYMBOL_GPL(unregister_mscandev);
666
667struct net_device *alloc_mscandev(void)
668{
669 struct net_device *dev;
670 struct mscan_priv *priv;
671 int i;
672
673 dev = alloc_candev(sizeof(struct mscan_priv), MSCAN_ECHO_SKB_MAX);
674 if (!dev)
675 return NULL;
676 priv = netdev_priv(dev);
677
678 dev->netdev_ops = &mscan_netdev_ops;
679
680 dev->flags |= IFF_ECHO; /* we support local echo */
681
682 netif_napi_add(dev, &priv->napi, mscan_rx_poll, 8);
683
684 priv->can.bittiming_const = &mscan_bittiming_const;
685 priv->can.do_set_bittiming = mscan_do_set_bittiming;
686 priv->can.do_set_mode = mscan_do_set_mode;
687
688 for (i = 0; i < TX_QUEUE_SIZE; i++) {
689 priv->tx_queue[i].id = i;
690 priv->tx_queue[i].mask = 1 << i;
691 }
692
693 return dev;
694}
695EXPORT_SYMBOL_GPL(alloc_mscandev);
696
697MODULE_AUTHOR("Andrey Volkov <avolkov@varma-el.com>");
698MODULE_LICENSE("GPL v2");
699MODULE_DESCRIPTION("CAN port driver for a MSCAN based chips");
diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
new file mode 100644
index 000000000000..57820f5fb817
--- /dev/null
+++ b/drivers/net/can/mscan/mscan.h
@@ -0,0 +1,262 @@
1/*
2 * Definitions of consts/structs to drive the Freescale MSCAN.
3 *
4 * Copyright (C) 2005-2006 Andrey Volkov <avolkov@varma-el.com>,
5 * Varma Electronics Oy
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the version 2 of the GNU General Public License
9 * as published by the Free Software Foundation
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#ifndef __MSCAN_H__
22#define __MSCAN_H__
23
24#include <linux/types.h>
25
26/* MSCAN control register 0 (CANCTL0) bits */
27#define MSCAN_RXFRM 0x80
28#define MSCAN_RXACT 0x40
29#define MSCAN_CSWAI 0x20
30#define MSCAN_SYNCH 0x10
31#define MSCAN_TIME 0x08
32#define MSCAN_WUPE 0x04
33#define MSCAN_SLPRQ 0x02
34#define MSCAN_INITRQ 0x01
35
36/* MSCAN control register 1 (CANCTL1) bits */
37#define MSCAN_CANE 0x80
38#define MSCAN_CLKSRC 0x40
39#define MSCAN_LOOPB 0x20
40#define MSCAN_LISTEN 0x10
41#define MSCAN_WUPM 0x04
42#define MSCAN_SLPAK 0x02
43#define MSCAN_INITAK 0x01
44
45/* Use the MPC5200 MSCAN variant? */
46#ifdef CONFIG_PPC
47#define MSCAN_FOR_MPC5200
48#endif
49
50#ifdef MSCAN_FOR_MPC5200
51#define MSCAN_CLKSRC_BUS 0
52#define MSCAN_CLKSRC_XTAL MSCAN_CLKSRC
53#else
54#define MSCAN_CLKSRC_BUS MSCAN_CLKSRC
55#define MSCAN_CLKSRC_XTAL 0
56#endif
57
58/* MSCAN receiver flag register (CANRFLG) bits */
59#define MSCAN_WUPIF 0x80
60#define MSCAN_CSCIF 0x40
61#define MSCAN_RSTAT1 0x20
62#define MSCAN_RSTAT0 0x10
63#define MSCAN_TSTAT1 0x08
64#define MSCAN_TSTAT0 0x04
65#define MSCAN_OVRIF 0x02
66#define MSCAN_RXF 0x01
67#define MSCAN_ERR_IF (MSCAN_OVRIF | MSCAN_CSCIF)
68#define MSCAN_RSTAT_MSK (MSCAN_RSTAT1 | MSCAN_RSTAT0)
69#define MSCAN_TSTAT_MSK (MSCAN_TSTAT1 | MSCAN_TSTAT0)
70#define MSCAN_STAT_MSK (MSCAN_RSTAT_MSK | MSCAN_TSTAT_MSK)
71
72#define MSCAN_STATE_BUS_OFF (MSCAN_RSTAT1 | MSCAN_RSTAT0 | \
73 MSCAN_TSTAT1 | MSCAN_TSTAT0)
74#define MSCAN_STATE_TX(canrflg) (((canrflg)&MSCAN_TSTAT_MSK)>>2)
75#define MSCAN_STATE_RX(canrflg) (((canrflg)&MSCAN_RSTAT_MSK)>>4)
76#define MSCAN_STATE_ACTIVE 0
77#define MSCAN_STATE_WARNING 1
78#define MSCAN_STATE_PASSIVE 2
79#define MSCAN_STATE_BUSOFF 3
80
81/* MSCAN receiver interrupt enable register (CANRIER) bits */
82#define MSCAN_WUPIE 0x80
83#define MSCAN_CSCIE 0x40
84#define MSCAN_RSTATE1 0x20
85#define MSCAN_RSTATE0 0x10
86#define MSCAN_TSTATE1 0x08
87#define MSCAN_TSTATE0 0x04
88#define MSCAN_OVRIE 0x02
89#define MSCAN_RXFIE 0x01
90
91/* MSCAN transmitter flag register (CANTFLG) bits */
92#define MSCAN_TXE2 0x04
93#define MSCAN_TXE1 0x02
94#define MSCAN_TXE0 0x01
95#define MSCAN_TXE (MSCAN_TXE2 | MSCAN_TXE1 | MSCAN_TXE0)
96
97/* MSCAN transmitter interrupt enable register (CANTIER) bits */
98#define MSCAN_TXIE2 0x04
99#define MSCAN_TXIE1 0x02
100#define MSCAN_TXIE0 0x01
101#define MSCAN_TXIE (MSCAN_TXIE2 | MSCAN_TXIE1 | MSCAN_TXIE0)
102
103/* MSCAN transmitter message abort request (CANTARQ) bits */
104#define MSCAN_ABTRQ2 0x04
105#define MSCAN_ABTRQ1 0x02
106#define MSCAN_ABTRQ0 0x01
107
108/* MSCAN transmitter message abort ack (CANTAAK) bits */
109#define MSCAN_ABTAK2 0x04
110#define MSCAN_ABTAK1 0x02
111#define MSCAN_ABTAK0 0x01
112
113/* MSCAN transmit buffer selection (CANTBSEL) bits */
114#define MSCAN_TX2 0x04
115#define MSCAN_TX1 0x02
116#define MSCAN_TX0 0x01
117
118/* MSCAN ID acceptance control register (CANIDAC) bits */
119#define MSCAN_IDAM1 0x20
120#define MSCAN_IDAM0 0x10
121#define MSCAN_IDHIT2 0x04
122#define MSCAN_IDHIT1 0x02
123#define MSCAN_IDHIT0 0x01
124
125#define MSCAN_AF_32BIT 0x00
126#define MSCAN_AF_16BIT MSCAN_IDAM0
127#define MSCAN_AF_8BIT MSCAN_IDAM1
128#define MSCAN_AF_CLOSED (MSCAN_IDAM0|MSCAN_IDAM1)
129#define MSCAN_AF_MASK (~(MSCAN_IDAM0|MSCAN_IDAM1))
130
131/* MSCAN Miscellaneous Register (CANMISC) bits */
132#define MSCAN_BOHOLD 0x01
133
134#ifdef MSCAN_FOR_MPC5200
135#define _MSCAN_RESERVED_(n, num) u8 _res##n[num]
136#define _MSCAN_RESERVED_DSR_SIZE 2
137#else
138#define _MSCAN_RESERVED_(n, num)
139#define _MSCAN_RESERVED_DSR_SIZE 0
140#endif
141
142/* Structure of the hardware registers */
143struct mscan_regs {
144 /* (see doc S12MSCANV3/D) MPC5200 MSCAN */
145 u8 canctl0; /* + 0x00 0x00 */
146 u8 canctl1; /* + 0x01 0x01 */
147 _MSCAN_RESERVED_(1, 2); /* + 0x02 */
148 u8 canbtr0; /* + 0x04 0x02 */
149 u8 canbtr1; /* + 0x05 0x03 */
150 _MSCAN_RESERVED_(2, 2); /* + 0x06 */
151 u8 canrflg; /* + 0x08 0x04 */
152 u8 canrier; /* + 0x09 0x05 */
153 _MSCAN_RESERVED_(3, 2); /* + 0x0a */
154 u8 cantflg; /* + 0x0c 0x06 */
155 u8 cantier; /* + 0x0d 0x07 */
156 _MSCAN_RESERVED_(4, 2); /* + 0x0e */
157 u8 cantarq; /* + 0x10 0x08 */
158 u8 cantaak; /* + 0x11 0x09 */
159 _MSCAN_RESERVED_(5, 2); /* + 0x12 */
160 u8 cantbsel; /* + 0x14 0x0a */
161 u8 canidac; /* + 0x15 0x0b */
162 u8 reserved; /* + 0x16 0x0c */
163 _MSCAN_RESERVED_(6, 5); /* + 0x17 */
164#ifndef MSCAN_FOR_MPC5200
165 u8 canmisc; /* 0x0d */
166#endif
167 u8 canrxerr; /* + 0x1c 0x0e */
168 u8 cantxerr; /* + 0x1d 0x0f */
169 _MSCAN_RESERVED_(7, 2); /* + 0x1e */
170 u16 canidar1_0; /* + 0x20 0x10 */
171 _MSCAN_RESERVED_(8, 2); /* + 0x22 */
172 u16 canidar3_2; /* + 0x24 0x12 */
173 _MSCAN_RESERVED_(9, 2); /* + 0x26 */
174 u16 canidmr1_0; /* + 0x28 0x14 */
175 _MSCAN_RESERVED_(10, 2); /* + 0x2a */
176 u16 canidmr3_2; /* + 0x2c 0x16 */
177 _MSCAN_RESERVED_(11, 2); /* + 0x2e */
178 u16 canidar5_4; /* + 0x30 0x18 */
179 _MSCAN_RESERVED_(12, 2); /* + 0x32 */
180 u16 canidar7_6; /* + 0x34 0x1a */
181 _MSCAN_RESERVED_(13, 2); /* + 0x36 */
182 u16 canidmr5_4; /* + 0x38 0x1c */
183 _MSCAN_RESERVED_(14, 2); /* + 0x3a */
184 u16 canidmr7_6; /* + 0x3c 0x1e */
185 _MSCAN_RESERVED_(15, 2); /* + 0x3e */
186 struct {
187 u16 idr1_0; /* + 0x40 0x20 */
188 _MSCAN_RESERVED_(16, 2); /* + 0x42 */
189 u16 idr3_2; /* + 0x44 0x22 */
190 _MSCAN_RESERVED_(17, 2); /* + 0x46 */
191 u16 dsr1_0; /* + 0x48 0x24 */
192 _MSCAN_RESERVED_(18, 2); /* + 0x4a */
193 u16 dsr3_2; /* + 0x4c 0x26 */
194 _MSCAN_RESERVED_(19, 2); /* + 0x4e */
195 u16 dsr5_4; /* + 0x50 0x28 */
196 _MSCAN_RESERVED_(20, 2); /* + 0x52 */
197 u16 dsr7_6; /* + 0x54 0x2a */
198 _MSCAN_RESERVED_(21, 2); /* + 0x56 */
199 u8 dlr; /* + 0x58 0x2c */
200 u8:8; /* + 0x59 0x2d */
201 _MSCAN_RESERVED_(22, 2); /* + 0x5a */
202 u16 time; /* + 0x5c 0x2e */
203 } rx;
204 _MSCAN_RESERVED_(23, 2); /* + 0x5e */
205 struct {
206 u16 idr1_0; /* + 0x60 0x30 */
207 _MSCAN_RESERVED_(24, 2); /* + 0x62 */
208 u16 idr3_2; /* + 0x64 0x32 */
209 _MSCAN_RESERVED_(25, 2); /* + 0x66 */
210 u16 dsr1_0; /* + 0x68 0x34 */
211 _MSCAN_RESERVED_(26, 2); /* + 0x6a */
212 u16 dsr3_2; /* + 0x6c 0x36 */
213 _MSCAN_RESERVED_(27, 2); /* + 0x6e */
214 u16 dsr5_4; /* + 0x70 0x38 */
215 _MSCAN_RESERVED_(28, 2); /* + 0x72 */
216 u16 dsr7_6; /* + 0x74 0x3a */
217 _MSCAN_RESERVED_(29, 2); /* + 0x76 */
218 u8 dlr; /* + 0x78 0x3c */
219 u8 tbpr; /* + 0x79 0x3d */
220 _MSCAN_RESERVED_(30, 2); /* + 0x7a */
221 u16 time; /* + 0x7c 0x3e */
222 } tx;
223 _MSCAN_RESERVED_(31, 2); /* + 0x7e */
224} __attribute__ ((packed));
225
226#undef _MSCAN_RESERVED_
227#define MSCAN_REGION sizeof(struct mscan)
228
229#define TX_QUEUE_SIZE 3
230
231struct tx_queue_entry {
232 struct list_head list;
233 u8 mask;
234 u8 id;
235};
236
237struct mscan_priv {
238 struct can_priv can; /* must be the first member */
239 long open_time;
240 unsigned long flags;
241 void __iomem *reg_base; /* ioremap'ed address to registers */
242 u8 shadow_statflg;
243 u8 shadow_canrier;
244 u8 cur_pri;
245 u8 prev_buf_id;
246 u8 tx_active;
247
248 struct list_head tx_head;
249 struct tx_queue_entry tx_queue[TX_QUEUE_SIZE];
250 struct napi_struct napi;
251};
252
253struct net_device *alloc_mscandev(void);
254/*
255 * clock_src:
256 * 1 = The MSCAN clock source is the onchip Bus Clock.
257 * 0 = The MSCAN clock source is the chip Oscillator Clock.
258 */
259extern int register_mscandev(struct net_device *dev, int clock_src);
260extern void unregister_mscandev(struct net_device *dev);
261
262#endif /* __MSCAN_H__ */