1352 lines
35 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
* Rk3576 CANFD driver
*/
#include <linux/delay.h>
#include <linux/iopoll.h>
#include <linux/pinctrl/consumer.h>
#include <linux/clk.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include <linux/reset.h>
#include <linux/pm_runtime.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
/* registers definition */
enum rk3576_canfd_reg {
CANFD_MODE = 0x00,
CANFD_CMD = 0x04,
CANFD_STATE = 0x08,
CANFD_INT = 0x0c,
CANFD_INT_MASK = 0x10,
CANFD_NBTP = 0x100,
CANFD_DBTP = 0x104,
CANFD_TDCR = 0x108,
CANFD_BRS_CFG = 0x10c,
CANFD_DMA_CTRL = 0x11c,
CANFD_TXFIC = 0x200,
CANFD_TXID = 0x204,
CANFD_TXDAT0 = 0x208,
CANFD_TXDAT1 = 0x20c,
CANFD_TXDAT2 = 0x210,
CANFD_TXDAT3 = 0x214,
CANFD_TXDAT4 = 0x218,
CANFD_TXDAT5 = 0x21c,
CANFD_TXDAT6 = 0x220,
CANFD_TXDAT7 = 0x224,
CANFD_TXDAT8 = 0x228,
CANFD_TXDAT9 = 0x22c,
CANFD_TXDAT10 = 0x230,
CANFD_TXDAT11 = 0x234,
CANFD_TXDAT12 = 0x238,
CANFD_TXDAT13 = 0x23c,
CANFD_TXDAT14 = 0x240,
CANFD_TXDAT15 = 0x244,
CANFD_RXFIC = 0x300,
CANFD_RXID = 0x304,
CANFD_RXTS = 0x308,
CANFD_RXDAT0 = 0x30c,
CANFD_RXDAT1 = 0x310,
CANFD_RXDAT2 = 0x314,
CANFD_RXDAT3 = 0x318,
CANFD_RXDAT4 = 0x31c,
CANFD_RXDAT5 = 0x320,
CANFD_RXDAT6 = 0x324,
CANFD_RXDAT7 = 0x328,
CANFD_RXDAT8 = 0x32c,
CANFD_RXDAT9 = 0x330,
CANFD_RXDAT10 = 0x334,
CANFD_RXDAT11 = 0x338,
CANFD_RXDAT12 = 0x33c,
CANFD_RXDAT13 = 0x340,
CANFD_RXDAT14 = 0x344,
CANFD_RXDAT15 = 0x348,
CANFD_RXFRD = 0x400,
CANFD_STR_CTL = 0x600,
CANFD_STR_STATE = 0x604,
CANFD_STR_TIMEOUT = 0x608,
CANFD_STR_WTM = 0x60c,
CANFD_EXTM_START_ADDR = 0x610,
CANFD_EXTM_SIZE = 0x614,
CANFD_EXTM_WADDR = 0x618,
CANFD_EXTM_RADDR = 0x61c,
CANFD_EXTM_AHB_TXTHR = 0x620,
CANFD_EXTM_LEFT_CNT = 0x624,
CANFD_ATF0 = 0x700,
CANFD_ATF1 = 0x704,
CANFD_ATF2 = 0x708,
CANFD_ATF3 = 0x70c,
CANFD_ATF4 = 0x710,
CANFD_ATFM0 = 0x714,
CANFD_ATFM1 = 0x718,
CANFD_ATFM2 = 0x71c,
CANFD_ATFM3 = 0x720,
CANFD_ATFM4 = 0x724,
CANFD_ATF_DLC = 0x728,
CANFD_ATF_CTL = 0x72c,
CANFD_SPACE_CTRL = 0x800,
CANFD_AUTO_RETX_CFG = 0x808,
CANFD_AUTO_RETX_STATE0 = 0x80c,
CANFD_AUTO_RETX_STATE1 = 0x810,
CANFD_OLF_CFG = 0x814,
CANFD_RXINT_CTRL = 0x818,
CANFD_RXINT_TIMEOUT = 0x81c,
CANFD_OTHER_CFG = 0x820,
CANFD_WAVE_FILTER_CFG = 0x824,
CANFD_RBC_CFG = 0x828,
CANFD_TXCRC_CFG = 0x82c,
CANFD_BUSOFFRCY_CFG = 0x830,
CANFD_BUSOFF_RCY_THR = 0x834,
CANFD_ERROR_CODE = 0x900,
CANFD_ERROR_MASK = 0x904,
CANFD_RXERRORCNT = 0x910,
CANFD_TXERRORCNT = 0x914,
CANFD_RX_RXSRAM_RDATA = 0xc00,
CANFD_RTL_VERSION = 0xf0c,
};
#define DATE_LENGTH_12_BYTE (0x9)
#define DATE_LENGTH_16_BYTE (0xa)
#define DATE_LENGTH_20_BYTE (0xb)
#define DATE_LENGTH_24_BYTE (0xc)
#define DATE_LENGTH_32_BYTE (0xd)
#define DATE_LENGTH_48_BYTE (0xe)
#define DATE_LENGTH_64_BYTE (0xf)
#define CANFD_TX0_REQ BIT(0)
#define CANFD_TX1_REQ BIT(1)
#define CANFD_TX_REQ_FULL ((CANFD_TX0_REQ) | (CANFD_TX1_REQ))
#define MODE_PASS_ERR BIT(10)
#define MODE_DIS_PEE BIT(9)
#define MODE_RETT BIT(8)
#define MODE_AUTO_BUS_ON BIT(7)
#define MODE_COVER BIT(6)
#define MODE_RXSTX BIT(5)
#define MODE_LBACK BIT(4)
#define MODE_SILENT BIT(3)
#define MODE_SELF_TEST BIT(2)
#define MODE_SLEEP BIT(1)
#define RESET_MODE 0
#define WORK_MODE BIT(0)
#define RETX_TIME_LIMIT_CNT 0x12c /* 300 */
#define RETX_TIME_LIMIT_SHIFT 3
#define RETX_LIMIT_EN BIT(1)
#define AUTO_RETX_EN BIT(0)
#define ERR_WARNING_STATE BIT(3)
#define BUS_OFF_STATE BIT(4)
#define RX_FINISH_INT BIT(0)
#define TX_FINISH_INT BIT(1)
#define ERR_WARN_INT BIT(2)
#define RX_BUF_OV_INT BIT(3)
#define PASSIVE_ERR_INT BIT(4)
#define TX_LOSTARB_INT BIT(5)
#define BUS_ERR_INT BIT(6)
#define RX_STR_FULL_INT BIT(7)
#define RX_STR_OV_INT BIT(8)
#define BUS_OFF_INT BIT(9)
#define BUS_OFF_RECOVERY_INT BIT(10)
#define WAKEUP_INT BIT(11)
#define AUTO_RETX_FAIL_INT BIT(12)
#define MFI_INT BIT(13)
#define MFI_TIMEOUT BIT(14)
#define RX_STR_TIMEOUT_INT BIT(15)
#define BUSINT_INT BIT(16)
#define ISM_WTM_INT BIT(17)
#define ESM_WTM_INT BIT(18)
#define BUSOFF_RCY_INT BIT(19)
#define INT_ENABLE BIT(0)
#define ERR_PHASE BIT(28)
#define ARB_PHASE 0
#define DATA_PHASE 1
#define ERR_TYPE_MASK GENMASK(27, 25)
#define ERR_TYPE_SHIFT 25
#define BIT_ERROR 0
#define BIT_STUFF_ERROR 1
#define FORM_ERROR 2
#define ACK_ERROR 3
#define CRC_ERROR 4
#define TRANSMIT_ACK_EOF BIT(24)
#define TRANSMIT_CRC BIT(23)
#define TRANSMIT_STUFF_COUNT BIT(22)
#define TRANSMIT_DATA BIT(21)
#define TRANSMIT_SOF_DLC BIT(20)
#define TRANSMIT_IDLE BIT(19)
#define RECEIVE_ERROR BIT(18)
#define RECEIVE_OVERLOAD BIT(17)
#define RECEIVE_SPACE BIT(16)
#define RECEIVE_EOF BIT(15)
#define RECEIVE_ACK_LIM BIT(14)
#define RECEIVE_ACK_SLOT BIT(13)
#define RECEIVE_CRC_LIM BIT(12)
#define RECEIVE_CRC BIT(11)
#define RECEIVE_STUFF_COUNT BIT(10)
#define RECEIVE_DATA BIT(9)
#define RECEIVE_DLC BIT(8)
#define RECEIVE_BRS_ESI BIT(7)
#define RECEIVE_RES BIT(6)
#define RECEIVE_FDF BIT(5)
#define RECEIVE_ID2_RTR BIT(4)
#define RECEIVE_SOF_IDE BIT(3)
#define RECEIVE_BUS_IDLE BIT(2)
#define RECEIVE_BUS_INT BIT(1)
#define RECEIVE_STOP BIT(0)
/* Nominal Bit Timing & Prescaler Register (NBTP) */
#define NBTP_MODE_3_SAMPLES BIT(31)
#define NBTP_NSJW_SHIFT 24
#define NBTP_NSJW_MASK (0x7f << NBTP_NSJW_SHIFT)
#define NBTP_NBRP_SHIFT 16
#define NBTP_NBRP_MASK (0xff << NBTP_NBRP_SHIFT)
#define NBTP_NTSEG2_SHIFT 8
#define NBTP_NTSEG2_MASK (0x7f << NBTP_NTSEG2_SHIFT)
#define NBTP_NTSEG1_SHIFT 0
#define NBTP_NTSEG1_MASK (0xff << NBTP_NTSEG1_SHIFT)
/* Data Bit Timing & Prescaler Register (DBTP) */
#define DBTP_BRS_TSEG1_SHIFT 24
#define DBTP_BRS_TSEG1_MASK (0xff << DBTP_BRS_TSEG1_SHIFT)
#define DBTP_BRS_MODE BIT(23)
#define DBTP_MODE_3_SAMPLES BIT(21)
#define DBTP_DSJW_SHIFT 17
#define DBTP_DSJW_MASK (0xf << DBTP_DSJW_SHIFT)
#define DBTP_DBRP_SHIFT 9
#define DBTP_DBRP_MASK (0xff << DBTP_DBRP_SHIFT)
#define DBTP_DTSEG2_SHIFT 5
#define DBTP_DTSEG2_MASK (0xf << DBTP_DTSEG2_SHIFT)
#define DBTP_DTSEG1_SHIFT 0
#define DBTP_DTSEG1_MASK (0x1f << DBTP_DTSEG1_SHIFT)
/* Transmitter Delay Compensation Register (TDCR) */
#define TDCR_TDCO_SHIFT 1
#define TDCR_TDCO_MASK (0x3f << TDCR_TDCO_SHIFT)
#define TDCR_TDC_ENABLE BIT(0)
#define RX_DMA_ENABLE BIT(9)
#define TX_FD_ENABLE BIT(5)
#define TX_FD_BRS_ENABLE BIT(4)
#define TX_FORMAT_SHIFT 7
#define TX_FORMAT_MASK (0x1 << TX_FORMAT_SHIFT)
#define TX_RTR_SHIFT 6
#define TX_RTR_MASK (0x1 << TX_RTR_SHIFT)
#define TX_FDF_SHIFT 5
#define TX_FDF_MASK (0x1 << TX_FDF_SHIFT)
#define TX_BRS_SHIFT 4
#define TX_BRS_MASK (0x1 << TX_BRS_SHIFT)
#define TX_DLC_SHIFT 0
#define TX_DLC_MASK (0xF << TX_DLC_SHIFT)
#define RX_FORMAT_SHIFT 23
#define RX_FORMAT_MASK (0x1 << RX_FORMAT_SHIFT)
#define RX_RTR_SHIFT 22
#define RX_RTR_MASK (0x1 << RX_RTR_SHIFT)
#define RX_FDF_SHIFT 21
#define RX_FDF_MASK (0x1 << RX_FDF_SHIFT)
#define RX_BRS_SHIFT 20
#define RX_BRS_MASK (0x1 << RX_BRS_SHIFT)
#define RX_DLC_SHIFT 24
#define RX_DLC_MASK (0xF << RX_DLC_SHIFT)
#define RX_ISM_LEN_SHIFT 8
#define RX_ISM_LEN_MASK (0xF << RX_ISM_LEN_SHIFT)
#define BUFFER_MODE_ENABLE BIT(0)
#define EXT_STORAGE_MODE BIT(1)
#define ISM_SEL_SHIFT 2
#define ISM_SEL_MASK (0x3 << ISM_SEL_SHIFT)
#define RX_STORAGE_RESET BIT(4)
#define ESM_SEL_SHIFT 6
#define ESM_SEL_MASK (0x3 << ESM_SEL_SHIFT)
#define STORAGE_TIMEOUT_MODE BIT(8)
#define INTM_CNT_SHIFT 17
#define INTM_CNT_MASK (0x1ff << INTM_CNT_SHIFT)
#define INTM_LEFT_CNT_SHIFT 8
#define INTM_LEFT_CNT_MASK (0x1ff << INTM_LEFT_CNT_SHIFT)
#define EXTM_FULL BIT(3)
#define EXTM_EMPTY BIT(2)
#define INTM_FULL BIT(1)
#define INTM_EMPTY BIT(0)
#define EXTTM_LEFT_CNT_SHIFT 0
#define EXTTM_LEFT_CNT_MASK (0x3fffff << EXTTM_LEFT_CNT_SHIFT)
#define ISM_WATERMASK_CAN 0x6c /* word */
#define ISM_WATERMASK_CANFD 0x6c /* word */
#define ESM_WATERMASK (0x50 << 8) /* word */
#define BUSOFF_RCY_MODE_EN BIT(8)
#define BUSOFF_RCY_TIME_CLR BIT(9)
#define BUSOFF_RCY_CNT_FAST 4
#define BUSOFF_RCY_CNT_SLOW 5
#define BUSOFF_RCY_TIME_FAST 0x3d0900 /* 40ms : cnt * (1 / can_clk) */
#define BUSOFF_RCY_TIME_SLOW 0x1312d00 /* 200ms : cnt * (1 / can_clk) */
#define ATF_MASK BIT(31)
#define ATF_RTR_EN BIT(30)
#define ATF_RTR BIT(29)
#define ATF_DLC_MODE BIT(5)
#define ATF_DLC_EN BIT(4)
#define ATF_DLC_SHIFT 0
#define ATF_DLC_MASK (0xf << ATF_DLC_SHIFT)
#define ATF_DIS(n) BIT(n)
#define ACK_ERROR_MASK BIT(4)
#define FORM_ERROR_MASK BIT(3)
#define CRC_ERROR_MASK BIT(2)
#define STUFF_ERROR_MASK BIT(1)
#define BIT_ERROR_MASK BIT(0)
#define SRAM_MAX_DEPTH 256 /* word */
#define EXT_MEM_SIZE 0x2000 /* 8KByte */
#define CANFD_FILTER_MASK 0x1fffffff
#define CANFD_FIFO_CNT_MASK 0xff
#define CANBUSOFF_RCY_SLOW 200 /* ms */
#define CANBUSOFF_RCY_FAST 30 /* ms */
#define DRV_NAME "rk3576_canfd"
enum rk3576_canfd_atf_mode {
CANFD_ATF_MASK_MODE = 0,
CANFD_ATF_LIST_MODE,
};
enum rk3576_canfd_storage_mode {
CANFD_DATA_FLEXIBLE = 0,
CANFD_DATA_CAN_FIXED,
CANFD_DATA_CANFD_FIXED,
};
/* rk3576_canfd private data structure */
struct rk3576_canfd {
struct can_priv can;
struct device *dev;
struct napi_struct napi;
struct clk_bulk_data *clks;
int num_clks;
struct reset_control *reset;
void __iomem *base;
u32 irqstatus;
unsigned long mode;
int rx_fifo_shift;
u32 rx_fifo_mask;
int rx_fifo_depth;
int rx_max_data;
bool use_dma;
u32 dma_size;
int quota;
struct dma_chan *rxchan;
u32 *rxbuf;
dma_addr_t rx_dma_src_addr;
dma_addr_t rx_dma_dst_addr;
};
static inline u32 rk3576_canfd_read(const struct rk3576_canfd *priv,
enum rk3576_canfd_reg reg)
{
return readl(priv->base + reg);
}
static inline void rk3576_canfd_write(const struct rk3576_canfd *priv,
enum rk3576_canfd_reg reg, u32 val)
{
writel(val, priv->base + reg);
}
static const struct can_bittiming_const rk3576_canfd_bittiming_const = {
.name = DRV_NAME,
.tseg1_min = 1,
.tseg1_max = 128,
.tseg2_min = 1,
.tseg2_max = 128,
.sjw_max = 128,
.brp_min = 1,
.brp_max = 256,
.brp_inc = 2,
};
static const struct can_bittiming_const rk3576_canfd_data_bittiming_const = {
.name = DRV_NAME,
.tseg1_min = 1,
.tseg1_max = 32,
.tseg2_min = 1,
.tseg2_max = 16,
.sjw_max = 16,
.brp_min = 1,
.brp_max = 256,
.brp_inc = 2,
};
static int set_reset_mode(struct net_device *ndev)
{
struct rk3576_canfd *rcan = netdev_priv(ndev);
reset_control_assert(rcan->reset);
udelay(2);
reset_control_deassert(rcan->reset);
rk3576_canfd_write(rcan, CANFD_MODE, 0);
netdev_dbg(ndev, "%s MODE=0x%08x\n", __func__,
rk3576_canfd_read(rcan, CANFD_MODE));
return 0;
}
static int set_normal_mode(struct net_device *ndev)
{
struct rk3576_canfd *rcan = netdev_priv(ndev);
u32 val;
val = rk3576_canfd_read(rcan, CANFD_MODE);
val |= WORK_MODE;
rk3576_canfd_write(rcan, CANFD_MODE, val);
netdev_dbg(ndev, "%s MODE=0x%08x\n", __func__,
rk3576_canfd_read(rcan, CANFD_MODE));
return 0;
}
/* bittiming is called in reset_mode only */
static int rk3576_canfd_set_bittiming(struct net_device *ndev)
{
struct rk3576_canfd *rcan = netdev_priv(ndev);
const struct can_bittiming *bt = &rcan->can.bittiming;
const struct can_bittiming *dbt = &rcan->can.data_bittiming;
u16 brp, sjw, tseg1, tseg2;
u32 reg_btp;
brp = (bt->brp >> 1) - 1;
sjw = bt->sjw - 1;
tseg1 = bt->prop_seg + bt->phase_seg1 - 1;
tseg2 = bt->phase_seg2 - 1;
reg_btp = (brp << NBTP_NBRP_SHIFT) | (sjw << NBTP_NSJW_SHIFT) |
(tseg1 << NBTP_NTSEG1_SHIFT) |
(tseg2 << NBTP_NTSEG2_SHIFT);
if (rcan->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
reg_btp |= NBTP_MODE_3_SAMPLES;
rk3576_canfd_write(rcan, CANFD_NBTP, reg_btp);
if (rcan->can.ctrlmode & CAN_CTRLMODE_FD) {
reg_btp = 0;
brp = (dbt->brp >> 1) - 1;
sjw = dbt->sjw - 1;
tseg1 = dbt->prop_seg + dbt->phase_seg1 - 1;
tseg2 = dbt->phase_seg2 - 1;
if (sjw < 2)
sjw = 2;
if (dbt->bitrate > 2200000) {
u32 tdco;
/* Equation based on Bosch's ROCKCHIP_CANFD User Manual's
* Transmitter Delay Compensation Section
*/
tdco = ((1 + 1 + tseg1) * (brp + 1)) - 2;
/* Max valid TDCO value is 63 */
if (tdco > 63)
tdco = 63;
rk3576_canfd_write(rcan, CANFD_TDCR,
(tdco << TDCR_TDCO_SHIFT) |
TDCR_TDC_ENABLE);
} else {
rk3576_canfd_write(rcan, CANFD_TDCR, 0);
}
reg_btp |= (brp << DBTP_DBRP_SHIFT) |
(sjw << DBTP_DSJW_SHIFT) |
(tseg1 << DBTP_DTSEG1_SHIFT) |
(tseg2 << DBTP_DTSEG2_SHIFT) |
DBTP_BRS_MODE |
((tseg1 / 2) << DBTP_BRS_TSEG1_SHIFT);
if (rcan->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
reg_btp |= DBTP_MODE_3_SAMPLES;
rk3576_canfd_write(rcan, CANFD_DBTP, reg_btp);
}
netdev_dbg(ndev, "%s NBTP=0x%08x, DBTP=0x%08x, TDCR=0x%08x\n", __func__,
rk3576_canfd_read(rcan, CANFD_NBTP),
rk3576_canfd_read(rcan, CANFD_DBTP),
rk3576_canfd_read(rcan, CANFD_TDCR));
return 0;
}
static int rk3576_canfd_get_berr_counter(const struct net_device *ndev,
struct can_berr_counter *bec)
{
struct rk3576_canfd *rcan = netdev_priv(ndev);
int err;
err = pm_runtime_get_sync(rcan->dev);
if (err < 0) {
netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
__func__, err);
return err;
}
bec->rxerr = rk3576_canfd_read(rcan, CANFD_RXERRORCNT);
bec->txerr = rk3576_canfd_read(rcan, CANFD_TXERRORCNT);
pm_runtime_put(rcan->dev);
netdev_dbg(ndev, "%s RX_ERR_CNT=0x%08x, TX_ERR_CNT=0x%08x\n", __func__,
rk3576_canfd_read(rcan, CANFD_RXERRORCNT),
rk3576_canfd_read(rcan, CANFD_TXERRORCNT));
return 0;
}
static int rk3576_canfd_atf_config(const struct net_device *ndev, int mode)
{
struct rk3576_canfd *rcan = netdev_priv(ndev);
u32 id[10] = {0};
u32 dlc = 0, dlc_over = 0;
switch (mode) {
case CANFD_ATF_MASK_MODE:
rk3576_canfd_write(rcan, CANFD_ATF0, id[0]);
rk3576_canfd_write(rcan, CANFD_ATF1, id[1]);
rk3576_canfd_write(rcan, CANFD_ATF2, id[2]);
rk3576_canfd_write(rcan, CANFD_ATF3, id[3]);
rk3576_canfd_write(rcan, CANFD_ATF4, id[4]);
rk3576_canfd_write(rcan, CANFD_ATFM0, 0x7fff);
rk3576_canfd_write(rcan, CANFD_ATFM1, 0x7fff);
rk3576_canfd_write(rcan, CANFD_ATFM2, 0x7fff);
rk3576_canfd_write(rcan, CANFD_ATFM3, 0x7fff);
rk3576_canfd_write(rcan, CANFD_ATFM4, 0x7fff);
break;
case CANFD_ATF_LIST_MODE:
rk3576_canfd_write(rcan, CANFD_ATF0, id[0]);
rk3576_canfd_write(rcan, CANFD_ATF1, id[1]);
rk3576_canfd_write(rcan, CANFD_ATF2, id[2]);
rk3576_canfd_write(rcan, CANFD_ATF3, id[3]);
rk3576_canfd_write(rcan, CANFD_ATF4, id[4]);
rk3576_canfd_write(rcan, CANFD_ATFM0, id[5] | (1 << 31));
rk3576_canfd_write(rcan, CANFD_ATFM1, id[6] | (1 << 31));
rk3576_canfd_write(rcan, CANFD_ATFM2, id[7] | (1 << 31));
rk3576_canfd_write(rcan, CANFD_ATFM3, id[8] | (1 << 31));
rk3576_canfd_write(rcan, CANFD_ATFM4, id[9] | (1 << 31));
break;
default:
rk3576_canfd_write(rcan, CANFD_ATF_CTL, 0xffff);
return -EINVAL;
}
if (dlc) {
if (dlc_over)
rk3576_canfd_write(rcan, CANFD_ATF_DLC, dlc | (1 << 4));
else
rk3576_canfd_write(rcan, CANFD_ATF_DLC, dlc | (1 << 4) | (1 << 5));
}
rk3576_canfd_write(rcan, CANFD_ATF_CTL, 0);
return 0;
}
static int rk3576_canfd_start(struct net_device *ndev)
{
struct rk3576_canfd *rcan = netdev_priv(ndev);
u32 val, ism = 0, water = 0;
/* we need to enter the reset mode */
set_reset_mode(ndev);
rk3576_canfd_write(rcan, CANFD_INT_MASK, INT_ENABLE);
rk3576_canfd_atf_config(ndev, CANFD_ATF_MASK_MODE);
/* set mode */
val = rk3576_canfd_read(rcan, CANFD_MODE);
if (rcan->rx_max_data > 4) {
ism = CANFD_DATA_CANFD_FIXED;
water = ISM_WATERMASK_CANFD;
} else {
ism = CANFD_DATA_CAN_FIXED;
water = ISM_WATERMASK_CAN;
}
/* internal sram mode */
rk3576_canfd_write(rcan, CANFD_STR_CTL,
(ism << ISM_SEL_SHIFT) | STORAGE_TIMEOUT_MODE);
rk3576_canfd_write(rcan, CANFD_STR_WTM, water);
/* Loopback Mode */
if (rcan->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
val |= MODE_LBACK;
rk3576_canfd_write(rcan, CANFD_ERROR_MASK, ACK_ERROR_MASK);
} else if (rcan->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
val |= MODE_SILENT;
rk3576_canfd_write(rcan, CANFD_ERROR_MASK, ACK_ERROR_MASK);
} else {
rk3576_canfd_write(rcan, CANFD_ERROR_MASK, 0);
}
rk3576_canfd_write(rcan, CANFD_AUTO_RETX_CFG,
AUTO_RETX_EN | RETX_LIMIT_EN |
(RETX_TIME_LIMIT_CNT << RETX_TIME_LIMIT_SHIFT));
rk3576_canfd_write(rcan, CANFD_MODE, val);
if (rcan->use_dma)
rk3576_canfd_write(rcan, CANFD_DMA_CTRL, RX_DMA_ENABLE);
rk3576_canfd_write(rcan, CANFD_BRS_CFG, 0x7);
rk3576_canfd_write(rcan, CANFD_BUSOFFRCY_CFG, BUSOFF_RCY_MODE_EN | BUSOFF_RCY_CNT_FAST);
rk3576_canfd_write(rcan, CANFD_BUSOFF_RCY_THR, BUSOFF_RCY_TIME_FAST);
rk3576_canfd_set_bittiming(ndev);
set_normal_mode(ndev);
rcan->can.state = CAN_STATE_ERROR_ACTIVE;
netdev_dbg(ndev, "%s MODE=0x%08x, INT_MASK=0x%08x\n", __func__,
rk3576_canfd_read(rcan, CANFD_MODE),
rk3576_canfd_read(rcan, CANFD_INT_MASK));
return 0;
}
static int rk3576_canfd_stop(struct net_device *ndev)
{
struct rk3576_canfd *rcan = netdev_priv(ndev);
rcan->can.state = CAN_STATE_STOPPED;
/* we need to enter reset mode */
set_reset_mode(ndev);
/* disable all interrupts */
rk3576_canfd_write(rcan, CANFD_INT_MASK, 0xffffffff);
netdev_dbg(ndev, "%s MODE=0x%08x, INT_MASK=0x%08x\n", __func__,
rk3576_canfd_read(rcan, CANFD_MODE),
rk3576_canfd_read(rcan, CANFD_INT_MASK));
return 0;
}
static int rk3576_canfd_set_mode(struct net_device *ndev,
enum can_mode mode)
{
int err;
switch (mode) {
case CAN_MODE_START:
err = rk3576_canfd_start(ndev);
if (err) {
netdev_err(ndev, "starting CANFD controller failed!\n");
return err;
}
if (netif_queue_stopped(ndev))
netif_wake_queue(ndev);
break;
default:
return -EOPNOTSUPP;
}
return 0;
}
/* transmit a CANFD message
* message layout in the sk_buff should be like this:
* xx xx xx xx ff ll 00 11 22 33 44 55 66 77
* [ can_id ] [flags] [len] [can data (up to 8 bytes]
*/
static netdev_tx_t rk3576_canfd_start_xmit(struct sk_buff *skb,
struct net_device *ndev)
{
struct rk3576_canfd *rcan = netdev_priv(ndev);
struct canfd_frame *cf = (struct canfd_frame *)skb->data;
u32 id, dlc;
u32 cmd = CANFD_TX0_REQ;
int i;
if (can_dropped_invalid_skb(ndev, skb))
return NETDEV_TX_OK;
netif_stop_queue(ndev);
if (rk3576_canfd_read(rcan, CANFD_CMD) & CANFD_TX0_REQ)
cmd = CANFD_TX1_REQ;
/* Watch carefully on the bit sequence */
if (cf->can_id & CAN_EFF_FLAG) {
/* Extended CANFD ID format */
id = cf->can_id & CAN_EFF_MASK;
dlc = can_fd_len2dlc(cf->len) & TX_DLC_MASK;
dlc |= TX_FORMAT_MASK;
/* Extended frames remote TX request */
if (cf->can_id & CAN_RTR_FLAG)
dlc |= TX_RTR_MASK;
} else {
/* Standard CANFD ID format */
id = cf->can_id & CAN_SFF_MASK;
dlc = can_fd_len2dlc(cf->len) & TX_DLC_MASK;
/* Standard frames remote TX request */
if (cf->can_id & CAN_RTR_FLAG)
dlc |= TX_RTR_MASK;
}
if ((rcan->can.ctrlmode & CAN_CTRLMODE_FD) && can_is_canfd_skb(skb)) {
dlc |= TX_FD_ENABLE;
if (cf->flags & CANFD_BRS)
dlc |= TX_FD_BRS_ENABLE;
}
rk3576_canfd_write(rcan, CANFD_TXID, id);
rk3576_canfd_write(rcan, CANFD_TXFIC, dlc);
for (i = 0; i < cf->len; i += 4)
rk3576_canfd_write(rcan, CANFD_TXDAT0 + i,
*(u32 *)(cf->data + i));
can_put_echo_skb(skb, ndev, 0, 0);
rk3576_canfd_write(rcan, CANFD_CMD, cmd);
return NETDEV_TX_OK;
}
static int rk3576_canfd_rx(struct net_device *ndev, u32 addr)
{
struct rk3576_canfd *rcan = netdev_priv(ndev);
struct net_device_stats *stats = &ndev->stats;
struct canfd_frame *cf;
struct sk_buff *skb;
u32 id_rk3576_canfd, dlc;
int i = 0;
u32 __maybe_unused ts, ret;
u32 data[16] = {0};
if (rcan->use_dma) {
dlc = readl(rcan->rxbuf + addr * rcan->rx_max_data);
id_rk3576_canfd = readl(rcan->rxbuf + 1 + addr * rcan->rx_max_data);
for (i = 0; i < (rcan->rx_max_data - 2); i++)
data[i] = readl(rcan->rxbuf + 2 + i + addr * rcan->rx_max_data);
} else {
dlc = rk3576_canfd_read(rcan, addr);
id_rk3576_canfd = rk3576_canfd_read(rcan, addr);
for (i = 0; i < (rcan->rx_max_data - 2); i++)
data[i] = rk3576_canfd_read(rcan, addr);
}
/* create zero'ed CANFD frame buffer */
if (dlc & RX_FDF_MASK)
skb = alloc_canfd_skb(ndev, &cf);
else
skb = alloc_can_skb(ndev, (struct can_frame **)&cf);
if (!skb) {
stats->rx_dropped++;
return 1;
}
/* Change CANFD data length format to SocketCAN data format */
if (dlc & RX_FDF_MASK)
cf->len = can_fd_dlc2len((dlc & RX_DLC_MASK) >> RX_DLC_SHIFT);
else
cf->len = can_cc_dlc2len((dlc & RX_DLC_MASK) >> RX_DLC_SHIFT);
/* Change CANFD ID format to SocketCAN ID format */
if (dlc & RX_FORMAT_MASK) {
/* The received frame is an Extended format frame */
cf->can_id = id_rk3576_canfd;
cf->can_id |= CAN_EFF_FLAG;
if (dlc & RX_RTR_MASK)
cf->can_id |= CAN_RTR_FLAG;
} else {
/* The received frame is a standard format frame */
cf->can_id = id_rk3576_canfd;
if (dlc & RX_RTR_MASK)
cf->can_id |= CAN_RTR_FLAG;
}
if (dlc & RX_BRS_MASK)
cf->flags |= CANFD_BRS;
if (!(cf->can_id & CAN_RTR_FLAG)) {
/* Change CANFD data format to SocketCAN data format */
for (i = 0; i < cf->len; i += 4)
*(u32 *)(cf->data + i) = data[i / 4];
}
stats->rx_packets++;
stats->rx_bytes += cf->len;
netif_rx(skb);
return 1;
}
/* rk3576_canfd_rx_poll - Poll routine for rx packets (NAPI)
* @napi: napi structure pointer
* @quota: Max number of rx packets to be processed.
*
* This is the poll routine for rx part.
* It will process the packets maximux quota value.
*
* Return: number of packets received
*/
static int rk3576_canfd_rx_poll(struct napi_struct *napi, int quota)
{
struct net_device *ndev = napi->dev;
struct rk3576_canfd *rcan = netdev_priv(ndev);
int work_done = 0, cnt = 0;
if (rcan->use_dma) {
while (work_done < rcan->quota)
work_done += rk3576_canfd_rx(ndev, work_done);
if (work_done <= rcan->rx_fifo_depth) {
napi_complete_done(napi, work_done);
rk3576_canfd_write(rcan, CANFD_INT_MASK, INT_ENABLE);
}
} else {
quota = (rk3576_canfd_read(rcan, CANFD_STR_STATE) & rcan->rx_fifo_mask) >>
rcan->rx_fifo_shift;
quota = quota / rcan->rx_max_data;
cnt = (rk3576_canfd_read(rcan, CANFD_STR_STATE) & INTM_CNT_MASK) >> INTM_CNT_SHIFT;
if (quota != cnt)
quota = ((rk3576_canfd_read(rcan, CANFD_STR_STATE) & rcan->rx_fifo_mask) >>
rcan->rx_fifo_shift) / rcan->rx_max_data;
while (work_done < quota)
work_done += rk3576_canfd_rx(ndev, CANFD_RXFRD);
if (work_done <= rcan->rx_fifo_depth) {
napi_complete_done(napi, work_done);
rk3576_canfd_write(rcan, CANFD_INT_MASK, INT_ENABLE);
}
}
return work_done;
}
static void rk3576_canfd_rx_dma_callback(void *data)
{
struct rk3576_canfd *rcan = data;
napi_schedule(&rcan->napi);
}
static int rk3576_canfd_rx_dma(struct rk3576_canfd *rcan)
{
struct dma_async_tx_descriptor *rxdesc = NULL;
int quota = 0, cnt = 0;
quota = (rk3576_canfd_read(rcan, CANFD_STR_STATE) & rcan->rx_fifo_mask) >>
rcan->rx_fifo_shift;
quota = quota / rcan->rx_max_data;
cnt = (rk3576_canfd_read(rcan, CANFD_STR_STATE) & INTM_CNT_MASK) >> INTM_CNT_SHIFT;
if (quota != cnt)
quota = ((rk3576_canfd_read(rcan, CANFD_STR_STATE) & rcan->rx_fifo_mask) >>
rcan->rx_fifo_shift) / rcan->rx_max_data;
rcan->quota = quota;
if (rcan->quota == 0)
return 1;
rxdesc = dmaengine_prep_slave_single(rcan->rxchan, rcan->rx_dma_dst_addr,
rcan->dma_size * rcan->quota, DMA_DEV_TO_MEM, 0);
if (!rxdesc)
return -EBUSY;
rxdesc->callback = rk3576_canfd_rx_dma_callback;
rxdesc->callback_param = rcan;
dmaengine_submit(rxdesc);
dma_async_issue_pending(rcan->rxchan);
return 1;
}
static int rk3576_canfd_err(struct net_device *ndev, u32 isr)
{
struct rk3576_canfd *rcan = netdev_priv(ndev);
struct net_device_stats *stats = &ndev->stats;
struct can_frame *cf;
struct sk_buff *skb;
unsigned int rxerr, txerr;
u32 sta_reg;
skb = alloc_can_err_skb(ndev, &cf);
rxerr = rk3576_canfd_read(rcan, CANFD_RXERRORCNT);
txerr = rk3576_canfd_read(rcan, CANFD_TXERRORCNT);
sta_reg = rk3576_canfd_read(rcan, CANFD_STATE);
if (skb) {
cf->data[6] = txerr;
cf->data[7] = rxerr;
}
if (isr & BUS_OFF_INT) {
rcan->can.state = CAN_STATE_BUS_OFF;
rcan->can.can_stats.bus_off++;
cf->can_id |= CAN_ERR_BUSOFF;
} else if (isr & PASSIVE_ERR_INT) {
rcan->can.can_stats.error_passive++;
rcan->can.state = CAN_STATE_ERROR_PASSIVE;
/* error passive state */
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = (txerr > rxerr) ?
CAN_ERR_CRTL_TX_WARNING :
CAN_ERR_CRTL_RX_WARNING;
cf->data[6] = txerr;
cf->data[7] = rxerr;
}
if (sta_reg & ERR_WARNING_STATE) {
rcan->can.can_stats.error_warning++;
rcan->can.state = CAN_STATE_ERROR_WARNING;
/* error warning state */
if (likely(skb)) {
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = (txerr > rxerr) ?
CAN_ERR_CRTL_TX_WARNING :
CAN_ERR_CRTL_RX_WARNING;
cf->data[6] = txerr;
cf->data[7] = rxerr;
}
}
if (isr & BUSOFF_RCY_INT) {
rk3576_canfd_write(rcan, CANFD_INT_MASK, 0xffff);
rk3576_canfd_write(rcan, CANFD_INT, isr);
napi_schedule(&rcan->napi);
rk3576_canfd_write(rcan, CANFD_BUSOFFRCY_CFG, BUSOFF_RCY_TIME_CLR);
rk3576_canfd_write(rcan, CANFD_BUSOFF_RCY_THR, BUSOFF_RCY_TIME_SLOW);
rk3576_canfd_write(rcan, CANFD_BUSOFFRCY_CFG,
BUSOFF_RCY_MODE_EN | BUSOFF_RCY_CNT_SLOW);
rk3576_canfd_write(rcan, CANFD_INT_MASK, INT_ENABLE);
netif_stop_queue(ndev);
can_free_echo_skb(ndev, 0, NULL);
netif_start_queue(ndev);
}
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
netif_rx(skb);
return 0;
}
static irqreturn_t rk3576_canfd_interrupt(int irq, void *dev_id)
{
struct net_device *ndev = (struct net_device *)dev_id;
struct rk3576_canfd *rcan = netdev_priv(ndev);
struct net_device_stats *stats = &ndev->stats;
u32 err_int = ERR_WARN_INT | RX_BUF_OV_INT | PASSIVE_ERR_INT |
BUS_ERR_INT | BUS_OFF_INT | BUSOFF_RCY_INT |
BUS_OFF_RECOVERY_INT | RX_STR_FULL_INT;
u32 isr;
isr = rk3576_canfd_read(rcan, CANFD_INT);
if ((isr & RX_STR_TIMEOUT_INT) || (isr & ISM_WTM_INT) || (isr & RX_STR_FULL_INT)) {
rk3576_canfd_write(rcan, CANFD_INT_MASK,
ISM_WTM_INT | RX_STR_TIMEOUT_INT |
RX_FINISH_INT);
if (rcan->use_dma)
rk3576_canfd_rx_dma(rcan);
else
napi_schedule(&rcan->napi);
}
if (isr & TX_FINISH_INT) {
rk3576_canfd_write(rcan, CANFD_CMD, 0);
stats->tx_bytes += can_get_echo_skb(ndev, 0, NULL);
stats->tx_packets++;
netif_wake_queue(ndev);
}
if (isr & err_int) {
/* error interrupt */
if (rk3576_canfd_err(ndev, isr))
netdev_err(ndev, "can't allocate buffer - clearing pending interrupts\n");
}
rk3576_canfd_write(rcan, CANFD_INT, isr);
return IRQ_HANDLED;
}
static int rk3576_canfd_open(struct net_device *ndev)
{
struct rk3576_canfd *rcan = netdev_priv(ndev);
int err;
/* common open */
err = open_candev(ndev);
if (err)
return err;
err = pm_runtime_get_sync(rcan->dev);
if (err < 0) {
netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
__func__, err);
goto exit;
}
err = rk3576_canfd_start(ndev);
if (err) {
netdev_err(ndev, "could not start CANFD peripheral\n");
goto exit_can_start;
}
napi_enable(&rcan->napi);
netif_start_queue(ndev);
netdev_dbg(ndev, "%s\n", __func__);
return 0;
exit_can_start:
pm_runtime_put(rcan->dev);
exit:
close_candev(ndev);
return err;
}
static int rk3576_canfd_close(struct net_device *ndev)
{
struct rk3576_canfd *rcan = netdev_priv(ndev);
netif_stop_queue(ndev);
napi_disable(&rcan->napi);
rk3576_canfd_stop(ndev);
close_candev(ndev);
pm_runtime_put(rcan->dev);
netdev_dbg(ndev, "%s\n", __func__);
return 0;
}
static const struct net_device_ops rk3576_canfd_netdev_ops = {
.ndo_open = rk3576_canfd_open,
.ndo_stop = rk3576_canfd_close,
.ndo_start_xmit = rk3576_canfd_start_xmit,
.ndo_change_mtu = can_change_mtu,
};
/**
* rk3576_canfd_suspend - Suspend method for the driver
* @dev: Address of the device structure
*
* Put the driver into low power mode.
* Return: 0 on success and failure value on error
*/
static int __maybe_unused rk3576_canfd_suspend(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
if (netif_running(ndev)) {
netif_stop_queue(ndev);
netif_device_detach(ndev);
rk3576_canfd_stop(ndev);
}
return pm_runtime_force_suspend(dev);
}
/**
* rk3576_canfd_resume - Resume from suspend
* @dev: Address of the device structure
*
* Resume operation after suspend.
* Return: 0 on success and failure value on error
*/
static int __maybe_unused rk3576_canfd_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
int ret;
ret = pm_runtime_force_resume(dev);
if (ret) {
dev_err(dev, "pm_runtime_force_resume failed on resume\n");
return ret;
}
if (netif_running(ndev)) {
ret = rk3576_canfd_start(ndev);
if (ret) {
dev_err(dev, "rk3576_canfd_chip_start failed on resume\n");
return ret;
}
netif_device_attach(ndev);
netif_start_queue(ndev);
}
return 0;
}
/**
* rk3576_canfd_runtime_suspend - Runtime suspend method for the driver
* @dev: Address of the device structure
*
* Put the driver into low power mode.
* Return: 0 always
*/
static int __maybe_unused rk3576_canfd_runtime_suspend(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct rk3576_canfd *rcan = netdev_priv(ndev);
clk_bulk_disable_unprepare(rcan->num_clks, rcan->clks);
return 0;
}
/**
* rk3576_canfd_runtime_resume - Runtime resume from suspend
* @dev: Address of the device structure
*
* Resume operation after suspend.
* Return: 0 on success and failure value on error
*/
static int __maybe_unused rk3576_canfd_runtime_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct rk3576_canfd *rcan = netdev_priv(ndev);
int ret;
ret = clk_bulk_prepare_enable(rcan->num_clks, rcan->clks);
if (ret) {
dev_err(dev, "Cannot enable clock.\n");
return ret;
}
return 0;
}
static const struct dev_pm_ops rk3576_canfd_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(rk3576_canfd_suspend, rk3576_canfd_resume)
SET_RUNTIME_PM_OPS(rk3576_canfd_runtime_suspend,
rk3576_canfd_runtime_resume, NULL)
};
static const struct of_device_id rk3576_canfd_of_match[] = {
{
.compatible = "rockchip,rk3576-canfd",
},
{},
};
MODULE_DEVICE_TABLE(of, rk3576_canfd_of_match);
static void rk3576_canfd_dma_init(struct rk3576_canfd *rcan)
{
struct dma_slave_config rxconf = {
.direction = DMA_DEV_TO_MEM,
.src_addr = rcan->rx_dma_src_addr,
.src_addr_width = 4,
.dst_addr_width = 4,
.src_maxburst = 16,
};
rcan->rxbuf = dma_alloc_coherent(rcan->dev, rcan->dma_size * rcan->rx_fifo_depth,
&rcan->rx_dma_dst_addr, GFP_KERNEL);
if (!rcan->rxbuf) {
rcan->use_dma = 0;
return;
}
dmaengine_slave_config(rcan->rxchan, &rxconf);
}
static int rk3576_canfd_probe(struct platform_device *pdev)
{
struct net_device *ndev;
struct rk3576_canfd *rcan;
struct resource *res;
void __iomem *addr;
int err, irq;
u32 val = 0;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "could not get a valid irq\n");
return -ENODEV;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
addr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(addr))
return -EBUSY;
ndev = alloc_candev(sizeof(struct rk3576_canfd), 1);
if (!ndev) {
dev_err(&pdev->dev, "could not allocate memory for CANFD device\n");
return -ENOMEM;
}
rcan = netdev_priv(ndev);
/* register interrupt handler */
err = devm_request_irq(&pdev->dev, irq, rk3576_canfd_interrupt,
0, ndev->name, ndev);
if (err) {
dev_err(&pdev->dev, "request_irq err: %d\n", err);
return err;
}
rcan->reset = devm_reset_control_array_get(&pdev->dev, false, false);
if (IS_ERR(rcan->reset)) {
if (PTR_ERR(rcan->reset) != -EPROBE_DEFER)
dev_err(&pdev->dev, "failed to get canfd reset lines\n");
return PTR_ERR(rcan->reset);
}
rcan->num_clks = devm_clk_bulk_get_all(&pdev->dev, &rcan->clks);
if (rcan->num_clks < 1)
return -ENODEV;
rcan->mode = (unsigned long)of_device_get_match_data(&pdev->dev);
rcan->base = addr;
rcan->can.clock.freq = clk_get_rate(rcan->clks[0].clk);
rcan->dev = &pdev->dev;
rcan->can.state = CAN_STATE_STOPPED;
rcan->can.bittiming_const = &rk3576_canfd_bittiming_const;
rcan->can.data_bittiming_const = &rk3576_canfd_data_bittiming_const;
rcan->can.do_set_mode = rk3576_canfd_set_mode;
rcan->can.do_get_berr_counter = rk3576_canfd_get_berr_counter;
rcan->can.do_set_bittiming = rk3576_canfd_set_bittiming;
rcan->can.do_set_data_bittiming = rk3576_canfd_set_bittiming;
rcan->can.ctrlmode = CAN_CTRLMODE_FD;
/* IFI CANFD can do both Bosch FD and ISO FD */
rcan->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_FD;
rcan->rx_fifo_shift = INTM_LEFT_CNT_SHIFT;
rcan->rx_fifo_mask = INTM_LEFT_CNT_MASK;
/* 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))
rcan->rx_max_data = 18;
else
rcan->rx_max_data = val;
if (rcan->rx_max_data != 4 && rcan->rx_max_data != 18) {
rcan->rx_max_data = 18;
dev_warn(&pdev->dev, "rx_max_data is invalid, set to 18 words!\n");
}
rcan->rx_fifo_depth = SRAM_MAX_DEPTH / rcan->rx_max_data;
rcan->rxchan = dma_request_chan(&pdev->dev, "rx");
if (IS_ERR(rcan->rxchan)) {
dev_warn(&pdev->dev, "Failed to request rxchan\n");
rcan->rxchan = NULL;
rcan->use_dma = 0;
} else {
rcan->rx_dma_src_addr = res->start + CANFD_RXFRD;
rcan->dma_size = rcan->rx_max_data * 4;
rcan->use_dma = 1;
}
if (rcan->use_dma)
rk3576_canfd_dma_init(rcan);
ndev->netdev_ops = &rk3576_canfd_netdev_ops;
ndev->irq = irq;
ndev->flags |= IFF_ECHO;
platform_set_drvdata(pdev, ndev);
SET_NETDEV_DEV(ndev, &pdev->dev);
pm_runtime_enable(&pdev->dev);
err = pm_runtime_get_sync(&pdev->dev);
if (err < 0) {
dev_err(&pdev->dev, "%s: pm_runtime_get failed(%d)\n",
__func__, err);
goto err_pmdisable;
}
netif_napi_add(ndev, &rcan->napi, rk3576_canfd_rx_poll);
err = register_candev(ndev);
if (err) {
dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
DRV_NAME, err);
goto err_disableclks;
}
dev_info(&pdev->dev, "CAN info: use_dma = %d, rx_max_data = %d, fifo_depth = %d\n",
rcan->use_dma, rcan->rx_max_data, rcan->rx_fifo_depth);
return 0;
err_disableclks:
pm_runtime_put(&pdev->dev);
err_pmdisable:
if (rcan->rxbuf) {
dma_free_coherent(rcan->dev, rcan->dma_size * rcan->rx_fifo_depth, rcan->rxbuf,
rcan->rx_dma_dst_addr);
rcan->rxbuf = NULL;
}
if (rcan->rxchan)
dma_release_channel(rcan->rxchan);
pm_runtime_disable(&pdev->dev);
free_candev(ndev);
return err;
}
static int rk3576_canfd_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct rk3576_canfd *rcan = netdev_priv(ndev);
if (rcan->rxbuf) {
dma_free_coherent(rcan->dev, rcan->dma_size * rcan->rx_fifo_depth, rcan->rxbuf,
rcan->rx_dma_dst_addr);
rcan->rxbuf = NULL;
}
if (rcan->rxchan)
dma_release_channel(rcan->rxchan);
unregister_netdev(ndev);
pm_runtime_disable(&pdev->dev);
netif_napi_del(&rcan->napi);
free_candev(ndev);
return 0;
}
static struct platform_driver rk3576_canfd_driver = {
.driver = {
.name = DRV_NAME,
.pm = &rk3576_canfd_dev_pm_ops,
.of_match_table = rk3576_canfd_of_match,
},
.probe = rk3576_canfd_probe,
.remove = rk3576_canfd_remove,
};
module_platform_driver(rk3576_canfd_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Elaine Zhang <zhangqing@rock-chips.com>");
MODULE_DESCRIPTION("RK3576 CANFD Drivers");