linux/drivers/net/can/rockchip/rockchip_canfd.h

/* SPDX-License-Identifier: GPL-2.0
 *
 * Copyright (c) 2023, 2024 Pengutronix,
 *               Marc Kleine-Budde <[email protected]>
 */

#ifndef _ROCKCHIP_CANFD_H
#define _ROCKCHIP_CANFD_H

#include <linux/bitfield.h>
#include <linux/can/dev.h>
#include <linux/can/rx-offload.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/netdevice.h>
#include <linux/reset.h>
#include <linux/skbuff.h>
#include <linux/timecounter.h>
#include <linux/types.h>
#include <linux/u64_stats_sync.h>
#include <linux/units.h>

#define RKCANFD_REG_MODE
#define RKCANFD_REG_MODE_CAN_FD_MODE_ENABLE
#define RKCANFD_REG_MODE_DPEE
#define RKCANFD_REG_MODE_BRSD
#define RKCANFD_REG_MODE_SPACE_RX_MODE
#define RKCANFD_REG_MODE_AUTO_BUS_ON
#define RKCANFD_REG_MODE_AUTO_RETX_MODE
#define RKCANFD_REG_MODE_OVLD_MODE
#define RKCANFD_REG_MODE_COVER_MODE
#define RKCANFD_REG_MODE_RXSORT_MODE
#define RKCANFD_REG_MODE_TXORDER_MODE
#define RKCANFD_REG_MODE_RXSTX_MODE
#define RKCANFD_REG_MODE_LBACK_MODE
#define RKCANFD_REG_MODE_SILENT_MODE
#define RKCANFD_REG_MODE_SELF_TEST
#define RKCANFD_REG_MODE_SLEEP_MODE
#define RKCANFD_REG_MODE_WORK_MODE

#define RKCANFD_REG_CMD
#define RKCANFD_REG_CMD_TX1_REQ
#define RKCANFD_REG_CMD_TX0_REQ
#define RKCANFD_REG_CMD_TX_REQ(i)

#define RKCANFD_REG_STATE
#define RKCANFD_REG_STATE_SLEEP_STATE
#define RKCANFD_REG_STATE_BUS_OFF_STATE
#define RKCANFD_REG_STATE_ERROR_WARNING_STATE
#define RKCANFD_REG_STATE_TX_PERIOD
#define RKCANFD_REG_STATE_RX_PERIOD
#define RKCANFD_REG_STATE_TX_BUFFER_FULL
#define RKCANFD_REG_STATE_RX_BUFFER_FULL

#define RKCANFD_REG_INT
#define RKCANFD_REG_INT_WAKEUP_INT
#define RKCANFD_REG_INT_TXE_FIFO_FULL_INT
#define RKCANFD_REG_INT_TXE_FIFO_OV_INT
#define RKCANFD_REG_INT_TIMESTAMP_COUNTER_OVERFLOW_INT
#define RKCANFD_REG_INT_BUS_OFF_RECOVERY_INT
#define RKCANFD_REG_INT_BUS_OFF_INT
#define RKCANFD_REG_INT_RX_FIFO_OVERFLOW_INT
#define RKCANFD_REG_INT_RX_FIFO_FULL_INT
#define RKCANFD_REG_INT_ERROR_INT
#define RKCANFD_REG_INT_TX_ARBIT_FAIL_INT
#define RKCANFD_REG_INT_PASSIVE_ERROR_INT
#define RKCANFD_REG_INT_OVERLOAD_INT
#define RKCANFD_REG_INT_ERROR_WARNING_INT
#define RKCANFD_REG_INT_TX_FINISH_INT
#define RKCANFD_REG_INT_RX_FINISH_INT

#define RKCANFD_REG_INT_ALL

#define RKCANFD_REG_INT_ALL_ERROR

#define RKCANFD_REG_INT_MASK

#define RKCANFD_REG_DMA_CTL
#define RKCANFD_REG_DMA_CTL_DMA_RX_MODE
#define RKCANFD_REG_DMA_CTL_DMA_TX_MODE

#define RKCANFD_REG_BITTIMING
#define RKCANFD_REG_BITTIMING_SAMPLE_MODE
#define RKCANFD_REG_BITTIMING_SJW
#define RKCANFD_REG_BITTIMING_BRP
#define RKCANFD_REG_BITTIMING_TSEG2
#define RKCANFD_REG_BITTIMING_TSEG1

#define RKCANFD_REG_ARBITFAIL
#define RKCANFD_REG_ARBITFAIL_ARBIT_FAIL_CODE

/* Register seems to be clear or read */
#define RKCANFD_REG_ERROR_CODE
#define RKCANFD_REG_ERROR_CODE_PHASE
#define RKCANFD_REG_ERROR_CODE_TYPE
#define RKCANFD_REG_ERROR_CODE_TYPE_BIT
#define RKCANFD_REG_ERROR_CODE_TYPE_STUFF
#define RKCANFD_REG_ERROR_CODE_TYPE_FORM
#define RKCANFD_REG_ERROR_CODE_TYPE_ACK
#define RKCANFD_REG_ERROR_CODE_TYPE_CRC
#define RKCANFD_REG_ERROR_CODE_DIRECTION_RX
#define RKCANFD_REG_ERROR_CODE_TX
#define RKCANFD_REG_ERROR_CODE_TX_OVERLOAD
#define RKCANFD_REG_ERROR_CODE_TX_ERROR
#define RKCANFD_REG_ERROR_CODE_TX_ACK
#define RKCANFD_REG_ERROR_CODE_TX_ACK_EOF
#define RKCANFD_REG_ERROR_CODE_TX_CRC
#define RKCANFD_REG_ERROR_CODE_TX_STUFF_COUNT
#define RKCANFD_REG_ERROR_CODE_TX_DATA
#define RKCANFD_REG_ERROR_CODE_TX_SOF_DLC
#define RKCANFD_REG_ERROR_CODE_TX_IDLE
#define RKCANFD_REG_ERROR_CODE_RX
#define RKCANFD_REG_ERROR_CODE_RX_BUF_INT
#define RKCANFD_REG_ERROR_CODE_RX_SPACE
#define RKCANFD_REG_ERROR_CODE_RX_EOF
#define RKCANFD_REG_ERROR_CODE_RX_ACK_LIM
#define RKCANFD_REG_ERROR_CODE_RX_ACK
#define RKCANFD_REG_ERROR_CODE_RX_CRC_LIM
#define RKCANFD_REG_ERROR_CODE_RX_CRC
#define RKCANFD_REG_ERROR_CODE_RX_STUFF_COUNT
#define RKCANFD_REG_ERROR_CODE_RX_DATA
#define RKCANFD_REG_ERROR_CODE_RX_DLC
#define RKCANFD_REG_ERROR_CODE_RX_BRS_ESI
#define RKCANFD_REG_ERROR_CODE_RX_RES
#define RKCANFD_REG_ERROR_CODE_RX_FDF
#define RKCANFD_REG_ERROR_CODE_RX_ID2_RTR
#define RKCANFD_REG_ERROR_CODE_RX_SOF_IDE
#define RKCANFD_REG_ERROR_CODE_RX_IDLE

#define RKCANFD_REG_ERROR_CODE_NOACK

#define RKCANFD_REG_RXERRORCNT
#define RKCANFD_REG_RXERRORCNT_RX_ERR_CNT

#define RKCANFD_REG_TXERRORCNT
#define RKCANFD_REG_TXERRORCNT_TX_ERR_CNT

#define RKCANFD_REG_IDCODE
#define RKCANFD_REG_IDCODE_STANDARD_FRAME_ID
#define RKCANFD_REG_IDCODE_EXTENDED_FRAME_ID

#define RKCANFD_REG_IDMASK

#define RKCANFD_REG_TXFRAMEINFO
#define RKCANFD_REG_FRAMEINFO_FRAME_FORMAT
#define RKCANFD_REG_FRAMEINFO_RTR
#define RKCANFD_REG_FRAMEINFO_DATA_LENGTH

#define RKCANFD_REG_TXID
#define RKCANFD_REG_TXID_TX_ID

#define RKCANFD_REG_TXDATA0
#define RKCANFD_REG_TXDATA1
#define RKCANFD_REG_RXFRAMEINFO
#define RKCANFD_REG_RXID
#define RKCANFD_REG_RXDATA0
#define RKCANFD_REG_RXDATA1

#define RKCANFD_REG_RTL_VERSION
#define RKCANFD_REG_RTL_VERSION_MAJOR
#define RKCANFD_REG_RTL_VERSION_MINOR

#define RKCANFD_REG_FD_NOMINAL_BITTIMING
#define RKCANFD_REG_FD_NOMINAL_BITTIMING_SAMPLE_MODE
#define RKCANFD_REG_FD_NOMINAL_BITTIMING_SJW
#define RKCANFD_REG_FD_NOMINAL_BITTIMING_BRP
#define RKCANFD_REG_FD_NOMINAL_BITTIMING_TSEG2
#define RKCANFD_REG_FD_NOMINAL_BITTIMING_TSEG1

#define RKCANFD_REG_FD_DATA_BITTIMING
#define RKCANFD_REG_FD_DATA_BITTIMING_SAMPLE_MODE
#define RKCANFD_REG_FD_DATA_BITTIMING_SJW
#define RKCANFD_REG_FD_DATA_BITTIMING_BRP
#define RKCANFD_REG_FD_DATA_BITTIMING_TSEG2
#define RKCANFD_REG_FD_DATA_BITTIMING_TSEG1

#define RKCANFD_REG_TRANSMIT_DELAY_COMPENSATION
#define RKCANFD_REG_TRANSMIT_DELAY_COMPENSATION_TDC_OFFSET
#define RKCANFD_REG_TRANSMIT_DELAY_COMPENSATION_TDC_ENABLE

#define RKCANFD_REG_TIMESTAMP_CTRL
/* datasheet says 6:1, which is wrong */
#define RKCANFD_REG_TIMESTAMP_CTRL_TIME_BASE_COUNTER_PRESCALE
#define RKCANFD_REG_TIMESTAMP_CTRL_TIME_BASE_COUNTER_ENABLE

#define RKCANFD_REG_TIMESTAMP

#define RKCANFD_REG_TXEVENT_FIFO_CTRL
#define RKCANFD_REG_TXEVENT_FIFO_CTRL_TXE_FIFO_CNT
#define RKCANFD_REG_TXEVENT_FIFO_CTRL_TXE_FIFO_WATERMARK
#define RKCANFD_REG_TXEVENT_FIFO_CTRL_TXE_FIFO_ENABLE

#define RKCANFD_REG_RX_FIFO_CTRL
#define RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT
#define RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_FULL_WATERMARK
#define RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_ENABLE

#define RKCANFD_REG_AFC_CTRL
#define RKCANFD_REG_AFC_CTRL_UAF5
#define RKCANFD_REG_AFC_CTRL_UAF4
#define RKCANFD_REG_AFC_CTRL_UAF3
#define RKCANFD_REG_AFC_CTRL_UAF2
#define RKCANFD_REG_AFC_CTRL_UAF1

#define RKCANFD_REG_IDCODE0
#define RKCANFD_REG_IDMASK0
#define RKCANFD_REG_IDCODE1
#define RKCANFD_REG_IDMASK1
#define RKCANFD_REG_IDCODE2
#define RKCANFD_REG_IDMASK2
#define RKCANFD_REG_IDCODE3
#define RKCANFD_REG_IDMASK3
#define RKCANFD_REG_IDCODE4
#define RKCANFD_REG_IDMASK4

#define RKCANFD_REG_FD_TXFRAMEINFO
#define RKCANFD_REG_FD_FRAMEINFO_FRAME_FORMAT
#define RKCANFD_REG_FD_FRAMEINFO_RTR
#define RKCANFD_REG_FD_FRAMEINFO_FDF
#define RKCANFD_REG_FD_FRAMEINFO_BRS
#define RKCANFD_REG_FD_FRAMEINFO_DATA_LENGTH

#define RKCANFD_REG_FD_TXID
#define RKCANFD_REG_FD_ID_EFF
#define RKCANFD_REG_FD_ID_SFF

#define RKCANFD_REG_FD_TXDATA0
#define RKCANFD_REG_FD_TXDATA1
#define RKCANFD_REG_FD_TXDATA2
#define RKCANFD_REG_FD_TXDATA3
#define RKCANFD_REG_FD_TXDATA4
#define RKCANFD_REG_FD_TXDATA5
#define RKCANFD_REG_FD_TXDATA6
#define RKCANFD_REG_FD_TXDATA7
#define RKCANFD_REG_FD_TXDATA8
#define RKCANFD_REG_FD_TXDATA9
#define RKCANFD_REG_FD_TXDATA10
#define RKCANFD_REG_FD_TXDATA11
#define RKCANFD_REG_FD_TXDATA12
#define RKCANFD_REG_FD_TXDATA13
#define RKCANFD_REG_FD_TXDATA14
#define RKCANFD_REG_FD_TXDATA15

#define RKCANFD_REG_FD_RXFRAMEINFO
#define RKCANFD_REG_FD_RXID
#define RKCANFD_REG_FD_RXTIMESTAMP
#define RKCANFD_REG_FD_RXDATA0
#define RKCANFD_REG_FD_RXDATA1
#define RKCANFD_REG_FD_RXDATA2
#define RKCANFD_REG_FD_RXDATA3
#define RKCANFD_REG_FD_RXDATA4
#define RKCANFD_REG_FD_RXDATA5
#define RKCANFD_REG_FD_RXDATA6
#define RKCANFD_REG_FD_RXDATA7
#define RKCANFD_REG_FD_RXDATA8
#define RKCANFD_REG_FD_RXDATA9
#define RKCANFD_REG_FD_RXDATA10
#define RKCANFD_REG_FD_RXDATA11
#define RKCANFD_REG_FD_RXDATA12
#define RKCANFD_REG_FD_RXDATA13
#define RKCANFD_REG_FD_RXDATA14
#define RKCANFD_REG_FD_RXDATA15

#define RKCANFD_REG_RX_FIFO_RDATA
#define RKCANFD_REG_TXE_FIFO_RDATA

#define DEVICE_NAME
#define RKCANFD_NAPI_WEIGHT
#define RKCANFD_TXFIFO_DEPTH
#define RKCANFD_TX_STOP_THRESHOLD
#define RKCANFD_TX_START_THRESHOLD

#define RKCANFD_TIMESTAMP_WORK_MAX_DELAY_SEC
#define RKCANFD_ERRATUM_5_SYSCLOCK_HZ_MIN

/* rk3568 CAN-FD Errata, as of Tue 07 Nov 2023 11:25:31 +08:00 */

/* Erratum 1: The error frame sent by the CAN controller has an
 * abnormal format.
 */
#define RKCANFD_QUIRK_RK3568_ERRATUM_1

/* Erratum 2: The error frame sent after detecting a CRC error has an
 * abnormal position.
 */
#define RKCANFD_QUIRK_RK3568_ERRATUM_2

/* Erratum 3: Intermittent CRC calculation errors. */
#define RKCANFD_QUIRK_RK3568_ERRATUM_3

/* Erratum 4: Intermittent occurrence of stuffing errors. */
#define RKCANFD_QUIRK_RK3568_ERRATUM_4

/* Erratum 5: Counters related to the TXFIFO and RXFIFO exhibit
 * abnormal counting behavior.
 *
 * 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 this erratum, but
 * tests with the rk3568v2 and rk3568v3 show that the RX_FIFO_CNT is
 * sometimes too high. This leads to CAN frames being read from the
 * FIFO, which is then already empty.
 *
 * Further tests on the rk3568v2 and rk3568v3 show that in this
 * situation (i.e. empty FIFO) all elements of the FIFO header
 * (frameinfo, id, ts) contain the same data.
 *
 * On the rk3568v2 and rk3568v3, this problem only occurs extremely
 * rarely with the standard clock of 300 MHz, but almost immediately
 * at 80 MHz.
 *
 * To workaround this problem, check for empty FIFO with
 * rkcanfd_fifo_header_empty() in rkcanfd_handle_rx_int_one() and exit
 * early.
 *
 * To reproduce:
 * assigned-clocks = <&cru CLK_CANx>;
 * assigned-clock-rates = <80000000>;
 */
#define RKCANFD_QUIRK_RK3568_ERRATUM_5

/* Erratum 6: The CAN controller's transmission of extended frames may
 * intermittently change into standard frames
 *
 * Work around this issue by activating self reception (RXSTX). If we
 * have pending TX CAN frames, check all RX'ed CAN frames in
 * rkcanfd_rxstx_filter().
 *
 * If it's a frame we've send and it's OK, call the TX complete
 * handler: rkcanfd_handle_tx_done_one(). Mask the TX complete IRQ.
 *
 * If it's a frame we've send, but the CAN-ID is mangled, resend the
 * original extended frame.
 *
 * To reproduce:
 * host:
 *   canfdtest -evx -g can0
 *   candump any,0:80000000 -cexdtA
 * dut:
 *   canfdtest -evx can0
 *   ethtool -S can0
 */
#define RKCANFD_QUIRK_RK3568_ERRATUM_6

/* Erratum 7: In the passive error state, the CAN controller's
 * interframe space segment counting is inaccurate.
 */
#define RKCANFD_QUIRK_RK3568_ERRATUM_7

/* Erratum 8: The Format-Error error flag is transmitted one bit
 * later.
 */
#define RKCANFD_QUIRK_RK3568_ERRATUM_8

/* Erratum 9: In the arbitration segment, the CAN controller will
 * identify stuffing errors as arbitration failures.
 */
#define RKCANFD_QUIRK_RK3568_ERRATUM_9

/* Erratum 10: Does not support the BUSOFF slow recovery mechanism. */
#define RKCANFD_QUIRK_RK3568_ERRATUM_10

/* Erratum 11: Arbitration error. */
#define RKCANFD_QUIRK_RK3568_ERRATUM_11

/* Erratum 12: A dominant bit at the third bit of the intermission may
 * cause a transmission error.
 */
#define RKCANFD_QUIRK_RK3568_ERRATUM_12

/* Tests on the rk3568v2 and rk3568v3 show that receiving certain
 * CAN-FD frames trigger an Error Interrupt.
 *
 * - Form Error in RX Arbitration Phase: TX_IDLE RX_STUFF_COUNT (0x0a010100) CMD=0 RX=0 TX=0
 *   Error-Warning=1 Bus-Off=0
 *   To reproduce:
 *   host:
 *     cansend can0 002##01f
 *   DUT:
 *     candump any,0:0,#FFFFFFFF -cexdHtA
 *
 * - Form Error in RX Arbitration Phase: TX_IDLE RX_CRC (0x0a010200) CMD=0 RX=0 TX=0
 *   Error-Warning=1 Bus-Off=0
 *   To reproduce:
 *   host:
 *     cansend can0 002##07217010000000000
 *   DUT:
 *     candump any,0:0,#FFFFFFFF -cexdHtA
 */
#define RKCANFD_QUIRK_CANFD_BROKEN

/* known issues with rk3568v3:
 *
 * - Overload situation during high bus load
 *   To reproduce:
 *   host:
 *     # add a 2nd CAN adapter to the CAN bus
 *     cangen can0 -I 1 -Li -Di -p10 -g 0.3
 *     cansequence -rve
 *   DUT:
 *     cangen can0 -I2 -L1 -Di -p10 -c10 -g 1 -e
 *     cansequence -rv -i 1
 *
 * - TX starvation after repeated Bus-Off
 *   To reproduce:
 *   host:
 *     sleep 3 && cangen can0 -I2 -Li -Di -p10 -g 0.0
 *   DUT:
 *     cangen can0 -I2 -Li -Di -p10 -g 0.05
 */

enum rkcanfd_model {};

struct rkcanfd_devtype_data {};

struct rkcanfd_fifo_header {};

struct rkcanfd_stats {};

struct rkcanfd_priv {};

static inline u32
rkcanfd_read(const struct rkcanfd_priv *priv, u32 reg)
{}

static inline void
rkcanfd_read_rep(const struct rkcanfd_priv *priv, u32 reg,
		 void *buf, unsigned int len)
{}

static inline void
rkcanfd_write(const struct rkcanfd_priv *priv, u32 reg, u32 val)
{}

static inline u32
rkcanfd_get_timestamp(const struct rkcanfd_priv *priv)
{}

static inline unsigned int
rkcanfd_get_tx_head(const struct rkcanfd_priv *priv)
{}

static inline unsigned int
rkcanfd_get_tx_tail(const struct rkcanfd_priv *priv)
{}

static inline unsigned int
rkcanfd_get_tx_pending(const struct rkcanfd_priv *priv)
{}

static inline unsigned int
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);

void rkcanfd_skb_set_timestamp(const struct rkcanfd_priv *priv,
			       struct sk_buff *skb, const u32 timestamp);
void rkcanfd_timestamp_init(struct rkcanfd_priv *priv);
void rkcanfd_timestamp_start(struct rkcanfd_priv *priv);
void rkcanfd_timestamp_stop(struct rkcanfd_priv *priv);
void rkcanfd_timestamp_stop_sync(struct rkcanfd_priv *priv);

unsigned int rkcanfd_get_effective_tx_free(const struct rkcanfd_priv *priv);
void rkcanfd_xmit_retry(struct rkcanfd_priv *priv);
netdev_tx_t rkcanfd_start_xmit(struct sk_buff *skb, struct net_device *ndev);
void rkcanfd_handle_tx_done_one(struct rkcanfd_priv *priv, const u32 ts,
				unsigned int *frame_len_p);

#endif