* [PATCH V4 1/3] can: add can_is_canfd_skb() API @ 2014-11-07 8:45 Dong Aisheng 2014-11-07 8:45 ` [PATCH V4 2/3] can: m_can: update to support CAN FD features Dong Aisheng ` (2 more replies) 0 siblings, 3 replies; 11+ messages in thread From: Dong Aisheng @ 2014-11-07 8:45 UTC (permalink / raw) To: linux-arm-kernel The CAN device drivers can use it to check if the frame to send is on CAN FD mode or normal CAN mode. Acked-by: Oliver Hartkopp <socketcan@hartkopp.net> Signed-off-by: Dong Aisheng <b29396@freescale.com> --- ChangesLog: * v3->v4: add comments and change prototype a bit * v1->v2: change to skb->len == CANFD_MTU; --- include/linux/can/dev.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index 6992afc..b37ea95 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h @@ -99,6 +99,12 @@ inval_skb: return 1; } +static inline bool can_is_canfd_skb(const struct sk_buff *skb) +{ + /* the CAN specific type of skb is identified by its data length */ + return skb->len == CANFD_MTU; +} + /* get data length from can_dlc with sanitized can_dlc */ u8 can_dlc2len(u8 can_dlc); -- 1.9.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH V4 2/3] can: m_can: update to support CAN FD features 2014-11-07 8:45 [PATCH V4 1/3] can: add can_is_canfd_skb() API Dong Aisheng @ 2014-11-07 8:45 ` Dong Aisheng 2014-11-13 10:10 ` Marc Kleine-Budde 2014-11-07 8:45 ` [PATCH V4 3/3] can: m_can: add missing message RAM initialization Dong Aisheng 2014-11-13 10:04 ` [PATCH V4 1/3] can: add can_is_canfd_skb() API Marc Kleine-Budde 2 siblings, 1 reply; 11+ messages in thread From: Dong Aisheng @ 2014-11-07 8:45 UTC (permalink / raw) To: linux-arm-kernel Bosch M_CAN is CAN FD capable device. This patch implements the CAN FD features include up to 64 bytes payload and bitrate switch function. 1) Change the Rx FIFO and Tx Buffer to 64 bytes for support CAN FD up to 64 bytes payload. It's backward compatible with old 8 bytes normal CAN frame. 2) Allocate can frame or canfd frame based on EDL bit 3) Bitrate Switch function is disabled by default and will be enabled according to CANFD_BRS bit in cf->flags. Acked-by: Oliver Hartkopp <socketcan@hartkopp.net> Signed-off-by: Dong Aisheng <b29396@freescale.com> --- ChangeLog: v3->v4: * no changes v2->v3: * integrate patch 4 into patch 1 in last series(allow to send std frame on can fd mode) * use suitable API to get cf->len according to RX_BUF_EDL bit v1->v2: * Allocate can frame or canfd frame based on EDL bit * Only check and set RTR bit for normal frame (no EDL bit set) --- drivers/net/can/m_can/m_can.c | 179 ++++++++++++++++++++++++++++++++---------- 1 file changed, 136 insertions(+), 43 deletions(-) diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 6160b9c..eee1533 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -105,14 +105,36 @@ enum m_can_mram_cfg { MRAM_CFG_NUM, }; +/* Fast Bit Timing & Prescaler Register (FBTP) */ +#define FBTR_FBRP_MASK 0x1f +#define FBTR_FBRP_SHIFT 16 +#define FBTR_FTSEG1_SHIFT 8 +#define FBTR_FTSEG1_MASK (0xf << FBTR_FTSEG1_SHIFT) +#define FBTR_FTSEG2_SHIFT 4 +#define FBTR_FTSEG2_MASK (0x7 << FBTR_FTSEG2_SHIFT) +#define FBTR_FSJW_SHIFT 0 +#define FBTR_FSJW_MASK 0x3 + /* Test Register (TEST) */ #define TEST_LBCK BIT(4) /* CC Control Register(CCCR) */ -#define CCCR_TEST BIT(7) -#define CCCR_MON BIT(5) -#define CCCR_CCE BIT(1) -#define CCCR_INIT BIT(0) +#define CCCR_TEST BIT(7) +#define CCCR_CMR_MASK 0x3 +#define CCCR_CMR_SHIFT 10 +#define CCCR_CMR_CANFD 0x1 +#define CCCR_CMR_CANFD_BRS 0x2 +#define CCCR_CMR_CAN 0x3 +#define CCCR_CME_MASK 0x3 +#define CCCR_CME_SHIFT 8 +#define CCCR_CME_CAN 0 +#define CCCR_CME_CANFD 0x1 +#define CCCR_CME_CANFD_BRS 0x2 +#define CCCR_TEST BIT(7) +#define CCCR_MON BIT(5) +#define CCCR_CCE BIT(1) +#define CCCR_INIT BIT(0) +#define CCCR_CANFD 0x10 /* Bit Timing & Prescaler Register (BTP) */ #define BTR_BRP_MASK 0x3ff @@ -204,6 +226,7 @@ enum m_can_mram_cfg { /* Rx Buffer / FIFO Element Size Configuration (RXESC) */ #define M_CAN_RXESC_8BYTES 0x0 +#define M_CAN_RXESC_64BYTES 0x777 /* Tx Buffer Configuration(TXBC) */ #define TXBC_NDTB_OFF 16 @@ -211,6 +234,7 @@ enum m_can_mram_cfg { /* Tx Buffer Element Size Configuration(TXESC) */ #define TXESC_TBDS_8BYTES 0x0 +#define TXESC_TBDS_64BYTES 0x7 /* Tx Event FIFO Con.guration (TXEFC) */ #define TXEFC_EFS_OFF 16 @@ -219,11 +243,11 @@ enum m_can_mram_cfg { /* Message RAM Configuration (in bytes) */ #define SIDF_ELEMENT_SIZE 4 #define XIDF_ELEMENT_SIZE 8 -#define RXF0_ELEMENT_SIZE 16 -#define RXF1_ELEMENT_SIZE 16 +#define RXF0_ELEMENT_SIZE 72 +#define RXF1_ELEMENT_SIZE 72 #define RXB_ELEMENT_SIZE 16 #define TXE_ELEMENT_SIZE 8 -#define TXB_ELEMENT_SIZE 16 +#define TXB_ELEMENT_SIZE 72 /* Message RAM Elements */ #define M_CAN_FIFO_ID 0x0 @@ -231,11 +255,17 @@ enum m_can_mram_cfg { #define M_CAN_FIFO_DATA(n) (0x8 + ((n) << 2)) /* Rx Buffer Element */ +/* R0 */ #define RX_BUF_ESI BIT(31) #define RX_BUF_XTD BIT(30) #define RX_BUF_RTR BIT(29) +/* R1 */ +#define RX_BUF_ANMF BIT(31) +#define RX_BUF_EDL BIT(21) +#define RX_BUF_BRS BIT(20) /* Tx Buffer Element */ +/* R0 */ #define TX_BUF_XTD BIT(30) #define TX_BUF_RTR BIT(29) @@ -327,41 +357,68 @@ static inline void m_can_disable_all_interrupts(const struct m_can_priv *priv) m_can_write(priv, M_CAN_ILE, 0x0); } -static void m_can_read_fifo(const struct net_device *dev, struct can_frame *cf, - u32 rxfs) +static void m_can_read_fifo(struct net_device *dev, u32 rxfs) { + struct net_device_stats *stats = &dev->stats; struct m_can_priv *priv = netdev_priv(dev); - u32 id, fgi; + struct canfd_frame *cf; + struct sk_buff *skb; + u32 id, fgi, dlc; + int i; /* calculate the fifo get index for where to read data */ fgi = (rxfs & RXFS_FGI_MASK) >> RXFS_FGI_OFF; + dlc = m_can_fifo_read(priv, fgi, M_CAN_FIFO_DLC); + if (dlc & RX_BUF_EDL) + skb = alloc_canfd_skb(dev, &cf); + else + skb = alloc_can_skb(dev, (struct can_frame **)&cf); + if (!skb) { + stats->rx_dropped++; + return; + } + id = m_can_fifo_read(priv, fgi, M_CAN_FIFO_ID); if (id & RX_BUF_XTD) cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG; else cf->can_id = (id >> 18) & CAN_SFF_MASK; - if (id & RX_BUF_RTR) { + if (id & RX_BUF_ESI) { + cf->flags |= CANFD_ESI; + netdev_dbg(dev, "ESI Error\n"); + } + + if (!(dlc & RX_BUF_EDL) && (id & RX_BUF_RTR)) { cf->can_id |= CAN_RTR_FLAG; } else { id = m_can_fifo_read(priv, fgi, M_CAN_FIFO_DLC); - cf->can_dlc = get_can_dlc((id >> 16) & 0x0F); - *(u32 *)(cf->data + 0) = m_can_fifo_read(priv, fgi, - M_CAN_FIFO_DATA(0)); - *(u32 *)(cf->data + 4) = m_can_fifo_read(priv, fgi, - M_CAN_FIFO_DATA(1)); + if (dlc & RX_BUF_EDL) + cf->len = can_dlc2len((id >> 16) & 0x0F); + else + cf->len = get_can_dlc((id >> 16) & 0x0F); + + if (id & RX_BUF_BRS) + cf->flags |= CANFD_BRS; + + for (i = 0; i < cf->len; i += 4) + *(u32 *)(cf->data + i) = + m_can_fifo_read(priv, fgi, + M_CAN_FIFO_DATA(i / 4)); } /* acknowledge rx fifo 0 */ m_can_write(priv, M_CAN_RXF0A, fgi); + + stats->rx_packets++; + stats->rx_bytes += cf->len; + + netif_receive_skb(skb); } static int m_can_do_rx_poll(struct net_device *dev, int quota) { struct m_can_priv *priv = netdev_priv(dev); - struct net_device_stats *stats = &dev->stats; - struct sk_buff *skb; - struct can_frame *frame; u32 pkts = 0; u32 rxfs; @@ -375,18 +432,7 @@ static int m_can_do_rx_poll(struct net_device *dev, int quota) if (rxfs & RXFS_RFL) netdev_warn(dev, "Rx FIFO 0 Message Lost\n"); - skb = alloc_can_skb(dev, &frame); - if (!skb) { - stats->rx_dropped++; - return pkts; - } - - m_can_read_fifo(dev, frame, rxfs); - - stats->rx_packets++; - stats->rx_bytes += frame->can_dlc; - - netif_receive_skb(skb); + m_can_read_fifo(dev, rxfs); quota--; pkts++; @@ -744,10 +790,23 @@ static const struct can_bittiming_const m_can_bittiming_const = { .brp_inc = 1, }; +static const struct can_bittiming_const m_can_data_bittiming_const = { + .name = KBUILD_MODNAME, + .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */ + .tseg1_max = 16, + .tseg2_min = 1, /* Time segment 2 = phase_seg2 */ + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 32, + .brp_inc = 1, +}; + static int m_can_set_bittiming(struct net_device *dev) { struct m_can_priv *priv = netdev_priv(dev); const struct can_bittiming *bt = &priv->can.bittiming; + const struct can_bittiming *dbt = &priv->can.data_bittiming; u16 brp, sjw, tseg1, tseg2; u32 reg_btp; @@ -758,7 +817,17 @@ static int m_can_set_bittiming(struct net_device *dev) reg_btp = (brp << BTR_BRP_SHIFT) | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) | (tseg2 << BTR_TSEG2_SHIFT); m_can_write(priv, M_CAN_BTP, reg_btp); - netdev_dbg(dev, "setting BTP 0x%x\n", reg_btp); + + if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { + brp = dbt->brp - 1; + sjw = dbt->sjw - 1; + tseg1 = dbt->prop_seg + dbt->phase_seg1 - 1; + tseg2 = dbt->phase_seg2 - 1; + reg_btp = (brp << FBTR_FBRP_SHIFT) | (sjw << FBTR_FSJW_SHIFT) | + (tseg1 << FBTR_FTSEG1_SHIFT) | + (tseg2 << FBTR_FTSEG2_SHIFT); + m_can_write(priv, M_CAN_FBTP, reg_btp); + } return 0; } @@ -778,8 +847,8 @@ static void m_can_chip_config(struct net_device *dev) m_can_config_endisable(priv, true); - /* RX Buffer/FIFO Element Size 8 bytes data field */ - m_can_write(priv, M_CAN_RXESC, M_CAN_RXESC_8BYTES); + /* RX Buffer/FIFO Element Size 64 bytes data field */ + m_can_write(priv, M_CAN_RXESC, M_CAN_RXESC_64BYTES); /* Accept Non-matching Frames Into FIFO 0 */ m_can_write(priv, M_CAN_GFC, 0x0); @@ -788,8 +857,8 @@ static void m_can_chip_config(struct net_device *dev) m_can_write(priv, M_CAN_TXBC, (1 << TXBC_NDTB_OFF) | priv->mcfg[MRAM_TXB].off); - /* only support 8 bytes firstly */ - m_can_write(priv, M_CAN_TXESC, TXESC_TBDS_8BYTES); + /* support 64 bytes payload */ + m_can_write(priv, M_CAN_TXESC, TXESC_TBDS_64BYTES); m_can_write(priv, M_CAN_TXEFC, (1 << TXEFC_EFS_OFF) | priv->mcfg[MRAM_TXE].off); @@ -804,7 +873,8 @@ static void m_can_chip_config(struct net_device *dev) RXFC_FWM_1 | priv->mcfg[MRAM_RXF1].off); cccr = m_can_read(priv, M_CAN_CCCR); - cccr &= ~(CCCR_TEST | CCCR_MON); + cccr &= ~(CCCR_TEST | CCCR_MON | (CCCR_CMR_MASK << CCCR_CMR_SHIFT) | + (CCCR_CME_MASK << CCCR_CME_SHIFT)); test = m_can_read(priv, M_CAN_TEST); test &= ~TEST_LBCK; @@ -816,6 +886,9 @@ static void m_can_chip_config(struct net_device *dev) test |= TEST_LBCK; } + if (priv->can.ctrlmode & CAN_CTRLMODE_FD) + cccr |= CCCR_CME_CANFD_BRS << CCCR_CME_SHIFT; + m_can_write(priv, M_CAN_CCCR, cccr); m_can_write(priv, M_CAN_TEST, test); @@ -880,11 +953,13 @@ static struct net_device *alloc_m_can_dev(void) priv->dev = dev; priv->can.bittiming_const = &m_can_bittiming_const; + priv->can.data_bittiming_const = &m_can_data_bittiming_const; priv->can.do_set_mode = m_can_set_mode; priv->can.do_get_berr_counter = m_can_get_berr_counter; priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY | - CAN_CTRLMODE_BERR_REPORTING; + CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_FD; return dev; } @@ -967,8 +1042,9 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct m_can_priv *priv = netdev_priv(dev); - struct can_frame *cf = (struct can_frame *)skb->data; - u32 id; + struct canfd_frame *cf = (struct canfd_frame *)skb->data; + u32 id, cccr; + int i; if (can_dropped_invalid_skb(dev, skb)) return NETDEV_TX_OK; @@ -987,11 +1063,28 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, /* message ram configuration */ m_can_fifo_write(priv, 0, M_CAN_FIFO_ID, id); - m_can_fifo_write(priv, 0, M_CAN_FIFO_DLC, cf->can_dlc << 16); - m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(0), *(u32 *)(cf->data + 0)); - m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(1), *(u32 *)(cf->data + 4)); + m_can_fifo_write(priv, 0, M_CAN_FIFO_DLC, can_len2dlc(cf->len) << 16); + + for (i = 0; i < cf->len; i += 4) + m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(i / 4), + *(u32 *)(cf->data + i)); + can_put_echo_skb(skb, dev, 0); + if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { + cccr = m_can_read(priv, M_CAN_CCCR); + cccr &= ~(CCCR_CMR_MASK << CCCR_CMR_SHIFT); + if (can_is_canfd_skb(skb)) { + if (cf->flags & CANFD_BRS) + cccr |= CCCR_CMR_CANFD_BRS << CCCR_CMR_SHIFT; + else + cccr |= CCCR_CMR_CANFD << CCCR_CMR_SHIFT; + } else { + cccr |= CCCR_CMR_CAN << CCCR_CMR_SHIFT; + } + m_can_write(priv, M_CAN_CCCR, cccr); + } + /* enable first TX buffer to start transfer */ m_can_write(priv, M_CAN_TXBTIE, 0x1); m_can_write(priv, M_CAN_TXBAR, 0x1); -- 1.9.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH V4 2/3] can: m_can: update to support CAN FD features 2014-11-07 8:45 ` [PATCH V4 2/3] can: m_can: update to support CAN FD features Dong Aisheng @ 2014-11-13 10:10 ` Marc Kleine-Budde 2014-11-13 16:56 ` Oliver Hartkopp 0 siblings, 1 reply; 11+ messages in thread From: Marc Kleine-Budde @ 2014-11-13 10:10 UTC (permalink / raw) To: linux-arm-kernel On 11/07/2014 09:45 AM, Dong Aisheng wrote: > Bosch M_CAN is CAN FD capable device. This patch implements the CAN > FD features include up to 64 bytes payload and bitrate switch function. > 1) Change the Rx FIFO and Tx Buffer to 64 bytes for support CAN FD > up to 64 bytes payload. It's backward compatible with old 8 bytes > normal CAN frame. > 2) Allocate can frame or canfd frame based on EDL bit > 3) Bitrate Switch function is disabled by default and will be enabled > according to CANFD_BRS bit in cf->flags. > > Acked-by: Oliver Hartkopp <socketcan@hartkopp.net> > Signed-off-by: Dong Aisheng <b29396@freescale.com> [...] > -static void m_can_read_fifo(const struct net_device *dev, struct can_frame *cf, > - u32 rxfs) > +static void m_can_read_fifo(struct net_device *dev, u32 rxfs) > { > + struct net_device_stats *stats = &dev->stats; > struct m_can_priv *priv = netdev_priv(dev); > - u32 id, fgi; > + struct canfd_frame *cf; > + struct sk_buff *skb; > + u32 id, fgi, dlc; > + int i; > > /* calculate the fifo get index for where to read data */ > fgi = (rxfs & RXFS_FGI_MASK) >> RXFS_FGI_OFF; > + dlc = m_can_fifo_read(priv, fgi, M_CAN_FIFO_DLC); > + if (dlc & RX_BUF_EDL) > + skb = alloc_canfd_skb(dev, &cf); > + else > + skb = alloc_can_skb(dev, (struct can_frame **)&cf); > + if (!skb) { > + stats->rx_dropped++; > + return; > + } > + > id = m_can_fifo_read(priv, fgi, M_CAN_FIFO_ID); > if (id & RX_BUF_XTD) > cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG; > else > cf->can_id = (id >> 18) & CAN_SFF_MASK; > > - if (id & RX_BUF_RTR) { > + if (id & RX_BUF_ESI) { > + cf->flags |= CANFD_ESI; > + netdev_dbg(dev, "ESI Error\n"); > + } > + > + if (!(dlc & RX_BUF_EDL) && (id & RX_BUF_RTR)) { > cf->can_id |= CAN_RTR_FLAG; I just noticed, that you don't set the cf->dlc (or cf->len) in the RTR case. Please create a separate patch that fixes this problem. > } else { > id = m_can_fifo_read(priv, fgi, M_CAN_FIFO_DLC); > - cf->can_dlc = get_can_dlc((id >> 16) & 0x0F); > - *(u32 *)(cf->data + 0) = m_can_fifo_read(priv, fgi, > - M_CAN_FIFO_DATA(0)); > - *(u32 *)(cf->data + 4) = m_can_fifo_read(priv, fgi, > - M_CAN_FIFO_DATA(1)); > + if (dlc & RX_BUF_EDL) > + cf->len = can_dlc2len((id >> 16) & 0x0F); > + else > + cf->len = get_can_dlc((id >> 16) & 0x0F); > + > + if (id & RX_BUF_BRS) > + cf->flags |= CANFD_BRS; > + > + for (i = 0; i < cf->len; i += 4) > + *(u32 *)(cf->data + i) = > + m_can_fifo_read(priv, fgi, > + M_CAN_FIFO_DATA(i / 4)); > } > > /* acknowledge rx fifo 0 */ > m_can_write(priv, M_CAN_RXF0A, fgi); > + > + stats->rx_packets++; > + stats->rx_bytes += cf->len; > + > + netif_receive_skb(skb); > } Regards, 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 | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141113/de63afbb/attachment.sig> ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH V4 2/3] can: m_can: update to support CAN FD features 2014-11-13 10:10 ` Marc Kleine-Budde @ 2014-11-13 16:56 ` Oliver Hartkopp 2014-11-14 9:24 ` Marc Kleine-Budde 0 siblings, 1 reply; 11+ messages in thread From: Oliver Hartkopp @ 2014-11-13 16:56 UTC (permalink / raw) To: linux-arm-kernel On 11/13/2014 11:10 AM, Marc Kleine-Budde wrote: > On 11/07/2014 09:45 AM, Dong Aisheng wrote: >> >> - if (id & RX_BUF_RTR) { >> + if (id & RX_BUF_ESI) { >> + cf->flags |= CANFD_ESI; >> + netdev_dbg(dev, "ESI Error\n"); >> + } >> + >> + if (!(dlc & RX_BUF_EDL) && (id & RX_BUF_RTR)) { >> cf->can_id |= CAN_RTR_FLAG; > > I just noticed, that you don't set the cf->dlc (or cf->len) in the RTR > case. Please create a separate patch that fixes this problem. > >> } else { >> id = m_can_fifo_read(priv, fgi, M_CAN_FIFO_DLC); >> - cf->can_dlc = get_can_dlc((id >> 16) & 0x0F); >> - *(u32 *)(cf->data + 0) = m_can_fifo_read(priv, fgi, >> - M_CAN_FIFO_DATA(0)); >> - *(u32 *)(cf->data + 4) = m_can_fifo_read(priv, fgi, >> - M_CAN_FIFO_DATA(1)); >> + if (dlc & RX_BUF_EDL) >> + cf->len = can_dlc2len((id >> 16) & 0x0F); >> + else >> + cf->len = get_can_dlc((id >> 16) & 0x0F); >> + Grr. I missed that one too :-( Thanks for catching it. As you committed patch 1 & 3 you expect a new single patch containing the (fixed) content of this patch 2, right? Regards, Oliver ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH V4 2/3] can: m_can: update to support CAN FD features 2014-11-13 16:56 ` Oliver Hartkopp @ 2014-11-14 9:24 ` Marc Kleine-Budde 2014-11-18 11:22 ` Dong Aisheng 0 siblings, 1 reply; 11+ messages in thread From: Marc Kleine-Budde @ 2014-11-14 9:24 UTC (permalink / raw) To: linux-arm-kernel On 11/13/2014 05:56 PM, Oliver Hartkopp wrote: > On 11/13/2014 11:10 AM, Marc Kleine-Budde wrote: >> On 11/07/2014 09:45 AM, Dong Aisheng wrote: > >>> >>> - if (id & RX_BUF_RTR) { >>> + if (id & RX_BUF_ESI) { >>> + cf->flags |= CANFD_ESI; >>> + netdev_dbg(dev, "ESI Error\n"); >>> + } >>> + >>> + if (!(dlc & RX_BUF_EDL) && (id & RX_BUF_RTR)) { >>> cf->can_id |= CAN_RTR_FLAG; >> >> I just noticed, that you don't set the cf->dlc (or cf->len) in the RTR >> case. Please create a separate patch that fixes this problem. >> >>> } else { >>> id = m_can_fifo_read(priv, fgi, M_CAN_FIFO_DLC); >>> - cf->can_dlc = get_can_dlc((id >> 16) & 0x0F); >>> - *(u32 *)(cf->data + 0) = m_can_fifo_read(priv, fgi, >>> - M_CAN_FIFO_DATA(0)); >>> - *(u32 *)(cf->data + 4) = m_can_fifo_read(priv, fgi, >>> - M_CAN_FIFO_DATA(1)); >>> + if (dlc & RX_BUF_EDL) >>> + cf->len = can_dlc2len((id >> 16) & 0x0F); >>> + else >>> + cf->len = get_can_dlc((id >> 16) & 0x0F); >>> + > > Grr. I missed that one too :-( > > Thanks for catching it. > > As you committed patch 1 & 3 you expect a new single patch containing the > (fixed) content of this patch 2, right? No, please make it two patches: First the Bugfix: One setting the cf->dlc in the RTR case, too. Then the new feature: The other one adding CAN-FD support. 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 | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141114/16d2ef11/attachment.sig> ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH V4 2/3] can: m_can: update to support CAN FD features 2014-11-14 9:24 ` Marc Kleine-Budde @ 2014-11-18 11:22 ` Dong Aisheng 0 siblings, 0 replies; 11+ messages in thread From: Dong Aisheng @ 2014-11-18 11:22 UTC (permalink / raw) To: linux-arm-kernel On Fri, Nov 14, 2014 at 10:24:23AM +0100, Marc Kleine-Budde wrote: > On 11/13/2014 05:56 PM, Oliver Hartkopp wrote: > > On 11/13/2014 11:10 AM, Marc Kleine-Budde wrote: > >> On 11/07/2014 09:45 AM, Dong Aisheng wrote: > > > >>> > >>> - if (id & RX_BUF_RTR) { > >>> + if (id & RX_BUF_ESI) { > >>> + cf->flags |= CANFD_ESI; > >>> + netdev_dbg(dev, "ESI Error\n"); > >>> + } > >>> + > >>> + if (!(dlc & RX_BUF_EDL) && (id & RX_BUF_RTR)) { > >>> cf->can_id |= CAN_RTR_FLAG; > >> > >> I just noticed, that you don't set the cf->dlc (or cf->len) in the RTR > >> case. Please create a separate patch that fixes this problem. > >> > >>> } else { > >>> id = m_can_fifo_read(priv, fgi, M_CAN_FIFO_DLC); > >>> - cf->can_dlc = get_can_dlc((id >> 16) & 0x0F); > >>> - *(u32 *)(cf->data + 0) = m_can_fifo_read(priv, fgi, > >>> - M_CAN_FIFO_DATA(0)); > >>> - *(u32 *)(cf->data + 4) = m_can_fifo_read(priv, fgi, > >>> - M_CAN_FIFO_DATA(1)); > >>> + if (dlc & RX_BUF_EDL) > >>> + cf->len = can_dlc2len((id >> 16) & 0x0F); > >>> + else > >>> + cf->len = get_can_dlc((id >> 16) & 0x0F); > >>> + > > > > Grr. I missed that one too :-( > > > > Thanks for catching it. > > > > As you committed patch 1 & 3 you expect a new single patch containing the > > (fixed) content of this patch 2, right? > > No, please make it two patches: > > First the Bugfix: One setting the cf->dlc in the RTR case, too. > Then the new feature: The other one adding CAN-FD support. > Thanks for finding this. Will do a patch soon as you said. Regards Dong Aisheng > 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 | > ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH V4 3/3] can: m_can: add missing message RAM initialization 2014-11-07 8:45 [PATCH V4 1/3] can: add can_is_canfd_skb() API Dong Aisheng 2014-11-07 8:45 ` [PATCH V4 2/3] can: m_can: update to support CAN FD features Dong Aisheng @ 2014-11-07 8:45 ` Dong Aisheng 2014-11-07 10:30 ` Marc Kleine-Budde 2014-11-07 11:53 ` Oliver Hartkopp 2014-11-13 10:04 ` [PATCH V4 1/3] can: add can_is_canfd_skb() API Marc Kleine-Budde 2 siblings, 2 replies; 11+ messages in thread From: Dong Aisheng @ 2014-11-07 8:45 UTC (permalink / raw) To: linux-arm-kernel The M_CAN message RAM is usually equipped with a parity or ECC functionality. But RAM cells suffer a hardware reset and can therefore hold arbitrary content at startup - including parity and/or ECC bits. To prevent the M_CAN controller detecting checksum errors when reading potentially uninitialized TX message RAM content to transmit CAN frames the TX message RAM has to be written with (any kind of) initial data. Signed-off-by: Dong Aisheng <b29396@freescale.com> --- ChangeLog: v3-v4: * initialize the entire Message RAM in use instead of only 8 bytes since this is a valid and needed initialization process. Patch title also changed. --- drivers/net/can/m_can/m_can.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index eee1533..de742d0 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -1114,7 +1114,7 @@ static int m_can_of_parse_mram(struct platform_device *pdev, struct resource *res; void __iomem *addr; u32 out_val[MRAM_CFG_LEN]; - int ret; + int i, start, end, ret; /* message ram could be shared */ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram"); @@ -1165,6 +1165,15 @@ static int m_can_of_parse_mram(struct platform_device *pdev, priv->mcfg[MRAM_TXE].off, priv->mcfg[MRAM_TXE].num, priv->mcfg[MRAM_TXB].off, priv->mcfg[MRAM_TXB].num); + /* initialize the entire Message RAM in use to avoid possible + * ECC/parity checksum errors when reading an uninitialized buffer + */ + start = priv->mcfg[MRAM_SIDF].off; + end = priv->mcfg[MRAM_TXB].off + + priv->mcfg[MRAM_TXB].num * TXB_ELEMENT_SIZE; + for (i = start; i < end; i += 4) + writel(0x0, priv->mram_base + i); + return 0; } -- 1.9.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH V4 3/3] can: m_can: add missing message RAM initialization 2014-11-07 8:45 ` [PATCH V4 3/3] can: m_can: add missing message RAM initialization Dong Aisheng @ 2014-11-07 10:30 ` Marc Kleine-Budde 2014-11-07 10:21 ` Dong Aisheng 2014-11-07 11:53 ` Oliver Hartkopp 1 sibling, 1 reply; 11+ messages in thread From: Marc Kleine-Budde @ 2014-11-07 10:30 UTC (permalink / raw) To: linux-arm-kernel On 11/07/2014 09:45 AM, Dong Aisheng wrote: > The M_CAN message RAM is usually equipped with a parity or ECC functionality. > But RAM cells suffer a hardware reset and can therefore hold arbitrary > content at startup - including parity and/or ECC bits. > > To prevent the M_CAN controller detecting checksum errors when reading > potentially uninitialized TX message RAM content to transmit CAN > frames the TX message RAM has to be written with (any kind of) initial > data. > > Signed-off-by: Dong Aisheng <b29396@freescale.com> > --- > ChangeLog: > v3-v4: > * initialize the entire Message RAM in use instead of only 8 bytes > since this is a valid and needed initialization process. > Patch title also changed. > --- > drivers/net/can/m_can/m_can.c | 11 ++++++++++- > 1 file changed, 10 insertions(+), 1 deletion(-) > > diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c > index eee1533..de742d0 100644 > --- a/drivers/net/can/m_can/m_can.c > +++ b/drivers/net/can/m_can/m_can.c > @@ -1114,7 +1114,7 @@ static int m_can_of_parse_mram(struct platform_device *pdev, > struct resource *res; > void __iomem *addr; > u32 out_val[MRAM_CFG_LEN]; > - int ret; > + int i, start, end, ret; > > /* message ram could be shared */ > res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram"); > @@ -1165,6 +1165,15 @@ static int m_can_of_parse_mram(struct platform_device *pdev, > priv->mcfg[MRAM_TXE].off, priv->mcfg[MRAM_TXE].num, > priv->mcfg[MRAM_TXB].off, priv->mcfg[MRAM_TXB].num); > > + /* initialize the entire Message RAM in use to avoid possible > + * ECC/parity checksum errors when reading an uninitialized buffer > + */ > + start = priv->mcfg[MRAM_SIDF].off; > + end = priv->mcfg[MRAM_TXB].off + > + priv->mcfg[MRAM_TXB].num * TXB_ELEMENT_SIZE; > + for (i = start; i < end; i += 4) > + writel(0x0, priv->mram_base + i); Can we access the mram without turning on the clock? 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 | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141107/23c5ba16/attachment.sig> ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH V4 3/3] can: m_can: add missing message RAM initialization 2014-11-07 10:30 ` Marc Kleine-Budde @ 2014-11-07 10:21 ` Dong Aisheng 0 siblings, 0 replies; 11+ messages in thread From: Dong Aisheng @ 2014-11-07 10:21 UTC (permalink / raw) To: linux-arm-kernel On Fri, Nov 07, 2014 at 11:30:38AM +0100, Marc Kleine-Budde wrote: > On 11/07/2014 09:45 AM, Dong Aisheng wrote: > > The M_CAN message RAM is usually equipped with a parity or ECC functionality. > > But RAM cells suffer a hardware reset and can therefore hold arbitrary > > content at startup - including parity and/or ECC bits. > > > > To prevent the M_CAN controller detecting checksum errors when reading > > potentially uninitialized TX message RAM content to transmit CAN > > frames the TX message RAM has to be written with (any kind of) initial > > data. > > > > Signed-off-by: Dong Aisheng <b29396@freescale.com> > > --- > > ChangeLog: > > v3-v4: > > * initialize the entire Message RAM in use instead of only 8 bytes > > since this is a valid and needed initialization process. > > Patch title also changed. > > --- > > drivers/net/can/m_can/m_can.c | 11 ++++++++++- > > 1 file changed, 10 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c > > index eee1533..de742d0 100644 > > --- a/drivers/net/can/m_can/m_can.c > > +++ b/drivers/net/can/m_can/m_can.c > > @@ -1114,7 +1114,7 @@ static int m_can_of_parse_mram(struct platform_device *pdev, > > struct resource *res; > > void __iomem *addr; > > u32 out_val[MRAM_CFG_LEN]; > > - int ret; > > + int i, start, end, ret; > > > > /* message ram could be shared */ > > res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram"); > > @@ -1165,6 +1165,15 @@ static int m_can_of_parse_mram(struct platform_device *pdev, > > priv->mcfg[MRAM_TXE].off, priv->mcfg[MRAM_TXE].num, > > priv->mcfg[MRAM_TXB].off, priv->mcfg[MRAM_TXB].num); > > > > + /* initialize the entire Message RAM in use to avoid possible > > + * ECC/parity checksum errors when reading an uninitialized buffer > > + */ > > + start = priv->mcfg[MRAM_SIDF].off; > > + end = priv->mcfg[MRAM_TXB].off + > > + priv->mcfg[MRAM_TXB].num * TXB_ELEMENT_SIZE; > > + for (i = start; i < end; i += 4) > > + writel(0x0, priv->mram_base + i); > > Can we access the mram without turning on the clock? > Yes, we can. Since it's CPU access, it seems it does not depend on M_CAN clocks. What i see from M_CAN subsystem block diagram of MX6SX, it requires CPU clock which should always be enabled. Regards Dong Aisheng > 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 | > ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH V4 3/3] can: m_can: add missing message RAM initialization 2014-11-07 8:45 ` [PATCH V4 3/3] can: m_can: add missing message RAM initialization Dong Aisheng 2014-11-07 10:30 ` Marc Kleine-Budde @ 2014-11-07 11:53 ` Oliver Hartkopp 1 sibling, 0 replies; 11+ messages in thread From: Oliver Hartkopp @ 2014-11-07 11:53 UTC (permalink / raw) To: linux-arm-kernel Thanks! Hopefully we can manage to push the patch series via can/master ;-) Regards, Oliver On 07.11.2014 09:45, Dong Aisheng wrote: > The M_CAN message RAM is usually equipped with a parity or ECC functionality. > But RAM cells suffer a hardware reset and can therefore hold arbitrary > content at startup - including parity and/or ECC bits. > > To prevent the M_CAN controller detecting checksum errors when reading > potentially uninitialized TX message RAM content to transmit CAN > frames the TX message RAM has to be written with (any kind of) initial > data. > > Signed-off-by: Dong Aisheng <b29396@freescale.com> > --- > ChangeLog: > v3-v4: > * initialize the entire Message RAM in use instead of only 8 bytes > since this is a valid and needed initialization process. > Patch title also changed. > --- > drivers/net/can/m_can/m_can.c | 11 ++++++++++- > 1 file changed, 10 insertions(+), 1 deletion(-) > > diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c > index eee1533..de742d0 100644 > --- a/drivers/net/can/m_can/m_can.c > +++ b/drivers/net/can/m_can/m_can.c > @@ -1114,7 +1114,7 @@ static int m_can_of_parse_mram(struct platform_device *pdev, > struct resource *res; > void __iomem *addr; > u32 out_val[MRAM_CFG_LEN]; > - int ret; > + int i, start, end, ret; > > /* message ram could be shared */ > res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram"); > @@ -1165,6 +1165,15 @@ static int m_can_of_parse_mram(struct platform_device *pdev, > priv->mcfg[MRAM_TXE].off, priv->mcfg[MRAM_TXE].num, > priv->mcfg[MRAM_TXB].off, priv->mcfg[MRAM_TXB].num); > > + /* initialize the entire Message RAM in use to avoid possible > + * ECC/parity checksum errors when reading an uninitialized buffer > + */ > + start = priv->mcfg[MRAM_SIDF].off; > + end = priv->mcfg[MRAM_TXB].off + > + priv->mcfg[MRAM_TXB].num * TXB_ELEMENT_SIZE; > + for (i = start; i < end; i += 4) > + writel(0x0, priv->mram_base + i); > + > return 0; > } > > ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH V4 1/3] can: add can_is_canfd_skb() API 2014-11-07 8:45 [PATCH V4 1/3] can: add can_is_canfd_skb() API Dong Aisheng 2014-11-07 8:45 ` [PATCH V4 2/3] can: m_can: update to support CAN FD features Dong Aisheng 2014-11-07 8:45 ` [PATCH V4 3/3] can: m_can: add missing message RAM initialization Dong Aisheng @ 2014-11-13 10:04 ` Marc Kleine-Budde 2 siblings, 0 replies; 11+ messages in thread From: Marc Kleine-Budde @ 2014-11-13 10:04 UTC (permalink / raw) To: linux-arm-kernel On 11/07/2014 09:45 AM, Dong Aisheng wrote: > The CAN device drivers can use it to check if the frame to send is on > CAN FD mode or normal CAN mode. Applied patches 1 and 3. 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 | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141113/7bf986df/attachment.sig> ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2014-11-18 11:22 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-11-07 8:45 [PATCH V4 1/3] can: add can_is_canfd_skb() API Dong Aisheng 2014-11-07 8:45 ` [PATCH V4 2/3] can: m_can: update to support CAN FD features Dong Aisheng 2014-11-13 10:10 ` Marc Kleine-Budde 2014-11-13 16:56 ` Oliver Hartkopp 2014-11-14 9:24 ` Marc Kleine-Budde 2014-11-18 11:22 ` Dong Aisheng 2014-11-07 8:45 ` [PATCH V4 3/3] can: m_can: add missing message RAM initialization Dong Aisheng 2014-11-07 10:30 ` Marc Kleine-Budde 2014-11-07 10:21 ` Dong Aisheng 2014-11-07 11:53 ` Oliver Hartkopp 2014-11-13 10:04 ` [PATCH V4 1/3] can: add can_is_canfd_skb() API 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).