Message ID | 1431603215-25546-6-git-send-email-bhupesh.sharma@freescale.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 05/14/2015 01:33 PM, Bhupesh Sharma wrote: > This patch adds support for non RX-FIFO (legacy) mode in > the flexcan driver. > > On certain SoCs, the RX-FIFO support might be broken, as > a result we need to fall-back on the legacy (non RX-FIFO) > mode to receive CAN frames. > > Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com> > Signed-off-by: Sakar Arora <Sakar.Arora@freescale.com> The non FIFO mode doesn't guarantee the order of the incoming frames, not does not even try to...this is not acceptable. I'm currently working on a patch by David Jander that brings in non FIFO mode, but tries to keep the order of the frames. Marc
> -----Original Message----- > From: Marc Kleine-Budde [mailto:mkl@pengutronix.de] > Sent: Thursday, May 14, 2015 9:12 PM > To: Sharma Bhupesh-B45370; arnd@arndb.de; linux-can@vger.kernel.org > Cc: bhupesh.linux@gmail.com; Arora Sakar-B45205; linux-arm- > kernel@lists.infradead.org > Subject: Re: [PATCH v2 5/5] can: flexcan: Add support for non RX-FIFO > mode > > On 05/14/2015 01:33 PM, Bhupesh Sharma wrote: > > This patch adds support for non RX-FIFO (legacy) mode in the flexcan > > driver. > > > > On certain SoCs, the RX-FIFO support might be broken, as a result we > > need to fall-back on the legacy (non RX-FIFO) mode to receive CAN > > frames. > > > > Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com> > > Signed-off-by: Sakar Arora <Sakar.Arora@freescale.com> > > The non FIFO mode doesn't guarantee the order of the incoming frames, not > does not even try to...this is not acceptable. I'm currently working on a > patch by David Jander that brings in non FIFO mode, but tries to keep the > order of the frames. That is already WIP at our end. V3 will contain the same change. If you are already working on it, I don't know how to proceed further as we had already v1 of this patchset with the non FIFO mode out since a month or so. Regards, Bhupesh
On 15/05/15 01:41, Marc Kleine-Budde wrote: > On 05/14/2015 01:33 PM, Bhupesh Sharma wrote: >> This patch adds support for non RX-FIFO (legacy) mode in >> the flexcan driver. >> >> On certain SoCs, the RX-FIFO support might be broken, as >> a result we need to fall-back on the legacy (non RX-FIFO) >> mode to receive CAN frames. >> >> Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com> >> Signed-off-by: Sakar Arora <Sakar.Arora@freescale.com> > > The non FIFO mode doesn't guarantee the order of the incoming frames, > not does not even try to...this is not acceptable. I'm currently working > on a patch by David Jander that brings in non FIFO mode, but tries to > keep the order of the frames. > > Marc In case it is of any help as a reference, here's a thread on the problems of receiving messages in order on another non-FIFO chip. This applies to the normal Microchip CAN controllers, in this case the very-hard-to-program on-the-end-of-an-SPI-bus MCP2515: http://www.microchip.com/forums/tm.aspx?m=620741 It has two receive buffers, and a "rollover" setting. This does not make the registers operate as a FIFO and it needs a state machine to keep track of which buffer holds which sequence message. Tom
Hi Mark, > -----Original Message----- > From: linux-arm-kernel [mailto:linux-arm-kernel- > bounces@lists.infradead.org] On Behalf Of Sharma Bhupesh > Sent: Thursday, May 14, 2015 9:14 PM > To: Marc Kleine-Budde; arnd@arndb.de; linux-can@vger.kernel.org > Cc: bhupesh.linux@gmail.com; linux-arm-kernel@lists.infradead.org; Arora > Sakar-B45205 > Subject: RE: [PATCH v2 5/5] can: flexcan: Add support for non RX-FIFO > mode > > > -----Original Message----- > > From: Marc Kleine-Budde [mailto:mkl@pengutronix.de] > > Sent: Thursday, May 14, 2015 9:12 PM > > To: Sharma Bhupesh-B45370; arnd@arndb.de; linux-can@vger.kernel.org > > Cc: bhupesh.linux@gmail.com; Arora Sakar-B45205; linux-arm- > > kernel@lists.infradead.org > > Subject: Re: [PATCH v2 5/5] can: flexcan: Add support for non RX-FIFO > > mode > > > > On 05/14/2015 01:33 PM, Bhupesh Sharma wrote: > > > This patch adds support for non RX-FIFO (legacy) mode in the flexcan > > > driver. > > > > > > On certain SoCs, the RX-FIFO support might be broken, as a result we > > > need to fall-back on the legacy (non RX-FIFO) mode to receive CAN > > > frames. > > > > > > Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com> > > > Signed-off-by: Sakar Arora <Sakar.Arora@freescale.com> > > > > The non FIFO mode doesn't guarantee the order of the incoming frames, > > not does not even try to...this is not acceptable. I'm currently > > working on a patch by David Jander that brings in non FIFO mode, but > > tries to keep the order of the frames. > > That is already WIP at our end. V3 will contain the same change. > If you are already working on it, I don't know how to proceed further as > we had already v1 of this patchset with the non FIFO mode out since a > month or so. I don't remember seeing a patch from you which supports non-FIFO mode for flexcan IP. Since we now have Freescale LS1021A chip out in the field on which the FIFO mode broken, we cannot use the upstream flexcan driver for enabling flexcan IP on these chips. Do you still have plans to work on this? Or should I submit my v3 with in-order reception supported for rx frames. Regards, Bhupesh
On 12/10/2015 12:05 PM, Sharma Bhupesh wrote: >>> -----Original Message----- >>> From: Marc Kleine-Budde [mailto:mkl@pengutronix.de] >>> Sent: Thursday, May 14, 2015 9:12 PM >>> To: Sharma Bhupesh-B45370; arnd@arndb.de; linux-can@vger.kernel.org >>> Cc: bhupesh.linux@gmail.com; Arora Sakar-B45205; linux-arm- >>> kernel@lists.infradead.org >>> Subject: Re: [PATCH v2 5/5] can: flexcan: Add support for non RX-FIFO >>> mode >>> >>> On 05/14/2015 01:33 PM, Bhupesh Sharma wrote: >>>> This patch adds support for non RX-FIFO (legacy) mode in the flexcan >>>> driver. >>>> >>>> On certain SoCs, the RX-FIFO support might be broken, as a result we >>>> need to fall-back on the legacy (non RX-FIFO) mode to receive CAN >>>> frames. >>>> >>>> Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com> >>>> Signed-off-by: Sakar Arora <Sakar.Arora@freescale.com> >>> >>> The non FIFO mode doesn't guarantee the order of the incoming frames, >>> not does not even try to...this is not acceptable. I'm currently >>> working on a patch by David Jander that brings in non FIFO mode, but >>> tries to keep the order of the frames. >> >> That is already WIP at our end. V3 will contain the same change. >> If you are already working on it, I don't know how to proceed further as >> we had already v1 of this patchset with the non FIFO mode out since a >> month or so. > > I don't remember seeing a patch from you which supports non-FIFO mode for flexcan IP. > Since we now have Freescale LS1021A chip out in the field on which the FIFO mode broken, > we cannot use the upstream flexcan driver for enabling flexcan IP on these chips. > > Do you still have plans to work on this? Or should I submit my v3 with in-order reception > supported for rx frames. The problem is, that the current code triggers a ordering issue (at least on the imx6) in non FIFO mode. The frames are not received as the documentation states. If you have access, take a look at "SR# 1-4074792564 : CAN Ordering Issues". It seems the freescale support doesn't have much interest in confirming the issue, nor bringing us in touch with the people who have access to the IP core source to see what's going on. If we have to rely on the timestamps the next logical step is to add sorting by timestamp to the rx-fifo implementation. I'll send a patch series of the current state. regards, Marc
> -----Original Message----- > From: Marc Kleine-Budde [mailto:mkl@pengutronix.de] > Sent: Thursday, December 10, 2015 5:49 PM > > On 12/10/2015 12:05 PM, Sharma Bhupesh wrote: > >>> -----Original Message----- > >>> From: Marc Kleine-Budde [mailto:mkl@pengutronix.de] > >>> Sent: Thursday, May 14, 2015 9:12 PM > >>> To: Sharma Bhupesh-B45370; arnd@arndb.de; linux-can@vger.kernel.org > >>> Cc: bhupesh.linux@gmail.com; Arora Sakar-B45205; linux-arm- > >>> kernel@lists.infradead.org > >>> Subject: Re: [PATCH v2 5/5] can: flexcan: Add support for non > >>> RX-FIFO mode > >>> > >>> On 05/14/2015 01:33 PM, Bhupesh Sharma wrote: > >>>> This patch adds support for non RX-FIFO (legacy) mode in the > >>>> flexcan driver. > >>>> > >>>> On certain SoCs, the RX-FIFO support might be broken, as a result > >>>> we need to fall-back on the legacy (non RX-FIFO) mode to receive > >>>> CAN frames. > >>>> > >>>> Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com> > >>>> Signed-off-by: Sakar Arora <Sakar.Arora@freescale.com> > >>> > >>> The non FIFO mode doesn't guarantee the order of the incoming > >>> frames, not does not even try to...this is not acceptable. I'm > >>> currently working on a patch by David Jander that brings in non FIFO > >>> mode, but tries to keep the order of the frames. > >> > >> That is already WIP at our end. V3 will contain the same change. > >> If you are already working on it, I don't know how to proceed further > >> as we had already v1 of this patchset with the non FIFO mode out > >> since a month or so. > > > > I don't remember seeing a patch from you which supports non-FIFO mode > for flexcan IP. > > Since we now have Freescale LS1021A chip out in the field on which the > > FIFO mode broken, we cannot use the upstream flexcan driver for > enabling flexcan IP on these chips. > > > > Do you still have plans to work on this? Or should I submit my v3 with > > in-order reception supported for rx frames. > > The problem is, that the current code triggers a ordering issue (at least > on the imx6) in non FIFO mode. The frames are not received as the > documentation states. If you have access, take a look at "SR# > 1-4074792564 : CAN Ordering Issues". It seems the freescale support > doesn't have much interest in confirming the issue, nor bringing us in > touch with the people who have access to the IP core source to see what's > going on. > > If we have to rely on the timestamps the next logical step is to add > sorting by timestamp to the rx-fifo implementation. I'll send a patch > series of the current state. With my current v3, I see no rx-frame ordering issues atleast on LS1021A. I can ask internally about more details on the "SR# 1-4074792564 : CAN Ordering Issues". Regards, Bhupesh
On 12/10/2015 12:44 PM, Tom Evans wrote: > I've just had to delve back into the deep murky past and try to get > Freescale's Kernel 2.6.35 FlexCAN driver working. That's because the > only code base that supports Freescale's Video Hardware is that one and > we need working video. 2.6.x I feel your pain. Another option would be to port the flexcan driver to that old kernel. But I'm getting off topic here :) > I'm suggesting this code as an "historical reference" that might be > useful for anyone looking for simple/simplistic ways to handle a FlexCAN > port. It isn't like the driver actually works fully. It can't have ever > been tested very much. Which is why I've had to fix it. > > It has the Driver, Register handling and Message Buffer handling split > into three separate source files, which is a useful simplification. YMMV :) > It can't be configured with "canconfig", but exposes a huge number of > variables in the sysfs which is actually quite powerful and extendable. > > Freescale's "2.6.35_maintain" kernel consists of 2.6.35 plus about 1200 > Freescale patches which basically replace all the hardware drivers. > > The source for this driver in this tree (until someone renames it to NXP): > > http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/log/?h=imx_2.6.35_maintain > > The Driver is in the expected place: > > http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/tree/drivers/net/can/flexcan?h=imx_2.6.35_maintain > > 1 - It defaults to 32 receive and 32 transmit MBs, but that can be changed. > > 2 - It can't receive in order, but you'd only need to sort on the > timestamps to fix that (or use the FIFO). In order reception is crucial. > 3 - It can't transmit in order either (unless you drop it to one > transmit MB), but a simple change to the Transmit MB assignment would > fix that. Same here. > 4 - It supports FIFO mode, but it doesn't work at all. The FIFO hardware > gets so badly screwed by the driver that it has to be power-cycled to > get it working again. > > 5 - Transmit doesn't work either. If you push it it'll start sending ONE > Message per SECOND. That's an easy fix by changing the code to actually > unblock the netif queue instead of what it does. > > 6 - The sysfs variable that reserves receive message buffers is named to > reserve transmit buffers, it messes up if the DLC is over 8 (because it > doesn't call get_can_dlc()), the Dump routines don't work properly, > off-by-one bug, comparison-reversal bug and so on. > > 7 - The only good thing about it is that it doesn't use NAPI, so when > fixed it doesn't drop messages when you try to use MMC/eMMC/ESDHC. > > FIFO bug documented and fixed here: > > https://community.freescale.com/thread/381075 > > Transmit bug documented and fixed here (and the other ones listed), also > MMC/eMMC problem: > > https://community.freescale.com/message/595897 > > Patches to fix all of it on the end of this thread: > > https://community.freescale.com/thread/303271 If there's interest in working with this prehistoric kernel, why isn't there anyone that picks up all the patches and add them to a git repo. fsl doesn't seem to care either, maybe unless you're using their newest product :( just my 2ยข, Marc
On 10/12/2015 11:44 PM, Marc Kleine-Budde wrote: > On 12/10/2015 12:44 PM, Tom Evans wrote: >> I've just had to delve back into the deep murky past and try to get >> Freescale's Kernel 2.6.35 FlexCAN driver working... On an i.MX53. That's the last supported kernel Freescale ever released for that series of parts. > 2.6.x I feel your pain. Another option would be to port the flexcan > driver to that old kernel. But I'm getting off topic here :) Been there. Options are to port 2.6.38 (Freescale's Android release) which has the 2.6.38 mainstream driver, but looks to have a full collection of all the bugs fixed since then. Some kind soul has already done that and released a patch (but I don't like the bugs). Or the 3.4 version we're running with our 3.4 kernel or something more modern. I don't trust later versions to even compile - the headers and interfaces change. Then I can't use modern ones anyway as they use NAPI and that simply doesn't work with Linux and CAN. So I'd have to apply all my de-NAPI patches. The simplest path was to fix the simple and stupidly obvious bugs in the existing driver rather than add new complicated bugs. >> 2 - It can't receive in order, but you'd only need to sort on the >> 3 - It can't transmit in order either (unless you drop it to one > > In order reception is crucial. So what mind-set at Freescale doesn't see this as a problem? I suspect their CAN knowledge stopped at the HCS08 stage, making tiny devices that control just one thing, like a door lock. So just receive and transmit one or two messages where "priority order" is more important than running any debug or diagnostic protocols. >> Patches to fix all of it on the end of this thread: >> >> https://community.freescale.com/thread/303271 > > If there's interest in working with this prehistoric kernel, why isn't > there anyone that picks up all the patches and add them to a git repo. There was. That's what the above post is meant to be for. But the last actual activity was in January 2013. It details how to submit patches, but it is too onerous for me. It has to use their exact complete distribution (of everything, not just the kernel) running on their exact development board. It also needs your .gitconfig set up "just so" matching your Freescale registration details. I'm using the thread as a dumping ground for "useful patches for customers", and hope google or Freescale's search can find them. > fsl doesn't seem to care either, maybe unless you're using > their newest product :( The team seems to disappear almost before the product is released. They all moved to i.MX6 years ago. Tom
On Thu, Dec 10, 2015 at 12:22:55PM +0000, Sharma Bhupesh wrote: > > If we have to rely on the timestamps the next logical step is to add > > sorting by timestamp to the rx-fifo implementation. I'll send a > > patch series of the current state. > > With my current v3, I see no rx-frame ordering issues atleast on > LS1021A. Marc can post our testcases here on the list (maybe with the description from the service request); perhaps this can clarify the issues. > I can ask internally about more details on the "SR# 1-4074792564 : CAN > Ordering Issues". That would be quite helpful, thanks! Understanding the root cause of the issue is often a good start, maybe there is an option for a software workaround. rsc
On 11/12/15 09:53, Tom Evans wrote: > On 10/12/2015 11:44 PM, Marc Kleine-Budde wrote: >> On 12/10/2015 12:44 PM, Tom Evans wrote: >>> I've just had to delve back into the deep murky past and try to get >>> Freescale's Kernel 2.6.35 FlexCAN driver working... > > On an i.MX53. That's the last supported kernel Freescale ever released for > that series of parts. > The simplest path was to fix the > simple and stupidly obvious bugs in the existing driver rather > than add new complicated bugs. There seems to be no end of bugs in this driver. It is a lesson in something. What's the dumbest driver bug ever? Interrupt hazard. Yes, this one has that too. The mainline sends a Message Buffer (or tries to) and DISABLES the netif queue if it can't send [1]. The transmit interrupt service routine ENABLES the netif queue. And when the interrupt routine happens in the middle of the mainline transmit routine? It locks forever. You have to power-cycle to get it back. Normally taking the interface "down" and "up" should fix it, as the "start" and "stop" functions normally stop and start the netif queue. Not these ones. They do now. Note 1: This is in the case where the transmit queues and MBs are full. The transmit function is always called twice. The first time it is called it sends the MB, leaves the queue running and return "OK". The second time it finds out it is full, stops the queue and returns "BUSY". Even better, with the default 32 transmit MBs it has to scan through all 32 MBs to find out it is full, and it may have also had to scan the same 32 to find an empty one. The FlexCAN registers are on a slow bus and take 180ns to read or write. So it can take the driver up to 12us to send one buffer. Or proportionally longer if you have more Transmit MBs (you might have 56). If you never send enough data to flow-control the driver this won't happen. If you have more than one Transmit MB (and can handle out of order transmissions) then the subsequent transmit interrupts will repair the damage and you won't see it either. That's probably why it passed whatever testing it had. Bug detailed here: https://community.freescale.com/message/597952 Patch to fix here: https://community.freescale.com/message/597951#597951 Tom
On 17/12/15 15:22, Tom Evans wrote: > On 11/12/15 09:53, Tom Evans wrote: >> On 10/12/2015 11:44 PM, Marc Kleine-Budde wrote: >> >> The simplest path was to fix the simple and stupidly obvious >> bugs in the existing driver rather than add new complicated bugs. > > There seems to be no end of bugs in this driver. It is a lesson > in something. The Bus Off Recovery doesn't work either. A Bus Off condition results in the module being soft-reset and then never woken up again, mainly because the calls to "mod_timer()" forget to add "jiffies", so the timer doesn't trigger. Then the Auto/Manual mode recovery test is probably backwards. Then it tests MDIS instead of HALT, so it never resets the module after the soft reset. If you program it in "Auto Recovery" mode it resets it anyway. Bugs detailed here: https://community.freescale.com/message/599099#599099 There'll probably be a link on that page to the patches to fix it after I've tested it some more. Tom
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index b0222ae..3240472 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -156,6 +156,9 @@ #define FLEXCAN_IFLAG_DEFAULT \ (FLEXCAN_IFLAG_RX_FIFO_OVERFLOW | FLEXCAN_IFLAG_RX_FIFO_AVAILABLE | \ FLEXCAN_IFLAG_BUF(FLEXCAN_TX_BUF_ID)) +#define FLEXCAN_IFLAG_DEFAULT_RX_MB_MODE \ + (FLEXCAN_IFLAG_BUF(FLEXCAN_TX_BUF_ID)) +#define FLEXCAN_IFLAG_RX_MB_RXMASK ((1 << FLEXCAN_TX_BUF_RESERVED) - 1) /* FLEXCAN message buffers */ #define FLEXCAN_MB_CNT_CODE(x) (((x) & 0xf) << 24) @@ -198,6 +201,8 @@ #define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */ #define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* [TR]WRN_INT not connected */ #define FLEXCAN_HAS_MECR_FEATURES BIT(3) /* Memory error detection */ +#define FLEXCAN_HAS_ONLY_LEGACY_RX_SUPPORT \ + BIT(4) /* No RX FIFO mode support */ /* Structure of the message buffer */ struct flexcan_mb { @@ -252,6 +257,7 @@ struct flexcan_priv { void __iomem *base; u32 reg_esr; u32 reg_ctrl_default; + u32 rx_msg_buf; struct clk *clk_ipg; struct clk *clk_per; @@ -303,8 +309,7 @@ static const struct can_bittiming_const flexcan_bittiming_const = { .brp_inc = 1, }; -/* - * FlexCAN module is essentially modelled as a little-endian IP in most +/* FlexCAN module is essentially modelled as a little-endian IP in most * SoCs, i.e the registers as well as the message buffer areas are * implemented in a little-endian fashion. * @@ -646,12 +651,10 @@ static int flexcan_poll_state(struct net_device *dev, u32 reg_esr) return 1; } -static void flexcan_read_fifo(const struct net_device *dev, - struct can_frame *cf) +static void flexcan_read_can_frame(const struct flexcan_priv *priv, + struct flexcan_mb __iomem *mb, + struct can_frame *cf) { - const struct flexcan_priv *priv = netdev_priv(dev); - struct flexcan_regs __iomem *regs = priv->base; - struct flexcan_mb __iomem *mb = ®s->cantxfg[0]; u32 reg_ctrl, reg_id; reg_ctrl = priv->read(&mb->can_ctrl); @@ -667,14 +670,39 @@ static void flexcan_read_fifo(const struct net_device *dev, *(__be32 *)(cf->data + 0) = cpu_to_be32(priv->read(&mb->data[0])); *(__be32 *)(cf->data + 4) = cpu_to_be32(priv->read(&mb->data[1])); +} + +static void flexcan_read_fifo(const struct net_device *dev, + struct can_frame *cf) +{ + const struct flexcan_priv *priv = netdev_priv(dev); + struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_mb __iomem *mb = ®s->cantxfg[0]; + + flexcan_read_can_frame(priv, mb, cf); /* mark as read */ priv->write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->iflag1); priv->read(®s->timer); } +static void flexcan_read_msg_buf(const struct net_device *dev, + struct can_frame *cf, u32 msg_buf) +{ + const struct flexcan_priv *priv = netdev_priv(dev); + struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_mb __iomem *mb = ®s->cantxfg[msg_buf]; + + flexcan_read_can_frame(priv, mb, cf); + + /* mark as read */ + priv->write(BIT(msg_buf), ®s->iflag1); + priv->read(®s->timer); +} + static int flexcan_read_frame(struct net_device *dev) { + const struct flexcan_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct can_frame *cf; struct sk_buff *skb; @@ -685,7 +713,11 @@ static int flexcan_read_frame(struct net_device *dev) return 0; } - flexcan_read_fifo(dev, cf); + if (priv->devtype_data->features & FLEXCAN_HAS_ONLY_LEGACY_RX_SUPPORT) + flexcan_read_msg_buf(dev, cf, priv->rx_msg_buf); + else + flexcan_read_fifo(dev, cf); + netif_receive_skb(skb); stats->rx_packets++; @@ -699,9 +731,10 @@ static int flexcan_read_frame(struct net_device *dev) static int flexcan_poll(struct napi_struct *napi, int quota) { struct net_device *dev = napi->dev; - const struct flexcan_priv *priv = netdev_priv(dev); + struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_regs __iomem *regs = priv->base; u32 reg_iflag1, reg_esr; + unsigned long iflag1; int work_done = 0; /* @@ -713,12 +746,25 @@ static int flexcan_poll(struct napi_struct *napi, int quota) /* handle state changes */ work_done += flexcan_poll_state(dev, reg_esr); - /* handle RX-FIFO */ reg_iflag1 = priv->read(®s->iflag1); - while (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE && - work_done < quota) { - work_done += flexcan_read_frame(dev); - reg_iflag1 = priv->read(®s->iflag1); + + if (priv->devtype_data->features & FLEXCAN_HAS_ONLY_LEGACY_RX_SUPPORT) { + /* handle legacy RX mode */ + iflag1 = reg_iflag1 & FLEXCAN_IFLAG_RX_MB_RXMASK; + while ((reg_iflag1 & FLEXCAN_IFLAG_RX_MB_RXMASK) && + work_done < quota) { + priv->rx_msg_buf = find_first_bit(&iflag1, + (FLEXCAN_TX_BUF_ID - 1)); + work_done += flexcan_read_frame(dev); + reg_iflag1 = priv->read(®s->iflag1); + } + } else { + /* handle RX-FIFO */ + while (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE && + work_done < quota) { + work_done += flexcan_read_frame(dev); + reg_iflag1 = priv->read(®s->iflag1); + } } /* report bus errors */ @@ -728,7 +774,13 @@ static int flexcan_poll(struct napi_struct *napi, int quota) if (work_done < quota) { napi_complete(napi); /* enable IRQs */ - priv->write(FLEXCAN_IFLAG_DEFAULT, ®s->imask1); + if (priv->devtype_data->features & + FLEXCAN_HAS_ONLY_LEGACY_RX_SUPPORT) + priv->write(FLEXCAN_IFLAG_DEFAULT_RX_MB_MODE | + FLEXCAN_IFLAG_RX_MB_RXMASK, ®s->imask1); + else + priv->write(FLEXCAN_IFLAG_DEFAULT, ®s->imask1); + priv->write(priv->reg_ctrl_default, ®s->ctrl); } @@ -755,26 +807,45 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) * - state change IRQ * - bus error IRQ and bus error reporting is activated */ - if ((reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE) || - (reg_esr & FLEXCAN_ESR_ERR_STATE) || - flexcan_has_and_handle_berr(priv, reg_esr)) { - /* - * The error bits are cleared on read, - * save them for later use. - */ - priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS; - priv->write(FLEXCAN_IFLAG_DEFAULT & - ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->imask1); - priv->write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, - ®s->ctrl); - napi_schedule(&priv->napi); - } + if (priv->devtype_data->features & FLEXCAN_HAS_ONLY_LEGACY_RX_SUPPORT) { + if ((reg_iflag1 & FLEXCAN_IFLAG_RX_MB_RXMASK) || + (reg_esr & FLEXCAN_ESR_ERR_STATE) || + flexcan_has_and_handle_berr(priv, reg_esr)) { + /* The error bits are cleared on read, + * save them for later use. + */ + priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS; + priv->write(FLEXCAN_IFLAG_DEFAULT_RX_MB_MODE & + ~FLEXCAN_IFLAG_RX_MB_RXMASK, ®s->imask1); + priv->write(priv->reg_ctrl_default & + ~FLEXCAN_CTRL_ERR_ALL, ®s->ctrl); + + napi_schedule(&priv->napi); + } + } else { + if ((reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE) || + (reg_esr & FLEXCAN_ESR_ERR_STATE) || + flexcan_has_and_handle_berr(priv, reg_esr)) { + /* + * The error bits are cleared on read, + * save them for later use. + */ + priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS; + priv->write(FLEXCAN_IFLAG_DEFAULT & + ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, + ®s->imask1); + priv->write(priv->reg_ctrl_default & + ~FLEXCAN_CTRL_ERR_ALL, ®s->ctrl); + napi_schedule(&priv->napi); + } - /* FIFO overflow */ - if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) { - priv->write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, ®s->iflag1); - dev->stats.rx_over_errors++; - dev->stats.rx_errors++; + /* FIFO overflow */ + if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) { + priv->write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, + ®s->iflag1); + dev->stats.rx_over_errors++; + dev->stats.rx_errors++; + } } /* transmission complete interrupt */ @@ -869,7 +940,12 @@ static int flexcan_chip_start(struct net_device *dev) */ reg_mcr = priv->read(®s->mcr); reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff); - reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT | + if (priv->devtype_data->features & FLEXCAN_HAS_ONLY_LEGACY_RX_SUPPORT) + reg_mcr &= ~FLEXCAN_MCR_FEN; + else + reg_mcr |= FLEXCAN_MCR_FEN; + + reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS | FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID); @@ -966,8 +1042,13 @@ static int flexcan_chip_start(struct net_device *dev) priv->can.state = CAN_STATE_ERROR_ACTIVE; - /* enable FIFO interrupts */ - priv->write(FLEXCAN_IFLAG_DEFAULT, ®s->imask1); + if (priv->devtype_data->features & FLEXCAN_HAS_ONLY_LEGACY_RX_SUPPORT) + /* enable mb interrupts */ + priv->write(FLEXCAN_IFLAG_DEFAULT_RX_MB_MODE | + FLEXCAN_IFLAG_RX_MB_RXMASK, ®s->imask1); + else + /* enable FIFO interrupts */ + priv->write(FLEXCAN_IFLAG_DEFAULT, ®s->imask1); /* print chip status */ netdev_dbg(dev, "%s: reading mcr=0x%08x ctrl=0x%08x\n", __func__, @@ -1125,22 +1206,29 @@ static int register_flexcandev(struct net_device *dev) if (err) goto out_chip_disable; - /* set freeze, halt and activate FIFO, restrict register access */ + /* set freeze, halt and activate FIFO/legacy mode, restrict + * register access + */ reg = priv->read(®s->mcr); - reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | - FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV; + if (priv->devtype_data->features & FLEXCAN_HAS_ONLY_LEGACY_RX_SUPPORT) + reg &= ~FLEXCAN_MCR_FEN; + else + reg |= FLEXCAN_MCR_FEN; + + reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV; priv->write(reg, ®s->mcr); - /* - * Currently we only support newer versions of this core - * featuring a RX FIFO. Older cores found on some Coldfire - * derivates are not yet supported. - */ - reg = priv->read(®s->mcr); - if (!(reg & FLEXCAN_MCR_FEN)) { - netdev_err(dev, "Could not enable RX FIFO, unsupported core\n"); - err = -ENODEV; - goto out_chip_disable; + if (priv->devtype_data->features & FLEXCAN_HAS_ONLY_LEGACY_RX_SUPPORT) { + /* Legacy RX mode*/ + netdev_info(dev, "Legacy mode (non RX-FIFO) enabled\n"); + } else { + /* RX FIFO mode */ + reg = priv->read(®s->mcr); + if (!(reg & FLEXCAN_MCR_FEN)) { + netdev_err(dev, "Could not enable RX FIFO, unsupported core\n"); + err = -ENODEV; + goto out_chip_disable; + } } err = register_candev(dev);