Root/target/linux/coldfire/patches/036-Add-FlexCAN-support-on-ColdFire-M548X-M54418-platfor.patch

1From c3b97e08b06be76ee9f2b410b13c045425fc7f3e Mon Sep 17 00:00:00 2001
2From: Jingchang Lu <b35083@freescale.com>
3Date: Thu, 4 Aug 2011 09:59:48 +0800
4Subject: [PATCH 36/52] Add FlexCAN support on ColdFire M548X, M54418 platform
5
6Each cpu core has two FlexCAN interface, and the M54418's FlexCAN
7also support Rx message buffer FIFO mode but M548X not.
8
9Signed-off-by: Jingchang Lu <b35083@freescale.com>
10---
11 arch/m68k/Kconfig | 2 +
12 arch/m68k/coldfire/m5441x/Makefile | 4 +
13 arch/m68k/coldfire/m5441x/mcf-flexcan.c | 121 ++++++++++++++++
14 arch/m68k/coldfire/m547x/Makefile | 3 +
15 arch/m68k/coldfire/m547x/mcf-flexcan.c | 117 +++++++++++++++
16 drivers/net/can/Kconfig | 9 ++
17 drivers/net/can/flexcan.c | 239 ++++++++++++++++++++++++++++++-
18 7 files changed, 489 insertions(+), 6 deletions(-)
19 create mode 100644 arch/m68k/coldfire/m5441x/mcf-flexcan.c
20 create mode 100644 arch/m68k/coldfire/m547x/mcf-flexcan.c
21
22--- a/arch/m68k/Kconfig
23+++ b/arch/m68k/Kconfig
24@@ -372,6 +372,7 @@ config M547X
25 config M548X
26     bool
27     depends on M547X_8X
28+ select HAVE_CAN_FLEXCAN
29     default n
30 
31 choice
32@@ -430,6 +431,7 @@ config M5441X
33     select GENERIC_TIME
34     select USB_EHCI_FSL
35     select HAVE_FSL_USB_DR
36+ select HAVE_CAN_FLEXCAN
37     help
38       This option will add support for the MCF5441x processor with mmu.
39 
40--- a/arch/m68k/coldfire/m5441x/Makefile
41+++ b/arch/m68k/coldfire/m5441x/Makefile
42@@ -36,3 +36,7 @@ endif
43 ifneq ($(CONFIG_MODELO_SWITCH),)
44 obj-y += l2switch.o
45 endif
46+
47+ifneq ($(CONFIG_CAN_FLEXCAN),)
48+obj-y += mcf-flexcan.o
49+endif
50--- /dev/null
51+++ b/arch/m68k/coldfire/m5441x/mcf-flexcan.c
52@@ -0,0 +1,121 @@
53+/*
54+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved.
55+ *
56+ * Author: Huan Wang, b18965@freescale.com, Fri Aug 08 2008
57+ *
58+ * Description:
59+ * CAN bus driver for Freescale Coldfire embedded CPU
60+ *
61+ * Changelog:
62+ * Fri Aug 08 2008 Huan Wang <b18965@freescale.com>
63+ * - create, support for MCF548x
64+ *
65+ * Tue Dec 08 2009 ChengJu Cai <b22600@freescale.com>
66+ * - support for MCF532x MCF5253 MCF5227x
67+ *
68+ * July 2011 Jingchang.Lu <b35083@freescale.com>
69+ * - Add into kernel CAN driver layer
70+ *
71+ * This file is part of the Linux kernel
72+ * This is free software; you can redistribute it and/or modify
73+ * it under the terms of the GNU General Public License as published by
74+ * the Free Software Foundation; either version 2 of the License, or
75+ * (at your option) any later version.
76+ *
77+ */
78+
79+#include <linux/kernel.h>
80+#include <linux/module.h>
81+#include <linux/interrupt.h>
82+#include <linux/platform_device.h>
83+#include <asm/mcfsim.h>
84+
85+
86+static struct resource mcf5441x_can0_resources[] = {
87+ [0] = {
88+ .start = 0xFC020000,
89+ .end = 0xFC0208C0,
90+ .flags = IORESOURCE_MEM,
91+ },
92+ [1] = {
93+ .start = 0 + 64 + 64,
94+ .end = 0 + 64 + 64,
95+ .flags = IORESOURCE_IRQ,
96+ },
97+};
98+
99+static struct resource mcf5441x_can1_resources[] = {
100+ [0] = {
101+ .start = 0xFC024000,
102+ .end = 0xFC0248C0,
103+ .flags = IORESOURCE_MEM,
104+ },
105+ [1] = {
106+ .start = 4 + 64 + 64,
107+ .end = 4 + 64 + 64,
108+ .flags = IORESOURCE_IRQ,
109+ },
110+};
111+
112+static struct platform_device mcf_flexcan[PDEV_MAX] = {
113+ [0] = {
114+ .name = "flexcan",
115+ .id = 0,
116+ .num_resources = ARRAY_SIZE(mcf5441x_can0_resources),
117+ .resource = mcf5441x_can0_resources,
118+ },
119+ [1] = {
120+ .name = "flexcan",
121+ .id = 1,
122+ .num_resources = ARRAY_SIZE(mcf5441x_can1_resources),
123+ .resource = mcf5441x_can1_resources,
124+ },
125+
126+};
127+
128+
129+static void __init mcf_flexcan_config(void)
130+{
131+ MCF_PM_PPMCR0 = 8; /* enable FlexCAN0 clock */
132+ MCF_PM_PPMCR0 = 9; /* enable FlexCAN1 clock */
133+
134+ /* CAN0 */
135+ MCF_GPIO_PAR_CANI2C =
136+ (MCF_GPIO_PAR_CANI2C & MCF_GPIO_PAR_CANI2C_I2C0SCL_MASK) |
137+ MCF_GPIO_PAR_CANI2C_I2C0SCL_CAN0TX;
138+ MCF_GPIO_PAR_CANI2C =
139+ (MCF_GPIO_PAR_CANI2C & MCF_GPIO_PAR_CANI2C_I2C0SDA_MASK) |
140+ MCF_GPIO_PAR_CANI2C_I2C0SDA_CAN0RX;
141+ /* CAN1 */
142+ MCF_GPIO_PAR_CANI2C =
143+ (MCF_GPIO_PAR_CANI2C & MCF_GPIO_PAR_CANI2C_CAN1TX_MASK) |
144+ MCF_GPIO_PAR_CANI2C_CAN1TX_CAN1TX;
145+ MCF_GPIO_PAR_CANI2C =
146+ (MCF_GPIO_PAR_CANI2C & MCF_GPIO_PAR_CANI2C_CAN1RX_MASK) |
147+ MCF_GPIO_PAR_CANI2C_CAN1RX_CAN1RX;
148+
149+
150+}
151+
152+static int __init flexcan_of_to_pdev(void)
153+{
154+ int i, err = -ENODEV;
155+ for (i = 0; i < PDEV_MAX; i++) {
156+ err = platform_device_register(&mcf_flexcan[i]);
157+ if (err)
158+ return err;
159+ printk(KERN_INFO "ColdFire FlexCAN devices loaded\n");
160+ }
161+ return err;
162+}
163+
164+static int __init mcf_flexcan_init(void)
165+{
166+ int err;
167+ mcf_flexcan_config();
168+ err = flexcan_of_to_pdev();
169+
170+ return 0;
171+}
172+
173+arch_initcall(mcf_flexcan_init);
174--- a/arch/m68k/coldfire/m547x/Makefile
175+++ b/arch/m68k/coldfire/m547x/Makefile
176@@ -5,3 +5,6 @@
177 obj-$(CONFIG_M547X_8X) += config.o mcf548x-devices.o devices.o
178 obj-$(CONFIG_PCI) += pci.o pci_dummy.o
179 obj-$(CONFIG_MCD_DMA) += dma.o
180+ifneq ($(CONFIG_CAN_FLEXCAN),)
181+obj-y += mcf-flexcan.o
182+endif
183--- /dev/null
184+++ b/arch/m68k/coldfire/m547x/mcf-flexcan.c
185@@ -0,0 +1,117 @@
186+/*
187+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved.
188+ *
189+ * Author: Huan Wang, b18965@freescale.com, Fri Aug 08 2008
190+ *
191+ * Description:
192+ * CAN bus driver for Freescale Coldfire embedded CPU
193+ *
194+ * Changelog:
195+ * Fri Aug 08 2008 Huan Wang <b18965@freescale.com>
196+ * - create, support for MCF548x
197+ *
198+ * Tue Dec 08 2009 ChengJu Cai <b22600@freescale.com>
199+ * - support for MCF532x MCF5253 MCF5227x
200+ *
201+ * July 2011 Jingchang.Lu <b35083@freescale.com>
202+ * - Add into kernel CAN driver layer
203+ *
204+ * This file is part of the Linux kernel
205+ * This is free software; you can redistribute it and/or modify
206+ * it under the terms of the GNU General Public License as published by
207+ * the Free Software Foundation; either version 2 of the License, or
208+ * (at your option) any later version.
209+ *
210+ */
211+
212+#include <linux/kernel.h>
213+#include <linux/module.h>
214+#include <linux/interrupt.h>
215+#include <linux/platform_device.h>
216+#include <asm/mcfsim.h>
217+
218+
219+static struct resource mcf548x_can0_resources[] = {
220+ [0] = {
221+ .start = MCF_MBAR + 0x0000A000,
222+ .end = MCF_MBAR + 0x0000A7FF,
223+ .flags = IORESOURCE_MEM,
224+ },
225+ [1] = {
226+ .start = 49 + 64,
227+ .end = 49 + 64,
228+ .flags = IORESOURCE_IRQ,
229+ },
230+};
231+
232+static struct resource mcf548x_can1_resources[] = {
233+ [0] = {
234+ .start = MCF_MBAR + 0x0000A800,
235+ .end = MCF_MBAR + 0x0000AFFF,
236+ .flags = IORESOURCE_MEM,
237+ },
238+ [1] = {
239+ .start = 55 + 64,
240+ .end = 55 + 64,
241+ .flags = IORESOURCE_IRQ,
242+ },
243+};
244+
245+static struct platform_device mcf_flexcan[PDEV_MAX] = {
246+ [0] = {
247+ .name = "flexcan",
248+ .id = 0,
249+ .num_resources = ARRAY_SIZE(mcf548x_can1_resources),
250+ .resource = mcf548x_can0_resources,
251+ },
252+ [1] = {
253+ .name = "flexcan",
254+ .id = 1,
255+ .num_resources = ARRAY_SIZE(mcf548x_can1_resources),
256+ .resource = mcf548x_can1_resources,
257+ },
258+
259+};
260+
261+
262+static void __init mcf_flexcan_config(void)
263+{
264+ int i;
265+ MCF_PAR_TIMER = MCF_PAR_TIMER | 0x28;
266+ MCF_PAR_TIMER = MCF_PAR_TIMER & 0xf8;
267+ MCF_PAR_DSPI = MCF_PAR_DSPI | 0x0a00;
268+ MCF_PAR_FECI2CIRQ = MCF_PAR_FECI2CIRQ | 0x0283;
269+ MCF_PAR_PSCn(2) = MCF_PAR_PSCn(2) & 0x0f;
270+ MCF_PAR_PSCn(2) = MCF_PAR_PSCn(2) | 0x50;
271+
272+ for (i = 0; i < 2; i++) {
273+ MCF_ICR(ISC_CANn_MBOR(i)) = 0x33 + 0x01 * i;
274+ MCF_ICR(ISC_CANn_ERR(i)) = 0x33 + 0x01 * i;
275+ MCF_ICR(ISC_CANn_BUSOFF(i)) = 0x33 + 0x01 * i;
276+ }
277+
278+
279+}
280+
281+static int __init flexcan_of_to_pdev(void)
282+{
283+ int i, err = -ENODEV;
284+ for (i = 0; i < PDEV_MAX; i++) {
285+ err = platform_device_register(&mcf_flexcan[i]);
286+ if (err)
287+ return err;
288+ printk(KERN_INFO "ColdFire FlexCAN devices loaded\n");
289+ }
290+ return err;
291+}
292+
293+static int __init mcf_flexcan_init(void)
294+{
295+ int err;
296+ mcf_flexcan_config();
297+ err = flexcan_of_to_pdev();
298+
299+ return 0;
300+}
301+
302+arch_initcall(mcf_flexcan_init);
303--- a/drivers/net/can/Kconfig
304+++ b/drivers/net/can/Kconfig
305@@ -103,6 +103,15 @@ config CAN_FLEXCAN
306     ---help---
307       Say Y here if you want to support for Freescale FlexCAN.
308 
309+config FLEXCAN_NORXFIFO
310+ bool "FlexCAN message buffer without Rx FIFO mode"
311+ depends on CAN_FLEXCAN && COLDFIRE
312+ default n
313+ ---help---
314+ Say Y here if you FlexCAN message buffer has no Rx FIFO mode.
315+ Freescale Coldfire series have different FlexCAN core version,
316+ MCF54418's support Rx FIFO mode while others such as MCF5485 not.
317+
318 config PCH_CAN
319     tristate "PCH CAN"
320     depends on CAN_DEV && PCI
321--- a/drivers/net/can/flexcan.c
322+++ b/drivers/net/can/flexcan.c
323@@ -4,6 +4,7 @@
324  * Copyright (c) 2005-2006 Varma Electronics Oy
325  * Copyright (c) 2009 Sascha Hauer, Pengutronix
326  * Copyright (c) 2010 Marc Kleine-Budde, Pengutronix
327+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved.
328  *
329  * Based on code originally by Andrey Volkov <avolkov@varma-el.com>
330  *
331@@ -35,8 +36,28 @@
332 #include <linux/module.h>
333 #include <linux/platform_device.h>
334 
335+#ifndef CONFIG_COLDFIRE
336 #include <mach/clock.h>
337 
338+#else
339+#include <asm/mcfsim.h>
340+
341+#undef readb
342+#undef readw
343+#undef readl
344+#define readb(addr) __raw_readb(addr)
345+#define readw(addr) __raw_readw(addr)
346+#define readl(addr) __raw_readl(addr)
347+
348+#undef writeb
349+#undef writew
350+#undef writel
351+#define writeb(b, addr) __raw_writeb(b, addr)
352+#define writew(b, addr) __raw_writew(b, addr)
353+#define writel(b, addr) __raw_writel(b, addr)
354+
355+#endif
356+
357 #define DRV_NAME "flexcan"
358 
359 /* 8 for RX fifo and 2 error handling */
360@@ -85,12 +106,34 @@
361 #define FLEXCAN_CTRL_LOM BIT(3)
362 #define FLEXCAN_CTRL_PROPSEG(x) ((x) & 0x07)
363 #define FLEXCAN_CTRL_ERR_BUS (FLEXCAN_CTRL_ERR_MSK)
364+
365+#ifdef CONFIG_COLDFIRE
366+
367+# if defined(CONFIG_M548X)
368+
369+#define FLEXCAN_CTRL_ERR_STATE FLEXCAN_CTRL_BOFF_MSK
370+#define FLEXCAN_CTRL_ERR_ALL \
371+ (FLEXCAN_CTRL_BOFF_MSK | FLEXCAN_CTRL_ERR_MSK)
372+
373+# elif defined(CONFIG_M5441X)
374+
375 #define FLEXCAN_CTRL_ERR_STATE \
376     (FLEXCAN_CTRL_TWRN_MSK | FLEXCAN_CTRL_RWRN_MSK | \
377      FLEXCAN_CTRL_BOFF_MSK)
378 #define FLEXCAN_CTRL_ERR_ALL \
379     (FLEXCAN_CTRL_ERR_BUS | FLEXCAN_CTRL_ERR_STATE)
380 
381+# endif
382+
383+#else /* !CONFIG_COLDFIRE */
384+
385+#define FLEXCAN_CTRL_ERR_STATE \
386+ (FLEXCAN_CTRL_TWRN_MSK | FLEXCAN_CTRL_RWRN_MSK | \
387+ FLEXCAN_CTRL_BOFF_MSK)
388+#define FLEXCAN_CTRL_ERR_ALL \
389+ (FLEXCAN_CTRL_ERR_BUS | FLEXCAN_CTRL_ERR_STATE)
390+
391+#endif
392 /* FLEXCAN error and status register (ESR) bits */
393 #define FLEXCAN_ESR_TWRN_INT BIT(17)
394 #define FLEXCAN_ESR_RWRN_INT BIT(16)
395@@ -121,6 +164,18 @@
396     (FLEXCAN_ESR_ERR_BUS | FLEXCAN_ESR_ERR_STATE)
397 
398 /* FLEXCAN interrupt flag register (IFLAG) bits */
399+
400+#ifdef CONFIG_FLEXCAN_NORXFIFO
401+
402+/* MB assignment for no Rx FIFO mode module */
403+#define FLEXCAN_TX_BUF_ID 0
404+#define FLEXCAN_RX_EXT_ID 15
405+#define FLEXCAN_IFLAG_RX_FIFO_AVAILABLE 0xfffe
406+#define FLEXCAN_IFLAG_DEFAULT \
407+ (FLEXCAN_IFLAG_RX_FIFO_AVAILABLE | (0x01 << FLEXCAN_TX_BUF_ID))
408+
409+#else
410+
411 #define FLEXCAN_TX_BUF_ID 8
412 #define FLEXCAN_IFLAG_BUF(x) BIT(x)
413 #define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW BIT(7)
414@@ -130,6 +185,7 @@
415     (FLEXCAN_IFLAG_RX_FIFO_OVERFLOW | FLEXCAN_IFLAG_RX_FIFO_AVAILABLE | \
416      FLEXCAN_IFLAG_BUF(FLEXCAN_TX_BUF_ID))
417 
418+#endif
419 /* FLEXCAN message buffers */
420 #define FLEXCAN_MB_CNT_CODE(x) (((x) & 0xf) << 24)
421 #define FLEXCAN_MB_CNT_SRR BIT(22)
422@@ -163,7 +219,11 @@ struct flexcan_regs {
423     u32 iflag2; /* 0x2c */
424     u32 iflag1; /* 0x30 */
425     u32 _reserved2[19];
426+#ifdef CONFIG_COLDFIRE
427+ struct flexcan_mb cantxfg[CAN_MB];
428+#else
429     struct flexcan_mb cantxfg[64];
430+#endif
431 };
432 
433 struct flexcan_priv {
434@@ -181,8 +241,13 @@ struct flexcan_priv {
435 
436 static struct can_bittiming_const flexcan_bittiming_const = {
437     .name = DRV_NAME,
438+#ifdef CONFIG_COLDFIRE
439+ .tseg1_min = 1,
440+ .tseg1_max = 8,
441+#else
442     .tseg1_min = 4,
443     .tseg1_max = 16,
444+#endif
445     .tseg2_min = 2,
446     .tseg2_max = 8,
447     .sjw_max = 4,
448@@ -248,7 +313,7 @@ static int flexcan_start_xmit(struct sk_
449     struct net_device_stats *stats = &dev->stats;
450     struct flexcan_regs __iomem *regs = priv->base;
451     struct can_frame *cf = (struct can_frame *)skb->data;
452- u32 can_id;
453+ u32 can_id, tmp, tmp1;
454     u32 ctrl = FLEXCAN_MB_CNT_CODE(0xc) | (cf->can_dlc << 16);
455 
456     if (can_dropped_invalid_skb(dev, skb))
457@@ -259,6 +324,11 @@ static int flexcan_start_xmit(struct sk_
458     if (cf->can_id & CAN_EFF_FLAG) {
459         can_id = cf->can_id & CAN_EFF_MASK;
460         ctrl |= FLEXCAN_MB_CNT_IDE | FLEXCAN_MB_CNT_SRR;
461+#ifdef CONFIG_COLDFIRE
462+ tmp = (can_id & CAN_SFF_MASK) << 18;
463+ tmp1 = can_id >> 11;
464+ can_id = tmp | tmp1;
465+#endif
466     } else {
467         can_id = (cf->can_id & CAN_SFF_MASK) << 18;
468     }
469@@ -456,6 +526,87 @@ static int flexcan_poll_state(struct net
470     return 1;
471 }
472 
473+#ifdef CONFIG_FLEXCAN_NORXFIFO
474+/* Get one frame from receive message buffer */
475+static int flexcan_read_frame(struct net_device *dev)
476+{
477+ const struct flexcan_priv *priv = netdev_priv(dev);
478+ struct flexcan_regs __iomem *regs = priv->base;
479+ struct net_device_stats *stats = &dev->stats;
480+ struct can_frame *cf;
481+ struct sk_buff *skb;
482+ struct flexcan_mb __iomem *mb;
483+ u32 reg_iflag1, reg_ctrl, reg_id, i;
484+
485+ reg_iflag1 = readl(&regs->iflag1);
486+
487+ /* buf[0] if for TX */
488+ for (i = 0; i < CAN_MB; i++) {
489+ if (i == FLEXCAN_TX_BUF_ID)
490+ continue;
491+ /* find one received message slot */
492+ if (reg_iflag1 & (0x01 << i))
493+ break;
494+ }
495+ if (i >= CAN_MB)
496+ return 0;
497+
498+ mb = &regs->cantxfg[i];
499+
500+ skb = alloc_can_skb(dev, &cf);
501+ if (unlikely(!skb)) {
502+ stats->rx_dropped++;
503+ return 0;
504+ }
505+
506+ reg_ctrl = readl(&mb->can_ctrl);
507+ reg_id = readl(&mb->can_id);
508+
509+ /* deactive RX buff */
510+ writel(0, &mb->can_ctrl);
511+
512+ if (reg_ctrl & FLEXCAN_MB_CNT_IDE) {
513+#ifdef CONFIG_COLDFIRE
514+ /* Coldfire can_id order */
515+ cf->can_id = (reg_id & CAN_EFF_MASK) >> 18;
516+ cf->can_id |= (reg_id & 0x3ffff) << 11;
517+ cf->can_id |= CAN_EFF_FLAG;
518+#else
519+ cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
520+#endif
521+ } else
522+ cf->can_id = (reg_id >> 18) & CAN_SFF_MASK;
523+
524+ if (reg_ctrl & FLEXCAN_MB_CNT_RTR)
525+ cf->can_id |= CAN_RTR_FLAG;
526+ cf->can_dlc = get_can_dlc((reg_ctrl >> 16) & 0xf);
527+
528+ *(__be32 *)(cf->data + 0) = cpu_to_be32(readl(&mb->data[0]));
529+ *(__be32 *)(cf->data + 4) = cpu_to_be32(readl(&mb->data[1]));
530+
531+ /* reactive RX buffer */
532+ if (i == FLEXCAN_RX_EXT_ID)
533+ writel(FLEXCAN_MB_CNT_CODE(0x4)|0x600000,
534+ &regs->cantxfg[i].can_ctrl);
535+ else
536+ writel(FLEXCAN_MB_CNT_CODE(0x4),
537+ &regs->cantxfg[i].can_ctrl);
538+
539+ /* mark as read */
540+ writel((0x01 << i), &regs->iflag1);
541+ /* release MB lock */
542+ readl(&regs->timer);
543+
544+ netif_receive_skb(skb);
545+
546+ stats->rx_packets++;
547+ stats->rx_bytes += cf->can_dlc;
548+
549+ return 1;
550+
551+}
552+#else
553+
554 static void flexcan_read_fifo(const struct net_device *dev,
555                   struct can_frame *cf)
556 {
557@@ -466,9 +617,16 @@ static void flexcan_read_fifo(const stru
558 
559     reg_ctrl = readl(&mb->can_ctrl);
560     reg_id = readl(&mb->can_id);
561- if (reg_ctrl & FLEXCAN_MB_CNT_IDE)
562+ if (reg_ctrl & FLEXCAN_MB_CNT_IDE) {
563+#ifdef CONFIG_COLDFIRE
564+ /* ColdFire can_id order as follow */
565+ cf->can_id = (reg_id & CAN_EFF_MASK) >> 18;
566+ cf->can_id |= (reg_id & 0x3ffff) << 11;
567+ cf->can_id |= CAN_EFF_FLAG;
568+#else
569         cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
570- else
571+#endif
572+ } else
573         cf->can_id = (reg_id >> 18) & CAN_SFF_MASK;
574 
575     if (reg_ctrl & FLEXCAN_MB_CNT_RTR)
576@@ -503,6 +661,7 @@ static int flexcan_read_frame(struct net
577 
578     return 1;
579 }
580+#endif
581 
582 static int flexcan_poll(struct napi_struct *napi, int quota)
583 {
584@@ -554,6 +713,14 @@ static irqreturn_t flexcan_irq(int irq,
585     reg_iflag1 = readl(&regs->iflag1);
586     reg_esr = readl(&regs->esr);
587     writel(FLEXCAN_ESR_ERR_INT, &regs->esr); /* ACK err IRQ */
588+#ifdef CONFIG_COLDFIRE
589+#ifdef CONFIG_FLEXCAN_NORXFIFO
590+ writel(FLEXCAN_ESR_BOFF_INT, &regs->esr);
591+#else
592+ /* ACK TWRN and RWRN error, and bus-off interrupt*/
593+ writel(FLEXCAN_ESR_ERR_STATE, &regs->esr);
594+#endif
595+#endif
596 
597     /*
598      * schedule NAPI in case of:
599@@ -575,13 +742,14 @@ static irqreturn_t flexcan_irq(int irq,
600                &regs->ctrl);
601         napi_schedule(&priv->napi);
602     }
603-
604+#ifndef CONFIG_FLEXCAN_NORXFIFO
605     /* FIFO overflow */
606     if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) {
607         writel(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, &regs->iflag1);
608         dev->stats.rx_over_errors++;
609         dev->stats.rx_errors++;
610     }
611+#endif
612 
613     /* transmission complete interrupt */
614     if (reg_iflag1 & (1 << FLEXCAN_TX_BUF_ID)) {
615@@ -676,9 +844,14 @@ static int flexcan_chip_start(struct net
616      *
617      */
618     reg_mcr = readl(&regs->mcr);
619+#ifdef CONFIG_FLEXCAN_NORXFIFO
620+ reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT |
621+ FLEXCAN_MCR_SUPV;
622+#else
623     reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
624         FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
625         FLEXCAN_MCR_IDAM_C;
626+#endif
627     dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr);
628     writel(reg_mcr, &regs->mcr);
629 
630@@ -713,9 +886,19 @@ static int flexcan_chip_start(struct net
631         writel(0, &regs->cantxfg[i].can_id);
632         writel(0, &regs->cantxfg[i].data[0]);
633         writel(0, &regs->cantxfg[i].data[1]);
634-
635+#ifdef CONFIG_FLEXCAN_NORXFIFO
636+ if (i == FLEXCAN_TX_BUF_ID)
637+ continue;
638+ if (i == FLEXCAN_RX_EXT_ID) /* enable receive extend message */
639+ writel(FLEXCAN_MB_CNT_CODE(0x4)|0x600000,
640+ &regs->cantxfg[i].can_ctrl);
641+ else
642+ writel(FLEXCAN_MB_CNT_CODE(0x4),
643+ &regs->cantxfg[i].can_ctrl);
644+#else
645         /* put MB into rx queue */
646         writel(FLEXCAN_MB_CNT_CODE(0x4), &regs->cantxfg[i].can_ctrl);
647+#endif
648     }
649 
650     /* acceptance mask/acceptance code (accept everything) */
651@@ -772,6 +955,7 @@ static void flexcan_chip_stop(struct net
652     return;
653 }
654 
655+
656 static int flexcan_open(struct net_device *dev)
657 {
658     struct flexcan_priv *priv = netdev_priv(dev);
659@@ -786,6 +970,24 @@ static int flexcan_open(struct net_devic
660     err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
661     if (err)
662         goto out_close;
663+ err = request_irq(dev->irq + 1, flexcan_irq, \
664+ IRQF_DISABLED, dev->name, dev);
665+ if (err) {
666+ free_irq(dev->irq, dev);
667+ goto out_close;
668+ }
669+#if defined(CONFIG_M548X)
670+ err = request_irq(dev->irq + 2, flexcan_irq, \
671+ IRQF_DISABLED, dev->name, dev);
672+#elif defined(CONFIG_M5441X)
673+ err = request_irq(dev->irq + 3, flexcan_irq, \
674+ IRQF_DISABLED, dev->name, dev);
675+#endif
676+ if (err) {
677+ free_irq(dev->irq, dev);
678+ free_irq(dev->irq + 1, dev);
679+ goto out_close;
680+ }
681 
682     /* start chip and queuing */
683     err = flexcan_chip_start(dev);
684@@ -813,6 +1015,14 @@ static int flexcan_close(struct net_devi
685     flexcan_chip_stop(dev);
686 
687     free_irq(dev->irq, dev);
688+#ifdef CONFIG_COLDFIRE
689+ free_irq(dev->irq + 1, dev);
690+#if defined(CONFIG_M548X)
691+ free_irq(dev->irq + 2, dev);
692+#elif defined(CONFIG_M5441X)
693+ free_irq(dev->irq + 3, dev);
694+#endif
695+#endif
696     clk_disable(priv->clk);
697 
698     close_candev(dev);
699@@ -854,14 +1064,23 @@ static int __devinit register_flexcandev
700 
701     clk_enable(priv->clk);
702 
703+#if !defined(CONFIG_M548X)
704     /* select "bus clock", chip must be disabled */
705     flexcan_chip_disable(priv);
706     reg = readl(&regs->ctrl);
707     reg |= FLEXCAN_CTRL_CLK_SRC;
708     writel(reg, &regs->ctrl);
709+#endif
710 
711     flexcan_chip_enable(priv);
712 
713+#ifdef CONFIG_FLEXCAN_NORXFIFO
714+ /* set freeze, halt and restrict register access */
715+ reg = readl(&regs->mcr);
716+ reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT |
717+ FLEXCAN_MCR_SUPV;
718+ writel(reg, &regs->mcr);
719+#else
720     /* set freeze, halt and activate FIFO, restrict register access */
721     reg = readl(&regs->mcr);
722     reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT |
723@@ -880,6 +1099,7 @@ static int __devinit register_flexcandev
724         err = -ENODEV;
725         goto out;
726     }
727+#endif
728 
729     err = register_candev(dev);
730 
731@@ -901,17 +1121,19 @@ static int __devinit flexcan_probe(struc
732     struct net_device *dev;
733     struct flexcan_priv *priv;
734     struct resource *mem;
735- struct clk *clk;
736+ struct clk *clk = NULL;
737     void __iomem *base;
738     resource_size_t mem_size;
739     int err, irq;
740 
741+#ifndef CONFIG_COLDFIRE
742     clk = clk_get(&pdev->dev, NULL);
743     if (IS_ERR(clk)) {
744         dev_err(&pdev->dev, "no clock defined\n");
745         err = PTR_ERR(clk);
746         goto failed_clock;
747     }
748+#endif
749 
750     mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
751     irq = platform_get_irq(pdev, 0);
752@@ -943,7 +1165,12 @@ static int __devinit flexcan_probe(struc
753     dev->flags |= IFF_ECHO; /* we support local echo in hardware */
754 
755     priv = netdev_priv(dev);
756+#ifdef CONFIG_COLDFIRE
757+ /* return value is core clock but we need bus clock */
758+ priv->can.clock.freq = (clk_get_rate(clk)/2);
759+#else
760     priv->can.clock.freq = clk_get_rate(clk);
761+#endif
762     priv->can.bittiming_const = &flexcan_bittiming_const;
763     priv->can.do_set_mode = flexcan_set_mode;
764     priv->can.do_get_berr_counter = flexcan_get_berr_counter;
765

Archive Download this file



interactive