|
@@ -126,6 +126,12 @@ enum m_can_mram_cfg {
|
|
|
#define DBTP_DSJW_SHIFT 0
|
|
|
#define DBTP_DSJW_MASK (0xf << DBTP_DSJW_SHIFT)
|
|
|
|
|
|
+/* Transmitter Delay Compensation Register (TDCR) */
|
|
|
+#define TDCR_TDCO_SHIFT 8
|
|
|
+#define TDCR_TDCO_MASK (0x7F << TDCR_TDCO_SHIFT)
|
|
|
+#define TDCR_TDCF_SHIFT 0
|
|
|
+#define TDCR_TDCF_MASK (0x7F << TDCR_TDCF_SHIFT)
|
|
|
+
|
|
|
/* Test Register (TEST) */
|
|
|
#define TEST_LBCK BIT(4)
|
|
|
|
|
@@ -987,13 +993,47 @@ static int m_can_set_bittiming(struct net_device *dev)
|
|
|
m_can_write(priv, M_CAN_NBTP, reg_btp);
|
|
|
|
|
|
if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
|
|
|
+ reg_btp = 0;
|
|
|
brp = dbt->brp - 1;
|
|
|
sjw = dbt->sjw - 1;
|
|
|
tseg1 = dbt->prop_seg + dbt->phase_seg1 - 1;
|
|
|
tseg2 = dbt->phase_seg2 - 1;
|
|
|
- reg_btp = (brp << DBTP_DBRP_SHIFT) | (sjw << DBTP_DSJW_SHIFT) |
|
|
|
- (tseg1 << DBTP_DTSEG1_SHIFT) |
|
|
|
- (tseg2 << DBTP_DTSEG2_SHIFT);
|
|
|
+
|
|
|
+ /* TDC is only needed for bitrates beyond 2.5 MBit/s.
|
|
|
+ * This is mentioned in the "Bit Time Requirements for CAN FD"
|
|
|
+ * paper presented at the International CAN Conference 2013
|
|
|
+ */
|
|
|
+ if (dbt->bitrate > 2500000) {
|
|
|
+ u32 tdco, ssp;
|
|
|
+
|
|
|
+ /* Use the same value of secondary sampling point
|
|
|
+ * as the data sampling point
|
|
|
+ */
|
|
|
+ ssp = dbt->sample_point;
|
|
|
+
|
|
|
+ /* Equation based on Bosch's M_CAN User Manual's
|
|
|
+ * Transmitter Delay Compensation Section
|
|
|
+ */
|
|
|
+ tdco = (priv->can.clock.freq / 1000) *
|
|
|
+ ssp / dbt->bitrate;
|
|
|
+
|
|
|
+ /* Max valid TDCO value is 127 */
|
|
|
+ if (tdco > 127) {
|
|
|
+ netdev_warn(dev, "TDCO value of %u is beyond maximum. Using maximum possible value\n",
|
|
|
+ tdco);
|
|
|
+ tdco = 127;
|
|
|
+ }
|
|
|
+
|
|
|
+ reg_btp |= DBTP_TDC;
|
|
|
+ m_can_write(priv, M_CAN_TDCR,
|
|
|
+ tdco << TDCR_TDCO_SHIFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ reg_btp |= (brp << DBTP_DBRP_SHIFT) |
|
|
|
+ (sjw << DBTP_DSJW_SHIFT) |
|
|
|
+ (tseg1 << DBTP_DTSEG1_SHIFT) |
|
|
|
+ (tseg2 << DBTP_DTSEG2_SHIFT);
|
|
|
+
|
|
|
m_can_write(priv, M_CAN_DBTP, reg_btp);
|
|
|
}
|
|
|
|