can: enhance bit timing ioctl to set both nominal and data bit timing
This adds field type to canioc_bittiming_s structure that allows to set/obtain bit timing for both CAN CC and CAN FD. CANIOC_GET_BITTIMING is now bidirectional: user specifies type field and gets other fields from the controller. The commit also updates current CAN FD capable controllers using the ioctl. The type is not checked for classical CAN only controllers and nominal bit timing is returned regardless of type value. Signed-off-by: Michal Lenc <michallenc@seznam.cz>
This commit is contained in:
parent
816b1b28a0
commit
e16ee4dba3
@ -2652,18 +2652,39 @@ static int mcan_ioctl(struct can_dev_s *dev, int cmd, unsigned long arg)
|
||||
|
||||
DEBUGASSERT(bt != NULL);
|
||||
|
||||
regval = mcan_getreg(priv, SAM_MCAN_BTP_OFFSET);
|
||||
bt->bt_sjw = ((regval & MCAN_BTP_SJW_MASK) >>
|
||||
MCAN_BTP_SJW_SHIFT) + 1;
|
||||
bt->bt_tseg1 = ((regval & MCAN_BTP_TSEG1_MASK) >>
|
||||
MCAN_BTP_TSEG1_SHIFT) + 1;
|
||||
bt->bt_tseg2 = ((regval & MCAN_BTP_TSEG2_MASK) >>
|
||||
MCAN_BTP_TSEG2_SHIFT) + 1;
|
||||
#ifdef CONFIG_CAN_FD
|
||||
if (bt->type == CAN_BITTIMING_DATA)
|
||||
{
|
||||
regval = mcan_getreg(priv, SAM_MCAN_FBTP_OFFSET);
|
||||
bt->bt_sjw = ((regval & MCAN_FBTP_FSJW_MASK) >>
|
||||
MCAN_FBTP_FSJW_SHIFT) + 1;
|
||||
bt->bt_tseg1 = ((regval & MCAN_FBTP_FTSEG1_MASK) >>
|
||||
MCAN_FBTP_FTSEG1_SHIFT) + 1;
|
||||
bt->bt_tseg2 = ((regval & MCAN_FBTP_FTSEG2_MASK) >>
|
||||
MCAN_FBTP_FTSEG2_SHIFT) + 1;
|
||||
|
||||
brp = ((regval & MCAN_FBTP_FBRP_MASK) >>
|
||||
MCAN_FBTP_FBRP_SHIFT) + 1;
|
||||
bt->bt_baud = SAMA5_MCANCLK_FREQUENCY / brp /
|
||||
(bt->bt_tseg1 + bt->bt_tseg2 + 1);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
regval = mcan_getreg(priv, SAM_MCAN_BTP_OFFSET);
|
||||
bt->bt_sjw = ((regval & MCAN_BTP_SJW_MASK) >>
|
||||
MCAN_BTP_SJW_SHIFT) + 1;
|
||||
bt->bt_tseg1 = ((regval & MCAN_BTP_TSEG1_MASK) >>
|
||||
MCAN_BTP_TSEG1_SHIFT) + 1;
|
||||
bt->bt_tseg2 = ((regval & MCAN_BTP_TSEG2_MASK) >>
|
||||
MCAN_BTP_TSEG2_SHIFT) + 1;
|
||||
|
||||
brp = ((regval & MCAN_BTP_BRP_MASK) >>
|
||||
MCAN_BTP_BRP_SHIFT) + 1;
|
||||
bt->bt_baud = SAMA5_MCANCLK_FREQUENCY / brp /
|
||||
(bt->bt_tseg1 + bt->bt_tseg2 + 1);
|
||||
}
|
||||
|
||||
brp = ((regval & MCAN_BTP_BRP_MASK) >>
|
||||
MCAN_BTP_BRP_SHIFT) + 1;
|
||||
bt->bt_baud = SAMA5_MCANCLK_FREQUENCY / brp /
|
||||
(bt->bt_tseg1 + bt->bt_tseg2 + 1);
|
||||
ret = OK;
|
||||
}
|
||||
break;
|
||||
@ -2716,8 +2737,18 @@ static int mcan_ioctl(struct can_dev_s *dev, int cmd, unsigned long arg)
|
||||
/* Save the value of the new bit timing register */
|
||||
|
||||
flags = enter_critical_section();
|
||||
priv->btp = MCAN_BTP_BRP(brp) | MCAN_BTP_TSEG1(tseg1) |
|
||||
MCAN_BTP_TSEG2(tseg2) | MCAN_BTP_SJW(sjw);
|
||||
#ifdef CONFIG_CAN_FD
|
||||
if (bt->type == CAN_BITTIMING_DATA)
|
||||
{
|
||||
priv->fbtp = MCAN_FBTP_FBRP(brp) | MCAN_FBTP_FTSEG1(tseg1) |
|
||||
MCAN_FBTP_FTSEG2(tseg2) | MCAN_FBTP_FSJW(sjw);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
priv->btp = MCAN_BTP_BRP(brp) | MCAN_BTP_TSEG1(tseg1) |
|
||||
MCAN_BTP_TSEG2(tseg2) | MCAN_BTP_SJW(sjw);
|
||||
}
|
||||
|
||||
/* We need to reset to instantiate the new timing. Save
|
||||
* current state information so that recover to this
|
||||
|
@ -144,10 +144,10 @@
|
||||
(float)CONFIG_SAMV7_MCAN0_FBITRATE)) - 1))
|
||||
# define MCAN0_DSJW (CONFIG_SAMV7_MCAN0_FFSJW - 1)
|
||||
|
||||
# if MCAN0_DTSEG1 > 15
|
||||
# if MCAN0_DTSEG1 > 31
|
||||
# error Invalid MCAN0 DTSEG1
|
||||
# endif
|
||||
# if MCAN0_DTSEG2 > 7
|
||||
# if MCAN0_DTSEG2 > 15
|
||||
# error Invalid MCAN0 DTSEG2
|
||||
# endif
|
||||
# if MCAN0_DSJW > 3
|
||||
@ -429,10 +429,10 @@
|
||||
(float)CONFIG_SAMV7_MCAN1_FBITRATE)) - 1))
|
||||
# define MCAN1_DSJW (CONFIG_SAMV7_MCAN1_FFSJW - 1)
|
||||
|
||||
#if MCAN1_DTSEG1 > 15
|
||||
#if MCAN1_DTSEG1 > 31
|
||||
# error Invalid MCAN1 DTSEG1
|
||||
#endif
|
||||
#if MCAN1_DTSEG2 > 7
|
||||
#if MCAN1_DTSEG2 > 15
|
||||
# error Invalid MCAN1 DTSEG2
|
||||
#endif
|
||||
#if MCAN1_DSJW > 3
|
||||
@ -2650,33 +2650,70 @@ static int mcan_ioctl(struct can_dev_s *dev, int cmd, unsigned long arg)
|
||||
|
||||
DEBUGASSERT(bt != NULL);
|
||||
|
||||
regval = mcan_getreg(priv, SAM_MCAN_NBTP_OFFSET);
|
||||
|
||||
if (priv->rev == 0)
|
||||
#ifdef CONFIG_CAN_FD
|
||||
if (bt->type == CAN_BITTIMING_DATA)
|
||||
{
|
||||
/* Revision A */
|
||||
if (priv->rev == 0)
|
||||
{
|
||||
/* Revision A */
|
||||
|
||||
bt->bt_sjw = ((regval & MCAN_REVA_BTP_SJW_MASK) >>
|
||||
MCAN_REVA_BTP_SJW_SHIFT) + 1;
|
||||
bt->bt_tseg1 = ((regval & MCAN_REVA_BTP_TSEG1_MASK) >>
|
||||
MCAN_REVA_BTP_TSEG1_SHIFT) + 1;
|
||||
bt->bt_tseg2 = ((regval & MCAN_REVA_BTP_TSEG2_MASK) >>
|
||||
MCAN_REVA_BTP_TSEG2_SHIFT) + 1;
|
||||
brp = ((regval & MCAN_REVA_BTP_BRP_MASK) >>
|
||||
MCAN_REVA_BTP_BRP_SHIFT) + 1;
|
||||
regval = mcan_getreg(priv,
|
||||
SAM_MCAN_REVA_FBTP_OFFSET);
|
||||
bt->bt_sjw = ((regval & MCAN_REVA_FBTP_FSJW_MASK) >>
|
||||
MCAN_REVA_FBTP_FSJW_SHIFT) + 1;
|
||||
bt->bt_tseg1 = ((regval & MCAN_REVA_FBTP_FTSEG1_MASK) >>
|
||||
MCAN_REVA_FBTP_FTSEG1_SHIFT) + 1;
|
||||
bt->bt_tseg2 = ((regval & MCAN_REVA_FBTP_FTSEG2_MASK) >>
|
||||
MCAN_REVA_FBTP_FTSEG2_SHIFT) + 1;
|
||||
brp = ((regval & MCAN_REVA_FBTP_FBRP_MASK) >>
|
||||
MCAN_REVA_FBTP_FBRP_SHIFT) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Revision B */
|
||||
|
||||
regval = mcan_getreg(priv, SAM_MCAN_DBTP_OFFSET);
|
||||
bt->bt_sjw = ((regval & MCAN_DBTP_DSJW_MASK) >>
|
||||
MCAN_DBTP_DSJW_SHIFT) + 1;
|
||||
bt->bt_tseg1 = ((regval & MCAN_DBTP_DTSEG1_MASK) >>
|
||||
MCAN_DBTP_DTSEG1_SHIFT) + 1;
|
||||
bt->bt_tseg2 = ((regval & MCAN_DBTP_DTSEG2_MASK) >>
|
||||
MCAN_DBTP_DTSEG2_SHIFT) + 1;
|
||||
brp = ((regval & MCAN_DBTP_DBRP_MASK) >>
|
||||
MCAN_DBTP_DBRP_SHIFT) + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Revision B */
|
||||
if (priv->rev == 0)
|
||||
{
|
||||
/* Revision A */
|
||||
|
||||
bt->bt_sjw = ((regval & MCAN_NBTP_NSJW_MASK) >>
|
||||
MCAN_NBTP_NSJW_SHIFT) + 1;
|
||||
bt->bt_tseg1 = ((regval & MCAN_NBTP_NTSEG1_MASK) >>
|
||||
MCAN_NBTP_NTSEG1_SHIFT) + 1;
|
||||
bt->bt_tseg2 = ((regval & MCAN_NBTP_NTSEG2_MASK) >>
|
||||
MCAN_NBTP_NTSEG2_SHIFT) + 1;
|
||||
brp = ((regval & MCAN_NBTP_NBRP_MASK) >>
|
||||
MCAN_NBTP_NBRP_SHIFT) + 1;
|
||||
regval = mcan_getreg(priv, SAM_MCAN_REVA_BTP_OFFSET);
|
||||
bt->bt_sjw = ((regval & MCAN_REVA_BTP_SJW_MASK) >>
|
||||
MCAN_REVA_BTP_SJW_SHIFT) + 1;
|
||||
bt->bt_tseg1 = ((regval & MCAN_REVA_BTP_TSEG1_MASK) >>
|
||||
MCAN_REVA_BTP_TSEG1_SHIFT) + 1;
|
||||
bt->bt_tseg2 = ((regval & MCAN_REVA_BTP_TSEG2_MASK) >>
|
||||
MCAN_REVA_BTP_TSEG2_SHIFT) + 1;
|
||||
brp = ((regval & MCAN_REVA_BTP_BRP_MASK) >>
|
||||
MCAN_REVA_BTP_BRP_SHIFT) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Revision B */
|
||||
|
||||
regval = mcan_getreg(priv, SAM_MCAN_NBTP_OFFSET);
|
||||
bt->bt_sjw = ((regval & MCAN_NBTP_NSJW_MASK) >>
|
||||
MCAN_NBTP_NSJW_SHIFT) + 1;
|
||||
bt->bt_tseg1 = ((regval & MCAN_NBTP_NTSEG1_MASK) >>
|
||||
MCAN_NBTP_NTSEG1_SHIFT) + 1;
|
||||
bt->bt_tseg2 = ((regval & MCAN_NBTP_NTSEG2_MASK) >>
|
||||
MCAN_NBTP_NTSEG2_SHIFT) + 1;
|
||||
brp = ((regval & MCAN_NBTP_NBRP_MASK) >>
|
||||
MCAN_NBTP_NBRP_SHIFT) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
bt->bt_baud = SAMV7_MCANCLK_FREQUENCY / brp /
|
||||
@ -2733,17 +2770,41 @@ static int mcan_ioctl(struct can_dev_s *dev, int cmd, unsigned long arg)
|
||||
/* Save the value of the new bit timing register */
|
||||
|
||||
flags = enter_critical_section();
|
||||
if (priv->rev == 0)
|
||||
#ifdef CONFIG_CAN_FD
|
||||
if (bt->type == CAN_BITTIMING_DATA)
|
||||
{
|
||||
priv->btp = MCAN_REVA_BTP_BRP(brp) |
|
||||
MCAN_REVA_BTP_TSEG1(tseg1) |
|
||||
MCAN_REVA_BTP_TSEG2(tseg2) |
|
||||
MCAN_REVA_BTP_SJW(sjw);
|
||||
if (priv->rev == 0)
|
||||
{
|
||||
priv->fbtp = MCAN_REVA_FBTP_FBRP(brp) |
|
||||
MCAN_REVA_FBTP_FTSEG1(tseg1) |
|
||||
MCAN_REVA_FBTP_FTSEG2(tseg2) |
|
||||
MCAN_REVA_FBTP_FSJW(sjw);
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->fbtp = MCAN_DBTP_DBRP(brp) |
|
||||
MCAN_DBTP_DTSEG1(tseg1) |
|
||||
MCAN_DBTP_DTSEG2(tseg2) |
|
||||
MCAN_DBTP_DSJW(sjw);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
priv->btp = MCAN_NBTP_NBRP(brp) | MCAN_NBTP_NTSEG1(tseg1) |
|
||||
MCAN_NBTP_NTSEG2(tseg2) | MCAN_NBTP_NSJW(sjw);
|
||||
if (priv->rev == 0)
|
||||
{
|
||||
priv->btp = MCAN_REVA_BTP_BRP(brp) |
|
||||
MCAN_REVA_BTP_TSEG1(tseg1) |
|
||||
MCAN_REVA_BTP_TSEG2(tseg2) |
|
||||
MCAN_REVA_BTP_SJW(sjw);
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->btp = MCAN_NBTP_NBRP(brp) |
|
||||
MCAN_NBTP_NTSEG1(tseg1) |
|
||||
MCAN_NBTP_NTSEG2(tseg2) |
|
||||
MCAN_NBTP_NSJW(sjw);
|
||||
}
|
||||
}
|
||||
|
||||
/* We need to reset to instantiate the new timing. Save
|
||||
|
@ -2068,18 +2068,39 @@ static int fdcan_ioctl(struct can_dev_s *dev, int cmd, unsigned long arg)
|
||||
|
||||
DEBUGASSERT(bt != NULL);
|
||||
|
||||
regval = fdcan_getreg(priv, STM32_FDCAN_NBTP_OFFSET);
|
||||
bt->bt_sjw = ((regval & FDCAN_NBTP_NSJW_MASK) >>
|
||||
FDCAN_NBTP_NSJW_SHIFT) + 1;
|
||||
bt->bt_tseg1 = ((regval & FDCAN_NBTP_NTSEG1_MASK) >>
|
||||
FDCAN_NBTP_NTSEG1_SHIFT) + 1;
|
||||
bt->bt_tseg2 = ((regval & FDCAN_NBTP_NTSEG2_MASK) >>
|
||||
FDCAN_NBTP_NTSEG2_SHIFT) + 1;
|
||||
#ifdef CONFIG_CAN_FD
|
||||
if (bt->type == CAN_BITTIMING_DATA)
|
||||
{
|
||||
regval = fdcan_getreg(priv, STM32_FDCAN_DBTP_OFFSET);
|
||||
bt->bt_sjw = ((regval & FDCAN_DBTP_DSJW_MASK) >>
|
||||
FDCAN_DBTP_DSJW_SHIFT) + 1;
|
||||
bt->bt_tseg1 = ((regval & FDCAN_DBTP_DTSEG1_MASK) >>
|
||||
FDCAN_DBTP_DTSEG1_SHIFT) + 1;
|
||||
bt->bt_tseg2 = ((regval & FDCAN_DBTP_DTSEG2_MASK) >>
|
||||
FDCAN_DBTP_DTSEG2_SHIFT) + 1;
|
||||
|
||||
nbrp = ((regval & FDCAN_DBTP_DBRP_MASK) >>
|
||||
FDCAN_DBTP_DBRP_SHIFT) + 1;
|
||||
bt->bt_baud = STM32_FDCANCLK_FREQUENCY / nbrp /
|
||||
(bt->bt_tseg1 + bt->bt_tseg2 + 1);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
regval = fdcan_getreg(priv, STM32_FDCAN_NBTP_OFFSET);
|
||||
bt->bt_sjw = ((regval & FDCAN_NBTP_NSJW_MASK) >>
|
||||
FDCAN_NBTP_NSJW_SHIFT) + 1;
|
||||
bt->bt_tseg1 = ((regval & FDCAN_NBTP_NTSEG1_MASK) >>
|
||||
FDCAN_NBTP_NTSEG1_SHIFT) + 1;
|
||||
bt->bt_tseg2 = ((regval & FDCAN_NBTP_NTSEG2_MASK) >>
|
||||
FDCAN_NBTP_NTSEG2_SHIFT) + 1;
|
||||
|
||||
nbrp = ((regval & FDCAN_NBTP_NBRP_MASK) >>
|
||||
FDCAN_NBTP_NBRP_SHIFT) + 1;
|
||||
bt->bt_baud = STM32_FDCANCLK_FREQUENCY / nbrp /
|
||||
(bt->bt_tseg1 + bt->bt_tseg2 + 1);
|
||||
}
|
||||
|
||||
nbrp = ((regval & FDCAN_NBTP_NBRP_MASK) >>
|
||||
FDCAN_NBTP_NBRP_SHIFT) + 1;
|
||||
bt->bt_baud = STM32_FDCANCLK_FREQUENCY / nbrp /
|
||||
(bt->bt_tseg1 + bt->bt_tseg2 + 1);
|
||||
ret = OK;
|
||||
}
|
||||
break;
|
||||
@ -2130,8 +2151,22 @@ static int fdcan_ioctl(struct can_dev_s *dev, int cmd, unsigned long arg)
|
||||
|
||||
/* Save the value of the new bit timing register */
|
||||
|
||||
priv->nbtp = FDCAN_NBTP_NBRP(nbrp) | FDCAN_NBTP_NTSEG1(ntseg1) |
|
||||
FDCAN_NBTP_NTSEG2(ntseg2) | FDCAN_NBTP_NSJW(nsjw);
|
||||
#ifdef CONFIG_CAN_FD
|
||||
if (bt->type == CAN_BITTIMING_DATA)
|
||||
{
|
||||
priv->dbtp = FDCAN_NBTP_DBRP(nbrp) |
|
||||
FDCAN_NBTP_DTSEG1(ntseg1) |
|
||||
FDCAN_DBTP_DTSEG2(ntseg2) |
|
||||
FDCAN_DBTP_DSJW(nsjw);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
priv->nbtp = FDCAN_NBTP_NBRP(nbrp) |
|
||||
FDCAN_NBTP_NTSEG1(ntseg1) |
|
||||
FDCAN_NBTP_NTSEG2(ntseg2) |
|
||||
FDCAN_NBTP_NSJW(nsjw);
|
||||
}
|
||||
|
||||
/* We need to reset to instantiate the new timing. Save
|
||||
* current state information so that recover to this
|
||||
|
@ -438,6 +438,11 @@
|
||||
#define CAN_FILTER_DUAL 1 /* Dual address match */
|
||||
#define CAN_FILTER_RANGE 2 /* Match a range of addresses */
|
||||
|
||||
/* CAN bit timing support ***************************************************/
|
||||
|
||||
#define CAN_BITTIMING_NOMINAL 0 /* Specifies nominal bittiming */
|
||||
#define CAN_BITTIMING_DATA 1 /* Specifies data bittiming */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
@ -713,6 +718,13 @@ struct canioc_rtr_s
|
||||
|
||||
struct canioc_bittiming_s
|
||||
{
|
||||
#ifdef CONFIG_CAN_FD
|
||||
uint8_t type; /* Nominal/Data bit timing. This is
|
||||
* used to specify which bit timing
|
||||
* should be set/obtained. Applies
|
||||
* only if CAN FD is configured.
|
||||
*/
|
||||
#endif
|
||||
uint32_t bt_baud; /* Bit rate = 1 / bit time */
|
||||
uint8_t bt_tseg1; /* TSEG1 in time quanta */
|
||||
uint8_t bt_tseg2; /* TSEG2 in time quanta */
|
||||
|
Loading…
Reference in New Issue
Block a user