linux/drivers/net/can/flexcan/flexcan-core.c

// SPDX-License-Identifier: GPL-2.0
//
// flexcan.c - FLEXCAN CAN controller driver
//
// Copyright (c) 2005-2006 Varma Electronics Oy
// Copyright (c) 2009 Sascha Hauer, Pengutronix
// Copyright (c) 2010-2017 Pengutronix, Marc Kleine-Budde <[email protected]>
// Copyright (c) 2014 David Jander, Protonic Holland
//
// Based on code originally by Andrey Volkov <[email protected]>

#include <dt-bindings/firmware/imx/rsrc.h>
#include <linux/bitfield.h>
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/firmware/imx/sci.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/can/platform/flexcan.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>

#include "flexcan.h"

#define DRV_NAME

/* 8 for RX fifo and 2 error handling */
#define FLEXCAN_NAPI_WEIGHT

/* FLEXCAN module configuration register (CANMCR) bits */
#define FLEXCAN_MCR_MDIS
#define FLEXCAN_MCR_FRZ
#define FLEXCAN_MCR_FEN
#define FLEXCAN_MCR_HALT
#define FLEXCAN_MCR_NOT_RDY
#define FLEXCAN_MCR_WAK_MSK
#define FLEXCAN_MCR_SOFTRST
#define FLEXCAN_MCR_FRZ_ACK
#define FLEXCAN_MCR_SUPV
#define FLEXCAN_MCR_SLF_WAK
#define FLEXCAN_MCR_WRN_EN
#define FLEXCAN_MCR_LPM_ACK
#define FLEXCAN_MCR_WAK_SRC
#define FLEXCAN_MCR_DOZE
#define FLEXCAN_MCR_SRX_DIS
#define FLEXCAN_MCR_IRMQ
#define FLEXCAN_MCR_LPRIO_EN
#define FLEXCAN_MCR_AEN
#define FLEXCAN_MCR_FDEN
/* MCR_MAXMB: maximum used MBs is MAXMB + 1 */
#define FLEXCAN_MCR_MAXMB(x)
#define FLEXCAN_MCR_IDAM_A
#define FLEXCAN_MCR_IDAM_B
#define FLEXCAN_MCR_IDAM_C
#define FLEXCAN_MCR_IDAM_D

/* FLEXCAN control register (CANCTRL) bits */
#define FLEXCAN_CTRL_PRESDIV(x)
#define FLEXCAN_CTRL_RJW(x)
#define FLEXCAN_CTRL_PSEG1(x)
#define FLEXCAN_CTRL_PSEG2(x)
#define FLEXCAN_CTRL_BOFF_MSK
#define FLEXCAN_CTRL_ERR_MSK
#define FLEXCAN_CTRL_CLK_SRC
#define FLEXCAN_CTRL_LPB
#define FLEXCAN_CTRL_TWRN_MSK
#define FLEXCAN_CTRL_RWRN_MSK
#define FLEXCAN_CTRL_SMP
#define FLEXCAN_CTRL_BOFF_REC
#define FLEXCAN_CTRL_TSYN
#define FLEXCAN_CTRL_LBUF
#define FLEXCAN_CTRL_LOM
#define FLEXCAN_CTRL_PROPSEG(x)
#define FLEXCAN_CTRL_ERR_BUS
#define FLEXCAN_CTRL_ERR_STATE
#define FLEXCAN_CTRL_ERR_ALL

/* FLEXCAN control register 2 (CTRL2) bits */
#define FLEXCAN_CTRL2_ECRWRE
#define FLEXCAN_CTRL2_WRMFRZ
#define FLEXCAN_CTRL2_RFFN(x)
#define FLEXCAN_CTRL2_TASD(x)
#define FLEXCAN_CTRL2_MRP
#define FLEXCAN_CTRL2_RRS
#define FLEXCAN_CTRL2_EACEN
#define FLEXCAN_CTRL2_ISOCANFDEN

/* FLEXCAN memory error control register (MECR) bits */
#define FLEXCAN_MECR_ECRWRDIS
#define FLEXCAN_MECR_HANCEI_MSK
#define FLEXCAN_MECR_FANCEI_MSK
#define FLEXCAN_MECR_CEI_MSK
#define FLEXCAN_MECR_HAERRIE
#define FLEXCAN_MECR_FAERRIE
#define FLEXCAN_MECR_EXTERRIE
#define FLEXCAN_MECR_RERRDIS
#define FLEXCAN_MECR_ECCDIS
#define FLEXCAN_MECR_NCEFAFRZ

/* FLEXCAN error and status register (ESR) bits */
#define FLEXCAN_ESR_TWRN_INT
#define FLEXCAN_ESR_RWRN_INT
#define FLEXCAN_ESR_BIT1_ERR
#define FLEXCAN_ESR_BIT0_ERR
#define FLEXCAN_ESR_ACK_ERR
#define FLEXCAN_ESR_CRC_ERR
#define FLEXCAN_ESR_FRM_ERR
#define FLEXCAN_ESR_STF_ERR
#define FLEXCAN_ESR_TX_WRN
#define FLEXCAN_ESR_RX_WRN
#define FLEXCAN_ESR_IDLE
#define FLEXCAN_ESR_TXRX
#define FLEXCAN_EST_FLT_CONF_SHIFT
#define FLEXCAN_ESR_FLT_CONF_MASK
#define FLEXCAN_ESR_FLT_CONF_ACTIVE
#define FLEXCAN_ESR_FLT_CONF_PASSIVE
#define FLEXCAN_ESR_BOFF_INT
#define FLEXCAN_ESR_ERR_INT
#define FLEXCAN_ESR_WAK_INT
#define FLEXCAN_ESR_ERR_BUS
#define FLEXCAN_ESR_ERR_STATE
#define FLEXCAN_ESR_ERR_ALL
#define FLEXCAN_ESR_ALL_INT

/* FLEXCAN Bit Timing register (CBT) bits */
#define FLEXCAN_CBT_BTF
#define FLEXCAN_CBT_EPRESDIV_MASK
#define FLEXCAN_CBT_ERJW_MASK
#define FLEXCAN_CBT_EPROPSEG_MASK
#define FLEXCAN_CBT_EPSEG1_MASK
#define FLEXCAN_CBT_EPSEG2_MASK

/* FLEXCAN FD control register (FDCTRL) bits */
#define FLEXCAN_FDCTRL_FDRATE
#define FLEXCAN_FDCTRL_MBDSR1
#define FLEXCAN_FDCTRL_MBDSR0
#define FLEXCAN_FDCTRL_MBDSR_8
#define FLEXCAN_FDCTRL_MBDSR_12
#define FLEXCAN_FDCTRL_MBDSR_32
#define FLEXCAN_FDCTRL_MBDSR_64
#define FLEXCAN_FDCTRL_TDCEN
#define FLEXCAN_FDCTRL_TDCFAIL
#define FLEXCAN_FDCTRL_TDCOFF
#define FLEXCAN_FDCTRL_TDCVAL

/* FLEXCAN FD Bit Timing register (FDCBT) bits */
#define FLEXCAN_FDCBT_FPRESDIV_MASK
#define FLEXCAN_FDCBT_FRJW_MASK
#define FLEXCAN_FDCBT_FPROPSEG_MASK
#define FLEXCAN_FDCBT_FPSEG1_MASK
#define FLEXCAN_FDCBT_FPSEG2_MASK

/* FLEXCAN interrupt flag register (IFLAG) bits */
/* Errata ERR005829 step7: Reserve first valid MB */
#define FLEXCAN_TX_MB_RESERVED_RX_FIFO
#define FLEXCAN_TX_MB_RESERVED_RX_MAILBOX
#define FLEXCAN_RX_MB_RX_MAILBOX_FIRST
#define FLEXCAN_IFLAG_MB(x)
#define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW
#define FLEXCAN_IFLAG_RX_FIFO_WARN
#define FLEXCAN_IFLAG_RX_FIFO_AVAILABLE

/* FLEXCAN message buffers */
#define FLEXCAN_MB_CODE_MASK
#define FLEXCAN_MB_CODE_RX_BUSY_BIT
#define FLEXCAN_MB_CODE_RX_INACTIVE
#define FLEXCAN_MB_CODE_RX_EMPTY
#define FLEXCAN_MB_CODE_RX_FULL
#define FLEXCAN_MB_CODE_RX_OVERRUN
#define FLEXCAN_MB_CODE_RX_RANSWER

#define FLEXCAN_MB_CODE_TX_INACTIVE
#define FLEXCAN_MB_CODE_TX_ABORT
#define FLEXCAN_MB_CODE_TX_DATA
#define FLEXCAN_MB_CODE_TX_TANSWER

#define FLEXCAN_MB_CNT_EDL
#define FLEXCAN_MB_CNT_BRS
#define FLEXCAN_MB_CNT_ESI
#define FLEXCAN_MB_CNT_SRR
#define FLEXCAN_MB_CNT_IDE
#define FLEXCAN_MB_CNT_RTR
#define FLEXCAN_MB_CNT_LENGTH(x)
#define FLEXCAN_MB_CNT_TIMESTAMP(x)

#define FLEXCAN_TIMEOUT_US

/* Structure of the message buffer */
struct flexcan_mb {};

/* Structure of the hardware registers */
struct flexcan_regs {};

static_assert();

static const struct flexcan_devtype_data fsl_mcf5441x_devtype_data =;

static const struct flexcan_devtype_data fsl_p1010_devtype_data =;

static const struct flexcan_devtype_data fsl_imx25_devtype_data =;

static const struct flexcan_devtype_data fsl_imx28_devtype_data =;

static const struct flexcan_devtype_data fsl_imx6q_devtype_data =;

static const struct flexcan_devtype_data fsl_imx8qm_devtype_data =;

static struct flexcan_devtype_data fsl_imx8mp_devtype_data =;

static struct flexcan_devtype_data fsl_imx93_devtype_data =;

static const struct flexcan_devtype_data fsl_vf610_devtype_data =;

static const struct flexcan_devtype_data fsl_ls1021a_r2_devtype_data =;

static const struct flexcan_devtype_data fsl_lx2160a_r1_devtype_data =;

static const struct can_bittiming_const flexcan_bittiming_const =;

static const struct can_bittiming_const flexcan_fd_bittiming_const =;

static const struct can_bittiming_const flexcan_fd_data_bittiming_const =;

/* FlexCAN module is essentially modelled as a little-endian IP in most
 * SoCs, i.e the registers as well as the message buffer areas are
 * implemented in a little-endian fashion.
 *
 * However there are some SoCs (e.g. LS1021A) which implement the FlexCAN
 * module in a big-endian fashion (i.e the registers as well as the
 * message buffer areas are implemented in a big-endian way).
 *
 * In addition, the FlexCAN module can be found on SoCs having ARM or
 * PPC cores. So, we need to abstract off the register read/write
 * functions, ensuring that these cater to all the combinations of module
 * endianness and underlying CPU endianness.
 */
static inline u32 flexcan_read_be(void __iomem *addr)
{}

static inline void flexcan_write_be(u32 val, void __iomem *addr)
{}

static inline u32 flexcan_read_le(void __iomem *addr)
{}

static inline void flexcan_write_le(u32 val, void __iomem *addr)
{}

static struct flexcan_mb __iomem *flexcan_get_mb(const struct flexcan_priv *priv,
						 u8 mb_index)
{}

static int flexcan_low_power_enter_ack(struct flexcan_priv *priv)
{}

static int flexcan_low_power_exit_ack(struct flexcan_priv *priv)
{}

static void flexcan_enable_wakeup_irq(struct flexcan_priv *priv, bool enable)
{}

static int flexcan_stop_mode_enable_scfw(struct flexcan_priv *priv, bool enabled)
{}

static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv)
{}

static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
{}

static inline void flexcan_error_irq_enable(const struct flexcan_priv *priv)
{}

static inline void flexcan_error_irq_disable(const struct flexcan_priv *priv)
{}

static int flexcan_clks_enable(const struct flexcan_priv *priv)
{}

static void flexcan_clks_disable(const struct flexcan_priv *priv)
{}

static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv)
{}

static inline int flexcan_transceiver_disable(const struct flexcan_priv *priv)
{}

static int flexcan_chip_enable(struct flexcan_priv *priv)
{}

static int flexcan_chip_disable(struct flexcan_priv *priv)
{}

static int flexcan_chip_freeze(struct flexcan_priv *priv)
{}

static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
{}

static int flexcan_chip_softreset(struct flexcan_priv *priv)
{}

static int __flexcan_get_berr_counter(const struct net_device *dev,
				      struct can_berr_counter *bec)
{}

static int flexcan_get_berr_counter(const struct net_device *dev,
				    struct can_berr_counter *bec)
{}

static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
{}

static void flexcan_irq_bus_err(struct net_device *dev, u32 reg_esr)
{}

static void flexcan_irq_state(struct net_device *dev, u32 reg_esr)
{}

static inline u64 flexcan_read64_mask(struct flexcan_priv *priv, void __iomem *addr, u64 mask)
{}

static inline void flexcan_write64(struct flexcan_priv *priv, u64 val, void __iomem *addr)
{}

static inline u64 flexcan_read_reg_iflag_rx(struct flexcan_priv *priv)
{}

static inline u64 flexcan_read_reg_iflag_tx(struct flexcan_priv *priv)
{}

static inline struct flexcan_priv *rx_offload_to_priv(struct can_rx_offload *offload)
{}

static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
					    unsigned int n, u32 *timestamp,
					    bool drop)
{}

static irqreturn_t flexcan_irq(int irq, void *dev_id)
{}

static void flexcan_set_bittiming_ctrl(const struct net_device *dev)
{}

static void flexcan_set_bittiming_cbt(const struct net_device *dev)
{}

static void flexcan_set_bittiming(struct net_device *dev)
{}

static void flexcan_ram_init(struct net_device *dev)
{}

static int flexcan_rx_offload_setup(struct net_device *dev)
{}

static void flexcan_chip_interrupts_enable(const struct net_device *dev)
{}

static void flexcan_chip_interrupts_disable(const struct net_device *dev)
{}

/* flexcan_chip_start
 *
 * this functions is entered with clocks enabled
 *
 */
static int flexcan_chip_start(struct net_device *dev)
{}

/* __flexcan_chip_stop
 *
 * this function is entered with clocks enabled
 */
static int __flexcan_chip_stop(struct net_device *dev, bool disable_on_error)
{}

static inline int flexcan_chip_stop_disable_on_error(struct net_device *dev)
{}

static inline int flexcan_chip_stop(struct net_device *dev)
{}

static int flexcan_open(struct net_device *dev)
{}

static int flexcan_close(struct net_device *dev)
{}

static int flexcan_set_mode(struct net_device *dev, enum can_mode mode)
{}

static const struct net_device_ops flexcan_netdev_ops =;

static int register_flexcandev(struct net_device *dev)
{}

static void unregister_flexcandev(struct net_device *dev)
{}

static int flexcan_setup_stop_mode_gpr(struct platform_device *pdev)
{}

static int flexcan_setup_stop_mode_scfw(struct platform_device *pdev)
{}

/* flexcan_setup_stop_mode - Setup stop mode for wakeup
 *
 * Return: = 0 setup stop mode successfully or doesn't support this feature
 *         < 0 fail to setup stop mode (could be deferred probe)
 */
static int flexcan_setup_stop_mode(struct platform_device *pdev)
{}

static const struct of_device_id flexcan_of_match[] =;
MODULE_DEVICE_TABLE(of, flexcan_of_match);

static const struct platform_device_id flexcan_id_table[] =;
MODULE_DEVICE_TABLE(platform, flexcan_id_table);

static int flexcan_probe(struct platform_device *pdev)
{}

static void flexcan_remove(struct platform_device *pdev)
{}

static int __maybe_unused flexcan_suspend(struct device *device)
{}

static int __maybe_unused flexcan_resume(struct device *device)
{}

static int __maybe_unused flexcan_runtime_suspend(struct device *device)
{}

static int __maybe_unused flexcan_runtime_resume(struct device *device)
{}

static int __maybe_unused flexcan_noirq_suspend(struct device *device)
{}

static int __maybe_unused flexcan_noirq_resume(struct device *device)
{}

static const struct dev_pm_ops flexcan_pm_ops =;

static struct platform_driver flexcan_driver =;

module_platform_driver();

MODULE_AUTHOR();
MODULE_LICENSE();
MODULE_DESCRIPTION();