// SPDX-License-Identifier: GPL-2.0 // // Copyright (c) 2023, 2024 Pengutronix, // Marc Kleine-Budde // // Based on: // // Rockchip CANFD driver // // Copyright (c) 2020 Rockchip Electronics Co. Ltd. // #include #include #include #include #include #include #include #include #include #include #include #include "rockchip_canfd.h" static const struct rkcanfd_devtype_data rkcanfd_devtype_data_rk3568v2 = { .model = RKCANFD_MODEL_RK3568V2, .quirks = RKCANFD_QUIRK_RK3568_ERRATUM_1 | RKCANFD_QUIRK_RK3568_ERRATUM_2 | RKCANFD_QUIRK_RK3568_ERRATUM_3 | RKCANFD_QUIRK_RK3568_ERRATUM_4 | RKCANFD_QUIRK_RK3568_ERRATUM_5 | RKCANFD_QUIRK_RK3568_ERRATUM_6 | RKCANFD_QUIRK_RK3568_ERRATUM_7 | RKCANFD_QUIRK_RK3568_ERRATUM_8 | RKCANFD_QUIRK_RK3568_ERRATUM_9 | RKCANFD_QUIRK_RK3568_ERRATUM_10 | RKCANFD_QUIRK_RK3568_ERRATUM_11 | RKCANFD_QUIRK_RK3568_ERRATUM_12 | RKCANFD_QUIRK_CANFD_BROKEN, }; /* The rk3568 CAN-FD errata sheet as of Tue 07 Nov 2023 11:25:31 +08:00 * states that only the rk3568v2 is affected by erratum 5, but tests * with the rk3568v2 and rk3568v3 show that the RX_FIFO_CNT is * sometimes too high. In contrast to the errata sheet mark rk3568v3 * as effected by erratum 5, too. */ static const struct rkcanfd_devtype_data rkcanfd_devtype_data_rk3568v3 = { .model = RKCANFD_MODEL_RK3568V3, .quirks = RKCANFD_QUIRK_RK3568_ERRATUM_1 | RKCANFD_QUIRK_RK3568_ERRATUM_2 | RKCANFD_QUIRK_RK3568_ERRATUM_5 | RKCANFD_QUIRK_RK3568_ERRATUM_7 | RKCANFD_QUIRK_RK3568_ERRATUM_8 | RKCANFD_QUIRK_RK3568_ERRATUM_10 | RKCANFD_QUIRK_RK3568_ERRATUM_11 | RKCANFD_QUIRK_RK3568_ERRATUM_12 | RKCANFD_QUIRK_CANFD_BROKEN, }; static const char *__rkcanfd_get_model_str(enum rkcanfd_model model) { switch (model) { case RKCANFD_MODEL_RK3568V2: return "rk3568v2"; case RKCANFD_MODEL_RK3568V3: return "rk3568v3"; } return ""; } static inline const char * rkcanfd_get_model_str(const struct rkcanfd_priv *priv) { return __rkcanfd_get_model_str(priv->devtype_data.model); } /* Note: * * The formula to calculate the CAN System Clock is: * * Tsclk = 2 x Tclk x (brp + 1) * * Double the data sheet's brp_min, brp_max and brp_inc values (both * for the arbitration and data bit timing) to take the "2 x" into * account. */ static const struct can_bittiming_const rkcanfd_bittiming_const = { .name = DEVICE_NAME, .tseg1_min = 1, .tseg1_max = 256, .tseg2_min = 1, .tseg2_max = 128, .sjw_max = 128, .brp_min = 2, /* value from data sheet x2 */ .brp_max = 512, /* value from data sheet x2 */ .brp_inc = 2, /* value from data sheet x2 */ }; static const struct can_bittiming_const rkcanfd_data_bittiming_const = { .name = DEVICE_NAME, .tseg1_min = 1, .tseg1_max = 32, .tseg2_min = 1, .tseg2_max = 16, .sjw_max = 16, .brp_min = 2, /* value from data sheet x2 */ .brp_max = 512, /* value from data sheet x2 */ .brp_inc = 2, /* value from data sheet x2 */ }; static void rkcanfd_chip_set_reset_mode(const struct rkcanfd_priv *priv) { reset_control_assert(priv->reset); udelay(2); reset_control_deassert(priv->reset); rkcanfd_write(priv, RKCANFD_REG_MODE, 0x0); } static void rkcanfd_chip_set_work_mode(const struct rkcanfd_priv *priv) { rkcanfd_write(priv, RKCANFD_REG_MODE, priv->reg_mode_default); } static int rkcanfd_set_bittiming(struct rkcanfd_priv *priv) { const struct can_bittiming *dbt = &priv->can.data_bittiming; const struct can_bittiming *bt = &priv->can.bittiming; u32 reg_nbt, reg_dbt, reg_tdc; u32 tdco; reg_nbt = FIELD_PREP(RKCANFD_REG_FD_NOMINAL_BITTIMING_SJW, bt->sjw - 1) | FIELD_PREP(RKCANFD_REG_FD_NOMINAL_BITTIMING_BRP, (bt->brp / 2) - 1) | FIELD_PREP(RKCANFD_REG_FD_NOMINAL_BITTIMING_TSEG2, bt->phase_seg2 - 1) | FIELD_PREP(RKCANFD_REG_FD_NOMINAL_BITTIMING_TSEG1, bt->prop_seg + bt->phase_seg1 - 1); rkcanfd_write(priv, RKCANFD_REG_FD_NOMINAL_BITTIMING, reg_nbt); if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD)) return 0; reg_dbt = FIELD_PREP(RKCANFD_REG_FD_DATA_BITTIMING_SJW, dbt->sjw - 1) | FIELD_PREP(RKCANFD_REG_FD_DATA_BITTIMING_BRP, (dbt->brp / 2) - 1) | FIELD_PREP(RKCANFD_REG_FD_DATA_BITTIMING_TSEG2, dbt->phase_seg2 - 1) | FIELD_PREP(RKCANFD_REG_FD_DATA_BITTIMING_TSEG1, dbt->prop_seg + dbt->phase_seg1 - 1); rkcanfd_write(priv, RKCANFD_REG_FD_DATA_BITTIMING, reg_dbt); tdco = (priv->can.clock.freq / dbt->bitrate) * 2 / 3; tdco = min(tdco, FIELD_MAX(RKCANFD_REG_TRANSMIT_DELAY_COMPENSATION_TDC_OFFSET)); reg_tdc = FIELD_PREP(RKCANFD_REG_TRANSMIT_DELAY_COMPENSATION_TDC_OFFSET, tdco) | RKCANFD_REG_TRANSMIT_DELAY_COMPENSATION_TDC_ENABLE; rkcanfd_write(priv, RKCANFD_REG_TRANSMIT_DELAY_COMPENSATION, reg_tdc); return 0; } 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; bec->rxerr = rkcanfd_read(priv, RKCANFD_REG_RXERRORCNT); bec->txerr = rkcanfd_read(priv, RKCANFD_REG_TXERRORCNT); bec_raw = *bec; /* Tests show that sometimes both CAN bus error counters read * 0x0, even if the controller is in warning mode * (RKCANFD_REG_STATE_ERROR_WARNING_STATE in RKCANFD_REG_STATE * set). * * In case both error counters read 0x0, use the struct * priv->bec, otherwise save the read value to priv->bec. * * rkcanfd_handle_rx_int_one() handles the decrementing of * priv->bec.rxerr for successfully RX'ed CAN frames. * * Luckily the controller doesn't decrement the RX CAN bus * error counter in hardware for self received TX'ed CAN * frames (RKCANFD_REG_MODE_RXSTX_MODE), so RXSTX doesn't * interfere with proper RX CAN bus error counters. * * rkcanfd_handle_tx_done_one() handles the decrementing of * priv->bec.txerr for successfully TX'ed CAN frames. */ if (!bec->rxerr && !bec->txerr) *bec = priv->bec; else priv->bec = *bec; reg_state = rkcanfd_read(priv, RKCANFD_REG_STATE); netdev_vdbg(priv->ndev, "%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)); } static int rkcanfd_get_berr_counter(const struct net_device *ndev, struct can_berr_counter *bec) { struct rkcanfd_priv *priv = netdev_priv(ndev); int err; err = pm_runtime_resume_and_get(ndev->dev.parent); if (err) return err; rkcanfd_get_berr_counter_corrected(priv, bec); pm_runtime_put(ndev->dev.parent); return 0; } static void rkcanfd_chip_interrupts_enable(const struct rkcanfd_priv *priv) { rkcanfd_write(priv, RKCANFD_REG_INT_MASK, priv->reg_int_mask_default); netdev_dbg(priv->ndev, "%s: reg_int_mask=0x%08x\n", __func__, rkcanfd_read(priv, RKCANFD_REG_INT_MASK)); } static void rkcanfd_chip_interrupts_disable(const struct rkcanfd_priv *priv) { 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); WRITE_ONCE(priv->tx_head, 0); WRITE_ONCE(priv->tx_tail, 0); netdev_reset_queue(priv->ndev); } static void rkcanfd_chip_start(struct rkcanfd_priv *priv) { u32 reg; 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); /* enable: * - CAN_FD: enable CAN-FD * - AUTO_RETX_MODE: auto retransmission on TX error * - COVER_MODE: RX-FIFO overwrite mode, do not send OVERLOAD frames * - RXSTX_MODE: Receive Self Transmit data mode * - 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; /* mask, i.e. ignore: * - TIMESTAMP_COUNTER_OVERFLOW_INT - timestamp counter overflow interrupt * - TX_ARBIT_FAIL_INT - TX arbitration fail interrupt * - 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; /* Do not mask the bus error interrupt if the bus error * reporting is requested. */ if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) priv->reg_int_mask_default |= RKCANFD_REG_INT_ERROR_INT; memset(&priv->bec, 0x0, sizeof(priv->bec)); rkcanfd_chip_fifo_setup(priv); rkcanfd_timestamp_init(priv); rkcanfd_timestamp_start(priv); rkcanfd_set_bittiming(priv); rkcanfd_chip_interrupts_disable(priv); rkcanfd_chip_set_work_mode(priv); priv->can.state = CAN_STATE_ERROR_ACTIVE; netdev_dbg(priv->ndev, "%s: reg_mode=0x%08x\n", __func__, rkcanfd_read(priv, RKCANFD_REG_MODE)); } static void __rkcanfd_chip_stop(struct rkcanfd_priv *priv, const enum can_state state) { priv->can.state = state; rkcanfd_chip_set_reset_mode(priv); rkcanfd_chip_interrupts_disable(priv); } static void rkcanfd_chip_stop(struct rkcanfd_priv *priv, const enum can_state state) { priv->can.state = state; rkcanfd_timestamp_stop(priv); __rkcanfd_chip_stop(priv, state); } static void rkcanfd_chip_stop_sync(struct rkcanfd_priv *priv, const enum can_state state) { priv->can.state = state; rkcanfd_timestamp_stop_sync(priv); __rkcanfd_chip_stop(priv, state); } static int rkcanfd_set_mode(struct net_device *ndev, enum can_mode mode) { struct rkcanfd_priv *priv = netdev_priv(ndev); switch (mode) { case CAN_MODE_START: rkcanfd_chip_start(priv); rkcanfd_chip_interrupts_enable(priv); netif_wake_queue(ndev); break; default: return -EOPNOTSUPP; } return 0; } static struct sk_buff * rkcanfd_alloc_can_err_skb(struct rkcanfd_priv *priv, struct can_frame **cf, u32 *timestamp) { struct sk_buff *skb; *timestamp = rkcanfd_get_timestamp(priv); skb = alloc_can_err_skb(priv->ndev, cf); if (skb) rkcanfd_skb_set_timestamp(priv, skb, *timestamp); return skb; } static const char *rkcanfd_get_error_type_str(unsigned int type) { switch (type) { case RKCANFD_REG_ERROR_CODE_TYPE_BIT: return "Bit"; case RKCANFD_REG_ERROR_CODE_TYPE_STUFF: return "Stuff"; case RKCANFD_REG_ERROR_CODE_TYPE_FORM: return "Form"; case RKCANFD_REG_ERROR_CODE_TYPE_ACK: return "ACK"; case RKCANFD_REG_ERROR_CODE_TYPE_CRC: return "CRC"; } return ""; } #define RKCAN_ERROR_CODE(reg_ec, code) \ ((reg_ec) & RKCANFD_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) { struct net_device_stats *stats = &priv->ndev->stats; unsigned int type; u32 reg_state, reg_cmd; type = FIELD_GET(RKCANFD_REG_ERROR_CODE_TYPE, reg_ec); reg_cmd = rkcanfd_read(priv, RKCANFD_REG_CMD); reg_state = rkcanfd_read(priv, RKCANFD_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 & RKCANFD_REG_ERROR_CODE_DIRECTION_RX ? "RX" : "TX", reg_ec & RKCANFD_REG_ERROR_CODE_PHASE ? "Data" : "Arbitration", RKCAN_ERROR_CODE(reg_ec, TX_OVERLOAD), RKCAN_ERROR_CODE(reg_ec, TX_ERROR), RKCAN_ERROR_CODE(reg_ec, TX_ACK), RKCAN_ERROR_CODE(reg_ec, TX_ACK_EOF), RKCAN_ERROR_CODE(reg_ec, TX_CRC), RKCAN_ERROR_CODE(reg_ec, TX_STUFF_COUNT), RKCAN_ERROR_CODE(reg_ec, TX_DATA), RKCAN_ERROR_CODE(reg_ec, TX_SOF_DLC), RKCAN_ERROR_CODE(reg_ec, TX_IDLE), RKCAN_ERROR_CODE(reg_ec, RX_BUF_INT), RKCAN_ERROR_CODE(reg_ec, RX_SPACE), RKCAN_ERROR_CODE(reg_ec, RX_EOF), RKCAN_ERROR_CODE(reg_ec, RX_ACK_LIM), RKCAN_ERROR_CODE(reg_ec, RX_ACK), RKCAN_ERROR_CODE(reg_ec, RX_CRC_LIM), RKCAN_ERROR_CODE(reg_ec, RX_CRC), RKCAN_ERROR_CODE(reg_ec, RX_STUFF_COUNT), RKCAN_ERROR_CODE(reg_ec, RX_DATA), RKCAN_ERROR_CODE(reg_ec, RX_DLC), RKCAN_ERROR_CODE(reg_ec, RX_BRS_ESI), RKCAN_ERROR_CODE(reg_ec, RX_RES), RKCAN_ERROR_CODE(reg_ec, RX_FDF), RKCAN_ERROR_CODE(reg_ec, RX_ID2_RTR), RKCAN_ERROR_CODE(reg_ec, RX_SOF_IDE), RKCAN_ERROR_CODE(reg_ec, RX_IDLE), reg_ec, reg_cmd, !!(reg_state & RKCANFD_REG_STATE_RX_PERIOD), !!(reg_state & RKCANFD_REG_STATE_TX_PERIOD), !!(reg_state & RKCANFD_REG_STATE_ERROR_WARNING_STATE), !!(reg_state & RKCANFD_REG_STATE_BUS_OFF_STATE)); priv->can.can_stats.bus_error++; if (reg_ec & RKCANFD_REG_ERROR_CODE_DIRECTION_RX) stats->rx_errors++; else stats->tx_errors++; if (!cf) return; if (reg_ec & RKCANFD_REG_ERROR_CODE_DIRECTION_RX) { if (reg_ec & RKCANFD_REG_ERROR_CODE_RX_SOF_IDE) cf->data[3] = CAN_ERR_PROT_LOC_SOF; else if (reg_ec & RKCANFD_REG_ERROR_CODE_RX_ID2_RTR) cf->data[3] = CAN_ERR_PROT_LOC_RTR; /* RKCANFD_REG_ERROR_CODE_RX_FDF */ else if (reg_ec & RKCANFD_REG_ERROR_CODE_RX_RES) cf->data[3] = CAN_ERR_PROT_LOC_RES0; /* RKCANFD_REG_ERROR_CODE_RX_BRS_ESI */ else if (reg_ec & RKCANFD_REG_ERROR_CODE_RX_DLC) cf->data[3] = CAN_ERR_PROT_LOC_DLC; else if (reg_ec & RKCANFD_REG_ERROR_CODE_RX_DATA) cf->data[3] = CAN_ERR_PROT_LOC_DATA; /* RKCANFD_REG_ERROR_CODE_RX_STUFF_COUNT */ else if (reg_ec & RKCANFD_REG_ERROR_CODE_RX_CRC) cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ; else if (reg_ec & RKCANFD_REG_ERROR_CODE_RX_CRC_LIM) cf->data[3] = CAN_ERR_PROT_LOC_ACK_DEL; else if (reg_ec & RKCANFD_REG_ERROR_CODE_RX_ACK) cf->data[3] = CAN_ERR_PROT_LOC_ACK; else if (reg_ec & RKCANFD_REG_ERROR_CODE_RX_ACK_LIM) cf->data[3] = CAN_ERR_PROT_LOC_ACK_DEL; else if (reg_ec & RKCANFD_REG_ERROR_CODE_RX_EOF) cf->data[3] = CAN_ERR_PROT_LOC_EOF; else if (reg_ec & RKCANFD_REG_ERROR_CODE_RX_SPACE) cf->data[3] = CAN_ERR_PROT_LOC_EOF; else if (reg_ec & RKCANFD_REG_ERROR_CODE_RX_BUF_INT) cf->data[3] = CAN_ERR_PROT_LOC_INTERM; } else { cf->data[2] |= CAN_ERR_PROT_TX; if (reg_ec & RKCANFD_REG_ERROR_CODE_TX_SOF_DLC) cf->data[3] = CAN_ERR_PROT_LOC_SOF; else if (reg_ec & RKCANFD_REG_ERROR_CODE_TX_DATA) cf->data[3] = CAN_ERR_PROT_LOC_DATA; /* RKCANFD_REG_ERROR_CODE_TX_STUFF_COUNT */ else if (reg_ec & RKCANFD_REG_ERROR_CODE_TX_CRC) cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ; else if (reg_ec & RKCANFD_REG_ERROR_CODE_TX_ACK_EOF) cf->data[3] = CAN_ERR_PROT_LOC_ACK_DEL; else if (reg_ec & RKCANFD_REG_ERROR_CODE_TX_ACK) cf->data[3] = CAN_ERR_PROT_LOC_ACK; /* RKCANFD_REG_ERROR_CODE_TX_ERROR */ else if (reg_ec & RKCANFD_REG_ERROR_CODE_TX_OVERLOAD) cf->data[2] |= CAN_ERR_PROT_OVERLOAD; } switch (reg_ec & RKCANFD_REG_ERROR_CODE_TYPE) { case FIELD_PREP_CONST(RKCANFD_REG_ERROR_CODE_TYPE, RKCANFD_REG_ERROR_CODE_TYPE_BIT): cf->data[2] |= CAN_ERR_PROT_BIT; break; case FIELD_PREP_CONST(RKCANFD_REG_ERROR_CODE_TYPE, RKCANFD_REG_ERROR_CODE_TYPE_STUFF): cf->data[2] |= CAN_ERR_PROT_STUFF; break; case FIELD_PREP_CONST(RKCANFD_REG_ERROR_CODE_TYPE, RKCANFD_REG_ERROR_CODE_TYPE_FORM): cf->data[2] |= CAN_ERR_PROT_FORM; break; case FIELD_PREP_CONST(RKCANFD_REG_ERROR_CODE_TYPE, RKCANFD_REG_ERROR_CODE_TYPE_ACK): cf->can_id |= CAN_ERR_ACK; break; case FIELD_PREP_CONST(RKCANFD_REG_ERROR_CODE_TYPE, RKCANFD_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; struct can_frame *cf = NULL; u32 reg_ec, timestamp; struct sk_buff *skb; int err; 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 (cf) { struct can_berr_counter bec; rkcanfd_get_berr_counter_corrected(priv, &bec); cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR | CAN_ERR_CNT; cf->data[6] = bec.txerr; cf->data[7] = bec.rxerr; } } 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 (err) stats->rx_fifo_errors++; return 0; } static int rkcanfd_handle_state_error_int(struct rkcanfd_priv *priv) { struct net_device_stats *stats = &priv->ndev->stats; enum can_state new_state, rx_state, tx_state; struct net_device *ndev = priv->ndev; struct can_berr_counter bec; struct can_frame *cf = NULL; struct sk_buff *skb; u32 timestamp; int err; rkcanfd_get_berr_counter_corrected(priv, &bec); can_state_get_by_berr_counter(ndev, &bec, &tx_state, &rx_state); new_state = max(tx_state, rx_state); if (new_state == priv->can.state) return 0; /* The skb allocation might fail, but can_change_state() * handles cf == NULL. */ 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) { rkcanfd_chip_stop(priv, CAN_STATE_BUS_OFF); can_bus_off(ndev); } if (!skb) return 0; if (new_state != CAN_STATE_BUS_OFF) { cf->can_id |= CAN_ERR_CNT; cf->data[6] = bec.txerr; cf->data[7] = bec.rxerr; } err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp); if (err) stats->rx_fifo_errors++; return 0; } static int rkcanfd_handle_rx_fifo_overflow_int(struct rkcanfd_priv *priv) { struct net_device_stats *stats = &priv->ndev->stats; struct can_berr_counter bec; struct can_frame *cf = NULL; struct sk_buff *skb; u32 timestamp; int err; stats->rx_over_errors++; stats->rx_errors++; netdev_dbg(priv->ndev, "RX-FIFO overflow\n"); skb = rkcanfd_alloc_can_err_skb(priv, &cf, ×tamp); if (skb) return 0; rkcanfd_get_berr_counter_corrected(priv, &bec); cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; cf->data[6] = bec.txerr; cf->data[7] = bec.rxerr; err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp); if (err) stats->rx_fifo_errors++; return 0; } #define rkcanfd_handle(priv, irq, ...) \ ({ \ struct rkcanfd_priv *_priv = (priv); \ int err; \ \ err = rkcanfd_handle_##irq(_priv, ## __VA_ARGS__); \ if (err) \ netdev_err(_priv->ndev, \ "IRQ handler rkcanfd_handle_%s() returned error: %pe\n", \ __stringify(irq), ERR_PTR(err)); \ err; \ }) static irqreturn_t rkcanfd_irq(int irq, void *dev_id) { struct rkcanfd_priv *priv = dev_id; u32 reg_int_unmasked, reg_int; reg_int_unmasked = rkcanfd_read(priv, RKCANFD_REG_INT); reg_int = reg_int_unmasked & ~priv->reg_int_mask_default; if (!reg_int) return IRQ_NONE; /* First ACK then handle, to avoid lost-IRQ race condition on * fast re-occurring interrupts. */ rkcanfd_write(priv, RKCANFD_REG_INT, reg_int); if (reg_int & RKCANFD_REG_INT_RX_FINISH_INT) rkcanfd_handle(priv, rx_int); if (reg_int & RKCANFD_REG_INT_ERROR_INT) rkcanfd_handle(priv, error_int); if (reg_int & (RKCANFD_REG_INT_BUS_OFF_INT | RKCANFD_REG_INT_PASSIVE_ERROR_INT | RKCANFD_REG_INT_ERROR_WARNING_INT) || priv->can.state > CAN_STATE_ERROR_ACTIVE) rkcanfd_handle(priv, state_error_int); if (reg_int & RKCANFD_REG_INT_RX_FIFO_OVERFLOW_INT) rkcanfd_handle(priv, rx_fifo_overflow_int); if (reg_int & ~(RKCANFD_REG_INT_ALL_ERROR | RKCANFD_REG_INT_RX_FIFO_OVERFLOW_INT | RKCANFD_REG_INT_RX_FINISH_INT)) netdev_err(priv->ndev, "%s: int=0x%08x\n", __func__, reg_int); if (reg_int & RKCANFD_REG_INT_WAKEUP_INT) netdev_info(priv->ndev, "%s: WAKEUP_INT\n", __func__); if (reg_int & RKCANFD_REG_INT_TXE_FIFO_FULL_INT) netdev_info(priv->ndev, "%s: TXE_FIFO_FULL_INT\n", __func__); if (reg_int & RKCANFD_REG_INT_TXE_FIFO_OV_INT) netdev_info(priv->ndev, "%s: TXE_FIFO_OV_INT\n", __func__); if (reg_int & RKCANFD_REG_INT_BUS_OFF_RECOVERY_INT) netdev_info(priv->ndev, "%s: BUS_OFF_RECOVERY_INT\n", __func__); if (reg_int & RKCANFD_REG_INT_RX_FIFO_FULL_INT) netdev_info(priv->ndev, "%s: RX_FIFO_FULL_INT\n", __func__); if (reg_int & RKCANFD_REG_INT_OVERLOAD_INT) netdev_info(priv->ndev, "%s: OVERLOAD_INT\n", __func__); can_rx_offload_irq_finish(&priv->offload); return IRQ_HANDLED; } static int rkcanfd_open(struct net_device *ndev) { struct rkcanfd_priv *priv = netdev_priv(ndev); int err; err = open_candev(ndev); if (err) return err; err = pm_runtime_resume_and_get(ndev->dev.parent); if (err) goto out_close_candev; rkcanfd_chip_start(priv); can_rx_offload_enable(&priv->offload); err = request_irq(ndev->irq, rkcanfd_irq, IRQF_SHARED, ndev->name, priv); if (err) goto out_rkcanfd_chip_stop; rkcanfd_chip_interrupts_enable(priv); netif_start_queue(ndev); return 0; out_rkcanfd_chip_stop: rkcanfd_chip_stop_sync(priv, CAN_STATE_STOPPED); pm_runtime_put(ndev->dev.parent); out_close_candev: close_candev(ndev); return err; } static int rkcanfd_stop(struct net_device *ndev) { struct rkcanfd_priv *priv = netdev_priv(ndev); netif_stop_queue(ndev); rkcanfd_chip_interrupts_disable(priv); free_irq(ndev->irq, priv); can_rx_offload_disable(&priv->offload); rkcanfd_chip_stop_sync(priv, CAN_STATE_STOPPED); close_candev(ndev); pm_runtime_put(ndev->dev.parent); return 0; } static const struct net_device_ops rkcanfd_netdev_ops = { .ndo_open = rkcanfd_open, .ndo_stop = rkcanfd_stop, .ndo_start_xmit = rkcanfd_start_xmit, .ndo_change_mtu = can_change_mtu, }; static int __maybe_unused rkcanfd_runtime_suspend(struct device *dev) { struct rkcanfd_priv *priv = dev_get_drvdata(dev); clk_bulk_disable_unprepare(priv->clks_num, priv->clks); return 0; } static int __maybe_unused rkcanfd_runtime_resume(struct device *dev) { struct rkcanfd_priv *priv = dev_get_drvdata(dev); return clk_bulk_prepare_enable(priv->clks_num, priv->clks); } static void rkcanfd_register_done(const struct rkcanfd_priv *priv) { u32 dev_id; 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); if (priv->devtype_data.quirks & RKCANFD_QUIRK_RK3568_ERRATUM_5 && priv->can.clock.freq < RKCANFD_ERRATUM_5_SYSCLOCK_HZ_MIN) netdev_info(priv->ndev, "Erratum 5: CAN clock frequency (%luMHz) lower than known good (%luMHz), expect degraded performance\n", priv->can.clock.freq / MEGA, RKCANFD_ERRATUM_5_SYSCLOCK_HZ_MIN / MEGA); } static int rkcanfd_register(struct rkcanfd_priv *priv) { struct net_device *ndev = priv->ndev; int err; pm_runtime_enable(ndev->dev.parent); err = pm_runtime_resume_and_get(ndev->dev.parent); if (err) goto out_pm_runtime_disable; rkcanfd_ethtool_init(priv); err = register_candev(ndev); if (err) goto out_pm_runtime_put_sync; rkcanfd_register_done(priv); pm_runtime_put(ndev->dev.parent); return 0; out_pm_runtime_put_sync: pm_runtime_put_sync(ndev->dev.parent); out_pm_runtime_disable: pm_runtime_disable(ndev->dev.parent); return err; } static inline void rkcanfd_unregister(struct rkcanfd_priv *priv) { struct net_device *ndev = priv->ndev; unregister_candev(ndev); pm_runtime_disable(ndev->dev.parent); } static const struct of_device_id rkcanfd_of_match[] = { { .compatible = "rockchip,rk3568v2-canfd", .data = &rkcanfd_devtype_data_rk3568v2, }, { .compatible = "rockchip,rk3568v3-canfd", .data = &rkcanfd_devtype_data_rk3568v3, }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, rkcanfd_of_match); static int rkcanfd_probe(struct platform_device *pdev) { struct rkcanfd_priv *priv; struct net_device *ndev; const void *match; int err; ndev = alloc_candev(sizeof(struct rkcanfd_priv), RKCANFD_TXFIFO_DEPTH); if (!ndev) return -ENOMEM; priv = netdev_priv(ndev); ndev->irq = platform_get_irq(pdev, 0); if (ndev->irq < 0) { err = ndev->irq; goto out_free_candev; } priv->clks_num = devm_clk_bulk_get_all(&pdev->dev, &priv->clks); if (priv->clks_num < 0) { err = priv->clks_num; goto out_free_candev; } priv->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->regs)) { err = PTR_ERR(priv->regs); goto out_free_candev; } priv->reset = devm_reset_control_array_get_exclusive(&pdev->dev); if (IS_ERR(priv->reset)) { err = dev_err_probe(&pdev->dev, PTR_ERR(priv->reset), "Failed to get reset line\n"); goto out_free_candev; } SET_NETDEV_DEV(ndev, &pdev->dev); ndev->netdev_ops = &rkcanfd_netdev_ops; ndev->flags |= IFF_ECHO; platform_set_drvdata(pdev, priv); priv->can.clock.freq = clk_get_rate(priv->clks[0].clk); priv->can.bittiming_const = &rkcanfd_bittiming_const; priv->can.data_bittiming_const = &rkcanfd_data_bittiming_const; priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_BERR_REPORTING; if (!(priv->devtype_data.quirks & RKCANFD_QUIRK_CANFD_BROKEN)) priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD; priv->can.do_set_mode = rkcanfd_set_mode; priv->can.do_get_berr_counter = rkcanfd_get_berr_counter; priv->ndev = ndev; match = device_get_match_data(&pdev->dev); if (match) priv->devtype_data = *(struct rkcanfd_devtype_data *)match; err = can_rx_offload_add_manual(ndev, &priv->offload, RKCANFD_NAPI_WEIGHT); if (err) goto out_free_candev; err = rkcanfd_register(priv); if (err) goto out_can_rx_offload_del; return 0; out_can_rx_offload_del: can_rx_offload_del(&priv->offload); out_free_candev: free_candev(ndev); return err; } static void rkcanfd_remove(struct platform_device *pdev) { struct rkcanfd_priv *priv = platform_get_drvdata(pdev); struct net_device *ndev = priv->ndev; can_rx_offload_del(&priv->offload); rkcanfd_unregister(priv); free_candev(ndev); } static const struct dev_pm_ops rkcanfd_pm_ops = { SET_RUNTIME_PM_OPS(rkcanfd_runtime_suspend, rkcanfd_runtime_resume, NULL) }; static struct platform_driver rkcanfd_driver = { .driver = { .name = DEVICE_NAME, .pm = &rkcanfd_pm_ops, .of_match_table = rkcanfd_of_match, }, .probe = rkcanfd_probe, .remove = rkcanfd_remove, }; module_platform_driver(rkcanfd_driver); MODULE_AUTHOR("Marc Kleine-Budde "); MODULE_DESCRIPTION("Rockchip CAN-FD Driver"); MODULE_LICENSE("GPL");