mirror of
https://github.com/apache/nuttx.git
synced 2025-12-17 10:16:49 +08:00
arch/arm64/src/imx9/imx9_flexcan.c: add CAN ID filtering.
Add simple single ID mask filter. Only pkts with set CAN ID are accepted. This works for both STD and EXT CAN ID. Signed-off-by: haitomatic <hai.to@unikie.com>
This commit is contained in:
@@ -552,6 +552,17 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd,
|
||||
unsigned long arg);
|
||||
#endif
|
||||
|
||||
/* CAN ID filtering */
|
||||
|
||||
#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL
|
||||
static uint32_t imx9_add_filter(struct imx9_driver_s *priv,
|
||||
uint8_t filter_type,
|
||||
bool ext_id,
|
||||
uint32_t filter_id1,
|
||||
uint32_t filter_id2);
|
||||
static uint8_t imx9_reset_filter(struct imx9_driver_s *priv);
|
||||
#endif
|
||||
|
||||
/* Initialization */
|
||||
|
||||
static int imx9_initialize(struct imx9_driver_s *priv);
|
||||
@@ -646,7 +657,7 @@ static int imx9_transmit(struct imx9_driver_s *priv)
|
||||
{
|
||||
nwarn("No TX MB available mbi %" PRIi32 "\n", mbi);
|
||||
NETDEV_TXERRORS(&priv->dev);
|
||||
return ERROR;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
|
||||
@@ -663,7 +674,7 @@ static int imx9_transmit(struct imx9_driver_s *priv)
|
||||
+ ((tv->tv_usec - ts.tv_nsec / 1000)*CLK_TCK) / 1000000;
|
||||
if (timeout < 0)
|
||||
{
|
||||
return ERROR;
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1426,7 +1437,7 @@ static volatile struct mb_s *flexcan_get_mb(struct imx9_driver_s *priv,
|
||||
* dev - Reference to the NuttX driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* OK or ERROR
|
||||
* return OK on success, negated error number on failure
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
@@ -1439,7 +1450,7 @@ static int imx9_ifup(struct net_driver_s *dev)
|
||||
if (imx9_initialize(priv) != OK)
|
||||
{
|
||||
canerr("initialize failed");
|
||||
return ERROR;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
priv->bifup = true;
|
||||
@@ -1463,7 +1474,7 @@ static int imx9_ifup(struct net_driver_s *dev)
|
||||
* dev - Reference to the NuttX driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* return OK on success, negated error number on failure
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
@@ -1645,6 +1656,45 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd,
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL
|
||||
case SIOCACANSTDFILTER: /* Set STD ID CAN filter */
|
||||
{
|
||||
struct imx9_driver_s *priv = (struct imx9_driver_s *)dev;
|
||||
struct can_ioctl_filter_s *req =
|
||||
(struct can_ioctl_filter_s *)((uintptr_t)arg);
|
||||
if (!req)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = imx9_add_filter(priv, req->ftype, 0, req->fid1, req->fid2);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCACANEXTFILTER: /* Set EXT ID CAN filter */
|
||||
{
|
||||
struct imx9_driver_s *priv = (struct imx9_driver_s *)dev;
|
||||
struct can_ioctl_filter_s *req =
|
||||
(struct can_ioctl_filter_s *)((uintptr_t)arg);
|
||||
if (!req)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = imx9_add_filter(priv, req->ftype, 1, req->fid1, req->fid2);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCDCANSTDFILTER: /* Reset STD ID CAN filter */
|
||||
case SIOCDCANEXTFILTER: /* Reset EXT ID CAN filter */
|
||||
{
|
||||
struct imx9_driver_s *priv = (struct imx9_driver_s *)dev;
|
||||
ret = imx9_reset_filter(priv);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
@@ -1654,6 +1704,168 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd,
|
||||
}
|
||||
#endif /* CONFIG_NETDEV_IOCTL */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imx9_add_filter
|
||||
*
|
||||
* Description:
|
||||
* Add new MB filter. Currently only support single ID mask filter.
|
||||
* TODO: add support for multiple ID mask filters
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - Pointer to the private CAN driver state structure
|
||||
* filter_type - The type of the filter: mask, range or dual filter
|
||||
* ext_id - true: extended id, false: standard id
|
||||
* filter_id1 - filter id 1 (refer to can_ioctl_filter_s in if.h)
|
||||
* filter_id2 - filter id 2 (refer to can_ioctl_filter_s in if.h)
|
||||
*
|
||||
* Returned Value:
|
||||
* return OK on success, negated error number on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL
|
||||
static uint32_t imx9_add_filter(struct imx9_driver_s *priv,
|
||||
uint8_t filter_type,
|
||||
bool ext_id,
|
||||
uint32_t filter_id1,
|
||||
uint32_t filter_id2)
|
||||
{
|
||||
volatile struct mb_s *mb;
|
||||
uint32_t mbi = 0;
|
||||
|
||||
/* Enter freeze mode */
|
||||
|
||||
if (!imx9_setfreeze(priv->base, true))
|
||||
{
|
||||
canerr("FLEXCAN: freeze fail\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
switch (filter_type)
|
||||
{
|
||||
case CAN_FILTER_MASK:
|
||||
{
|
||||
if (ext_id)
|
||||
{
|
||||
for (mbi = 0; mbi < RXMBCOUNT; mbi++)
|
||||
{
|
||||
/* Set individual mask register */
|
||||
|
||||
putreg32(filter_id2 & CAN_MB_ID_ID_MASK,
|
||||
priv->base + IMX9_CAN_RXIMR_OFFSET(mbi));
|
||||
|
||||
/* Set the acceptance EXT ID filter in MB */
|
||||
|
||||
mb = flexcan_get_mb(priv, mbi);
|
||||
mb->id = filter_id1 & CAN_MB_ID_ID_MASK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (mbi = 0; mbi < RXMBCOUNT; mbi++)
|
||||
{
|
||||
/* Set individual mask register */
|
||||
|
||||
putreg32(((filter_id2 & CAN_SFF_MASK)
|
||||
<< CAN_MB_ID_ID_STD_SHIFT)
|
||||
& CAN_MB_ID_ID_STD_MASK,
|
||||
priv->base + IMX9_CAN_RXIMR_OFFSET(mbi));
|
||||
|
||||
/* Set the acceptance STD ID filter in MB */
|
||||
|
||||
mb = flexcan_get_mb(priv, mbi);
|
||||
mb->id = ((filter_id1 & CAN_SFF_MASK)
|
||||
<< CAN_MB_ID_ID_STD_SHIFT)
|
||||
& CAN_MB_ID_ID_STD_MASK;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CAN_FILTER_RANGE:
|
||||
{
|
||||
canerr("Range filter type not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case CAN_FILTER_DUAL:
|
||||
{
|
||||
canerr("Dual filter type not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
canerr("FLEXCAN: invalid filter type\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Exit freeze mode */
|
||||
|
||||
if (!imx9_setfreeze(priv->base, false))
|
||||
{
|
||||
canerr("FLEXCAN: unfreeze fail\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imx9_reset_filter
|
||||
*
|
||||
* Description:
|
||||
* Clear all ID filters in the MBs
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - Reference to the private FLEXCAN driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* return OK on success, negated error number on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint8_t imx9_reset_filter(struct imx9_driver_s *priv)
|
||||
{
|
||||
volatile struct mb_s *mb;
|
||||
uint32_t mbi = 0;
|
||||
|
||||
/* Enter freeze mode */
|
||||
|
||||
if (!imx9_setfreeze(priv->base, true))
|
||||
{
|
||||
canerr("FLEXCAN: freeze fail\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
for (mbi = 0; mbi < RXMBCOUNT; mbi++)
|
||||
{
|
||||
/* Clear individual mask register */
|
||||
|
||||
putreg32(0, priv->base + IMX9_CAN_RXIMR_OFFSET(mbi));
|
||||
|
||||
/* clear the acceptance ID filter */
|
||||
|
||||
mb = flexcan_get_mb(priv, mbi);
|
||||
mb->id = 0;
|
||||
}
|
||||
|
||||
/* Exit freeze mode */
|
||||
|
||||
if (!imx9_setfreeze(priv->base, false))
|
||||
{
|
||||
canerr("FLEXCAN: unfreeze fail\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */
|
||||
|
||||
/****************************************************************************
|
||||
* Function: imx9_init_eccram
|
||||
*
|
||||
@@ -1753,7 +1965,7 @@ static int imx9_init_eccram(struct imx9_driver_s *priv)
|
||||
* priv - Reference to the private FLEXCAN driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* OK or ERROR
|
||||
* return OK on success, negated error number on failure
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
@@ -1770,7 +1982,7 @@ static int imx9_initialize(struct imx9_driver_s *priv)
|
||||
if (!imx9_setenable(priv->base, true))
|
||||
{
|
||||
canerr("FLEXCAN: enable fail\n");
|
||||
return ERROR;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Enter freeze mode */
|
||||
@@ -1778,7 +1990,7 @@ static int imx9_initialize(struct imx9_driver_s *priv)
|
||||
if (!imx9_setfreeze(priv->base, true))
|
||||
{
|
||||
canerr("FLEXCAN: freeze fail\n");
|
||||
return ERROR;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Initialize memory buffers */
|
||||
@@ -1888,7 +2100,7 @@ static int imx9_initialize(struct imx9_driver_s *priv)
|
||||
if (!imx9_setfreeze(priv->base, false))
|
||||
{
|
||||
canerr("FLEXCAN: unfreeze fail\n");
|
||||
return ERROR;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
Reference in New Issue
Block a user