Is new controller: Support CAN and CANFD protocol. Signed-off-by: Elaine Zhang <zhangqing@xxxxxxxxxxxxxx> --- .../net/can/rockchip/rockchip_canfd-core.c | 453 +++++++++++++++--- drivers/net/can/rockchip/rockchip_canfd-rx.c | 111 ++++- drivers/net/can/rockchip/rockchip_canfd-tx.c | 29 ++ drivers/net/can/rockchip/rockchip_canfd.h | 285 +++++++++++ 4 files changed, 820 insertions(+), 58 deletions(-) diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/can/rockchip/rockchip_canfd-core.c index df18c85fc078..ceae691412d4 100644 --- a/drivers/net/can/rockchip/rockchip_canfd-core.c +++ b/drivers/net/can/rockchip/rockchip_canfd-core.c @@ -50,6 +50,11 @@ static const struct rkcanfd_devtype_data rkcanfd_devtype_data_rk3568v3 = { RKCANFD_QUIRK_CANFD_BROKEN, }; +/* The rk3576 CAN-FD */ +static const struct rkcanfd_devtype_data rkcanfd_devtype_data_rk3576 = { + .model = RKCANFD_MODEL_RK3576, +}; + static const char *__rkcanfd_get_model_str(enum rkcanfd_model model) { switch (model) { @@ -57,6 +62,8 @@ static const char *__rkcanfd_get_model_str(enum rkcanfd_model model) return "rk3568v2"; case RKCANFD_MODEL_RK3568V3: return "rk3568v3"; + case RKCANFD_MODEL_RK3576: + return "rk3576"; } return "<unknown>"; @@ -163,10 +170,21 @@ static void rkcanfd_get_berr_counter_corrected(struct rkcanfd_priv *priv, struct can_berr_counter *bec) { struct can_berr_counter bec_raw; - u32 reg_state; + u32 reg_state, rxerr, txerr, busoff_state, error_war_state; - bec->rxerr = rkcanfd_read(priv, RKCANFD_REG_RXERRORCNT); - bec->txerr = rkcanfd_read(priv, RKCANFD_REG_TXERRORCNT); + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) { + rxerr = RK3576CANFD_REG_RXERRORCNT; + txerr = RK3576CANFD_REG_TXERRORCNT; + busoff_state = RK3576CANFD_REG_STATE_BUS_OFF_STATE; + error_war_state = RK3576CANFD_REG_STATE_ERROR_WARNING_STATE; + } else { + rxerr = RKCANFD_REG_RXERRORCNT; + txerr = RKCANFD_REG_TXERRORCNT; + busoff_state = RKCANFD_REG_STATE_BUS_OFF_STATE; + error_war_state = RKCANFD_REG_STATE_ERROR_WARNING_STATE; + } + bec->rxerr = rkcanfd_read(priv, rxerr); + bec->txerr = rkcanfd_read(priv, txerr); bec_raw = *bec; /* Tests show that sometimes both CAN bus error counters read @@ -198,8 +216,8 @@ static void rkcanfd_get_berr_counter_corrected(struct rkcanfd_priv *priv, "%s: Raw/Cor: txerr=%3u/%3u rxerr=%3u/%3u Bus Off=%u Warning=%u\n", __func__, bec_raw.txerr, bec->txerr, bec_raw.rxerr, bec->rxerr, - !!(reg_state & RKCANFD_REG_STATE_BUS_OFF_STATE), - !!(reg_state & RKCANFD_REG_STATE_ERROR_WARNING_STATE)); + !!(reg_state & busoff_state), + !!(reg_state & error_war_state)); } static int rkcanfd_get_berr_counter(const struct net_device *ndev, @@ -229,28 +247,106 @@ static void rkcanfd_chip_interrupts_enable(const struct rkcanfd_priv *priv) static void rkcanfd_chip_interrupts_disable(const struct rkcanfd_priv *priv) { - rkcanfd_write(priv, RKCANFD_REG_INT_MASK, RKCANFD_REG_INT_ALL); + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) + rkcanfd_write(priv, RK3576CANFD_REG_INT_MASK, RK3576CANFD_REG_INT_ALL); + else + rkcanfd_write(priv, RKCANFD_REG_INT_MASK, RKCANFD_REG_INT_ALL); } static void rkcanfd_chip_fifo_setup(struct rkcanfd_priv *priv) { - u32 reg; - - /* TXE FIFO */ - reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL); - reg |= RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_ENABLE; - rkcanfd_write(priv, RKCANFD_REG_RX_FIFO_CTRL, reg); - - /* RX FIFO */ - reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL); - reg |= RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_ENABLE; - rkcanfd_write(priv, RKCANFD_REG_RX_FIFO_CTRL, reg); + u32 reg, ism = 0, water = 0; + + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) { + if (priv->rx_max_data > 4) { + ism = RK3576CANFD_DATA_CANFD_FIXED; + water = RK3576CANFD_ISM_WATERMASK_CANFD; + } else { + ism = RK3576CANFD_DATA_CAN_FIXED; + water = RK3576CANFD_ISM_WATERMASK_CAN; + } + /* internal sram mode */ + rkcanfd_write(priv, RK3576CANFD_REG_STR_CTL, + (ism << RK3576CANFD_ISM_SEL_SHIFT) | + RK3576CANFD_STORAGE_TIMEOUT_MODE); + rkcanfd_write(priv, RK3576CANFD_REG_STR_WTM, water); + } else { + /* TXE FIFO */ + reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL); + reg |= RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_ENABLE; + rkcanfd_write(priv, RKCANFD_REG_RX_FIFO_CTRL, reg); + + /* RX FIFO */ + reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL); + reg |= RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_ENABLE; + rkcanfd_write(priv, RKCANFD_REG_RX_FIFO_CTRL, reg); + } WRITE_ONCE(priv->tx_head, 0); WRITE_ONCE(priv->tx_tail, 0); netdev_reset_queue(priv->ndev); } +static int rk3576canfd_atf_config(struct rkcanfd_priv *priv, int mode) +{ + u32 id[10] = {0}; + u32 dlc = 0, dlc_over = 0; + + switch (mode) { + case RK3576CANFD_ATF_MASK_MODE: + rkcanfd_write(priv, RK3576CANFD_REG_ATF0, id[0]); + rkcanfd_write(priv, RK3576CANFD_REG_ATF1, id[1]); + rkcanfd_write(priv, RK3576CANFD_REG_ATF2, id[2]); + rkcanfd_write(priv, RK3576CANFD_REG_ATF3, id[3]); + rkcanfd_write(priv, RK3576CANFD_REG_ATF4, id[4]); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM0, 0x7fff); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM1, 0x7fff); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM2, 0x7fff); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM3, 0x7fff); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM4, 0x7fff); + break; + case RK3576CANFD_ATF_LIST_MODE: + rkcanfd_write(priv, RK3576CANFD_REG_ATF0, id[0]); + rkcanfd_write(priv, RK3576CANFD_REG_ATF1, id[1]); + rkcanfd_write(priv, RK3576CANFD_REG_ATF2, id[2]); + rkcanfd_write(priv, RK3576CANFD_REG_ATF3, id[3]); + rkcanfd_write(priv, RK3576CANFD_REG_ATF4, id[4]); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM0, id[5] | (1 << 31)); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM1, id[6] | (1 << 31)); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM2, id[7] | (1 << 31)); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM3, id[8] | (1 << 31)); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM4, id[9] | (1 << 31)); + break; + default: + rkcanfd_write(priv, RK3576CANFD_REG_ATF_CTL, 0xffff); + return -EINVAL; + } + + if (dlc) { + if (dlc_over) + rkcanfd_write(priv, RK3576CANFD_REG_ATF_DLC, dlc | (1 << 4)); + else + rkcanfd_write(priv, RK3576CANFD_REG_ATF_DLC, dlc | (1 << 4) | (1 << 5)); + } + rkcanfd_write(priv, RK3576CANFD_REG_ATF_CTL, 0); + + return 0; +} + +static void rk3576canfd_init(struct rkcanfd_priv *priv) +{ + rkcanfd_write(priv, RK3576CANFD_REG_AUTO_RETX_CFG, + RK3576CANFD_AUTO_RETX_EN | RK3576CANFD_RETX_LIMIT_EN | + (RK3576CANFD_RETX_TIME_LIMIT_CNT << RK3576CANFD_RETX_TIME_LIMIT_SHIFT)); + + rkcanfd_write(priv, RK3576CANFD_REG_BRS_CFG, 0x7); + + rkcanfd_write(priv, RK3576CANFD_REG_BUSOFFRCY_CFG, + RK3576CANFD_BUSOFF_RCY_MODE_EN | + RK3576CANFD_BUSOFF_RCY_CNT_FAST); + rkcanfd_write(priv, RK3576CANFD_REG_BUSOFF_RCY_THR, RK3576CANFD_BUSOFF_RCY_TIME_FAST); +} + static void rkcanfd_chip_start(struct rkcanfd_priv *priv) { u32 reg; @@ -258,8 +354,12 @@ static void rkcanfd_chip_start(struct rkcanfd_priv *priv) rkcanfd_chip_set_reset_mode(priv); /* Receiving Filter: accept all */ - rkcanfd_write(priv, RKCANFD_REG_IDCODE, 0x0); - rkcanfd_write(priv, RKCANFD_REG_IDMASK, RKCANFD_REG_IDCODE_EXTENDED_FRAME_ID); + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) { + rk3576canfd_atf_config(priv, RK3576CANFD_ATF_MASK_MODE); + } else { + rkcanfd_write(priv, RKCANFD_REG_IDCODE, 0x0); + rkcanfd_write(priv, RKCANFD_REG_IDMASK, RKCANFD_REG_IDCODE_EXTENDED_FRAME_ID); + } /* enable: * - CAN_FD: enable CAN-FD @@ -269,17 +369,26 @@ static void rkcanfd_chip_start(struct rkcanfd_priv *priv) * - WORK_MODE: transition from reset to working mode */ reg = rkcanfd_read(priv, RKCANFD_REG_MODE); - priv->reg_mode_default = reg | - RKCANFD_REG_MODE_CAN_FD_MODE_ENABLE | - RKCANFD_REG_MODE_AUTO_RETX_MODE | - RKCANFD_REG_MODE_COVER_MODE | - RKCANFD_REG_MODE_RXSTX_MODE | - RKCANFD_REG_MODE_WORK_MODE; - - if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) - priv->reg_mode_default |= RKCANFD_REG_MODE_LBACK_MODE | - RKCANFD_REG_MODE_SILENT_MODE | - RKCANFD_REG_MODE_SELF_TEST; + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) + priv->reg_mode_default = reg | RKCANFD_REG_MODE_WORK_MODE; + else + priv->reg_mode_default = reg | + RKCANFD_REG_MODE_CAN_FD_MODE_ENABLE | + RKCANFD_REG_MODE_AUTO_RETX_MODE | + RKCANFD_REG_MODE_COVER_MODE | + RKCANFD_REG_MODE_RXSTX_MODE | + RKCANFD_REG_MODE_WORK_MODE; + + if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) { + priv->reg_mode_default |= RKCANFD_REG_MODE_LBACK_MODE; + rkcanfd_write(priv, RK3576CANFD_REG_ERROR_MASK, RK3576CANFD_ACK_ERROR_MASK); + } else { + priv->reg_mode_default |= RKCANFD_REG_MODE_LBACK_MODE | + RKCANFD_REG_MODE_SILENT_MODE | + RKCANFD_REG_MODE_SELF_TEST; + } + } /* mask, i.e. ignore: * - TIMESTAMP_COUNTER_OVERFLOW_INT - timestamp counter overflow interrupt @@ -287,11 +396,14 @@ static void rkcanfd_chip_start(struct rkcanfd_priv *priv) * - OVERLOAD_INT - CAN bus overload interrupt * - TX_FINISH_INT - Transmit finish interrupt */ - priv->reg_int_mask_default = - RKCANFD_REG_INT_TIMESTAMP_COUNTER_OVERFLOW_INT | - RKCANFD_REG_INT_TX_ARBIT_FAIL_INT | - RKCANFD_REG_INT_OVERLOAD_INT | - RKCANFD_REG_INT_TX_FINISH_INT; + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) + priv->reg_int_mask_default = RK3576CANFD_REG_INT_RX_FINISH_INT; + else + priv->reg_int_mask_default = + RKCANFD_REG_INT_TIMESTAMP_COUNTER_OVERFLOW_INT | + RKCANFD_REG_INT_TX_ARBIT_FAIL_INT | + RKCANFD_REG_INT_OVERLOAD_INT | + RKCANFD_REG_INT_TX_FINISH_INT; /* Do not mask the bus error interrupt if the bus error * reporting is requested. @@ -302,8 +414,13 @@ static void rkcanfd_chip_start(struct rkcanfd_priv *priv) memset(&priv->bec, 0x0, sizeof(priv->bec)); rkcanfd_chip_fifo_setup(priv); - rkcanfd_timestamp_init(priv); - rkcanfd_timestamp_start(priv); + if (priv->devtype_data.model != RKCANFD_MODEL_RK3576) { + rkcanfd_timestamp_init(priv); + rkcanfd_timestamp_start(priv); + } + + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) + rk3576canfd_init(priv); rkcanfd_set_bittiming(priv); @@ -328,7 +445,8 @@ static void rkcanfd_chip_stop(struct rkcanfd_priv *priv, const enum can_state st { priv->can.state = state; - rkcanfd_timestamp_stop(priv); + if (priv->devtype_data.model != RKCANFD_MODEL_RK3576) + rkcanfd_timestamp_stop(priv); __rkcanfd_chip_stop(priv, state); } @@ -336,7 +454,8 @@ static void rkcanfd_chip_stop_sync(struct rkcanfd_priv *priv, const enum can_sta { priv->can.state = state; - rkcanfd_timestamp_stop_sync(priv); + if (priv->devtype_data.model != RKCANFD_MODEL_RK3576) + rkcanfd_timestamp_stop_sync(priv); __rkcanfd_chip_stop(priv, state); } @@ -395,6 +514,9 @@ static const char *rkcanfd_get_error_type_str(unsigned int type) #define RKCAN_ERROR_CODE(reg_ec, code) \ ((reg_ec) & RKCANFD_REG_ERROR_CODE_##code ? __stringify(code) " " : "") +#define RK3576CAN_ERROR_CODE(reg_ec, code) \ + ((reg_ec) & RK3576CANFD_REG_ERROR_CODE_##code ? __stringify(code) " " : "") + static void rkcanfd_handle_error_int_reg_ec(struct rkcanfd_priv *priv, struct can_frame *cf, const u32 reg_ec) @@ -524,6 +646,128 @@ rkcanfd_handle_error_int_reg_ec(struct rkcanfd_priv *priv, struct can_frame *cf, } } +static void +rk3576canfd_handle_error_int_reg_ec(struct rkcanfd_priv *priv, struct can_frame *cf, + const u32 reg_ec) +{ + struct net_device_stats *stats = &priv->ndev->stats; + unsigned int type; + u32 reg_state, reg_cmd; + + type = FIELD_GET(RK3576CANFD_REG_ERROR_CODE_TYPE, reg_ec); + reg_cmd = rkcanfd_read(priv, RK3576CANFD_REG_CMD); + reg_state = rkcanfd_read(priv, RK3576CANFD_REG_STATE); + + netdev_dbg(priv->ndev, "%s Error in %s %s Phase: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s(0x%08x) CMD=%u RX=%u TX=%u Error-Warning=%u Bus-Off=%u\n", + rkcanfd_get_error_type_str(type), + reg_ec & RK3576CANFD_REG_ERROR_CODE_DIRECTION_RX ? "RX" : "TX", + reg_ec & RK3576CANFD_REG_ERROR_CODE_PHASE ? "Data" : "Arbitration", + RK3576CAN_ERROR_CODE(reg_ec, TX_ACK_EOF), + RK3576CAN_ERROR_CODE(reg_ec, TX_CRC), + RK3576CAN_ERROR_CODE(reg_ec, TX_STUFF_COUNT), + RK3576CAN_ERROR_CODE(reg_ec, TX_DATA), + RK3576CAN_ERROR_CODE(reg_ec, TX_SOF_DLC), + RK3576CAN_ERROR_CODE(reg_ec, TX_IDLE), + RK3576CAN_ERROR_CODE(reg_ec, RX_ERROR), + RK3576CAN_ERROR_CODE(reg_ec, RX_OVERLOAD), + RK3576CAN_ERROR_CODE(reg_ec, RX_SPACE), + RK3576CAN_ERROR_CODE(reg_ec, RX_EOF), + RK3576CAN_ERROR_CODE(reg_ec, RX_ACK_LIM), + RK3576CAN_ERROR_CODE(reg_ec, RX_ACK), + RK3576CAN_ERROR_CODE(reg_ec, RX_CRC_LIM), + RK3576CAN_ERROR_CODE(reg_ec, RX_CRC), + RK3576CAN_ERROR_CODE(reg_ec, RX_STUFF_COUNT), + RK3576CAN_ERROR_CODE(reg_ec, RX_DATA), + RK3576CAN_ERROR_CODE(reg_ec, RX_DLC), + RK3576CAN_ERROR_CODE(reg_ec, RX_BRS_ESI), + RK3576CAN_ERROR_CODE(reg_ec, RX_RES), + RK3576CAN_ERROR_CODE(reg_ec, RX_FDF), + RK3576CAN_ERROR_CODE(reg_ec, RX_ID2_RTR), + RK3576CAN_ERROR_CODE(reg_ec, RX_SOF_IDE), + RK3576CAN_ERROR_CODE(reg_ec, RX_BUS_IDLE), + RK3576CAN_ERROR_CODE(reg_ec, RX_BUS_INT), + RK3576CAN_ERROR_CODE(reg_ec, RX_STOP), + reg_ec, reg_cmd, + !!(reg_state & RK3576CANFD_REG_STATE_RX_PERIOD), + !!(reg_state & RK3576CANFD_REG_STATE_TX_PERIOD), + !!(reg_state & RK3576CANFD_REG_STATE_ERROR_WARNING_STATE), + !!(reg_state & RK3576CANFD_REG_STATE_BUS_OFF_STATE)); + + priv->can.can_stats.bus_error++; + + if (reg_ec & RK3576CANFD_REG_ERROR_CODE_DIRECTION_RX) + stats->rx_errors++; + else + stats->tx_errors++; + + if (!cf) + return; + + if (reg_ec & RK3576CANFD_REG_ERROR_CODE_DIRECTION_RX) { + if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_SOF_IDE) + cf->data[3] = CAN_ERR_PROT_LOC_SOF; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_ID2_RTR) + cf->data[3] = CAN_ERR_PROT_LOC_RTR; + /* RKCANFD_REG_ERROR_CODE_RX_FDF */ + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_RES) + cf->data[3] = CAN_ERR_PROT_LOC_RES0; + /* RKCANFD_REG_ERROR_CODE_RX_BRS_ESI */ + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_DLC) + cf->data[3] = CAN_ERR_PROT_LOC_DLC; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_DATA) + cf->data[3] = CAN_ERR_PROT_LOC_DATA; + /* RKCANFD_REG_ERROR_CODE_RX_STUFF_COUNT */ + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_CRC) + cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_CRC_LIM) + cf->data[3] = CAN_ERR_PROT_LOC_ACK_DEL; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_ACK) + cf->data[3] = CAN_ERR_PROT_LOC_ACK; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_ACK_LIM) + cf->data[3] = CAN_ERR_PROT_LOC_ACK_DEL; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_EOF) + cf->data[3] = CAN_ERR_PROT_LOC_EOF; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_SPACE) + cf->data[3] = CAN_ERR_PROT_LOC_EOF; + } else { + cf->data[2] |= CAN_ERR_PROT_TX; + + if (reg_ec & RK3576CANFD_REG_ERROR_CODE_TX_SOF_DLC) + cf->data[3] = CAN_ERR_PROT_LOC_SOF; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_TX_DATA) + cf->data[3] = CAN_ERR_PROT_LOC_DATA; + /* RKCANFD_REG_ERROR_CODE_TX_STUFF_COUNT */ + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_TX_CRC) + cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_TX_ACK_EOF) + cf->data[3] = CAN_ERR_PROT_LOC_ACK_DEL; + } + + switch (reg_ec & RK3576CANFD_REG_ERROR_CODE_TYPE) { + case FIELD_PREP_CONST(RK3576CANFD_REG_ERROR_CODE_TYPE, + RK3576CANFD_REG_ERROR_CODE_TYPE_BIT): + + cf->data[2] |= CAN_ERR_PROT_BIT; + break; + case FIELD_PREP_CONST(RK3576CANFD_REG_ERROR_CODE_TYPE, + RK3576CANFD_REG_ERROR_CODE_TYPE_STUFF): + cf->data[2] |= CAN_ERR_PROT_STUFF; + break; + case FIELD_PREP_CONST(RK3576CANFD_REG_ERROR_CODE_TYPE, + RK3576CANFD_REG_ERROR_CODE_TYPE_FORM): + cf->data[2] |= CAN_ERR_PROT_FORM; + break; + case FIELD_PREP_CONST(RK3576CANFD_REG_ERROR_CODE_TYPE, + RK3576CANFD_REG_ERROR_CODE_TYPE_ACK): + cf->can_id |= CAN_ERR_ACK; + break; + case FIELD_PREP_CONST(RK3576CANFD_REG_ERROR_CODE_TYPE, + RK3576CANFD_REG_ERROR_CODE_TYPE_CRC): + cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ; + break; + } +} + static int rkcanfd_handle_error_int(struct rkcanfd_priv *priv) { struct net_device_stats *stats = &priv->ndev->stats; @@ -532,13 +776,19 @@ static int rkcanfd_handle_error_int(struct rkcanfd_priv *priv) struct sk_buff *skb; int err; - reg_ec = rkcanfd_read(priv, RKCANFD_REG_ERROR_CODE); + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) + reg_ec = rkcanfd_read(priv, RK3576CANFD_REG_ERROR_CODE); + else + reg_ec = rkcanfd_read(priv, RKCANFD_REG_ERROR_CODE); if (!reg_ec) return 0; if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) { - skb = rkcanfd_alloc_can_err_skb(priv, &cf, ×tamp); + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) + skb = alloc_can_err_skb(priv->ndev, &cf); + else + skb = rkcanfd_alloc_can_err_skb(priv, &cf, ×tamp); if (cf) { struct can_berr_counter bec; @@ -549,12 +799,18 @@ static int rkcanfd_handle_error_int(struct rkcanfd_priv *priv) } } - rkcanfd_handle_error_int_reg_ec(priv, cf, reg_ec); + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) + rk3576canfd_handle_error_int_reg_ec(priv, cf, reg_ec); + else + rkcanfd_handle_error_int_reg_ec(priv, cf, reg_ec); if (!cf) return 0; - err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp); + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) + err = can_rx_offload_queue_tail(&priv->offload, skb); + else + err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp); if (err) stats->rx_fifo_errors++; @@ -582,7 +838,10 @@ static int rkcanfd_handle_state_error_int(struct rkcanfd_priv *priv) /* The skb allocation might fail, but can_change_state() * handles cf == NULL. */ - skb = rkcanfd_alloc_can_err_skb(priv, &cf, ×tamp); + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) + skb = alloc_can_err_skb(priv->ndev, &cf); + else + skb = rkcanfd_alloc_can_err_skb(priv, &cf, ×tamp); can_change_state(ndev, cf, tx_state, rx_state); if (new_state == CAN_STATE_BUS_OFF) { @@ -599,7 +858,10 @@ static int rkcanfd_handle_state_error_int(struct rkcanfd_priv *priv) cf->data[7] = bec.rxerr; } - err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp); + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) + err = can_rx_offload_queue_tail(&priv->offload, skb); + else + err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp); if (err) stats->rx_fifo_errors++; @@ -621,7 +883,10 @@ rkcanfd_handle_rx_fifo_overflow_int(struct rkcanfd_priv *priv) netdev_dbg(priv->ndev, "RX-FIFO overflow\n"); - skb = rkcanfd_alloc_can_err_skb(priv, &cf, ×tamp); + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) + skb = alloc_can_err_skb(priv->ndev, &cf); + else + skb = rkcanfd_alloc_can_err_skb(priv, &cf, ×tamp); if (skb) return 0; @@ -632,7 +897,10 @@ rkcanfd_handle_rx_fifo_overflow_int(struct rkcanfd_priv *priv) cf->data[6] = bec.txerr; cf->data[7] = bec.rxerr; - err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp); + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) + err = can_rx_offload_queue_tail(&priv->offload, skb); + else + err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp); if (err) stats->rx_fifo_errors++; @@ -652,11 +920,58 @@ rkcanfd_handle_rx_fifo_overflow_int(struct rkcanfd_priv *priv) err; \ }) +static irqreturn_t rk3576canfd_irq(int irq, void *dev_id) +{ + struct rkcanfd_priv *priv = dev_id; + u32 reg_int_unmasked, reg_int; + + reg_int_unmasked = rkcanfd_read(priv, RK3576CANFD_REG_INT); + reg_int = reg_int_unmasked & ~priv->reg_int_mask_default; + + if (!reg_int) + return IRQ_NONE; + + rkcanfd_write(priv, RK3576CANFD_REG_INT, reg_int); + + if (reg_int & (RK3576CANFD_REG_INT_RXSTR_TIMEOUT_INT | + RK3576CANFD_REG_INT_ISM_WTM_INT | + RK3576CANFD_REG_INT_RX_FIFO_FULL_INT)) + rkcanfd_handle(priv, rx_int); + + if (reg_int & RK3576CANFD_REG_INT_TX_FINISH_INT) + rkcanfd_handle(priv, tx_int); + + if (reg_int & RK3576CANFD_REG_INT_ERROR_INT) + rkcanfd_handle(priv, error_int); + + if (reg_int & (RK3576CANFD_REG_INT_BUS_OFF_INT | + RK3576CANFD_REG_INT_PASSIVE_ERROR_INT | + RK3576CANFD_REG_INT_ERROR_WARNING_INT) || + priv->can.state > CAN_STATE_ERROR_ACTIVE) + rkcanfd_handle(priv, state_error_int); + + if (reg_int & RK3576CANFD_REG_INT_WAKEUP_INT) + netdev_info(priv->ndev, "%s: WAKEUP_INT\n", __func__); + + if (reg_int & RK3576CANFD_REG_INT_BUS_OFF_RECOVERY_INT) + netdev_info(priv->ndev, "%s: BUS_OFF_RECOVERY_INT\n", __func__); + + if (reg_int & RK3576CANFD_REG_INT_OVERLOAD_INT) + netdev_info(priv->ndev, "%s: OVERLOAD_INT\n", __func__); + + can_rx_offload_irq_finish(&priv->offload); + + return IRQ_HANDLED; +} + static irqreturn_t rkcanfd_irq(int irq, void *dev_id) { struct rkcanfd_priv *priv = dev_id; u32 reg_int_unmasked, reg_int; + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) + return rk3576canfd_irq(irq, dev_id); + reg_int_unmasked = rkcanfd_read(priv, RKCANFD_REG_INT); reg_int = reg_int_unmasked & ~priv->reg_int_mask_default; @@ -789,14 +1104,21 @@ static void rkcanfd_register_done(const struct rkcanfd_priv *priv) { u32 dev_id; - dev_id = rkcanfd_read(priv, RKCANFD_REG_RTL_VERSION); + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) { + dev_id = rkcanfd_read(priv, RK3576CANFD_REG_RTL_VERSION); + netdev_info(priv->ndev, + "Rockchip-CANFD %s rev%u.\n", + rkcanfd_get_model_str(priv), dev_id); + } else { + dev_id = rkcanfd_read(priv, RKCANFD_REG_RTL_VERSION); - netdev_info(priv->ndev, - "Rockchip-CANFD %s rev%lu.%lu (errata 0x%04x) found\n", - rkcanfd_get_model_str(priv), - FIELD_GET(RKCANFD_REG_RTL_VERSION_MAJOR, dev_id), - FIELD_GET(RKCANFD_REG_RTL_VERSION_MINOR, dev_id), - priv->devtype_data.quirks); + netdev_info(priv->ndev, + "Rockchip-CANFD %s rev%lu.%lu (errata 0x%04x) found\n", + rkcanfd_get_model_str(priv), + FIELD_GET(RKCANFD_REG_RTL_VERSION_MAJOR, dev_id), + FIELD_GET(RKCANFD_REG_RTL_VERSION_MINOR, dev_id), + priv->devtype_data.quirks); + } if (priv->devtype_data.quirks & RKCANFD_QUIRK_RK3568_ERRATUM_5 && priv->can.clock.freq < RKCANFD_ERRATUM_5_SYSCLOCK_HZ_MIN) @@ -852,6 +1174,9 @@ static const struct of_device_id rkcanfd_of_match[] = { }, { .compatible = "rockchip,rk3568v3-canfd", .data = &rkcanfd_devtype_data_rk3568v3, + }, { + .compatible = "rockchip,rk3576-canfd", + .data = &rkcanfd_devtype_data_rk3576, }, { /* sentinel */ }, @@ -863,7 +1188,7 @@ static int rkcanfd_probe(struct platform_device *pdev) struct rkcanfd_priv *priv; struct net_device *ndev; const void *match; - int err; + int err, val; ndev = alloc_candev(sizeof(struct rkcanfd_priv), RKCANFD_TXFIFO_DEPTH); if (!ndev) @@ -917,8 +1242,24 @@ static int rkcanfd_probe(struct platform_device *pdev) if (match) priv->devtype_data = *(struct rkcanfd_devtype_data *)match; + /* rx-max-data only 4 Words or 18 words are supported */ + if (device_property_read_u32_array(&pdev->dev, "rockchip,rx-max-data", &val, 1)) + priv->rx_max_data = 18; + else + priv->rx_max_data = val; + + if (priv->rx_max_data != 4 && priv->rx_max_data != 18) { + priv->rx_max_data = 18; + dev_warn(&pdev->dev, "rx_max_data is invalid, set to 18 words!\n"); + } + priv->rx_fifo_depth = RK3576CANFD_SRAM_MAX_DEPTH / priv->rx_max_data; + + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) + val = priv->rx_fifo_depth + 1; + else + val = RKCANFD_NAPI_WEIGHT; err = can_rx_offload_add_manual(ndev, &priv->offload, - RKCANFD_NAPI_WEIGHT); + val); if (err) goto out_free_candev; diff --git a/drivers/net/can/rockchip/rockchip_canfd-rx.c b/drivers/net/can/rockchip/rockchip_canfd-rx.c index 475c0409e215..7dad674dc545 100644 --- a/drivers/net/can/rockchip/rockchip_canfd-rx.c +++ b/drivers/net/can/rockchip/rockchip_canfd-rx.c @@ -91,6 +91,47 @@ rkcanfd_fifo_header_to_cfd_header(const struct rkcanfd_priv *priv, return len + cfd->len; } +static unsigned int +rk3576canfd_fifo_header_to_cfd_header(const struct rkcanfd_priv *priv, + const struct rk3576canfd_fifo_header *header, + struct canfd_frame *cfd) +{ + unsigned int len = sizeof(*cfd) - sizeof(cfd->data); + u8 dlc; + + if (header->frameinfo & RK3576CANFD_REG_RXFRD_FRAMEINFO_FRAME_FORMAT) + cfd->can_id = FIELD_GET(RKCANFD_REG_FD_ID_EFF, header->id) | + CAN_EFF_FLAG; + else + cfd->can_id = FIELD_GET(RKCANFD_REG_FD_ID_SFF, header->id); + + dlc = FIELD_GET(RK3576CANFD_REG_RXFRD_FRAMEINFO_DATA_LENGTH, + header->frameinfo); + + /* CAN-FD */ + if (header->frameinfo & RK3576CANFD_REG_RXFRD_FRAMEINFO_FDF) { + cfd->len = can_fd_dlc2len(dlc); + + /* The cfd is not allocated by alloc_canfd_skb(), so + * set CANFD_FDF here. + */ + cfd->flags |= CANFD_FDF; + + if (header->frameinfo & RK3576CANFD_REG_RXFRD_FRAMEINFO_BRS) + cfd->flags |= CANFD_BRS; + } else { + cfd->len = can_cc_dlc2len(dlc); + + if (header->frameinfo & RK3576CANFD_REG_RXFRD_FRAMEINFO_RTR) { + cfd->can_id |= CAN_RTR_FLAG; + + return len; + } + } + + return len + cfd->len; +} + static int rkcanfd_rxstx_filter(struct rkcanfd_priv *priv, const struct canfd_frame *cfd_rx, const u32 ts, bool *tx_done) @@ -198,6 +239,62 @@ rkcanfd_fifo_header_empty(const struct rkcanfd_fifo_header *header) header->frameinfo == header->ts; } +static int rk3576canfd_handle_rx_int_one(struct rkcanfd_priv *priv) +{ + struct net_device_stats *stats = &priv->ndev->stats; + struct canfd_frame cfd[1] = { }, *skb_cfd; + struct rk3576canfd_fifo_header header[1] = { }; + struct sk_buff *skb; + unsigned int len; + int err; + + /* read header into separate struct and convert it later */ + rkcanfd_read_rep(priv, RKCANFD_REG_RX_FIFO_RDATA, + header, sizeof(*header)); + /* read data directly into cfd */ + rkcanfd_read_rep(priv, RKCANFD_REG_RX_FIFO_RDATA, + cfd->data, (priv->rx_max_data - 2) * 4); + + len = rk3576canfd_fifo_header_to_cfd_header(priv, header, cfd); + + /* Drop any received CAN-FD frames if CAN-FD mode is not + * requested. + */ + if (header->frameinfo & RKCANFD_REG_FD_FRAMEINFO_FDF && + !(priv->can.ctrlmode & CAN_CTRLMODE_FD)) { + stats->rx_dropped++; + + return 0; + } + + /* Manual handling of CAN Bus Error counters. See + * rkcanfd_get_corrected_berr_counter() for detailed + * explanation. + */ + if (priv->bec.rxerr) + priv->bec.rxerr = min(CAN_ERROR_PASSIVE_THRESHOLD, + priv->bec.rxerr) - 1; + + if (header->frameinfo & RKCANFD_REG_FD_FRAMEINFO_FDF) + skb = alloc_canfd_skb(priv->ndev, &skb_cfd); + else + skb = alloc_can_skb(priv->ndev, (struct can_frame **)&skb_cfd); + + if (!skb) { + stats->rx_dropped++; + + return 0; + } + + memcpy(skb_cfd, cfd, len); + + err = can_rx_offload_queue_tail(&priv->offload, skb); + if (err) + stats->rx_fifo_errors++; + + return 0; +} + static int rkcanfd_handle_rx_int_one(struct rkcanfd_priv *priv) { struct net_device_stats *stats = &priv->ndev->stats; @@ -207,6 +304,9 @@ static int rkcanfd_handle_rx_int_one(struct rkcanfd_priv *priv) unsigned int len; int err; + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) + return rk3576canfd_handle_rx_int_one(priv); + /* read header into separate struct and convert it later */ rkcanfd_read_rep(priv, RKCANFD_REG_RX_FIFO_RDATA, header, sizeof(*header)); @@ -279,9 +379,16 @@ static int rkcanfd_handle_rx_int_one(struct rkcanfd_priv *priv) static inline unsigned int rkcanfd_rx_fifo_get_len(const struct rkcanfd_priv *priv) { - const u32 reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL); + u32 reg, len; - return FIELD_GET(RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT, reg); + if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) { + reg = rkcanfd_read(priv, RK3576CANFD_REG_STR_STATE); + len = FIELD_GET(RK3576CANFD_REG_INTM_FRAME_CNT, reg); + } else { + reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL); + len = FIELD_GET(RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT, reg); + } + return len; } int rkcanfd_handle_rx_int(struct rkcanfd_priv *priv) diff --git a/drivers/net/can/rockchip/rockchip_canfd-tx.c b/drivers/net/can/rockchip/rockchip_canfd-tx.c index 865a15e033a9..e00f3447928f 100644 --- a/drivers/net/can/rockchip/rockchip_canfd-tx.c +++ b/drivers/net/can/rockchip/rockchip_canfd-tx.c @@ -165,3 +165,32 @@ void rkcanfd_handle_tx_done_one(struct rkcanfd_priv *priv, const u32 ts, frame_len_p); stats->tx_packets++; } + +int rkcanfd_handle_tx_int(struct rkcanfd_priv *priv) +{ + struct net_device_stats *stats = &priv->ndev->stats; + unsigned int tx_tail; + struct sk_buff *skb; + unsigned int frame_len = 0; + + tx_tail = rkcanfd_get_tx_tail(priv); + skb = priv->can.echo_skb[tx_tail]; + + /* Manual handling of CAN Bus Error counters. See + * rkcanfd_get_corrected_berr_counter() for detailed + * explanation. + */ + if (priv->bec.txerr) + priv->bec.txerr--; + + stats->tx_bytes += + can_rx_offload_get_echo_skb_queue_tail(&priv->offload, + tx_tail, &frame_len); + stats->tx_packets++; + WRITE_ONCE(priv->tx_tail, priv->tx_tail + 1); + netif_subqueue_completed_wake(priv->ndev, 0, 1, frame_len, + rkcanfd_get_effective_tx_free(priv), + RKCANFD_TX_START_THRESHOLD); + return 0; +} + diff --git a/drivers/net/can/rockchip/rockchip_canfd.h b/drivers/net/can/rockchip/rockchip_canfd.h index 93131c7d7f54..17f099ee08cf 100644 --- a/drivers/net/can/rockchip/rockchip_canfd.h +++ b/drivers/net/can/rockchip/rockchip_canfd.h @@ -287,6 +287,282 @@ #define RKCANFD_REG_RX_FIFO_RDATA 0x400 #define RKCANFD_REG_TXE_FIFO_RDATA 0x500 +#define RK3576CANFD_REG_MODE 0x000 +#define RK3576CANFD_REG_CMD 0x004 + +#define RK3576CANFD_REG_STATE 0x008 +#define RK3576CANFD_REG_STATE_SLEEP_STATE BIT(5) +#define RK3576CANFD_REG_STATE_BUS_OFF_STATE BIT(4) +#define RK3576CANFD_REG_STATE_ERROR_WARNING_STATE BIT(3) +#define RK3576CANFD_REG_STATE_TX_PERIOD BIT(2) +#define RK3576CANFD_REG_STATE_RX_PERIOD BIT(1) +#define RK3576CANFD_REG_STATE_TX_BUFFER_FULL BIT(0) + +#define RK3576CANFD_REG_INT 0x00c +#define RK3576CANFD_REG_INT_BUSOFF_RCY_INT BIT(19) +#define RK3576CANFD_REG_INT_ESM_WTM_INT BIT(18) +#define RK3576CANFD_REG_INT_ISM_WTM_INT BIT(17) +#define RK3576CANFD_REG_INT_BUSINT_INT BIT(16) +#define RK3576CANFD_REG_INT_RXSTR_TIMEOUT_INT BIT(15) +#define RK3576CANFD_REG_INT_MFI_TIMEOUT_INT BIT(14) +#define RK3576CANFD_REG_INT_MFI_INT BIT(13) +#define RK3576CANFD_REG_INT_AUTO_RETX_FAIL_INT BIT(12) +#define RK3576CANFD_REG_INT_WAKEUP_INT BIT(11) +#define RK3576CANFD_REG_INT_BUS_OFF_RECOVERY_INT BIT(10) +#define RK3576CANFD_REG_INT_BUS_OFF_INT BIT(9) +#define RK3576CANFD_REG_INT_RX_FIFO_OVERFLOW_INT BIT(8) +#define RK3576CANFD_REG_INT_RX_FIFO_FULL_INT BIT(7) +#define RK3576CANFD_REG_INT_ERROR_INT BIT(6) +#define RK3576CANFD_REG_INT_TX_ARBIT_FAIL_INT BIT(5) +#define RK3576CANFD_REG_INT_PASSIVE_ERROR_INT BIT(4) +#define RK3576CANFD_REG_INT_OVERLOAD_INT BIT(3) +#define RK3576CANFD_REG_INT_ERROR_WARNING_INT BIT(2) +#define RK3576CANFD_REG_INT_TX_FINISH_INT BIT(1) +#define RK3576CANFD_REG_INT_RX_FINISH_INT BIT(0) + +#define RK3576CANFD_REG_INT_ALL \ + (RK3576CANFD_REG_INT_BUSOFF_RCY_INT | \ + RK3576CANFD_REG_INT_ESM_WTM_INT | \ + RK3576CANFD_REG_INT_ISM_WTM_INT | \ + RK3576CANFD_REG_INT_BUSINT_INT | \ + RK3576CANFD_REG_INT_RXSTR_TIMEOUT_INT | \ + RK3576CANFD_REG_INT_MFI_TIMEOUT_INT | \ + RK3576CANFD_REG_INT_MFI_INT | \ + RK3576CANFD_REG_INT_AUTO_RETX_FAIL_INT | \ + RK3576CANFD_REG_INT_WAKEUP_INT | \ + RK3576CANFD_REG_INT_BUS_OFF_RECOVERY_INT | \ + RK3576CANFD_REG_INT_BUS_OFF_INT | \ + RK3576CANFD_REG_INT_RX_FIFO_OVERFLOW_INT | \ + RK3576CANFD_REG_INT_RX_FIFO_FULL_INT | \ + RK3576CANFD_REG_INT_ERROR_INT | \ + RK3576CANFD_REG_INT_TX_ARBIT_FAIL_INT | \ + RK3576CANFD_REG_INT_PASSIVE_ERROR_INT | \ + RK3576CANFD_REG_INT_OVERLOAD_INT | \ + RK3576CANFD_REG_INT_ERROR_WARNING_INT | \ + RK3576CANFD_REG_INT_TX_FINISH_INT | \ + RK3576CANFD_REG_INT_RX_FINISH_INT) + +#define RK3576CANFD_REG_INT_ALL_ERROR \ + (RK3576CANFD_REG_INT_BUS_OFF_INT | \ + RK3576CANFD_REG_INT_ERROR_INT | \ + RK3576CANFD_REG_INT_PASSIVE_ERROR_INT | \ + RK3576CANFD_REG_INT_ERROR_WARNING_INT) + +#define RK3576CANFD_REG_INT_MASK 0x010 + +#define RK3576CANFD_REG_FD_NOMINAL_BITTIMING 0x100 +#define RK3576CANFD_REG_FD_NOMINAL_BITTIMING_SAMPLE_MODE BIT(31) +#define RK3576CANFD_REG_FD_NOMINAL_BITTIMING_SJW GENMASK(30, 24) +#define RK3576CANFD_REG_FD_NOMINAL_BITTIMING_BRP GENMASK(23, 16) +#define RK3576CANFD_REG_FD_NOMINAL_BITTIMING_TSEG2 GENMASK(14, 8) +#define RK3576CANFD_REG_FD_NOMINAL_BITTIMING_TSEG1 GENMASK(7, 0) + +#define RK3576CANFD_REG_FD_DATA_BITTIMING 0x104 +#define RK3576CANFD_REG_FD_DATA_BITTIMING_BRS_TSEG1 GENMASK(31, 24) +#define RK3576CANFD_REG_FD_DATA_BITTIMING_BRS_MODE BIT(23) +#define RK3576CANFD_REG_FD_DATA_BITTIMING_ACKSLOT_SYNC_DIS BIT(22) +#define RK3576CANFD_REG_FD_DATA_BITTIMING_SJW GENMASK(20, 17) +#define RK3576CANFD_REG_FD_DATA_BITTIMING_BRP GENMASK(16, 9) +#define RK3576CANFD_REG_FD_DATA_BITTIMING_TSEG2 GENMASK(8, 5) +#define RK3576CANFD_REG_FD_DATA_BITTIMING_TSEG1 GENMASK(4, 0) + +#define RK3576CANFD_REG_TRANSMIT_DELAY_COMPENSATION 0x108 +#define RK3576CANFD_REG_TRANSMIT_DELAY_COMPENSATION_TDC_OFFSET GENMASK(6, 1) +#define RK3576CANFD_REG_TRANSMIT_DELAY_COMPENSATION_TDC_ENABLE BIT(0) + +#define RK3576CANFD_REG_BRS_CFG 0x10c +#define RK3576CANFD_REG_BRS_CFG_TRIPLE_SYNC_MODE BIT(31) +#define RK3576CANFD_REG_BRS_CFG_SP2_DTSEG1 GENMASK(30, 26) +#define RK3576CANFD_REG_BRS_CFG_SP2_NTSEG1 GENMASK(25, 18) +#define RK3576CANFD_REG_BRS_CFG_SP1_DTSEG1 GENMASK(17, 13) +#define RK3576CANFD_REG_BRS_CFG_SP1_NTSEG1 GENMASK(12, 5) +#define RK3576CANFD_REG_BRS_CFG_RESYNC_MODE BIT(3) +#define RK3576CANFD_REG_BRS_CFG_BRS_POSSYNC_EN BIT(1) +#define RK3576CANFD_REG_BRS_CFG_BRS_NEGSYNC_EN BIT(0) + +#define RK3576CANFD_REG_LOOP_CNT 0x110 + +#define RK3576CANFD_REG_DMA_CTRL 0x11c +#define RK3576CANFD_REG_DMA_CTRL_DMA_RX_EN BIT(9) +#define RK3576CANFD_REG_DMA_CTRL_DMA_THR GENMASK(8, 0) + +#define RK3576CANFD_REG_FD_TXFRAMEINFO 0x200 + +#define RK3576CANFD_REG_FD_TXID 0x204 +#define RK3576CANFD_REG_FD_ID_EFF GENMASK(28, 0) +#define RK3576CANFD_REG_FD_ID_SFF GENMASK(11, 0) + +#define RK3576CANFD_REG_FD_TXDATA0 0x208 +#define RK3576CANFD_REG_FD_TXDATA1 0x20c +#define RK3576CANFD_REG_FD_TXDATA2 0x210 +#define RK3576CANFD_REG_FD_TXDATA3 0x214 +#define RK3576CANFD_REG_FD_TXDATA4 0x218 +#define RK3576CANFD_REG_FD_TXDATA5 0x21c +#define RK3576CANFD_REG_FD_TXDATA6 0x220 +#define RK3576CANFD_REG_FD_TXDATA7 0x224 +#define RK3576CANFD_REG_FD_TXDATA8 0x228 +#define RK3576CANFD_REG_FD_TXDATA9 0x22c +#define RK3576CANFD_REG_FD_TXDATA10 0x230 +#define RK3576CANFD_REG_FD_TXDATA11 0x234 +#define RK3576CANFD_REG_FD_TXDATA12 0x238 +#define RK3576CANFD_REG_FD_TXDATA13 0x23c +#define RK3576CANFD_REG_FD_TXDATA14 0x240 +#define RK3576CANFD_REG_FD_TXDATA15 0x244 + +#define RK3576CANFD_REG_RXFRD 0x400 +#define RK3576CANFD_REG_RXFRD_FRAMEINFO_FRAME_FORMAT BIT(23) +#define RK3576CANFD_REG_RXFRD_FRAMEINFO_RTR BIT(22) +#define RK3576CANFD_REG_RXFRD_FRAMEINFO_FDF BIT(21) +#define RK3576CANFD_REG_RXFRD_FRAMEINFO_BRS BIT(20) +#define RK3576CANFD_REG_RXFRD_FRAMEINFO_DATA_LENGTH GENMASK(27, 24) + +#define RK3576CANFD_REG_STR_CTL 0x600 +#define RK3576CANFD_REG_STR_STATE 0x604 +#define RK3576CANFD_REG_INTM_FRAME_CNT GENMASK(25, 17) + +#define RK3576CANFD_REG_STR_TIMEOUT 0x608 + +#define RK3576CANFD_BUFFER_MODE_ENABLE BIT(0) +#define RK3576CANFD_EXT_STORAGE_MODE BIT(1) +#define RK3576CANFD_ISM_SEL_SHIFT 2 +#define RK3576CANFD_ISM_SEL_MASK (0x3 << RK3576CANFD_ISM_SEL_SHIFT) +#define RK3576CANFD_RX_STORAGE_RESET BIT(4) +#define RK3576CANFD_ESM_SEL_SHIFT 6 +#define RK3576CANFD_ESM_SEL_MASK (0x3 << RK3576CANFD_ESM_SEL_SHIFT) +#define RK3576CANFD_STORAGE_TIMEOUT_MODE BIT(8) + +#define RK3576CANFD_INTM_CNT_SHIFT 17 +#define RK3576CANFD_INTM_CNT_MASK (0x1ff << RK3576CANFD_INTM_CNT_SHIFT) +#define RK3576CANFD_INTM_LEFT_CNT_SHIFT 8 +#define RK3576CANFD_INTM_LEFT_CNT_MASK (0x1ff << RK3576CANFD_INTM_LEFT_CNT_SHIFT) +#define RK3576CANFD_EXTM_FULL BIT(3) +#define RK3576CANFD_EXTM_EMPTY BIT(2) +#define RK3576CANFD_INTM_FULL BIT(1) +#define RK3576CANFD_INTM_EMPTY BIT(0) + +#define RK3576CANFD_REG_STR_WTM 0x60c +#define RK3576CANFD_REG_ATF0 0x700 +#define RK3576CANFD_REG_ATF1 0x704 +#define RK3576CANFD_REG_ATF2 0x708 +#define RK3576CANFD_REG_ATF3 0x70c +#define RK3576CANFD_REG_ATF4 0x710 +#define RK3576CANFD_REG_ATFM0 0x714 +#define RK3576CANFD_REG_ATFM1 0x718 +#define RK3576CANFD_REG_ATFM2 0x71c +#define RK3576CANFD_REG_ATFM3 0x720 +#define RK3576CANFD_REG_ATFM4 0x724 +#define RK3576CANFD_REG_ATF_DLC 0x728 +#define RK3576CANFD_REG_ATF_CTL 0x72c +#define RK3576CANFD_ATF_MASK BIT(31) +#define RK3576CANFD_ATF_RTR_EN BIT(30) +#define RK3576CANFD_ATF_RTR BIT(29) +#define RK3576CANFD_ATF_DLC_MODE BIT(5) +#define RK3576CANFD_ATF_DLC_EN BIT(4) +#define RK3576CANFD_ATF_DLC_SHIFT 0 +#define RK3576CANFD_ATF_DLC_MASK (0xf << RK3576CANFD_ATF_DLC_SHIFT) +#define RK3576CANFD_ATF_DIS(n) BIT(n) + +#define RK3576CANFD_REG_SPACE_CTRL 0x800 + +#define RK3576CANFD_REG_AUTO_RETX_CFG 0x808 +#define RK3576CANFD_RETX_TIME_LIMIT_CNT 0x12c /* 300 */ +#define RK3576CANFD_RETX_TIME_LIMIT_SHIFT 3 +#define RK3576CANFD_RETX_LIMIT_EN BIT(1) +#define RK3576CANFD_AUTO_RETX_EN BIT(0) + +#define RK3576CANFD_REG_AUTO_RETX_STATE0 0x80c +#define RK3576CANFD_REG_AUTO_RETX_STATE1 0x810 +#define RK3576CANFD_REG_OLF_CFG 0x814 +#define RK3576CANFD_REG_RXINT_CTRL 0x818 +#define RK3576CANFD_REG_RXINT_TIMEOUT 0x81c +#define RK3576CANFD_REG_OTHER_CFG 0x820 +#define RK3576CANFD_REG_WAVE_FILTER_CFG 0x824 +#define RK3576CANFD_REG_RBC_CFG 0x828 +#define RK3576CANFD_REG_TXCRC_CFG 0x82c + +#define RK3576CANFD_REG_BUSOFFRCY_CFG 0x830 +#define RK3576CANFD_REG_BUSOFF_RCY_THR 0x834 +#define RK3576CANFD_BUSOFF_RCY_MODE_EN BIT(8) +#define RK3576CANFD_BUSOFF_RCY_TIME_CLR BIT(9) +#define RK3576CANFD_BUSOFF_RCY_CNT_FAST 4 +#define RK3576CANFD_BUSOFF_RCY_CNT_SLOW 5 +#define RK3576CANFD_BUSOFF_RCY_TIME_FAST 0x3d0900 /* 40ms : cnt * (1 / can_clk) */ +#define RK3576CANFD_BUSOFF_RCY_TIME_SLOW 0x1312d00 /* 200ms : cnt * (1 / can_clk) */ + +#define RK3576CANFD_REG_ERROR_CODE 0x900 +#define RK3576CANFD_REG_ERROR_MASK 0x904 +#define RK3576CANFD_ACK_ERROR_MASK BIT(4) +#define RK3576CANFD_FORM_ERROR_MASK BIT(3) +#define RK3576CANFD_CRC_ERROR_MASK BIT(2) +#define RK3576CANFD_STUFF_ERROR_MASK BIT(1) +#define RK3576CANFD_BIT_ERROR_MASK BIT(0) + +#define RK3576CANFD_REG_RXERRORCNT 0x910 +#define RK3576CANFD_REG_TXERRORCNT 0x914 +#define RK3576CANFD_REG_RX_RXSRAM_RDATA 0xc00 +#define RK3576CANFD_REG_RTL_VERSION 0xf0c + +#define RK3576CANFD_REG_ERROR_CODE_PHASE BIT(29) +#define RK3576CANFD_REG_ERROR_CODE_TYPE GENMASK(28, 26) +#define RK3576CANFD_REG_ERROR_CODE_TYPE_BIT 0x0 +#define RK3576CANFD_REG_ERROR_CODE_TYPE_STUFF 0x1 +#define RK3576CANFD_REG_ERROR_CODE_TYPE_FORM 0x2 +#define RK3576CANFD_REG_ERROR_CODE_TYPE_ACK 0x3 +#define RK3576CANFD_REG_ERROR_CODE_TYPE_CRC 0x4 +#define RK3576CANFD_REG_ERROR_CODE_DIRECTION_RX BIT(25) +#define RK3576CANFD_REG_ERROR_CODE_TX GENMASK(24, 19) +#define RK3576CANFD_REG_ERROR_CODE_TX_ACK_EOF BIT(24) +#define RK3576CANFD_REG_ERROR_CODE_TX_CRC BIT(23) +#define RK3576CANFD_REG_ERROR_CODE_TX_STUFF_COUNT BIT(22) +#define RK3576CANFD_REG_ERROR_CODE_TX_DATA BIT(21) +#define RK3576CANFD_REG_ERROR_CODE_TX_SOF_DLC BIT(20) +#define RK3576CANFD_REG_ERROR_CODE_TX_IDLE BIT(19) +#define RK3576CANFD_REG_ERROR_CODE_RX GENMASK(18, 0) +#define RK3576CANFD_REG_ERROR_CODE_RX_ERROR BIT(18) +#define RK3576CANFD_REG_ERROR_CODE_RX_OVERLOAD BIT(17) +#define RK3576CANFD_REG_ERROR_CODE_RX_SPACE BIT(16) +#define RK3576CANFD_REG_ERROR_CODE_RX_EOF BIT(15) +#define RK3576CANFD_REG_ERROR_CODE_RX_ACK_LIM BIT(14) +#define RK3576CANFD_REG_ERROR_CODE_RX_ACK BIT(13) +#define RK3576CANFD_REG_ERROR_CODE_RX_CRC_LIM BIT(12) +#define RK3576CANFD_REG_ERROR_CODE_RX_CRC BIT(11) +#define RK3576CANFD_REG_ERROR_CODE_RX_STUFF_COUNT BIT(10) +#define RK3576CANFD_REG_ERROR_CODE_RX_DATA BIT(9) +#define RK3576CANFD_REG_ERROR_CODE_RX_DLC BIT(8) +#define RK3576CANFD_REG_ERROR_CODE_RX_BRS_ESI BIT(7) +#define RK3576CANFD_REG_ERROR_CODE_RX_RES BIT(6) +#define RK3576CANFD_REG_ERROR_CODE_RX_FDF BIT(5) +#define RK3576CANFD_REG_ERROR_CODE_RX_ID2_RTR BIT(4) +#define RK3576CANFD_REG_ERROR_CODE_RX_SOF_IDE BIT(3) +#define RK3576CANFD_REG_ERROR_CODE_RX_BUS_IDLE BIT(2) +#define RK3576CANFD_REG_ERROR_CODE_RX_BUS_INT BIT(1) +#define RK3576CANFD_REG_ERROR_CODE_RX_STOP BIT(0) + +#define RK3576CANFD_ISM_WATERMASK_CAN 0x6c /* word */ +#define RK3576CANFD_ISM_WATERMASK_CANFD 0x6c /* word */ +#define RK3576CANFD_ESM_WATERMASK (0x50 << 8) /* word */ + +#define RK3576CANFD_SRAM_MAX_DEPTH 256 /* word */ +#define RK3576CANFD_EXT_MEM_SIZE 0x2000 /* 8KByte */ + +#define RK3576CANFD_CANFD_FILTER_MASK 0x1fffffff + +#define RK3576CANFD_CANFD_FIFO_CNT_MASK 0xff + +#define RK3576CANFD_CANBUSOFF_RCY_SLOW 200 /* ms */ +#define RK3576CANFD_CANBUSOFF_RCY_FAST 30 /* ms */ + +enum rk3576canfd_atf_mode { + RK3576CANFD_ATF_MASK_MODE = 0, + RK3576CANFD_ATF_LIST_MODE, +}; + +enum rk3576canfd_storage_mode { + RK3576CANFD_DATA_FLEXIBLE = 0, + RK3576CANFD_DATA_CAN_FIXED, + RK3576CANFD_DATA_CANFD_FIXED, +}; + #define DEVICE_NAME "rockchip_canfd" #define RKCANFD_NAPI_WEIGHT 32 #define RKCANFD_TXFIFO_DEPTH 2 @@ -434,6 +710,7 @@ enum rkcanfd_model { RKCANFD_MODEL_RK3568V2 = 0x35682, RKCANFD_MODEL_RK3568V3 = 0x35683, + RKCANFD_MODEL_RK3576 = 0x3576, }; struct rkcanfd_devtype_data { @@ -447,6 +724,11 @@ struct rkcanfd_fifo_header { u32 ts; }; +struct rk3576canfd_fifo_header { + u32 frameinfo; + u32 id; +}; + struct rkcanfd_stats { struct u64_stats_sync syncp; @@ -482,6 +764,8 @@ struct rkcanfd_priv { struct reset_control *reset; struct clk_bulk_data *clks; int clks_num; + int rx_fifo_depth; + int rx_max_data; }; static inline u32 @@ -536,6 +820,7 @@ rkcanfd_get_tx_free(const struct rkcanfd_priv *priv) void rkcanfd_ethtool_init(struct rkcanfd_priv *priv); int rkcanfd_handle_rx_int(struct rkcanfd_priv *priv); +int rkcanfd_handle_tx_int(struct rkcanfd_priv *priv); void rkcanfd_skb_set_timestamp(const struct rkcanfd_priv *priv, struct sk_buff *skb, const u32 timestamp); -- 2.34.1