[PATCH v5 2/4] net: can: rockchip: Refactor the rkcanfd_devtype_data structure

Elaine Zhang
2025-05-23T10:08:27Z

Add new function pointer:
Encapsulate some hardware operation functions into
rkcanfd_devtype_data to provide differentiated implementations for
different models (such as RK3568v2/v3).

Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
.../net/can/rockchip/rockchip_canfd-core.c | 104 ++++++++++--------
drivers/net/can/rockchip/rockchip_canfd.h | 11 ++
2 files changed, 72 insertions(+), 43 deletions(-)

diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/can/rockchip/rockchip_canfd-core.c
index c3fb3176ce42..c21ca4c1fb9a 100644
--- a/drivers/net/can/rockchip/rockchip_canfd-core.c
+++ b/drivers/net/can/rockchip/rockchip_canfd-core.c
@@ -24,32 +24,6 @@

#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) {
@@ -212,7 +186,7 @@ static int rkcanfd_get_berr_counter(const struct net_device *ndev,
if (err)
return err;

- rkcanfd_get_berr_counter_corrected(priv, bec);
+ priv->devtype_data.get_berr_counter(priv, bec);

pm_runtime_put(ndev->dev.parent);

@@ -296,13 +270,13 @@ static void rkcanfd_chip_start(struct rkcanfd_priv *priv)

memset(&priv->bec, 0x0, sizeof(priv->bec));

- rkcanfd_chip_fifo_setup(priv);
+ priv->devtype_data.fifo_setup(priv);
rkcanfd_timestamp_init(priv);
rkcanfd_timestamp_start(priv);

rkcanfd_set_bittiming(priv);

- rkcanfd_chip_interrupts_disable(priv);
+ priv->devtype_data.interrupts_disable(priv);
rkcanfd_chip_set_work_mode(priv);

priv->can.state = CAN_STATE_ERROR_ACTIVE;
@@ -316,7 +290,7 @@ static void __rkcanfd_chip_stop(struct rkcanfd_priv *priv, const enum can_state
priv->can.state = state;

rkcanfd_chip_set_reset_mode(priv);
- rkcanfd_chip_interrupts_disable(priv);
+ priv->devtype_data.interrupts_disable(priv);
}

static void rkcanfd_chip_stop(struct rkcanfd_priv *priv, const enum can_state state)
@@ -342,8 +316,8 @@ static int rkcanfd_set_mode(struct net_device *ndev,

switch (mode) {
case CAN_MODE_START:
- rkcanfd_chip_start(priv);
- rkcanfd_chip_interrupts_enable(priv);
+ priv->devtype_data.chip_start(priv);
+ priv->devtype_data.interrupts_enable(priv);
netif_wake_queue(ndev);
break;

@@ -537,7 +511,7 @@ static int rkcanfd_handle_error_int(struct rkcanfd_priv *priv)
if (cf) {
struct can_berr_counter bec;

- rkcanfd_get_berr_counter_corrected(priv, &bec);
+ priv->devtype_data.get_berr_counter(priv, &bec);
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR | CAN_ERR_CNT;
cf->data[6] = bec.txerr;
cf->data[7] = bec.rxerr;
@@ -567,7 +541,7 @@ static int rkcanfd_handle_state_error_int(struct rkcanfd_priv *priv)
u32 timestamp;
int err;

- rkcanfd_get_berr_counter_corrected(priv, &bec);
+ priv->devtype_data.get_berr_counter(priv, &bec);
can_state_get_by_berr_counter(ndev, &bec, &tx_state, &rx_state);

new_state = max(tx_state, rx_state);
@@ -581,7 +555,7 @@ static int rkcanfd_handle_state_error_int(struct rkcanfd_priv *priv)
can_change_state(ndev, cf, tx_state, rx_state);

if (new_state == CAN_STATE_BUS_OFF) {
- rkcanfd_chip_stop(priv, CAN_STATE_BUS_OFF);
+ priv->devtype_data.chip_stop(priv, CAN_STATE_BUS_OFF);
can_bus_off(ndev);
}

@@ -620,7 +594,7 @@ rkcanfd_handle_rx_fifo_overflow_int(struct rkcanfd_priv *priv)
if (!skb)
return 0;

- rkcanfd_get_berr_counter_corrected(priv, &bec);
+ priv->devtype_data.get_berr_counter(priv, &bec);

cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
@@ -719,21 +693,21 @@ static int rkcanfd_open(struct net_device *ndev)
if (err)
goto out_close_candev;

- rkcanfd_chip_start(priv);
+ priv->devtype_data.chip_start(priv);
can_rx_offload_enable(&priv->offload);

- err = request_irq(ndev->irq, rkcanfd_irq, IRQF_SHARED, ndev->name, priv);
+ err = request_irq(ndev->irq, priv->devtype_data.irq, IRQF_SHARED, ndev->name, priv);
if (err)
goto out_rkcanfd_chip_stop;

- rkcanfd_chip_interrupts_enable(priv);
+ priv->devtype_data.interrupts_enable(priv);

netif_start_queue(ndev);

return 0;

out_rkcanfd_chip_stop:
- rkcanfd_chip_stop_sync(priv, CAN_STATE_STOPPED);
+ priv->devtype_data.chip_stop_sync(priv, CAN_STATE_STOPPED);
pm_runtime_put(ndev->dev.parent);
out_close_candev:
close_candev(ndev);
@@ -746,10 +720,10 @@ static int rkcanfd_stop(struct net_device *ndev)

netif_stop_queue(ndev);

- rkcanfd_chip_interrupts_disable(priv);
+ priv->devtype_data.interrupts_disable(priv);
free_irq(ndev->irq, priv);
can_rx_offload_disable(&priv->offload);
- rkcanfd_chip_stop_sync(priv, CAN_STATE_STOPPED);
+ priv->devtype_data.chip_stop_sync(priv, CAN_STATE_STOPPED);
close_candev(ndev);

pm_runtime_put(ndev->dev.parent);
@@ -818,7 +792,7 @@ static int rkcanfd_register(struct rkcanfd_priv *priv)
if (err)
goto out_pm_runtime_put_sync;

- rkcanfd_register_done(priv);
+ priv->devtype_data.register_done(priv);

pm_runtime_put(ndev->dev.parent);

@@ -840,6 +814,50 @@ static inline void rkcanfd_unregister(struct rkcanfd_priv *priv)
pm_runtime_disable(ndev->dev.parent);
}

+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,
+ .get_berr_counter = rkcanfd_get_berr_counter_corrected,
+ .interrupts_enable = rkcanfd_chip_interrupts_enable,
+ .interrupts_disable = rkcanfd_chip_interrupts_disable,
+ .fifo_setup = rkcanfd_chip_fifo_setup,
+ .chip_start = rkcanfd_chip_start,
+ .chip_stop = rkcanfd_chip_stop,
+ .chip_stop_sync = rkcanfd_chip_stop_sync,
+ .irq = rkcanfd_irq,
+ .register_done = rkcanfd_register_done,
+};
+
+/* 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,
+ .get_berr_counter = rkcanfd_get_berr_counter_corrected,
+ .interrupts_enable = rkcanfd_chip_interrupts_enable,
+ .interrupts_disable = rkcanfd_chip_interrupts_disable,
+ .fifo_setup = rkcanfd_chip_fifo_setup,
+ .chip_start = rkcanfd_chip_start,
+ .chip_stop = rkcanfd_chip_stop,
+ .chip_stop_sync = rkcanfd_chip_stop_sync,
+ .irq = rkcanfd_irq,
+ .register_done = rkcanfd_register_done,
+};
+
static const struct of_device_id rkcanfd_of_match[] = {
{
.compatible = "rockchip,rk3568v2-canfd",
diff --git a/drivers/net/can/rockchip/rockchip_canfd.h b/drivers/net/can/rockchip/rockchip_canfd.h
index 93131c7d7f54..d898260794aa 100644
--- a/drivers/net/can/rockchip/rockchip_canfd.h
+++ b/drivers/net/can/rockchip/rockchip_canfd.h
@@ -436,9 +436,20 @@ enum rkcanfd_model {
RKCANFD_MODEL_RK3568V3 = 0x35683,
};

+static struct rkcanfd_priv *priv;
+
struct rkcanfd_devtype_data {
enum rkcanfd_model model;
u32 quirks;
+ void (*get_berr_counter)(struct rkcanfd_priv *priv, struct can_berr_counter *bec);
+ void (*interrupts_enable)(const struct rkcanfd_priv *priv);
+ void (*interrupts_disable)(const struct rkcanfd_priv *priv);
+ void (*fifo_setup)(struct rkcanfd_priv *priv);
+ void (*chip_start)(struct rkcanfd_priv *priv);
+ void (*chip_stop)(struct rkcanfd_priv *priv, const enum can_state state);
+ void (*chip_stop_sync)(struct rkcanfd_priv *priv, const enum can_state state);
+ irqreturn_t (*irq)(int irq, void *dev_id);
+ void (*register_done)(const struct rkcanfd_priv *priv);
};

struct rkcanfd_fifo_header {
--
2.34.1