162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// bxcan.c - STM32 Basic Extended CAN controller driver 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Copyright (c) 2022 Dario Binacchi <dario.binacchi@amarulasolutions.com> 662306a36Sopenharmony_ci// 762306a36Sopenharmony_ci// NOTE: The ST documentation uses the terms master/slave instead of 862306a36Sopenharmony_ci// primary/secondary. 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/bitfield.h> 1362306a36Sopenharmony_ci#include <linux/can.h> 1462306a36Sopenharmony_ci#include <linux/can/dev.h> 1562306a36Sopenharmony_ci#include <linux/can/error.h> 1662306a36Sopenharmony_ci#include <linux/can/rx-offload.h> 1762306a36Sopenharmony_ci#include <linux/clk.h> 1862306a36Sopenharmony_ci#include <linux/ethtool.h> 1962306a36Sopenharmony_ci#include <linux/interrupt.h> 2062306a36Sopenharmony_ci#include <linux/io.h> 2162306a36Sopenharmony_ci#include <linux/iopoll.h> 2262306a36Sopenharmony_ci#include <linux/kernel.h> 2362306a36Sopenharmony_ci#include <linux/mfd/syscon.h> 2462306a36Sopenharmony_ci#include <linux/module.h> 2562306a36Sopenharmony_ci#include <linux/of.h> 2662306a36Sopenharmony_ci#include <linux/platform_device.h> 2762306a36Sopenharmony_ci#include <linux/regmap.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define BXCAN_NAPI_WEIGHT 3 3062306a36Sopenharmony_ci#define BXCAN_TIMEOUT_US 10000 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#define BXCAN_RX_MB_NUM 2 3362306a36Sopenharmony_ci#define BXCAN_TX_MB_NUM 3 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* Primary control register (MCR) bits */ 3662306a36Sopenharmony_ci#define BXCAN_MCR_RESET BIT(15) 3762306a36Sopenharmony_ci#define BXCAN_MCR_TTCM BIT(7) 3862306a36Sopenharmony_ci#define BXCAN_MCR_ABOM BIT(6) 3962306a36Sopenharmony_ci#define BXCAN_MCR_AWUM BIT(5) 4062306a36Sopenharmony_ci#define BXCAN_MCR_NART BIT(4) 4162306a36Sopenharmony_ci#define BXCAN_MCR_RFLM BIT(3) 4262306a36Sopenharmony_ci#define BXCAN_MCR_TXFP BIT(2) 4362306a36Sopenharmony_ci#define BXCAN_MCR_SLEEP BIT(1) 4462306a36Sopenharmony_ci#define BXCAN_MCR_INRQ BIT(0) 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* Primary status register (MSR) bits */ 4762306a36Sopenharmony_ci#define BXCAN_MSR_ERRI BIT(2) 4862306a36Sopenharmony_ci#define BXCAN_MSR_SLAK BIT(1) 4962306a36Sopenharmony_ci#define BXCAN_MSR_INAK BIT(0) 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/* Transmit status register (TSR) bits */ 5262306a36Sopenharmony_ci#define BXCAN_TSR_RQCP2 BIT(16) 5362306a36Sopenharmony_ci#define BXCAN_TSR_RQCP1 BIT(8) 5462306a36Sopenharmony_ci#define BXCAN_TSR_RQCP0 BIT(0) 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* Receive FIFO 0 register (RF0R) bits */ 5762306a36Sopenharmony_ci#define BXCAN_RF0R_RFOM0 BIT(5) 5862306a36Sopenharmony_ci#define BXCAN_RF0R_FMP0_MASK GENMASK(1, 0) 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* Interrupt enable register (IER) bits */ 6162306a36Sopenharmony_ci#define BXCAN_IER_SLKIE BIT(17) 6262306a36Sopenharmony_ci#define BXCAN_IER_WKUIE BIT(16) 6362306a36Sopenharmony_ci#define BXCAN_IER_ERRIE BIT(15) 6462306a36Sopenharmony_ci#define BXCAN_IER_LECIE BIT(11) 6562306a36Sopenharmony_ci#define BXCAN_IER_BOFIE BIT(10) 6662306a36Sopenharmony_ci#define BXCAN_IER_EPVIE BIT(9) 6762306a36Sopenharmony_ci#define BXCAN_IER_EWGIE BIT(8) 6862306a36Sopenharmony_ci#define BXCAN_IER_FOVIE1 BIT(6) 6962306a36Sopenharmony_ci#define BXCAN_IER_FFIE1 BIT(5) 7062306a36Sopenharmony_ci#define BXCAN_IER_FMPIE1 BIT(4) 7162306a36Sopenharmony_ci#define BXCAN_IER_FOVIE0 BIT(3) 7262306a36Sopenharmony_ci#define BXCAN_IER_FFIE0 BIT(2) 7362306a36Sopenharmony_ci#define BXCAN_IER_FMPIE0 BIT(1) 7462306a36Sopenharmony_ci#define BXCAN_IER_TMEIE BIT(0) 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci/* Error status register (ESR) bits */ 7762306a36Sopenharmony_ci#define BXCAN_ESR_REC_MASK GENMASK(31, 24) 7862306a36Sopenharmony_ci#define BXCAN_ESR_TEC_MASK GENMASK(23, 16) 7962306a36Sopenharmony_ci#define BXCAN_ESR_LEC_MASK GENMASK(6, 4) 8062306a36Sopenharmony_ci#define BXCAN_ESR_BOFF BIT(2) 8162306a36Sopenharmony_ci#define BXCAN_ESR_EPVF BIT(1) 8262306a36Sopenharmony_ci#define BXCAN_ESR_EWGF BIT(0) 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci/* Bit timing register (BTR) bits */ 8562306a36Sopenharmony_ci#define BXCAN_BTR_SILM BIT(31) 8662306a36Sopenharmony_ci#define BXCAN_BTR_LBKM BIT(30) 8762306a36Sopenharmony_ci#define BXCAN_BTR_SJW_MASK GENMASK(25, 24) 8862306a36Sopenharmony_ci#define BXCAN_BTR_TS2_MASK GENMASK(22, 20) 8962306a36Sopenharmony_ci#define BXCAN_BTR_TS1_MASK GENMASK(19, 16) 9062306a36Sopenharmony_ci#define BXCAN_BTR_BRP_MASK GENMASK(9, 0) 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci/* TX mailbox identifier register (TIxR, x = 0..2) bits */ 9362306a36Sopenharmony_ci#define BXCAN_TIxR_STID_MASK GENMASK(31, 21) 9462306a36Sopenharmony_ci#define BXCAN_TIxR_EXID_MASK GENMASK(31, 3) 9562306a36Sopenharmony_ci#define BXCAN_TIxR_IDE BIT(2) 9662306a36Sopenharmony_ci#define BXCAN_TIxR_RTR BIT(1) 9762306a36Sopenharmony_ci#define BXCAN_TIxR_TXRQ BIT(0) 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci/* TX mailbox data length and time stamp register (TDTxR, x = 0..2 bits */ 10062306a36Sopenharmony_ci#define BXCAN_TDTxR_DLC_MASK GENMASK(3, 0) 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci/* RX FIFO mailbox identifier register (RIxR, x = 0..1 */ 10362306a36Sopenharmony_ci#define BXCAN_RIxR_STID_MASK GENMASK(31, 21) 10462306a36Sopenharmony_ci#define BXCAN_RIxR_EXID_MASK GENMASK(31, 3) 10562306a36Sopenharmony_ci#define BXCAN_RIxR_IDE BIT(2) 10662306a36Sopenharmony_ci#define BXCAN_RIxR_RTR BIT(1) 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/* RX FIFO mailbox data length and timestamp register (RDTxR, x = 0..1) bits */ 10962306a36Sopenharmony_ci#define BXCAN_RDTxR_TIME_MASK GENMASK(31, 16) 11062306a36Sopenharmony_ci#define BXCAN_RDTxR_DLC_MASK GENMASK(3, 0) 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#define BXCAN_FMR_REG 0x00 11362306a36Sopenharmony_ci#define BXCAN_FM1R_REG 0x04 11462306a36Sopenharmony_ci#define BXCAN_FS1R_REG 0x0c 11562306a36Sopenharmony_ci#define BXCAN_FFA1R_REG 0x14 11662306a36Sopenharmony_ci#define BXCAN_FA1R_REG 0x1c 11762306a36Sopenharmony_ci#define BXCAN_FiR1_REG(b) (0x40 + (b) * 8) 11862306a36Sopenharmony_ci#define BXCAN_FiR2_REG(b) (0x44 + (b) * 8) 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#define BXCAN_FILTER_ID(cfg) ((cfg) == BXCAN_CFG_DUAL_SECONDARY ? 14 : 0) 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci/* Filter primary register (FMR) bits */ 12362306a36Sopenharmony_ci#define BXCAN_FMR_CANSB_MASK GENMASK(13, 8) 12462306a36Sopenharmony_ci#define BXCAN_FMR_FINIT BIT(0) 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cienum bxcan_lec_code { 12762306a36Sopenharmony_ci BXCAN_LEC_NO_ERROR = 0, 12862306a36Sopenharmony_ci BXCAN_LEC_STUFF_ERROR, 12962306a36Sopenharmony_ci BXCAN_LEC_FORM_ERROR, 13062306a36Sopenharmony_ci BXCAN_LEC_ACK_ERROR, 13162306a36Sopenharmony_ci BXCAN_LEC_BIT1_ERROR, 13262306a36Sopenharmony_ci BXCAN_LEC_BIT0_ERROR, 13362306a36Sopenharmony_ci BXCAN_LEC_CRC_ERROR, 13462306a36Sopenharmony_ci BXCAN_LEC_UNUSED 13562306a36Sopenharmony_ci}; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cienum bxcan_cfg { 13862306a36Sopenharmony_ci BXCAN_CFG_SINGLE = 0, 13962306a36Sopenharmony_ci BXCAN_CFG_DUAL_PRIMARY, 14062306a36Sopenharmony_ci BXCAN_CFG_DUAL_SECONDARY 14162306a36Sopenharmony_ci}; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci/* Structure of the message buffer */ 14462306a36Sopenharmony_cistruct bxcan_mb { 14562306a36Sopenharmony_ci u32 id; /* can identifier */ 14662306a36Sopenharmony_ci u32 dlc; /* data length control and timestamp */ 14762306a36Sopenharmony_ci u32 data[2]; /* data */ 14862306a36Sopenharmony_ci}; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci/* Structure of the hardware registers */ 15162306a36Sopenharmony_cistruct bxcan_regs { 15262306a36Sopenharmony_ci u32 mcr; /* 0x00 - primary control */ 15362306a36Sopenharmony_ci u32 msr; /* 0x04 - primary status */ 15462306a36Sopenharmony_ci u32 tsr; /* 0x08 - transmit status */ 15562306a36Sopenharmony_ci u32 rf0r; /* 0x0c - FIFO 0 */ 15662306a36Sopenharmony_ci u32 rf1r; /* 0x10 - FIFO 1 */ 15762306a36Sopenharmony_ci u32 ier; /* 0x14 - interrupt enable */ 15862306a36Sopenharmony_ci u32 esr; /* 0x18 - error status */ 15962306a36Sopenharmony_ci u32 btr; /* 0x1c - bit timing*/ 16062306a36Sopenharmony_ci u32 reserved0[88]; /* 0x20 */ 16162306a36Sopenharmony_ci struct bxcan_mb tx_mb[BXCAN_TX_MB_NUM]; /* 0x180 - tx mailbox */ 16262306a36Sopenharmony_ci struct bxcan_mb rx_mb[BXCAN_RX_MB_NUM]; /* 0x1b0 - rx mailbox */ 16362306a36Sopenharmony_ci}; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistruct bxcan_priv { 16662306a36Sopenharmony_ci struct can_priv can; 16762306a36Sopenharmony_ci struct can_rx_offload offload; 16862306a36Sopenharmony_ci struct device *dev; 16962306a36Sopenharmony_ci struct net_device *ndev; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci struct bxcan_regs __iomem *regs; 17262306a36Sopenharmony_ci struct regmap *gcan; 17362306a36Sopenharmony_ci int tx_irq; 17462306a36Sopenharmony_ci int sce_irq; 17562306a36Sopenharmony_ci enum bxcan_cfg cfg; 17662306a36Sopenharmony_ci struct clk *clk; 17762306a36Sopenharmony_ci spinlock_t rmw_lock; /* lock for read-modify-write operations */ 17862306a36Sopenharmony_ci unsigned int tx_head; 17962306a36Sopenharmony_ci unsigned int tx_tail; 18062306a36Sopenharmony_ci u32 timestamp; 18162306a36Sopenharmony_ci}; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic const struct can_bittiming_const bxcan_bittiming_const = { 18462306a36Sopenharmony_ci .name = KBUILD_MODNAME, 18562306a36Sopenharmony_ci .tseg1_min = 1, 18662306a36Sopenharmony_ci .tseg1_max = 16, 18762306a36Sopenharmony_ci .tseg2_min = 1, 18862306a36Sopenharmony_ci .tseg2_max = 8, 18962306a36Sopenharmony_ci .sjw_max = 4, 19062306a36Sopenharmony_ci .brp_min = 1, 19162306a36Sopenharmony_ci .brp_max = 1024, 19262306a36Sopenharmony_ci .brp_inc = 1, 19362306a36Sopenharmony_ci}; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistatic inline void bxcan_rmw(struct bxcan_priv *priv, void __iomem *addr, 19662306a36Sopenharmony_ci u32 clear, u32 set) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci unsigned long flags; 19962306a36Sopenharmony_ci u32 old, val; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci spin_lock_irqsave(&priv->rmw_lock, flags); 20262306a36Sopenharmony_ci old = readl(addr); 20362306a36Sopenharmony_ci val = (old & ~clear) | set; 20462306a36Sopenharmony_ci if (val != old) 20562306a36Sopenharmony_ci writel(val, addr); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->rmw_lock, flags); 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistatic void bxcan_disable_filters(struct bxcan_priv *priv, enum bxcan_cfg cfg) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci unsigned int fid = BXCAN_FILTER_ID(cfg); 21362306a36Sopenharmony_ci u32 fmask = BIT(fid); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci regmap_update_bits(priv->gcan, BXCAN_FA1R_REG, fmask, 0); 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_cistatic void bxcan_enable_filters(struct bxcan_priv *priv, enum bxcan_cfg cfg) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci unsigned int fid = BXCAN_FILTER_ID(cfg); 22162306a36Sopenharmony_ci u32 fmask = BIT(fid); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci /* Filter settings: 22462306a36Sopenharmony_ci * 22562306a36Sopenharmony_ci * Accept all messages. 22662306a36Sopenharmony_ci * Assign filter 0 to CAN1 and filter 14 to CAN2 in identifier 22762306a36Sopenharmony_ci * mask mode with 32 bits width. 22862306a36Sopenharmony_ci */ 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci /* Enter filter initialization mode and assing filters to CAN 23162306a36Sopenharmony_ci * controllers. 23262306a36Sopenharmony_ci */ 23362306a36Sopenharmony_ci regmap_update_bits(priv->gcan, BXCAN_FMR_REG, 23462306a36Sopenharmony_ci BXCAN_FMR_CANSB_MASK | BXCAN_FMR_FINIT, 23562306a36Sopenharmony_ci FIELD_PREP(BXCAN_FMR_CANSB_MASK, 14) | 23662306a36Sopenharmony_ci BXCAN_FMR_FINIT); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci /* Deactivate filter */ 23962306a36Sopenharmony_ci regmap_update_bits(priv->gcan, BXCAN_FA1R_REG, fmask, 0); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci /* Two 32-bit registers in identifier mask mode */ 24262306a36Sopenharmony_ci regmap_update_bits(priv->gcan, BXCAN_FM1R_REG, fmask, 0); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci /* Single 32-bit scale configuration */ 24562306a36Sopenharmony_ci regmap_update_bits(priv->gcan, BXCAN_FS1R_REG, fmask, fmask); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci /* Assign filter to FIFO 0 */ 24862306a36Sopenharmony_ci regmap_update_bits(priv->gcan, BXCAN_FFA1R_REG, fmask, 0); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci /* Accept all messages */ 25162306a36Sopenharmony_ci regmap_write(priv->gcan, BXCAN_FiR1_REG(fid), 0); 25262306a36Sopenharmony_ci regmap_write(priv->gcan, BXCAN_FiR2_REG(fid), 0); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* Activate filter */ 25562306a36Sopenharmony_ci regmap_update_bits(priv->gcan, BXCAN_FA1R_REG, fmask, fmask); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci /* Exit filter initialization mode */ 25862306a36Sopenharmony_ci regmap_update_bits(priv->gcan, BXCAN_FMR_REG, BXCAN_FMR_FINIT, 0); 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic inline u8 bxcan_get_tx_head(const struct bxcan_priv *priv) 26262306a36Sopenharmony_ci{ 26362306a36Sopenharmony_ci return priv->tx_head % BXCAN_TX_MB_NUM; 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic inline u8 bxcan_get_tx_tail(const struct bxcan_priv *priv) 26762306a36Sopenharmony_ci{ 26862306a36Sopenharmony_ci return priv->tx_tail % BXCAN_TX_MB_NUM; 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cistatic inline u8 bxcan_get_tx_free(const struct bxcan_priv *priv) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci return BXCAN_TX_MB_NUM - (priv->tx_head - priv->tx_tail); 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cistatic bool bxcan_tx_busy(const struct bxcan_priv *priv) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci if (bxcan_get_tx_free(priv) > 0) 27962306a36Sopenharmony_ci return false; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci netif_stop_queue(priv->ndev); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci /* Memory barrier before checking tx_free (head and tail) */ 28462306a36Sopenharmony_ci smp_mb(); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci if (bxcan_get_tx_free(priv) == 0) { 28762306a36Sopenharmony_ci netdev_dbg(priv->ndev, 28862306a36Sopenharmony_ci "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, len=%d).\n", 28962306a36Sopenharmony_ci priv->tx_head, priv->tx_tail, 29062306a36Sopenharmony_ci priv->tx_head - priv->tx_tail); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci return true; 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci netif_start_queue(priv->ndev); 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci return false; 29862306a36Sopenharmony_ci} 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_cistatic int bxcan_chip_softreset(struct bxcan_priv *priv) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci struct bxcan_regs __iomem *regs = priv->regs; 30362306a36Sopenharmony_ci u32 value; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci bxcan_rmw(priv, ®s->mcr, 0, BXCAN_MCR_RESET); 30662306a36Sopenharmony_ci return readx_poll_timeout(readl, ®s->msr, value, 30762306a36Sopenharmony_ci value & BXCAN_MSR_SLAK, BXCAN_TIMEOUT_US, 30862306a36Sopenharmony_ci USEC_PER_SEC); 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cistatic int bxcan_enter_init_mode(struct bxcan_priv *priv) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci struct bxcan_regs __iomem *regs = priv->regs; 31462306a36Sopenharmony_ci u32 value; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci bxcan_rmw(priv, ®s->mcr, 0, BXCAN_MCR_INRQ); 31762306a36Sopenharmony_ci return readx_poll_timeout(readl, ®s->msr, value, 31862306a36Sopenharmony_ci value & BXCAN_MSR_INAK, BXCAN_TIMEOUT_US, 31962306a36Sopenharmony_ci USEC_PER_SEC); 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic int bxcan_leave_init_mode(struct bxcan_priv *priv) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci struct bxcan_regs __iomem *regs = priv->regs; 32562306a36Sopenharmony_ci u32 value; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci bxcan_rmw(priv, ®s->mcr, BXCAN_MCR_INRQ, 0); 32862306a36Sopenharmony_ci return readx_poll_timeout(readl, ®s->msr, value, 32962306a36Sopenharmony_ci !(value & BXCAN_MSR_INAK), BXCAN_TIMEOUT_US, 33062306a36Sopenharmony_ci USEC_PER_SEC); 33162306a36Sopenharmony_ci} 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_cistatic int bxcan_enter_sleep_mode(struct bxcan_priv *priv) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci struct bxcan_regs __iomem *regs = priv->regs; 33662306a36Sopenharmony_ci u32 value; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci bxcan_rmw(priv, ®s->mcr, 0, BXCAN_MCR_SLEEP); 33962306a36Sopenharmony_ci return readx_poll_timeout(readl, ®s->msr, value, 34062306a36Sopenharmony_ci value & BXCAN_MSR_SLAK, BXCAN_TIMEOUT_US, 34162306a36Sopenharmony_ci USEC_PER_SEC); 34262306a36Sopenharmony_ci} 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistatic int bxcan_leave_sleep_mode(struct bxcan_priv *priv) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci struct bxcan_regs __iomem *regs = priv->regs; 34762306a36Sopenharmony_ci u32 value; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci bxcan_rmw(priv, ®s->mcr, BXCAN_MCR_SLEEP, 0); 35062306a36Sopenharmony_ci return readx_poll_timeout(readl, ®s->msr, value, 35162306a36Sopenharmony_ci !(value & BXCAN_MSR_SLAK), BXCAN_TIMEOUT_US, 35262306a36Sopenharmony_ci USEC_PER_SEC); 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic inline 35662306a36Sopenharmony_cistruct bxcan_priv *rx_offload_to_priv(struct can_rx_offload *offload) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci return container_of(offload, struct bxcan_priv, offload); 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_cistatic struct sk_buff *bxcan_mailbox_read(struct can_rx_offload *offload, 36262306a36Sopenharmony_ci unsigned int mbxno, u32 *timestamp, 36362306a36Sopenharmony_ci bool drop) 36462306a36Sopenharmony_ci{ 36562306a36Sopenharmony_ci struct bxcan_priv *priv = rx_offload_to_priv(offload); 36662306a36Sopenharmony_ci struct bxcan_regs __iomem *regs = priv->regs; 36762306a36Sopenharmony_ci struct bxcan_mb __iomem *mb_regs = ®s->rx_mb[0]; 36862306a36Sopenharmony_ci struct sk_buff *skb = NULL; 36962306a36Sopenharmony_ci struct can_frame *cf; 37062306a36Sopenharmony_ci u32 rf0r, id, dlc; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci rf0r = readl(®s->rf0r); 37362306a36Sopenharmony_ci if (unlikely(drop)) { 37462306a36Sopenharmony_ci skb = ERR_PTR(-ENOBUFS); 37562306a36Sopenharmony_ci goto mark_as_read; 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci if (!(rf0r & BXCAN_RF0R_FMP0_MASK)) 37962306a36Sopenharmony_ci goto mark_as_read; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci skb = alloc_can_skb(offload->dev, &cf); 38262306a36Sopenharmony_ci if (unlikely(!skb)) { 38362306a36Sopenharmony_ci skb = ERR_PTR(-ENOMEM); 38462306a36Sopenharmony_ci goto mark_as_read; 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci id = readl(&mb_regs->id); 38862306a36Sopenharmony_ci if (id & BXCAN_RIxR_IDE) 38962306a36Sopenharmony_ci cf->can_id = FIELD_GET(BXCAN_RIxR_EXID_MASK, id) | CAN_EFF_FLAG; 39062306a36Sopenharmony_ci else 39162306a36Sopenharmony_ci cf->can_id = FIELD_GET(BXCAN_RIxR_STID_MASK, id) & CAN_SFF_MASK; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci dlc = readl(&mb_regs->dlc); 39462306a36Sopenharmony_ci priv->timestamp = FIELD_GET(BXCAN_RDTxR_TIME_MASK, dlc); 39562306a36Sopenharmony_ci cf->len = can_cc_dlc2len(FIELD_GET(BXCAN_RDTxR_DLC_MASK, dlc)); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci if (id & BXCAN_RIxR_RTR) { 39862306a36Sopenharmony_ci cf->can_id |= CAN_RTR_FLAG; 39962306a36Sopenharmony_ci } else { 40062306a36Sopenharmony_ci int i, j; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci for (i = 0, j = 0; i < cf->len; i += 4, j++) 40362306a36Sopenharmony_ci *(u32 *)(cf->data + i) = readl(&mb_regs->data[j]); 40462306a36Sopenharmony_ci } 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci mark_as_read: 40762306a36Sopenharmony_ci rf0r |= BXCAN_RF0R_RFOM0; 40862306a36Sopenharmony_ci writel(rf0r, ®s->rf0r); 40962306a36Sopenharmony_ci return skb; 41062306a36Sopenharmony_ci} 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_cistatic irqreturn_t bxcan_rx_isr(int irq, void *dev_id) 41362306a36Sopenharmony_ci{ 41462306a36Sopenharmony_ci struct net_device *ndev = dev_id; 41562306a36Sopenharmony_ci struct bxcan_priv *priv = netdev_priv(ndev); 41662306a36Sopenharmony_ci struct bxcan_regs __iomem *regs = priv->regs; 41762306a36Sopenharmony_ci u32 rf0r; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci rf0r = readl(®s->rf0r); 42062306a36Sopenharmony_ci if (!(rf0r & BXCAN_RF0R_FMP0_MASK)) 42162306a36Sopenharmony_ci return IRQ_NONE; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci can_rx_offload_irq_offload_fifo(&priv->offload); 42462306a36Sopenharmony_ci can_rx_offload_irq_finish(&priv->offload); 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci return IRQ_HANDLED; 42762306a36Sopenharmony_ci} 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_cistatic irqreturn_t bxcan_tx_isr(int irq, void *dev_id) 43062306a36Sopenharmony_ci{ 43162306a36Sopenharmony_ci struct net_device *ndev = dev_id; 43262306a36Sopenharmony_ci struct bxcan_priv *priv = netdev_priv(ndev); 43362306a36Sopenharmony_ci struct bxcan_regs __iomem *regs = priv->regs; 43462306a36Sopenharmony_ci struct net_device_stats *stats = &ndev->stats; 43562306a36Sopenharmony_ci u32 tsr, rqcp_bit; 43662306a36Sopenharmony_ci int idx; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci tsr = readl(®s->tsr); 43962306a36Sopenharmony_ci if (!(tsr & (BXCAN_TSR_RQCP0 | BXCAN_TSR_RQCP1 | BXCAN_TSR_RQCP2))) 44062306a36Sopenharmony_ci return IRQ_NONE; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci while (priv->tx_head - priv->tx_tail > 0) { 44362306a36Sopenharmony_ci idx = bxcan_get_tx_tail(priv); 44462306a36Sopenharmony_ci rqcp_bit = BXCAN_TSR_RQCP0 << (idx << 3); 44562306a36Sopenharmony_ci if (!(tsr & rqcp_bit)) 44662306a36Sopenharmony_ci break; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci stats->tx_packets++; 44962306a36Sopenharmony_ci stats->tx_bytes += can_get_echo_skb(ndev, idx, NULL); 45062306a36Sopenharmony_ci priv->tx_tail++; 45162306a36Sopenharmony_ci } 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci writel(tsr, ®s->tsr); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci if (bxcan_get_tx_free(priv)) { 45662306a36Sopenharmony_ci /* Make sure that anybody stopping the queue after 45762306a36Sopenharmony_ci * this sees the new tx_ring->tail. 45862306a36Sopenharmony_ci */ 45962306a36Sopenharmony_ci smp_mb(); 46062306a36Sopenharmony_ci netif_wake_queue(ndev); 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci return IRQ_HANDLED; 46462306a36Sopenharmony_ci} 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_cistatic void bxcan_handle_state_change(struct net_device *ndev, u32 esr) 46762306a36Sopenharmony_ci{ 46862306a36Sopenharmony_ci struct bxcan_priv *priv = netdev_priv(ndev); 46962306a36Sopenharmony_ci enum can_state new_state = priv->can.state; 47062306a36Sopenharmony_ci struct can_berr_counter bec; 47162306a36Sopenharmony_ci enum can_state rx_state, tx_state; 47262306a36Sopenharmony_ci struct sk_buff *skb; 47362306a36Sopenharmony_ci struct can_frame *cf; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci /* Early exit if no error flag is set */ 47662306a36Sopenharmony_ci if (!(esr & (BXCAN_ESR_EWGF | BXCAN_ESR_EPVF | BXCAN_ESR_BOFF))) 47762306a36Sopenharmony_ci return; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci bec.txerr = FIELD_GET(BXCAN_ESR_TEC_MASK, esr); 48062306a36Sopenharmony_ci bec.rxerr = FIELD_GET(BXCAN_ESR_REC_MASK, esr); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci if (esr & BXCAN_ESR_BOFF) 48362306a36Sopenharmony_ci new_state = CAN_STATE_BUS_OFF; 48462306a36Sopenharmony_ci else if (esr & BXCAN_ESR_EPVF) 48562306a36Sopenharmony_ci new_state = CAN_STATE_ERROR_PASSIVE; 48662306a36Sopenharmony_ci else if (esr & BXCAN_ESR_EWGF) 48762306a36Sopenharmony_ci new_state = CAN_STATE_ERROR_WARNING; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci /* state hasn't changed */ 49062306a36Sopenharmony_ci if (unlikely(new_state == priv->can.state)) 49162306a36Sopenharmony_ci return; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci skb = alloc_can_err_skb(ndev, &cf); 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci tx_state = bec.txerr >= bec.rxerr ? new_state : 0; 49662306a36Sopenharmony_ci rx_state = bec.txerr <= bec.rxerr ? new_state : 0; 49762306a36Sopenharmony_ci can_change_state(ndev, cf, tx_state, rx_state); 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci if (new_state == CAN_STATE_BUS_OFF) { 50062306a36Sopenharmony_ci can_bus_off(ndev); 50162306a36Sopenharmony_ci } else if (skb) { 50262306a36Sopenharmony_ci cf->can_id |= CAN_ERR_CNT; 50362306a36Sopenharmony_ci cf->data[6] = bec.txerr; 50462306a36Sopenharmony_ci cf->data[7] = bec.rxerr; 50562306a36Sopenharmony_ci } 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci if (skb) { 50862306a36Sopenharmony_ci int err; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci err = can_rx_offload_queue_timestamp(&priv->offload, skb, 51162306a36Sopenharmony_ci priv->timestamp); 51262306a36Sopenharmony_ci if (err) 51362306a36Sopenharmony_ci ndev->stats.rx_fifo_errors++; 51462306a36Sopenharmony_ci } 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cistatic void bxcan_handle_bus_err(struct net_device *ndev, u32 esr) 51862306a36Sopenharmony_ci{ 51962306a36Sopenharmony_ci struct bxcan_priv *priv = netdev_priv(ndev); 52062306a36Sopenharmony_ci enum bxcan_lec_code lec_code; 52162306a36Sopenharmony_ci struct can_frame *cf; 52262306a36Sopenharmony_ci struct sk_buff *skb; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci lec_code = FIELD_GET(BXCAN_ESR_LEC_MASK, esr); 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci /* Early exit if no lec update or no error. 52762306a36Sopenharmony_ci * No lec update means that no CAN bus event has been detected 52862306a36Sopenharmony_ci * since CPU wrote BXCAN_LEC_UNUSED value to status reg. 52962306a36Sopenharmony_ci */ 53062306a36Sopenharmony_ci if (lec_code == BXCAN_LEC_UNUSED || lec_code == BXCAN_LEC_NO_ERROR) 53162306a36Sopenharmony_ci return; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci /* Common for all type of bus errors */ 53462306a36Sopenharmony_ci priv->can.can_stats.bus_error++; 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci /* Propagate the error condition to the CAN stack */ 53762306a36Sopenharmony_ci skb = alloc_can_err_skb(ndev, &cf); 53862306a36Sopenharmony_ci if (skb) 53962306a36Sopenharmony_ci cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci switch (lec_code) { 54262306a36Sopenharmony_ci case BXCAN_LEC_STUFF_ERROR: 54362306a36Sopenharmony_ci netdev_dbg(ndev, "Stuff error\n"); 54462306a36Sopenharmony_ci ndev->stats.rx_errors++; 54562306a36Sopenharmony_ci if (skb) 54662306a36Sopenharmony_ci cf->data[2] |= CAN_ERR_PROT_STUFF; 54762306a36Sopenharmony_ci break; 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci case BXCAN_LEC_FORM_ERROR: 55062306a36Sopenharmony_ci netdev_dbg(ndev, "Form error\n"); 55162306a36Sopenharmony_ci ndev->stats.rx_errors++; 55262306a36Sopenharmony_ci if (skb) 55362306a36Sopenharmony_ci cf->data[2] |= CAN_ERR_PROT_FORM; 55462306a36Sopenharmony_ci break; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci case BXCAN_LEC_ACK_ERROR: 55762306a36Sopenharmony_ci netdev_dbg(ndev, "Ack error\n"); 55862306a36Sopenharmony_ci ndev->stats.tx_errors++; 55962306a36Sopenharmony_ci if (skb) { 56062306a36Sopenharmony_ci cf->can_id |= CAN_ERR_ACK; 56162306a36Sopenharmony_ci cf->data[3] = CAN_ERR_PROT_LOC_ACK; 56262306a36Sopenharmony_ci } 56362306a36Sopenharmony_ci break; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci case BXCAN_LEC_BIT1_ERROR: 56662306a36Sopenharmony_ci netdev_dbg(ndev, "Bit error (recessive)\n"); 56762306a36Sopenharmony_ci ndev->stats.tx_errors++; 56862306a36Sopenharmony_ci if (skb) 56962306a36Sopenharmony_ci cf->data[2] |= CAN_ERR_PROT_BIT1; 57062306a36Sopenharmony_ci break; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci case BXCAN_LEC_BIT0_ERROR: 57362306a36Sopenharmony_ci netdev_dbg(ndev, "Bit error (dominant)\n"); 57462306a36Sopenharmony_ci ndev->stats.tx_errors++; 57562306a36Sopenharmony_ci if (skb) 57662306a36Sopenharmony_ci cf->data[2] |= CAN_ERR_PROT_BIT0; 57762306a36Sopenharmony_ci break; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci case BXCAN_LEC_CRC_ERROR: 58062306a36Sopenharmony_ci netdev_dbg(ndev, "CRC error\n"); 58162306a36Sopenharmony_ci ndev->stats.rx_errors++; 58262306a36Sopenharmony_ci if (skb) { 58362306a36Sopenharmony_ci cf->data[2] |= CAN_ERR_PROT_BIT; 58462306a36Sopenharmony_ci cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ; 58562306a36Sopenharmony_ci } 58662306a36Sopenharmony_ci break; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci default: 58962306a36Sopenharmony_ci break; 59062306a36Sopenharmony_ci } 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci if (skb) { 59362306a36Sopenharmony_ci int err; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci err = can_rx_offload_queue_timestamp(&priv->offload, skb, 59662306a36Sopenharmony_ci priv->timestamp); 59762306a36Sopenharmony_ci if (err) 59862306a36Sopenharmony_ci ndev->stats.rx_fifo_errors++; 59962306a36Sopenharmony_ci } 60062306a36Sopenharmony_ci} 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_cistatic irqreturn_t bxcan_state_change_isr(int irq, void *dev_id) 60362306a36Sopenharmony_ci{ 60462306a36Sopenharmony_ci struct net_device *ndev = dev_id; 60562306a36Sopenharmony_ci struct bxcan_priv *priv = netdev_priv(ndev); 60662306a36Sopenharmony_ci struct bxcan_regs __iomem *regs = priv->regs; 60762306a36Sopenharmony_ci u32 msr, esr; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci msr = readl(®s->msr); 61062306a36Sopenharmony_ci if (!(msr & BXCAN_MSR_ERRI)) 61162306a36Sopenharmony_ci return IRQ_NONE; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci esr = readl(®s->esr); 61462306a36Sopenharmony_ci bxcan_handle_state_change(ndev, esr); 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) 61762306a36Sopenharmony_ci bxcan_handle_bus_err(ndev, esr); 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci msr |= BXCAN_MSR_ERRI; 62062306a36Sopenharmony_ci writel(msr, ®s->msr); 62162306a36Sopenharmony_ci can_rx_offload_irq_finish(&priv->offload); 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci return IRQ_HANDLED; 62462306a36Sopenharmony_ci} 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_cistatic int bxcan_chip_start(struct net_device *ndev) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci struct bxcan_priv *priv = netdev_priv(ndev); 62962306a36Sopenharmony_ci struct bxcan_regs __iomem *regs = priv->regs; 63062306a36Sopenharmony_ci struct can_bittiming *bt = &priv->can.bittiming; 63162306a36Sopenharmony_ci u32 clr, set; 63262306a36Sopenharmony_ci int err; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci err = bxcan_chip_softreset(priv); 63562306a36Sopenharmony_ci if (err) { 63662306a36Sopenharmony_ci netdev_err(ndev, "failed to reset chip, error %pe\n", 63762306a36Sopenharmony_ci ERR_PTR(err)); 63862306a36Sopenharmony_ci return err; 63962306a36Sopenharmony_ci } 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci err = bxcan_leave_sleep_mode(priv); 64262306a36Sopenharmony_ci if (err) { 64362306a36Sopenharmony_ci netdev_err(ndev, "failed to leave sleep mode, error %pe\n", 64462306a36Sopenharmony_ci ERR_PTR(err)); 64562306a36Sopenharmony_ci goto failed_leave_sleep; 64662306a36Sopenharmony_ci } 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci err = bxcan_enter_init_mode(priv); 64962306a36Sopenharmony_ci if (err) { 65062306a36Sopenharmony_ci netdev_err(ndev, "failed to enter init mode, error %pe\n", 65162306a36Sopenharmony_ci ERR_PTR(err)); 65262306a36Sopenharmony_ci goto failed_enter_init; 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci /* MCR 65662306a36Sopenharmony_ci * 65762306a36Sopenharmony_ci * select request order priority 65862306a36Sopenharmony_ci * enable time triggered mode 65962306a36Sopenharmony_ci * bus-off state left on sw request 66062306a36Sopenharmony_ci * sleep mode left on sw request 66162306a36Sopenharmony_ci * retransmit automatically on error 66262306a36Sopenharmony_ci * do not lock RX FIFO on overrun 66362306a36Sopenharmony_ci */ 66462306a36Sopenharmony_ci bxcan_rmw(priv, ®s->mcr, 66562306a36Sopenharmony_ci BXCAN_MCR_ABOM | BXCAN_MCR_AWUM | BXCAN_MCR_NART | 66662306a36Sopenharmony_ci BXCAN_MCR_RFLM, BXCAN_MCR_TTCM | BXCAN_MCR_TXFP); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci /* Bit timing register settings */ 66962306a36Sopenharmony_ci set = FIELD_PREP(BXCAN_BTR_BRP_MASK, bt->brp - 1) | 67062306a36Sopenharmony_ci FIELD_PREP(BXCAN_BTR_TS1_MASK, bt->phase_seg1 + 67162306a36Sopenharmony_ci bt->prop_seg - 1) | 67262306a36Sopenharmony_ci FIELD_PREP(BXCAN_BTR_TS2_MASK, bt->phase_seg2 - 1) | 67362306a36Sopenharmony_ci FIELD_PREP(BXCAN_BTR_SJW_MASK, bt->sjw - 1); 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci /* loopback + silent mode put the controller in test mode, 67662306a36Sopenharmony_ci * useful for hot self-test 67762306a36Sopenharmony_ci */ 67862306a36Sopenharmony_ci if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) 67962306a36Sopenharmony_ci set |= BXCAN_BTR_LBKM; 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) 68262306a36Sopenharmony_ci set |= BXCAN_BTR_SILM; 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci bxcan_rmw(priv, ®s->btr, BXCAN_BTR_SILM | BXCAN_BTR_LBKM | 68562306a36Sopenharmony_ci BXCAN_BTR_BRP_MASK | BXCAN_BTR_TS1_MASK | BXCAN_BTR_TS2_MASK | 68662306a36Sopenharmony_ci BXCAN_BTR_SJW_MASK, set); 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci bxcan_enable_filters(priv, priv->cfg); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci /* Clear all internal status */ 69162306a36Sopenharmony_ci priv->tx_head = 0; 69262306a36Sopenharmony_ci priv->tx_tail = 0; 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci err = bxcan_leave_init_mode(priv); 69562306a36Sopenharmony_ci if (err) { 69662306a36Sopenharmony_ci netdev_err(ndev, "failed to leave init mode, error %pe\n", 69762306a36Sopenharmony_ci ERR_PTR(err)); 69862306a36Sopenharmony_ci goto failed_leave_init; 69962306a36Sopenharmony_ci } 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci /* Set a `lec` value so that we can check for updates later */ 70262306a36Sopenharmony_ci bxcan_rmw(priv, ®s->esr, BXCAN_ESR_LEC_MASK, 70362306a36Sopenharmony_ci FIELD_PREP(BXCAN_ESR_LEC_MASK, BXCAN_LEC_UNUSED)); 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci /* IER 70662306a36Sopenharmony_ci * 70762306a36Sopenharmony_ci * Enable interrupt for: 70862306a36Sopenharmony_ci * bus-off 70962306a36Sopenharmony_ci * passive error 71062306a36Sopenharmony_ci * warning error 71162306a36Sopenharmony_ci * last error code 71262306a36Sopenharmony_ci * RX FIFO pending message 71362306a36Sopenharmony_ci * TX mailbox empty 71462306a36Sopenharmony_ci */ 71562306a36Sopenharmony_ci clr = BXCAN_IER_WKUIE | BXCAN_IER_SLKIE | BXCAN_IER_FOVIE1 | 71662306a36Sopenharmony_ci BXCAN_IER_FFIE1 | BXCAN_IER_FMPIE1 | BXCAN_IER_FOVIE0 | 71762306a36Sopenharmony_ci BXCAN_IER_FFIE0; 71862306a36Sopenharmony_ci set = BXCAN_IER_ERRIE | BXCAN_IER_BOFIE | BXCAN_IER_EPVIE | 71962306a36Sopenharmony_ci BXCAN_IER_EWGIE | BXCAN_IER_FMPIE0 | BXCAN_IER_TMEIE; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) 72262306a36Sopenharmony_ci set |= BXCAN_IER_LECIE; 72362306a36Sopenharmony_ci else 72462306a36Sopenharmony_ci clr |= BXCAN_IER_LECIE; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci bxcan_rmw(priv, ®s->ier, clr, set); 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci priv->can.state = CAN_STATE_ERROR_ACTIVE; 72962306a36Sopenharmony_ci return 0; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_cifailed_leave_init: 73262306a36Sopenharmony_cifailed_enter_init: 73362306a36Sopenharmony_cifailed_leave_sleep: 73462306a36Sopenharmony_ci bxcan_chip_softreset(priv); 73562306a36Sopenharmony_ci return err; 73662306a36Sopenharmony_ci} 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_cistatic int bxcan_open(struct net_device *ndev) 73962306a36Sopenharmony_ci{ 74062306a36Sopenharmony_ci struct bxcan_priv *priv = netdev_priv(ndev); 74162306a36Sopenharmony_ci int err; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci err = clk_prepare_enable(priv->clk); 74462306a36Sopenharmony_ci if (err) { 74562306a36Sopenharmony_ci netdev_err(ndev, "failed to enable clock, error %pe\n", 74662306a36Sopenharmony_ci ERR_PTR(err)); 74762306a36Sopenharmony_ci return err; 74862306a36Sopenharmony_ci } 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci err = open_candev(ndev); 75162306a36Sopenharmony_ci if (err) { 75262306a36Sopenharmony_ci netdev_err(ndev, "open_candev() failed, error %pe\n", 75362306a36Sopenharmony_ci ERR_PTR(err)); 75462306a36Sopenharmony_ci goto out_disable_clock; 75562306a36Sopenharmony_ci } 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci can_rx_offload_enable(&priv->offload); 75862306a36Sopenharmony_ci err = request_irq(ndev->irq, bxcan_rx_isr, IRQF_SHARED, ndev->name, 75962306a36Sopenharmony_ci ndev); 76062306a36Sopenharmony_ci if (err) { 76162306a36Sopenharmony_ci netdev_err(ndev, "failed to register rx irq(%d), error %pe\n", 76262306a36Sopenharmony_ci ndev->irq, ERR_PTR(err)); 76362306a36Sopenharmony_ci goto out_close_candev; 76462306a36Sopenharmony_ci } 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci err = request_irq(priv->tx_irq, bxcan_tx_isr, IRQF_SHARED, ndev->name, 76762306a36Sopenharmony_ci ndev); 76862306a36Sopenharmony_ci if (err) { 76962306a36Sopenharmony_ci netdev_err(ndev, "failed to register tx irq(%d), error %pe\n", 77062306a36Sopenharmony_ci priv->tx_irq, ERR_PTR(err)); 77162306a36Sopenharmony_ci goto out_free_rx_irq; 77262306a36Sopenharmony_ci } 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci err = request_irq(priv->sce_irq, bxcan_state_change_isr, IRQF_SHARED, 77562306a36Sopenharmony_ci ndev->name, ndev); 77662306a36Sopenharmony_ci if (err) { 77762306a36Sopenharmony_ci netdev_err(ndev, "failed to register sce irq(%d), error %pe\n", 77862306a36Sopenharmony_ci priv->sce_irq, ERR_PTR(err)); 77962306a36Sopenharmony_ci goto out_free_tx_irq; 78062306a36Sopenharmony_ci } 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci err = bxcan_chip_start(ndev); 78362306a36Sopenharmony_ci if (err) 78462306a36Sopenharmony_ci goto out_free_sce_irq; 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci netif_start_queue(ndev); 78762306a36Sopenharmony_ci return 0; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ciout_free_sce_irq: 79062306a36Sopenharmony_ci free_irq(priv->sce_irq, ndev); 79162306a36Sopenharmony_ciout_free_tx_irq: 79262306a36Sopenharmony_ci free_irq(priv->tx_irq, ndev); 79362306a36Sopenharmony_ciout_free_rx_irq: 79462306a36Sopenharmony_ci free_irq(ndev->irq, ndev); 79562306a36Sopenharmony_ciout_close_candev: 79662306a36Sopenharmony_ci can_rx_offload_disable(&priv->offload); 79762306a36Sopenharmony_ci close_candev(ndev); 79862306a36Sopenharmony_ciout_disable_clock: 79962306a36Sopenharmony_ci clk_disable_unprepare(priv->clk); 80062306a36Sopenharmony_ci return err; 80162306a36Sopenharmony_ci} 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_cistatic void bxcan_chip_stop(struct net_device *ndev) 80462306a36Sopenharmony_ci{ 80562306a36Sopenharmony_ci struct bxcan_priv *priv = netdev_priv(ndev); 80662306a36Sopenharmony_ci struct bxcan_regs __iomem *regs = priv->regs; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci /* disable all interrupts */ 80962306a36Sopenharmony_ci bxcan_rmw(priv, ®s->ier, BXCAN_IER_SLKIE | BXCAN_IER_WKUIE | 81062306a36Sopenharmony_ci BXCAN_IER_ERRIE | BXCAN_IER_LECIE | BXCAN_IER_BOFIE | 81162306a36Sopenharmony_ci BXCAN_IER_EPVIE | BXCAN_IER_EWGIE | BXCAN_IER_FOVIE1 | 81262306a36Sopenharmony_ci BXCAN_IER_FFIE1 | BXCAN_IER_FMPIE1 | BXCAN_IER_FOVIE0 | 81362306a36Sopenharmony_ci BXCAN_IER_FFIE0 | BXCAN_IER_FMPIE0 | BXCAN_IER_TMEIE, 0); 81462306a36Sopenharmony_ci bxcan_disable_filters(priv, priv->cfg); 81562306a36Sopenharmony_ci bxcan_enter_sleep_mode(priv); 81662306a36Sopenharmony_ci priv->can.state = CAN_STATE_STOPPED; 81762306a36Sopenharmony_ci} 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_cistatic int bxcan_stop(struct net_device *ndev) 82062306a36Sopenharmony_ci{ 82162306a36Sopenharmony_ci struct bxcan_priv *priv = netdev_priv(ndev); 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci netif_stop_queue(ndev); 82462306a36Sopenharmony_ci bxcan_chip_stop(ndev); 82562306a36Sopenharmony_ci free_irq(ndev->irq, ndev); 82662306a36Sopenharmony_ci free_irq(priv->tx_irq, ndev); 82762306a36Sopenharmony_ci free_irq(priv->sce_irq, ndev); 82862306a36Sopenharmony_ci can_rx_offload_disable(&priv->offload); 82962306a36Sopenharmony_ci close_candev(ndev); 83062306a36Sopenharmony_ci clk_disable_unprepare(priv->clk); 83162306a36Sopenharmony_ci return 0; 83262306a36Sopenharmony_ci} 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_cistatic netdev_tx_t bxcan_start_xmit(struct sk_buff *skb, 83562306a36Sopenharmony_ci struct net_device *ndev) 83662306a36Sopenharmony_ci{ 83762306a36Sopenharmony_ci struct bxcan_priv *priv = netdev_priv(ndev); 83862306a36Sopenharmony_ci struct can_frame *cf = (struct can_frame *)skb->data; 83962306a36Sopenharmony_ci struct bxcan_regs __iomem *regs = priv->regs; 84062306a36Sopenharmony_ci struct bxcan_mb __iomem *mb_regs; 84162306a36Sopenharmony_ci unsigned int idx; 84262306a36Sopenharmony_ci u32 id; 84362306a36Sopenharmony_ci int i, j; 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci if (can_dropped_invalid_skb(ndev, skb)) 84662306a36Sopenharmony_ci return NETDEV_TX_OK; 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci if (bxcan_tx_busy(priv)) 84962306a36Sopenharmony_ci return NETDEV_TX_BUSY; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci idx = bxcan_get_tx_head(priv); 85262306a36Sopenharmony_ci priv->tx_head++; 85362306a36Sopenharmony_ci if (bxcan_get_tx_free(priv) == 0) 85462306a36Sopenharmony_ci netif_stop_queue(ndev); 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci mb_regs = ®s->tx_mb[idx]; 85762306a36Sopenharmony_ci if (cf->can_id & CAN_EFF_FLAG) 85862306a36Sopenharmony_ci id = FIELD_PREP(BXCAN_TIxR_EXID_MASK, cf->can_id) | 85962306a36Sopenharmony_ci BXCAN_TIxR_IDE; 86062306a36Sopenharmony_ci else 86162306a36Sopenharmony_ci id = FIELD_PREP(BXCAN_TIxR_STID_MASK, cf->can_id); 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci if (cf->can_id & CAN_RTR_FLAG) { /* Remote transmission request */ 86462306a36Sopenharmony_ci id |= BXCAN_TIxR_RTR; 86562306a36Sopenharmony_ci } else { 86662306a36Sopenharmony_ci for (i = 0, j = 0; i < cf->len; i += 4, j++) 86762306a36Sopenharmony_ci writel(*(u32 *)(cf->data + i), &mb_regs->data[j]); 86862306a36Sopenharmony_ci } 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci writel(FIELD_PREP(BXCAN_TDTxR_DLC_MASK, cf->len), &mb_regs->dlc); 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci can_put_echo_skb(skb, ndev, idx, 0); 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci /* Start transmission */ 87562306a36Sopenharmony_ci writel(id | BXCAN_TIxR_TXRQ, &mb_regs->id); 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci return NETDEV_TX_OK; 87862306a36Sopenharmony_ci} 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_cistatic const struct net_device_ops bxcan_netdev_ops = { 88162306a36Sopenharmony_ci .ndo_open = bxcan_open, 88262306a36Sopenharmony_ci .ndo_stop = bxcan_stop, 88362306a36Sopenharmony_ci .ndo_start_xmit = bxcan_start_xmit, 88462306a36Sopenharmony_ci .ndo_change_mtu = can_change_mtu, 88562306a36Sopenharmony_ci}; 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_cistatic const struct ethtool_ops bxcan_ethtool_ops = { 88862306a36Sopenharmony_ci .get_ts_info = ethtool_op_get_ts_info, 88962306a36Sopenharmony_ci}; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_cistatic int bxcan_do_set_mode(struct net_device *ndev, enum can_mode mode) 89262306a36Sopenharmony_ci{ 89362306a36Sopenharmony_ci int err; 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci switch (mode) { 89662306a36Sopenharmony_ci case CAN_MODE_START: 89762306a36Sopenharmony_ci err = bxcan_chip_start(ndev); 89862306a36Sopenharmony_ci if (err) 89962306a36Sopenharmony_ci return err; 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci netif_wake_queue(ndev); 90262306a36Sopenharmony_ci break; 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci default: 90562306a36Sopenharmony_ci return -EOPNOTSUPP; 90662306a36Sopenharmony_ci } 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci return 0; 90962306a36Sopenharmony_ci} 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_cistatic int bxcan_get_berr_counter(const struct net_device *ndev, 91262306a36Sopenharmony_ci struct can_berr_counter *bec) 91362306a36Sopenharmony_ci{ 91462306a36Sopenharmony_ci struct bxcan_priv *priv = netdev_priv(ndev); 91562306a36Sopenharmony_ci struct bxcan_regs __iomem *regs = priv->regs; 91662306a36Sopenharmony_ci u32 esr; 91762306a36Sopenharmony_ci int err; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci err = clk_prepare_enable(priv->clk); 92062306a36Sopenharmony_ci if (err) 92162306a36Sopenharmony_ci return err; 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci esr = readl(®s->esr); 92462306a36Sopenharmony_ci bec->txerr = FIELD_GET(BXCAN_ESR_TEC_MASK, esr); 92562306a36Sopenharmony_ci bec->rxerr = FIELD_GET(BXCAN_ESR_REC_MASK, esr); 92662306a36Sopenharmony_ci clk_disable_unprepare(priv->clk); 92762306a36Sopenharmony_ci return 0; 92862306a36Sopenharmony_ci} 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_cistatic int bxcan_probe(struct platform_device *pdev) 93162306a36Sopenharmony_ci{ 93262306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 93362306a36Sopenharmony_ci struct device *dev = &pdev->dev; 93462306a36Sopenharmony_ci struct net_device *ndev; 93562306a36Sopenharmony_ci struct bxcan_priv *priv; 93662306a36Sopenharmony_ci struct clk *clk = NULL; 93762306a36Sopenharmony_ci void __iomem *regs; 93862306a36Sopenharmony_ci struct regmap *gcan; 93962306a36Sopenharmony_ci enum bxcan_cfg cfg; 94062306a36Sopenharmony_ci int err, rx_irq, tx_irq, sce_irq; 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci regs = devm_platform_ioremap_resource(pdev, 0); 94362306a36Sopenharmony_ci if (IS_ERR(regs)) { 94462306a36Sopenharmony_ci dev_err(dev, "failed to get base address\n"); 94562306a36Sopenharmony_ci return PTR_ERR(regs); 94662306a36Sopenharmony_ci } 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci gcan = syscon_regmap_lookup_by_phandle(np, "st,gcan"); 94962306a36Sopenharmony_ci if (IS_ERR(gcan)) { 95062306a36Sopenharmony_ci dev_err(dev, "failed to get shared memory base address\n"); 95162306a36Sopenharmony_ci return PTR_ERR(gcan); 95262306a36Sopenharmony_ci } 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci if (of_property_read_bool(np, "st,can-primary")) 95562306a36Sopenharmony_ci cfg = BXCAN_CFG_DUAL_PRIMARY; 95662306a36Sopenharmony_ci else if (of_property_read_bool(np, "st,can-secondary")) 95762306a36Sopenharmony_ci cfg = BXCAN_CFG_DUAL_SECONDARY; 95862306a36Sopenharmony_ci else 95962306a36Sopenharmony_ci cfg = BXCAN_CFG_SINGLE; 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci clk = devm_clk_get(dev, NULL); 96262306a36Sopenharmony_ci if (IS_ERR(clk)) { 96362306a36Sopenharmony_ci dev_err(dev, "failed to get clock\n"); 96462306a36Sopenharmony_ci return PTR_ERR(clk); 96562306a36Sopenharmony_ci } 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci rx_irq = platform_get_irq_byname(pdev, "rx0"); 96862306a36Sopenharmony_ci if (rx_irq < 0) 96962306a36Sopenharmony_ci return rx_irq; 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci tx_irq = platform_get_irq_byname(pdev, "tx"); 97262306a36Sopenharmony_ci if (tx_irq < 0) 97362306a36Sopenharmony_ci return tx_irq; 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci sce_irq = platform_get_irq_byname(pdev, "sce"); 97662306a36Sopenharmony_ci if (sce_irq < 0) 97762306a36Sopenharmony_ci return sce_irq; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci ndev = alloc_candev(sizeof(struct bxcan_priv), BXCAN_TX_MB_NUM); 98062306a36Sopenharmony_ci if (!ndev) { 98162306a36Sopenharmony_ci dev_err(dev, "alloc_candev() failed\n"); 98262306a36Sopenharmony_ci return -ENOMEM; 98362306a36Sopenharmony_ci } 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci priv = netdev_priv(ndev); 98662306a36Sopenharmony_ci platform_set_drvdata(pdev, ndev); 98762306a36Sopenharmony_ci SET_NETDEV_DEV(ndev, dev); 98862306a36Sopenharmony_ci ndev->netdev_ops = &bxcan_netdev_ops; 98962306a36Sopenharmony_ci ndev->ethtool_ops = &bxcan_ethtool_ops; 99062306a36Sopenharmony_ci ndev->irq = rx_irq; 99162306a36Sopenharmony_ci ndev->flags |= IFF_ECHO; 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci priv->dev = dev; 99462306a36Sopenharmony_ci priv->ndev = ndev; 99562306a36Sopenharmony_ci priv->regs = regs; 99662306a36Sopenharmony_ci priv->gcan = gcan; 99762306a36Sopenharmony_ci priv->clk = clk; 99862306a36Sopenharmony_ci priv->tx_irq = tx_irq; 99962306a36Sopenharmony_ci priv->sce_irq = sce_irq; 100062306a36Sopenharmony_ci priv->cfg = cfg; 100162306a36Sopenharmony_ci priv->can.clock.freq = clk_get_rate(clk); 100262306a36Sopenharmony_ci spin_lock_init(&priv->rmw_lock); 100362306a36Sopenharmony_ci priv->tx_head = 0; 100462306a36Sopenharmony_ci priv->tx_tail = 0; 100562306a36Sopenharmony_ci priv->can.bittiming_const = &bxcan_bittiming_const; 100662306a36Sopenharmony_ci priv->can.do_set_mode = bxcan_do_set_mode; 100762306a36Sopenharmony_ci priv->can.do_get_berr_counter = bxcan_get_berr_counter; 100862306a36Sopenharmony_ci priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | 100962306a36Sopenharmony_ci CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING; 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci priv->offload.mailbox_read = bxcan_mailbox_read; 101262306a36Sopenharmony_ci err = can_rx_offload_add_fifo(ndev, &priv->offload, BXCAN_NAPI_WEIGHT); 101362306a36Sopenharmony_ci if (err) { 101462306a36Sopenharmony_ci dev_err(dev, "failed to add FIFO rx_offload\n"); 101562306a36Sopenharmony_ci goto out_free_candev; 101662306a36Sopenharmony_ci } 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci err = register_candev(ndev); 101962306a36Sopenharmony_ci if (err) { 102062306a36Sopenharmony_ci dev_err(dev, "failed to register netdev\n"); 102162306a36Sopenharmony_ci goto out_can_rx_offload_del; 102262306a36Sopenharmony_ci } 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci dev_info(dev, "clk: %d Hz, IRQs: %d, %d, %d\n", priv->can.clock.freq, 102562306a36Sopenharmony_ci tx_irq, rx_irq, sce_irq); 102662306a36Sopenharmony_ci return 0; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ciout_can_rx_offload_del: 102962306a36Sopenharmony_ci can_rx_offload_del(&priv->offload); 103062306a36Sopenharmony_ciout_free_candev: 103162306a36Sopenharmony_ci free_candev(ndev); 103262306a36Sopenharmony_ci return err; 103362306a36Sopenharmony_ci} 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_cistatic void bxcan_remove(struct platform_device *pdev) 103662306a36Sopenharmony_ci{ 103762306a36Sopenharmony_ci struct net_device *ndev = platform_get_drvdata(pdev); 103862306a36Sopenharmony_ci struct bxcan_priv *priv = netdev_priv(ndev); 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci unregister_candev(ndev); 104162306a36Sopenharmony_ci clk_disable_unprepare(priv->clk); 104262306a36Sopenharmony_ci can_rx_offload_del(&priv->offload); 104362306a36Sopenharmony_ci free_candev(ndev); 104462306a36Sopenharmony_ci} 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_cistatic int __maybe_unused bxcan_suspend(struct device *dev) 104762306a36Sopenharmony_ci{ 104862306a36Sopenharmony_ci struct net_device *ndev = dev_get_drvdata(dev); 104962306a36Sopenharmony_ci struct bxcan_priv *priv = netdev_priv(ndev); 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci if (!netif_running(ndev)) 105262306a36Sopenharmony_ci return 0; 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci netif_stop_queue(ndev); 105562306a36Sopenharmony_ci netif_device_detach(ndev); 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci bxcan_enter_sleep_mode(priv); 105862306a36Sopenharmony_ci priv->can.state = CAN_STATE_SLEEPING; 105962306a36Sopenharmony_ci clk_disable_unprepare(priv->clk); 106062306a36Sopenharmony_ci return 0; 106162306a36Sopenharmony_ci} 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_cistatic int __maybe_unused bxcan_resume(struct device *dev) 106462306a36Sopenharmony_ci{ 106562306a36Sopenharmony_ci struct net_device *ndev = dev_get_drvdata(dev); 106662306a36Sopenharmony_ci struct bxcan_priv *priv = netdev_priv(ndev); 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci if (!netif_running(ndev)) 106962306a36Sopenharmony_ci return 0; 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci clk_prepare_enable(priv->clk); 107262306a36Sopenharmony_ci bxcan_leave_sleep_mode(priv); 107362306a36Sopenharmony_ci priv->can.state = CAN_STATE_ERROR_ACTIVE; 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci netif_device_attach(ndev); 107662306a36Sopenharmony_ci netif_start_queue(ndev); 107762306a36Sopenharmony_ci return 0; 107862306a36Sopenharmony_ci} 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(bxcan_pm_ops, bxcan_suspend, bxcan_resume); 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_cistatic const struct of_device_id bxcan_of_match[] = { 108362306a36Sopenharmony_ci {.compatible = "st,stm32f4-bxcan"}, 108462306a36Sopenharmony_ci { /* sentinel */ }, 108562306a36Sopenharmony_ci}; 108662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, bxcan_of_match); 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_cistatic struct platform_driver bxcan_driver = { 108962306a36Sopenharmony_ci .driver = { 109062306a36Sopenharmony_ci .name = KBUILD_MODNAME, 109162306a36Sopenharmony_ci .pm = &bxcan_pm_ops, 109262306a36Sopenharmony_ci .of_match_table = bxcan_of_match, 109362306a36Sopenharmony_ci }, 109462306a36Sopenharmony_ci .probe = bxcan_probe, 109562306a36Sopenharmony_ci .remove_new = bxcan_remove, 109662306a36Sopenharmony_ci}; 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_cimodule_platform_driver(bxcan_driver); 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ciMODULE_AUTHOR("Dario Binacchi <dario.binacchi@amarulasolutions.com>"); 110162306a36Sopenharmony_ciMODULE_DESCRIPTION("STMicroelectronics Basic Extended CAN controller driver"); 110262306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1103