* mcp251x.c : patch to avoid repeated frame bug
@ 2012-08-27 13:02 Benoit
2012-09-03 12:11 ` Marc Kleine-Budde
0 siblings, 1 reply; 2+ messages in thread
From: Benoit @ 2012-08-27 13:02 UTC (permalink / raw)
To: linux-can
Hello,
The MCP2515 has a silicon bug causing repeated frame transmission, see
section 5 of MCP2515 Rev. B Silicon Errata Revision G (March 2007).
Basically, setting TXBnCTRL.TXREQ in either SPI mode (00 or 11) will
eventually cause the bug. The workaround proposed by Microchip is to use
mode 00 and send an RTS command on the SPI bus to initiate the
transmission. Accordingly, I have modified the transmission routine as
follows in file mcp251x.c:
--- drivers/net/can/mcp251x.c-original 2012-08-26 15:00:28.000000000 +0200
+++ drivers/net/can/mcp251x.c 2012-08-26 20:42:58.000000000 +0200
@@ -83,6 +83,10 @@
#define INSTRUCTION_LOAD_TXB(n) (0x40 + 2 * (n))
#define INSTRUCTION_READ_RXB(n) (((n) == 0) ? 0x90 : 0x94)
#define INSTRUCTION_RESET 0xC0
+#define RTS_TXB0 0x01
+#define RTS_TXB1 0x02
+#define RTS_TXB2 0x04
+#define INSTRUCTION_RTS(txb) (0x80 | ((txb) & 0x07))
/* MPC251x registers */
#define CANSTAT 0x0e
@@ -394,9 +398,20 @@
}
}
+
+/*
+ * CAN frame is now sent using instruction RTS over SPI to work around
+ * repeated frame problem as per MCP2515 Rev B. Silicon Errata revision G
+ * (March 2007) about repeated frames (see section 5 of document).
+ * Note that repeated frames can still occur if using SPI mode 11. It seems
+ * however that spi mode is forcibly set to 0, so it looks safe.
+ *
+ */
static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,
int tx_buf_idx)
{
+ struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
+ int ret;
u32 sid, eid, exide, rtr;
u8 buf[SPI_TRANSFER_BUF_LEN];
@@ -418,7 +433,12 @@
buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc;
memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc);
mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx);
- mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ);
+
+ priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx);
+ ret = spi_write(spi, priv->spi_tx_buf, 1);
+ if (ret) {
+ dev_err(&spi->dev, "RTS failed: ret = %d\n", ret);
+ }
}
static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf,
Would it be possible to integrate this patch into mainstream mcp251x.c?
Kind Regards,
Benoît.
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: mcp251x.c : patch to avoid repeated frame bug
2012-08-27 13:02 mcp251x.c : patch to avoid repeated frame bug Benoit
@ 2012-09-03 12:11 ` Marc Kleine-Budde
0 siblings, 0 replies; 2+ messages in thread
From: Marc Kleine-Budde @ 2012-09-03 12:11 UTC (permalink / raw)
To: Benoit; +Cc: linux-can
[-- Attachment #1: Type: text/plain, Size: 3172 bytes --]
On 08/27/2012 03:02 PM, Benoit wrote:
> Hello,
>
> The MCP2515 has a silicon bug causing repeated frame transmission, see
> section 5 of MCP2515 Rev. B Silicon Errata Revision G (March 2007).
>
> Basically, setting TXBnCTRL.TXREQ in either SPI mode (00 or 11) will
> eventually cause the bug. The workaround proposed by Microchip is to use
> mode 00 and send an RTS command on the SPI bus to initiate the
> transmission. Accordingly, I have modified the transmission routine as
> follows in file mcp251x.c:
I've some questions about the code:
> --- drivers/net/can/mcp251x.c-original 2012-08-26 15:00:28.000000000
> +0200
> +++ drivers/net/can/mcp251x.c 2012-08-26 20:42:58.000000000 +0200
> @@ -83,6 +83,10 @@
> #define INSTRUCTION_LOAD_TXB(n) (0x40 + 2 * (n))
> #define INSTRUCTION_READ_RXB(n) (((n) == 0) ? 0x90 : 0x94)
> #define INSTRUCTION_RESET 0xC0
> +#define RTS_TXB0 0x01
> +#define RTS_TXB1 0x02
> +#define RTS_TXB2 0x04
^^^^
Please use a space between define and RTS_
> +#define INSTRUCTION_RTS(txb) (0x80 | ((txb) & 0x07))
>
> /* MPC251x registers */
> #define CANSTAT 0x0e
> @@ -394,9 +398,20 @@
> }
> }
>
> +
> +/*
> + * CAN frame is now sent using instruction RTS over SPI to work around
> + * repeated frame problem as per MCP2515 Rev B. Silicon Errata revision G
> + * (March 2007) about repeated frames (see section 5 of document).
> + * Note that repeated frames can still occur if using SPI mode 11. It
> seems
> + * however that spi mode is forcibly set to 0, so it looks safe.
> + *
> + */
I think we don't need this in the code it will go into the commit
message. A short note before the priv->spi_tx_buf[0] should be enough.
> static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,
> int tx_buf_idx)
> {
> + struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> + int ret;
> u32 sid, eid, exide, rtr;
> u8 buf[SPI_TRANSFER_BUF_LEN];
>
> @@ -418,7 +433,12 @@
> buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc;
> memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc);
> mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx);
> - mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ);
> +
> + priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx);
> + ret = spi_write(spi, priv->spi_tx_buf, 1);
Why don't you use mcp251x_spi_trans() here?
> + if (ret) {
> + dev_err(&spi->dev, "RTS failed: ret = %d\n", ret);
> + }
> }
>
> static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf,
>
>
>
> Would it be possible to integrate this patch into mainstream mcp251x.c?
>
> Kind Regards,
>
> Benoît
I'll send an updated version of your proposed patch.
regards, Marc
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2012-09-03 12:12 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-27 13:02 mcp251x.c : patch to avoid repeated frame bug Benoit
2012-09-03 12:11 ` Marc Kleine-Budde
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).