162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Socket CAN driver for Aeroflex Gaisler GRCAN and GRHCAN. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * 2012 (c) Aeroflex Gaisler AB 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This driver supports GRCAN and GRHCAN CAN controllers available in the GRLIB 862306a36Sopenharmony_ci * VHDL IP core library. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Full documentation of the GRCAN core can be found here: 1162306a36Sopenharmony_ci * http://www.gaisler.com/products/grlib/grip.pdf 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * See "Documentation/devicetree/bindings/net/can/grcan.txt" for information on 1462306a36Sopenharmony_ci * open firmware properties. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * See "Documentation/ABI/testing/sysfs-class-net-grcan" for information on the 1762306a36Sopenharmony_ci * sysfs interface. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * See "Documentation/admin-guide/kernel-parameters.rst" for information on the module 2062306a36Sopenharmony_ci * parameters. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * Contributors: Andreas Larsson <andreas@gaisler.com> 2362306a36Sopenharmony_ci */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include <linux/kernel.h> 2662306a36Sopenharmony_ci#include <linux/module.h> 2762306a36Sopenharmony_ci#include <linux/interrupt.h> 2862306a36Sopenharmony_ci#include <linux/netdevice.h> 2962306a36Sopenharmony_ci#include <linux/delay.h> 3062306a36Sopenharmony_ci#include <linux/ethtool.h> 3162306a36Sopenharmony_ci#include <linux/io.h> 3262306a36Sopenharmony_ci#include <linux/can/dev.h> 3362306a36Sopenharmony_ci#include <linux/platform_device.h> 3462306a36Sopenharmony_ci#include <linux/spinlock.h> 3562306a36Sopenharmony_ci#include <linux/of.h> 3662306a36Sopenharmony_ci#include <linux/of_irq.h> 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#include <linux/dma-mapping.h> 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define DRV_NAME "grcan" 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define GRCAN_NAPI_WEIGHT 32 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define GRCAN_RESERVE_SIZE(slot1, slot2) (((slot2) - (slot1)) / 4 - 1) 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistruct grcan_registers { 4762306a36Sopenharmony_ci u32 conf; /* 0x00 */ 4862306a36Sopenharmony_ci u32 stat; /* 0x04 */ 4962306a36Sopenharmony_ci u32 ctrl; /* 0x08 */ 5062306a36Sopenharmony_ci u32 __reserved1[GRCAN_RESERVE_SIZE(0x08, 0x18)]; 5162306a36Sopenharmony_ci u32 smask; /* 0x18 - CanMASK */ 5262306a36Sopenharmony_ci u32 scode; /* 0x1c - CanCODE */ 5362306a36Sopenharmony_ci u32 __reserved2[GRCAN_RESERVE_SIZE(0x1c, 0x100)]; 5462306a36Sopenharmony_ci u32 pimsr; /* 0x100 */ 5562306a36Sopenharmony_ci u32 pimr; /* 0x104 */ 5662306a36Sopenharmony_ci u32 pisr; /* 0x108 */ 5762306a36Sopenharmony_ci u32 pir; /* 0x10C */ 5862306a36Sopenharmony_ci u32 imr; /* 0x110 */ 5962306a36Sopenharmony_ci u32 picr; /* 0x114 */ 6062306a36Sopenharmony_ci u32 __reserved3[GRCAN_RESERVE_SIZE(0x114, 0x200)]; 6162306a36Sopenharmony_ci u32 txctrl; /* 0x200 */ 6262306a36Sopenharmony_ci u32 txaddr; /* 0x204 */ 6362306a36Sopenharmony_ci u32 txsize; /* 0x208 */ 6462306a36Sopenharmony_ci u32 txwr; /* 0x20C */ 6562306a36Sopenharmony_ci u32 txrd; /* 0x210 */ 6662306a36Sopenharmony_ci u32 txirq; /* 0x214 */ 6762306a36Sopenharmony_ci u32 __reserved4[GRCAN_RESERVE_SIZE(0x214, 0x300)]; 6862306a36Sopenharmony_ci u32 rxctrl; /* 0x300 */ 6962306a36Sopenharmony_ci u32 rxaddr; /* 0x304 */ 7062306a36Sopenharmony_ci u32 rxsize; /* 0x308 */ 7162306a36Sopenharmony_ci u32 rxwr; /* 0x30C */ 7262306a36Sopenharmony_ci u32 rxrd; /* 0x310 */ 7362306a36Sopenharmony_ci u32 rxirq; /* 0x314 */ 7462306a36Sopenharmony_ci u32 rxmask; /* 0x318 */ 7562306a36Sopenharmony_ci u32 rxcode; /* 0x31C */ 7662306a36Sopenharmony_ci}; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#define GRCAN_CONF_ABORT 0x00000001 7962306a36Sopenharmony_ci#define GRCAN_CONF_ENABLE0 0x00000002 8062306a36Sopenharmony_ci#define GRCAN_CONF_ENABLE1 0x00000004 8162306a36Sopenharmony_ci#define GRCAN_CONF_SELECT 0x00000008 8262306a36Sopenharmony_ci#define GRCAN_CONF_SILENT 0x00000010 8362306a36Sopenharmony_ci#define GRCAN_CONF_SAM 0x00000020 /* Available in some hardware */ 8462306a36Sopenharmony_ci#define GRCAN_CONF_BPR 0x00000300 /* Note: not BRP */ 8562306a36Sopenharmony_ci#define GRCAN_CONF_RSJ 0x00007000 8662306a36Sopenharmony_ci#define GRCAN_CONF_PS1 0x00f00000 8762306a36Sopenharmony_ci#define GRCAN_CONF_PS2 0x000f0000 8862306a36Sopenharmony_ci#define GRCAN_CONF_SCALER 0xff000000 8962306a36Sopenharmony_ci#define GRCAN_CONF_OPERATION \ 9062306a36Sopenharmony_ci (GRCAN_CONF_ABORT | GRCAN_CONF_ENABLE0 | GRCAN_CONF_ENABLE1 \ 9162306a36Sopenharmony_ci | GRCAN_CONF_SELECT | GRCAN_CONF_SILENT | GRCAN_CONF_SAM) 9262306a36Sopenharmony_ci#define GRCAN_CONF_TIMING \ 9362306a36Sopenharmony_ci (GRCAN_CONF_BPR | GRCAN_CONF_RSJ | GRCAN_CONF_PS1 \ 9462306a36Sopenharmony_ci | GRCAN_CONF_PS2 | GRCAN_CONF_SCALER) 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#define GRCAN_CONF_RSJ_MIN 1 9762306a36Sopenharmony_ci#define GRCAN_CONF_RSJ_MAX 4 9862306a36Sopenharmony_ci#define GRCAN_CONF_PS1_MIN 1 9962306a36Sopenharmony_ci#define GRCAN_CONF_PS1_MAX 15 10062306a36Sopenharmony_ci#define GRCAN_CONF_PS2_MIN 2 10162306a36Sopenharmony_ci#define GRCAN_CONF_PS2_MAX 8 10262306a36Sopenharmony_ci#define GRCAN_CONF_SCALER_MIN 0 10362306a36Sopenharmony_ci#define GRCAN_CONF_SCALER_MAX 255 10462306a36Sopenharmony_ci#define GRCAN_CONF_SCALER_INC 1 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci#define GRCAN_CONF_BPR_BIT 8 10762306a36Sopenharmony_ci#define GRCAN_CONF_RSJ_BIT 12 10862306a36Sopenharmony_ci#define GRCAN_CONF_PS1_BIT 20 10962306a36Sopenharmony_ci#define GRCAN_CONF_PS2_BIT 16 11062306a36Sopenharmony_ci#define GRCAN_CONF_SCALER_BIT 24 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#define GRCAN_STAT_PASS 0x000001 11362306a36Sopenharmony_ci#define GRCAN_STAT_OFF 0x000002 11462306a36Sopenharmony_ci#define GRCAN_STAT_OR 0x000004 11562306a36Sopenharmony_ci#define GRCAN_STAT_AHBERR 0x000008 11662306a36Sopenharmony_ci#define GRCAN_STAT_ACTIVE 0x000010 11762306a36Sopenharmony_ci#define GRCAN_STAT_RXERRCNT 0x00ff00 11862306a36Sopenharmony_ci#define GRCAN_STAT_TXERRCNT 0xff0000 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#define GRCAN_STAT_ERRCTR_RELATED (GRCAN_STAT_PASS | GRCAN_STAT_OFF) 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci#define GRCAN_STAT_RXERRCNT_BIT 8 12362306a36Sopenharmony_ci#define GRCAN_STAT_TXERRCNT_BIT 16 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci#define GRCAN_STAT_ERRCNT_WARNING_LIMIT 96 12662306a36Sopenharmony_ci#define GRCAN_STAT_ERRCNT_PASSIVE_LIMIT 127 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci#define GRCAN_CTRL_RESET 0x2 12962306a36Sopenharmony_ci#define GRCAN_CTRL_ENABLE 0x1 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci#define GRCAN_TXCTRL_ENABLE 0x1 13262306a36Sopenharmony_ci#define GRCAN_TXCTRL_ONGOING 0x2 13362306a36Sopenharmony_ci#define GRCAN_TXCTRL_SINGLE 0x4 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci#define GRCAN_RXCTRL_ENABLE 0x1 13662306a36Sopenharmony_ci#define GRCAN_RXCTRL_ONGOING 0x2 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci/* Relative offset of IRQ sources to AMBA Plug&Play */ 13962306a36Sopenharmony_ci#define GRCAN_IRQIX_IRQ 0 14062306a36Sopenharmony_ci#define GRCAN_IRQIX_TXSYNC 1 14162306a36Sopenharmony_ci#define GRCAN_IRQIX_RXSYNC 2 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci#define GRCAN_IRQ_PASS 0x00001 14462306a36Sopenharmony_ci#define GRCAN_IRQ_OFF 0x00002 14562306a36Sopenharmony_ci#define GRCAN_IRQ_OR 0x00004 14662306a36Sopenharmony_ci#define GRCAN_IRQ_RXAHBERR 0x00008 14762306a36Sopenharmony_ci#define GRCAN_IRQ_TXAHBERR 0x00010 14862306a36Sopenharmony_ci#define GRCAN_IRQ_RXIRQ 0x00020 14962306a36Sopenharmony_ci#define GRCAN_IRQ_TXIRQ 0x00040 15062306a36Sopenharmony_ci#define GRCAN_IRQ_RXFULL 0x00080 15162306a36Sopenharmony_ci#define GRCAN_IRQ_TXEMPTY 0x00100 15262306a36Sopenharmony_ci#define GRCAN_IRQ_RX 0x00200 15362306a36Sopenharmony_ci#define GRCAN_IRQ_TX 0x00400 15462306a36Sopenharmony_ci#define GRCAN_IRQ_RXSYNC 0x00800 15562306a36Sopenharmony_ci#define GRCAN_IRQ_TXSYNC 0x01000 15662306a36Sopenharmony_ci#define GRCAN_IRQ_RXERRCTR 0x02000 15762306a36Sopenharmony_ci#define GRCAN_IRQ_TXERRCTR 0x04000 15862306a36Sopenharmony_ci#define GRCAN_IRQ_RXMISS 0x08000 15962306a36Sopenharmony_ci#define GRCAN_IRQ_TXLOSS 0x10000 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci#define GRCAN_IRQ_NONE 0 16262306a36Sopenharmony_ci#define GRCAN_IRQ_ALL \ 16362306a36Sopenharmony_ci (GRCAN_IRQ_PASS | GRCAN_IRQ_OFF | GRCAN_IRQ_OR \ 16462306a36Sopenharmony_ci | GRCAN_IRQ_RXAHBERR | GRCAN_IRQ_TXAHBERR \ 16562306a36Sopenharmony_ci | GRCAN_IRQ_RXIRQ | GRCAN_IRQ_TXIRQ \ 16662306a36Sopenharmony_ci | GRCAN_IRQ_RXFULL | GRCAN_IRQ_TXEMPTY \ 16762306a36Sopenharmony_ci | GRCAN_IRQ_RX | GRCAN_IRQ_TX | GRCAN_IRQ_RXSYNC \ 16862306a36Sopenharmony_ci | GRCAN_IRQ_TXSYNC | GRCAN_IRQ_RXERRCTR \ 16962306a36Sopenharmony_ci | GRCAN_IRQ_TXERRCTR | GRCAN_IRQ_RXMISS \ 17062306a36Sopenharmony_ci | GRCAN_IRQ_TXLOSS) 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci#define GRCAN_IRQ_ERRCTR_RELATED (GRCAN_IRQ_RXERRCTR | GRCAN_IRQ_TXERRCTR \ 17362306a36Sopenharmony_ci | GRCAN_IRQ_PASS | GRCAN_IRQ_OFF) 17462306a36Sopenharmony_ci#define GRCAN_IRQ_ERRORS (GRCAN_IRQ_ERRCTR_RELATED | GRCAN_IRQ_OR \ 17562306a36Sopenharmony_ci | GRCAN_IRQ_TXAHBERR | GRCAN_IRQ_RXAHBERR \ 17662306a36Sopenharmony_ci | GRCAN_IRQ_TXLOSS) 17762306a36Sopenharmony_ci#define GRCAN_IRQ_DEFAULT (GRCAN_IRQ_RX | GRCAN_IRQ_TX | GRCAN_IRQ_ERRORS) 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci#define GRCAN_MSG_SIZE 16 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci#define GRCAN_MSG_IDE 0x80000000 18262306a36Sopenharmony_ci#define GRCAN_MSG_RTR 0x40000000 18362306a36Sopenharmony_ci#define GRCAN_MSG_BID 0x1ffc0000 18462306a36Sopenharmony_ci#define GRCAN_MSG_EID 0x1fffffff 18562306a36Sopenharmony_ci#define GRCAN_MSG_IDE_BIT 31 18662306a36Sopenharmony_ci#define GRCAN_MSG_RTR_BIT 30 18762306a36Sopenharmony_ci#define GRCAN_MSG_BID_BIT 18 18862306a36Sopenharmony_ci#define GRCAN_MSG_EID_BIT 0 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci#define GRCAN_MSG_DLC 0xf0000000 19162306a36Sopenharmony_ci#define GRCAN_MSG_TXERRC 0x00ff0000 19262306a36Sopenharmony_ci#define GRCAN_MSG_RXERRC 0x0000ff00 19362306a36Sopenharmony_ci#define GRCAN_MSG_DLC_BIT 28 19462306a36Sopenharmony_ci#define GRCAN_MSG_TXERRC_BIT 16 19562306a36Sopenharmony_ci#define GRCAN_MSG_RXERRC_BIT 8 19662306a36Sopenharmony_ci#define GRCAN_MSG_AHBERR 0x00000008 19762306a36Sopenharmony_ci#define GRCAN_MSG_OR 0x00000004 19862306a36Sopenharmony_ci#define GRCAN_MSG_OFF 0x00000002 19962306a36Sopenharmony_ci#define GRCAN_MSG_PASS 0x00000001 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci#define GRCAN_MSG_DATA_SLOT_INDEX(i) (2 + (i) / 4) 20262306a36Sopenharmony_ci#define GRCAN_MSG_DATA_SHIFT(i) ((3 - (i) % 4) * 8) 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci#define GRCAN_BUFFER_ALIGNMENT 1024 20562306a36Sopenharmony_ci#define GRCAN_DEFAULT_BUFFER_SIZE 1024 20662306a36Sopenharmony_ci#define GRCAN_VALID_TR_SIZE_MASK 0x001fffc0 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci#define GRCAN_INVALID_BUFFER_SIZE(s) \ 20962306a36Sopenharmony_ci ((s) == 0 || ((s) & ~GRCAN_VALID_TR_SIZE_MASK)) 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci#if GRCAN_INVALID_BUFFER_SIZE(GRCAN_DEFAULT_BUFFER_SIZE) 21262306a36Sopenharmony_ci#error "Invalid default buffer size" 21362306a36Sopenharmony_ci#endif 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistruct grcan_dma_buffer { 21662306a36Sopenharmony_ci size_t size; 21762306a36Sopenharmony_ci void *buf; 21862306a36Sopenharmony_ci dma_addr_t handle; 21962306a36Sopenharmony_ci}; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_cistruct grcan_dma { 22262306a36Sopenharmony_ci size_t base_size; 22362306a36Sopenharmony_ci void *base_buf; 22462306a36Sopenharmony_ci dma_addr_t base_handle; 22562306a36Sopenharmony_ci struct grcan_dma_buffer tx; 22662306a36Sopenharmony_ci struct grcan_dma_buffer rx; 22762306a36Sopenharmony_ci}; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci/* GRCAN configuration parameters */ 23062306a36Sopenharmony_cistruct grcan_device_config { 23162306a36Sopenharmony_ci unsigned short enable0; 23262306a36Sopenharmony_ci unsigned short enable1; 23362306a36Sopenharmony_ci unsigned short select; 23462306a36Sopenharmony_ci unsigned int txsize; 23562306a36Sopenharmony_ci unsigned int rxsize; 23662306a36Sopenharmony_ci}; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci#define GRCAN_DEFAULT_DEVICE_CONFIG { \ 23962306a36Sopenharmony_ci .enable0 = 0, \ 24062306a36Sopenharmony_ci .enable1 = 0, \ 24162306a36Sopenharmony_ci .select = 0, \ 24262306a36Sopenharmony_ci .txsize = GRCAN_DEFAULT_BUFFER_SIZE, \ 24362306a36Sopenharmony_ci .rxsize = GRCAN_DEFAULT_BUFFER_SIZE, \ 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci#define GRCAN_TXBUG_SAFE_GRLIB_VERSION 4100 24762306a36Sopenharmony_ci#define GRLIB_VERSION_MASK 0xffff 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci/* GRCAN private data structure */ 25062306a36Sopenharmony_cistruct grcan_priv { 25162306a36Sopenharmony_ci struct can_priv can; /* must be the first member */ 25262306a36Sopenharmony_ci struct net_device *dev; 25362306a36Sopenharmony_ci struct device *ofdev_dev; 25462306a36Sopenharmony_ci struct napi_struct napi; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci struct grcan_registers __iomem *regs; /* ioremap'ed registers */ 25762306a36Sopenharmony_ci struct grcan_device_config config; 25862306a36Sopenharmony_ci struct grcan_dma dma; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci struct sk_buff **echo_skb; /* We allocate this on our own */ 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci /* The echo skb pointer, pointing into echo_skb and indicating which 26362306a36Sopenharmony_ci * frames can be echoed back. See the "Notes on the tx cyclic buffer 26462306a36Sopenharmony_ci * handling"-comment for grcan_start_xmit for more details. 26562306a36Sopenharmony_ci */ 26662306a36Sopenharmony_ci u32 eskbp; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci /* Lock for controlling changes to the netif tx queue state, accesses to 26962306a36Sopenharmony_ci * the echo_skb pointer eskbp and for making sure that a running reset 27062306a36Sopenharmony_ci * and/or a close of the interface is done without interference from 27162306a36Sopenharmony_ci * other parts of the code. 27262306a36Sopenharmony_ci * 27362306a36Sopenharmony_ci * The echo_skb pointer, eskbp, should only be accessed under this lock 27462306a36Sopenharmony_ci * as it can be changed in several places and together with decisions on 27562306a36Sopenharmony_ci * whether to wake up the tx queue. 27662306a36Sopenharmony_ci * 27762306a36Sopenharmony_ci * The tx queue must never be woken up if there is a running reset or 27862306a36Sopenharmony_ci * close in progress. 27962306a36Sopenharmony_ci * 28062306a36Sopenharmony_ci * A running reset (see below on need_txbug_workaround) should never be 28162306a36Sopenharmony_ci * done if the interface is closing down and several running resets 28262306a36Sopenharmony_ci * should never be scheduled simultaneously. 28362306a36Sopenharmony_ci */ 28462306a36Sopenharmony_ci spinlock_t lock; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci /* Whether a workaround is needed due to a bug in older hardware. In 28762306a36Sopenharmony_ci * this case, the driver both tries to prevent the bug from being 28862306a36Sopenharmony_ci * triggered and recovers, if the bug nevertheless happens, by doing a 28962306a36Sopenharmony_ci * running reset. A running reset, resets the device and continues from 29062306a36Sopenharmony_ci * where it were without being noticeable from outside the driver (apart 29162306a36Sopenharmony_ci * from slight delays). 29262306a36Sopenharmony_ci */ 29362306a36Sopenharmony_ci bool need_txbug_workaround; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci /* To trigger initization of running reset and to trigger running reset 29662306a36Sopenharmony_ci * respectively in the case of a hanged device due to a txbug. 29762306a36Sopenharmony_ci */ 29862306a36Sopenharmony_ci struct timer_list hang_timer; 29962306a36Sopenharmony_ci struct timer_list rr_timer; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci /* To avoid waking up the netif queue and restarting timers 30262306a36Sopenharmony_ci * when a reset is scheduled or when closing of the device is 30362306a36Sopenharmony_ci * undergoing 30462306a36Sopenharmony_ci */ 30562306a36Sopenharmony_ci bool resetting; 30662306a36Sopenharmony_ci bool closing; 30762306a36Sopenharmony_ci}; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci/* Wait time for a short wait for ongoing to clear */ 31062306a36Sopenharmony_ci#define GRCAN_SHORTWAIT_USECS 10 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci/* Limit on the number of transmitted bits of an eff frame according to the CAN 31362306a36Sopenharmony_ci * specification: 1 bit start of frame, 32 bits arbitration field, 6 bits 31462306a36Sopenharmony_ci * control field, 8 bytes data field, 16 bits crc field, 2 bits ACK field and 7 31562306a36Sopenharmony_ci * bits end of frame 31662306a36Sopenharmony_ci */ 31762306a36Sopenharmony_ci#define GRCAN_EFF_FRAME_MAX_BITS (1+32+6+8*8+16+2+7) 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci#if defined(__BIG_ENDIAN) 32062306a36Sopenharmony_cistatic inline u32 grcan_read_reg(u32 __iomem *reg) 32162306a36Sopenharmony_ci{ 32262306a36Sopenharmony_ci return ioread32be(reg); 32362306a36Sopenharmony_ci} 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_cistatic inline void grcan_write_reg(u32 __iomem *reg, u32 val) 32662306a36Sopenharmony_ci{ 32762306a36Sopenharmony_ci iowrite32be(val, reg); 32862306a36Sopenharmony_ci} 32962306a36Sopenharmony_ci#else 33062306a36Sopenharmony_cistatic inline u32 grcan_read_reg(u32 __iomem *reg) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci return ioread32(reg); 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_cistatic inline void grcan_write_reg(u32 __iomem *reg, u32 val) 33662306a36Sopenharmony_ci{ 33762306a36Sopenharmony_ci iowrite32(val, reg); 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci#endif 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cistatic inline void grcan_clear_bits(u32 __iomem *reg, u32 mask) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci grcan_write_reg(reg, grcan_read_reg(reg) & ~mask); 34462306a36Sopenharmony_ci} 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_cistatic inline void grcan_set_bits(u32 __iomem *reg, u32 mask) 34762306a36Sopenharmony_ci{ 34862306a36Sopenharmony_ci grcan_write_reg(reg, grcan_read_reg(reg) | mask); 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_cistatic inline u32 grcan_read_bits(u32 __iomem *reg, u32 mask) 35262306a36Sopenharmony_ci{ 35362306a36Sopenharmony_ci return grcan_read_reg(reg) & mask; 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cistatic inline void grcan_write_bits(u32 __iomem *reg, u32 value, u32 mask) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci u32 old = grcan_read_reg(reg); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci grcan_write_reg(reg, (old & ~mask) | (value & mask)); 36162306a36Sopenharmony_ci} 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci/* a and b should both be in [0,size] and a == b == size should not hold */ 36462306a36Sopenharmony_cistatic inline u32 grcan_ring_add(u32 a, u32 b, u32 size) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci u32 sum = a + b; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci if (sum < size) 36962306a36Sopenharmony_ci return sum; 37062306a36Sopenharmony_ci else 37162306a36Sopenharmony_ci return sum - size; 37262306a36Sopenharmony_ci} 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci/* a and b should both be in [0,size) */ 37562306a36Sopenharmony_cistatic inline u32 grcan_ring_sub(u32 a, u32 b, u32 size) 37662306a36Sopenharmony_ci{ 37762306a36Sopenharmony_ci return grcan_ring_add(a, size - b, size); 37862306a36Sopenharmony_ci} 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci/* Available slots for new transmissions */ 38162306a36Sopenharmony_cistatic inline u32 grcan_txspace(size_t txsize, u32 txwr, u32 eskbp) 38262306a36Sopenharmony_ci{ 38362306a36Sopenharmony_ci u32 slots = txsize / GRCAN_MSG_SIZE - 1; 38462306a36Sopenharmony_ci u32 used = grcan_ring_sub(txwr, eskbp, txsize) / GRCAN_MSG_SIZE; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci return slots - used; 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci/* Configuration parameters that can be set via module parameters */ 39062306a36Sopenharmony_cistatic struct grcan_device_config grcan_module_config = 39162306a36Sopenharmony_ci GRCAN_DEFAULT_DEVICE_CONFIG; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_cistatic const struct can_bittiming_const grcan_bittiming_const = { 39462306a36Sopenharmony_ci .name = DRV_NAME, 39562306a36Sopenharmony_ci .tseg1_min = GRCAN_CONF_PS1_MIN + 1, 39662306a36Sopenharmony_ci .tseg1_max = GRCAN_CONF_PS1_MAX + 1, 39762306a36Sopenharmony_ci .tseg2_min = GRCAN_CONF_PS2_MIN, 39862306a36Sopenharmony_ci .tseg2_max = GRCAN_CONF_PS2_MAX, 39962306a36Sopenharmony_ci .sjw_max = GRCAN_CONF_RSJ_MAX, 40062306a36Sopenharmony_ci .brp_min = GRCAN_CONF_SCALER_MIN + 1, 40162306a36Sopenharmony_ci .brp_max = GRCAN_CONF_SCALER_MAX + 1, 40262306a36Sopenharmony_ci .brp_inc = GRCAN_CONF_SCALER_INC, 40362306a36Sopenharmony_ci}; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cistatic int grcan_set_bittiming(struct net_device *dev) 40662306a36Sopenharmony_ci{ 40762306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 40862306a36Sopenharmony_ci struct grcan_registers __iomem *regs = priv->regs; 40962306a36Sopenharmony_ci struct can_bittiming *bt = &priv->can.bittiming; 41062306a36Sopenharmony_ci u32 timing = 0; 41162306a36Sopenharmony_ci int bpr, rsj, ps1, ps2, scaler; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci /* Should never happen - function will not be called when 41462306a36Sopenharmony_ci * device is up 41562306a36Sopenharmony_ci */ 41662306a36Sopenharmony_ci if (grcan_read_bits(®s->ctrl, GRCAN_CTRL_ENABLE)) 41762306a36Sopenharmony_ci return -EBUSY; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci bpr = 0; /* Note bpr and brp are different concepts */ 42062306a36Sopenharmony_ci rsj = bt->sjw; 42162306a36Sopenharmony_ci ps1 = (bt->prop_seg + bt->phase_seg1) - 1; /* tseg1 - 1 */ 42262306a36Sopenharmony_ci ps2 = bt->phase_seg2; 42362306a36Sopenharmony_ci scaler = (bt->brp - 1); 42462306a36Sopenharmony_ci netdev_dbg(dev, "Request for BPR=%d, RSJ=%d, PS1=%d, PS2=%d, SCALER=%d", 42562306a36Sopenharmony_ci bpr, rsj, ps1, ps2, scaler); 42662306a36Sopenharmony_ci if (!(ps1 > ps2)) { 42762306a36Sopenharmony_ci netdev_err(dev, "PS1 > PS2 must hold: PS1=%d, PS2=%d\n", 42862306a36Sopenharmony_ci ps1, ps2); 42962306a36Sopenharmony_ci return -EINVAL; 43062306a36Sopenharmony_ci } 43162306a36Sopenharmony_ci if (!(ps2 >= rsj)) { 43262306a36Sopenharmony_ci netdev_err(dev, "PS2 >= RSJ must hold: PS2=%d, RSJ=%d\n", 43362306a36Sopenharmony_ci ps2, rsj); 43462306a36Sopenharmony_ci return -EINVAL; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci timing |= (bpr << GRCAN_CONF_BPR_BIT) & GRCAN_CONF_BPR; 43862306a36Sopenharmony_ci timing |= (rsj << GRCAN_CONF_RSJ_BIT) & GRCAN_CONF_RSJ; 43962306a36Sopenharmony_ci timing |= (ps1 << GRCAN_CONF_PS1_BIT) & GRCAN_CONF_PS1; 44062306a36Sopenharmony_ci timing |= (ps2 << GRCAN_CONF_PS2_BIT) & GRCAN_CONF_PS2; 44162306a36Sopenharmony_ci timing |= (scaler << GRCAN_CONF_SCALER_BIT) & GRCAN_CONF_SCALER; 44262306a36Sopenharmony_ci netdev_info(dev, "setting timing=0x%x\n", timing); 44362306a36Sopenharmony_ci grcan_write_bits(®s->conf, timing, GRCAN_CONF_TIMING); 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci return 0; 44662306a36Sopenharmony_ci} 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_cistatic int grcan_get_berr_counter(const struct net_device *dev, 44962306a36Sopenharmony_ci struct can_berr_counter *bec) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 45262306a36Sopenharmony_ci struct grcan_registers __iomem *regs = priv->regs; 45362306a36Sopenharmony_ci u32 status = grcan_read_reg(®s->stat); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci bec->txerr = (status & GRCAN_STAT_TXERRCNT) >> GRCAN_STAT_TXERRCNT_BIT; 45662306a36Sopenharmony_ci bec->rxerr = (status & GRCAN_STAT_RXERRCNT) >> GRCAN_STAT_RXERRCNT_BIT; 45762306a36Sopenharmony_ci return 0; 45862306a36Sopenharmony_ci} 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_cistatic int grcan_poll(struct napi_struct *napi, int budget); 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci/* Reset device, but keep configuration information */ 46362306a36Sopenharmony_cistatic void grcan_reset(struct net_device *dev) 46462306a36Sopenharmony_ci{ 46562306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 46662306a36Sopenharmony_ci struct grcan_registers __iomem *regs = priv->regs; 46762306a36Sopenharmony_ci u32 config = grcan_read_reg(®s->conf); 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci grcan_set_bits(®s->ctrl, GRCAN_CTRL_RESET); 47062306a36Sopenharmony_ci grcan_write_reg(®s->conf, config); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci priv->eskbp = grcan_read_reg(®s->txrd); 47362306a36Sopenharmony_ci priv->can.state = CAN_STATE_STOPPED; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci /* Turn off hardware filtering - regs->rxcode set to 0 by reset */ 47662306a36Sopenharmony_ci grcan_write_reg(®s->rxmask, 0); 47762306a36Sopenharmony_ci} 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci/* stop device without changing any configurations */ 48062306a36Sopenharmony_cistatic void grcan_stop_hardware(struct net_device *dev) 48162306a36Sopenharmony_ci{ 48262306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 48362306a36Sopenharmony_ci struct grcan_registers __iomem *regs = priv->regs; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci grcan_write_reg(®s->imr, GRCAN_IRQ_NONE); 48662306a36Sopenharmony_ci grcan_clear_bits(®s->txctrl, GRCAN_TXCTRL_ENABLE); 48762306a36Sopenharmony_ci grcan_clear_bits(®s->rxctrl, GRCAN_RXCTRL_ENABLE); 48862306a36Sopenharmony_ci grcan_clear_bits(®s->ctrl, GRCAN_CTRL_ENABLE); 48962306a36Sopenharmony_ci} 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci/* Let priv->eskbp catch up to regs->txrd and echo back the skbs if echo 49262306a36Sopenharmony_ci * is true and free them otherwise. 49362306a36Sopenharmony_ci * 49462306a36Sopenharmony_ci * If budget is >= 0, stop after handling at most budget skbs. Otherwise, 49562306a36Sopenharmony_ci * continue until priv->eskbp catches up to regs->txrd. 49662306a36Sopenharmony_ci * 49762306a36Sopenharmony_ci * priv->lock *must* be held when calling this function 49862306a36Sopenharmony_ci */ 49962306a36Sopenharmony_cistatic int catch_up_echo_skb(struct net_device *dev, int budget, bool echo) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 50262306a36Sopenharmony_ci struct grcan_registers __iomem *regs = priv->regs; 50362306a36Sopenharmony_ci struct grcan_dma *dma = &priv->dma; 50462306a36Sopenharmony_ci struct net_device_stats *stats = &dev->stats; 50562306a36Sopenharmony_ci int i, work_done; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci /* Updates to priv->eskbp and wake-ups of the queue needs to 50862306a36Sopenharmony_ci * be atomic towards the reads of priv->eskbp and shut-downs 50962306a36Sopenharmony_ci * of the queue in grcan_start_xmit. 51062306a36Sopenharmony_ci */ 51162306a36Sopenharmony_ci u32 txrd = grcan_read_reg(®s->txrd); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci for (work_done = 0; work_done < budget || budget < 0; work_done++) { 51462306a36Sopenharmony_ci if (priv->eskbp == txrd) 51562306a36Sopenharmony_ci break; 51662306a36Sopenharmony_ci i = priv->eskbp / GRCAN_MSG_SIZE; 51762306a36Sopenharmony_ci if (echo) { 51862306a36Sopenharmony_ci /* Normal echo of messages */ 51962306a36Sopenharmony_ci stats->tx_packets++; 52062306a36Sopenharmony_ci stats->tx_bytes += can_get_echo_skb(dev, i, NULL); 52162306a36Sopenharmony_ci } else { 52262306a36Sopenharmony_ci /* For cleanup of untransmitted messages */ 52362306a36Sopenharmony_ci can_free_echo_skb(dev, i, NULL); 52462306a36Sopenharmony_ci } 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci priv->eskbp = grcan_ring_add(priv->eskbp, GRCAN_MSG_SIZE, 52762306a36Sopenharmony_ci dma->tx.size); 52862306a36Sopenharmony_ci txrd = grcan_read_reg(®s->txrd); 52962306a36Sopenharmony_ci } 53062306a36Sopenharmony_ci return work_done; 53162306a36Sopenharmony_ci} 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_cistatic void grcan_lost_one_shot_frame(struct net_device *dev) 53462306a36Sopenharmony_ci{ 53562306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 53662306a36Sopenharmony_ci struct grcan_registers __iomem *regs = priv->regs; 53762306a36Sopenharmony_ci struct grcan_dma *dma = &priv->dma; 53862306a36Sopenharmony_ci u32 txrd; 53962306a36Sopenharmony_ci unsigned long flags; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci catch_up_echo_skb(dev, -1, true); 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci if (unlikely(grcan_read_bits(®s->txctrl, GRCAN_TXCTRL_ENABLE))) { 54662306a36Sopenharmony_ci /* Should never happen */ 54762306a36Sopenharmony_ci netdev_err(dev, "TXCTRL enabled at TXLOSS in one shot mode\n"); 54862306a36Sopenharmony_ci } else { 54962306a36Sopenharmony_ci /* By the time an GRCAN_IRQ_TXLOSS is generated in 55062306a36Sopenharmony_ci * one-shot mode there is no problem in writing 55162306a36Sopenharmony_ci * to TXRD even in versions of the hardware in 55262306a36Sopenharmony_ci * which GRCAN_TXCTRL_ONGOING is not cleared properly 55362306a36Sopenharmony_ci * in one-shot mode. 55462306a36Sopenharmony_ci */ 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci /* Skip message and discard echo-skb */ 55762306a36Sopenharmony_ci txrd = grcan_read_reg(®s->txrd); 55862306a36Sopenharmony_ci txrd = grcan_ring_add(txrd, GRCAN_MSG_SIZE, dma->tx.size); 55962306a36Sopenharmony_ci grcan_write_reg(®s->txrd, txrd); 56062306a36Sopenharmony_ci catch_up_echo_skb(dev, -1, false); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci if (!priv->resetting && !priv->closing && 56362306a36Sopenharmony_ci !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) { 56462306a36Sopenharmony_ci netif_wake_queue(dev); 56562306a36Sopenharmony_ci grcan_set_bits(®s->txctrl, GRCAN_TXCTRL_ENABLE); 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 57062306a36Sopenharmony_ci} 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_cistatic void grcan_err(struct net_device *dev, u32 sources, u32 status) 57362306a36Sopenharmony_ci{ 57462306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 57562306a36Sopenharmony_ci struct grcan_registers __iomem *regs = priv->regs; 57662306a36Sopenharmony_ci struct grcan_dma *dma = &priv->dma; 57762306a36Sopenharmony_ci struct net_device_stats *stats = &dev->stats; 57862306a36Sopenharmony_ci struct can_frame cf; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci /* Zero potential error_frame */ 58162306a36Sopenharmony_ci memset(&cf, 0, sizeof(cf)); 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci /* Message lost interrupt. This might be due to arbitration error, but 58462306a36Sopenharmony_ci * is also triggered when there is no one else on the can bus or when 58562306a36Sopenharmony_ci * there is a problem with the hardware interface or the bus itself. As 58662306a36Sopenharmony_ci * arbitration errors can not be singled out, no error frames are 58762306a36Sopenharmony_ci * generated reporting this event as an arbitration error. 58862306a36Sopenharmony_ci */ 58962306a36Sopenharmony_ci if (sources & GRCAN_IRQ_TXLOSS) { 59062306a36Sopenharmony_ci /* Take care of failed one-shot transmit */ 59162306a36Sopenharmony_ci if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) 59262306a36Sopenharmony_ci grcan_lost_one_shot_frame(dev); 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci /* Stop printing as soon as error passive or bus off is in 59562306a36Sopenharmony_ci * effect to limit the amount of txloss debug printouts. 59662306a36Sopenharmony_ci */ 59762306a36Sopenharmony_ci if (!(status & GRCAN_STAT_ERRCTR_RELATED)) { 59862306a36Sopenharmony_ci netdev_dbg(dev, "tx message lost\n"); 59962306a36Sopenharmony_ci stats->tx_errors++; 60062306a36Sopenharmony_ci } 60162306a36Sopenharmony_ci } 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci /* Conditions dealing with the error counters. There is no interrupt for 60462306a36Sopenharmony_ci * error warning, but there are interrupts for increases of the error 60562306a36Sopenharmony_ci * counters. 60662306a36Sopenharmony_ci */ 60762306a36Sopenharmony_ci if ((sources & GRCAN_IRQ_ERRCTR_RELATED) || 60862306a36Sopenharmony_ci (status & GRCAN_STAT_ERRCTR_RELATED)) { 60962306a36Sopenharmony_ci enum can_state state = priv->can.state; 61062306a36Sopenharmony_ci enum can_state oldstate = state; 61162306a36Sopenharmony_ci u32 txerr = (status & GRCAN_STAT_TXERRCNT) 61262306a36Sopenharmony_ci >> GRCAN_STAT_TXERRCNT_BIT; 61362306a36Sopenharmony_ci u32 rxerr = (status & GRCAN_STAT_RXERRCNT) 61462306a36Sopenharmony_ci >> GRCAN_STAT_RXERRCNT_BIT; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci /* Figure out current state */ 61762306a36Sopenharmony_ci if (status & GRCAN_STAT_OFF) { 61862306a36Sopenharmony_ci state = CAN_STATE_BUS_OFF; 61962306a36Sopenharmony_ci } else if (status & GRCAN_STAT_PASS) { 62062306a36Sopenharmony_ci state = CAN_STATE_ERROR_PASSIVE; 62162306a36Sopenharmony_ci } else if (txerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT || 62262306a36Sopenharmony_ci rxerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT) { 62362306a36Sopenharmony_ci state = CAN_STATE_ERROR_WARNING; 62462306a36Sopenharmony_ci } else { 62562306a36Sopenharmony_ci state = CAN_STATE_ERROR_ACTIVE; 62662306a36Sopenharmony_ci } 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci /* Handle and report state changes */ 62962306a36Sopenharmony_ci if (state != oldstate) { 63062306a36Sopenharmony_ci switch (state) { 63162306a36Sopenharmony_ci case CAN_STATE_BUS_OFF: 63262306a36Sopenharmony_ci netdev_dbg(dev, "bus-off\n"); 63362306a36Sopenharmony_ci netif_carrier_off(dev); 63462306a36Sopenharmony_ci priv->can.can_stats.bus_off++; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci /* Prevent the hardware from recovering from bus 63762306a36Sopenharmony_ci * off on its own if restart is disabled. 63862306a36Sopenharmony_ci */ 63962306a36Sopenharmony_ci if (!priv->can.restart_ms) 64062306a36Sopenharmony_ci grcan_stop_hardware(dev); 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci cf.can_id |= CAN_ERR_BUSOFF; 64362306a36Sopenharmony_ci break; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci case CAN_STATE_ERROR_PASSIVE: 64662306a36Sopenharmony_ci netdev_dbg(dev, "Error passive condition\n"); 64762306a36Sopenharmony_ci priv->can.can_stats.error_passive++; 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci cf.can_id |= CAN_ERR_CRTL; 65062306a36Sopenharmony_ci if (txerr >= GRCAN_STAT_ERRCNT_PASSIVE_LIMIT) 65162306a36Sopenharmony_ci cf.data[1] |= CAN_ERR_CRTL_TX_PASSIVE; 65262306a36Sopenharmony_ci if (rxerr >= GRCAN_STAT_ERRCNT_PASSIVE_LIMIT) 65362306a36Sopenharmony_ci cf.data[1] |= CAN_ERR_CRTL_RX_PASSIVE; 65462306a36Sopenharmony_ci break; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci case CAN_STATE_ERROR_WARNING: 65762306a36Sopenharmony_ci netdev_dbg(dev, "Error warning condition\n"); 65862306a36Sopenharmony_ci priv->can.can_stats.error_warning++; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci cf.can_id |= CAN_ERR_CRTL; 66162306a36Sopenharmony_ci if (txerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT) 66262306a36Sopenharmony_ci cf.data[1] |= CAN_ERR_CRTL_TX_WARNING; 66362306a36Sopenharmony_ci if (rxerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT) 66462306a36Sopenharmony_ci cf.data[1] |= CAN_ERR_CRTL_RX_WARNING; 66562306a36Sopenharmony_ci break; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci case CAN_STATE_ERROR_ACTIVE: 66862306a36Sopenharmony_ci netdev_dbg(dev, "Error active condition\n"); 66962306a36Sopenharmony_ci cf.can_id |= CAN_ERR_CRTL; 67062306a36Sopenharmony_ci break; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci default: 67362306a36Sopenharmony_ci /* There are no others at this point */ 67462306a36Sopenharmony_ci break; 67562306a36Sopenharmony_ci } 67662306a36Sopenharmony_ci cf.can_id |= CAN_ERR_CNT; 67762306a36Sopenharmony_ci cf.data[6] = txerr; 67862306a36Sopenharmony_ci cf.data[7] = rxerr; 67962306a36Sopenharmony_ci priv->can.state = state; 68062306a36Sopenharmony_ci } 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci /* Report automatic restarts */ 68362306a36Sopenharmony_ci if (priv->can.restart_ms && oldstate == CAN_STATE_BUS_OFF) { 68462306a36Sopenharmony_ci unsigned long flags; 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci cf.can_id |= CAN_ERR_RESTARTED; 68762306a36Sopenharmony_ci netdev_dbg(dev, "restarted\n"); 68862306a36Sopenharmony_ci priv->can.can_stats.restarts++; 68962306a36Sopenharmony_ci netif_carrier_on(dev); 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci if (!priv->resetting && !priv->closing) { 69462306a36Sopenharmony_ci u32 txwr = grcan_read_reg(®s->txwr); 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci if (grcan_txspace(dma->tx.size, txwr, 69762306a36Sopenharmony_ci priv->eskbp)) 69862306a36Sopenharmony_ci netif_wake_queue(dev); 69962306a36Sopenharmony_ci } 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 70262306a36Sopenharmony_ci } 70362306a36Sopenharmony_ci } 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci /* Data overrun interrupt */ 70662306a36Sopenharmony_ci if ((sources & GRCAN_IRQ_OR) || (status & GRCAN_STAT_OR)) { 70762306a36Sopenharmony_ci netdev_dbg(dev, "got data overrun interrupt\n"); 70862306a36Sopenharmony_ci stats->rx_over_errors++; 70962306a36Sopenharmony_ci stats->rx_errors++; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci cf.can_id |= CAN_ERR_CRTL; 71262306a36Sopenharmony_ci cf.data[1] |= CAN_ERR_CRTL_RX_OVERFLOW; 71362306a36Sopenharmony_ci } 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci /* AHB bus error interrupts (not CAN bus errors) - shut down the 71662306a36Sopenharmony_ci * device. 71762306a36Sopenharmony_ci */ 71862306a36Sopenharmony_ci if (sources & (GRCAN_IRQ_TXAHBERR | GRCAN_IRQ_RXAHBERR) || 71962306a36Sopenharmony_ci (status & GRCAN_STAT_AHBERR)) { 72062306a36Sopenharmony_ci char *txrx = ""; 72162306a36Sopenharmony_ci unsigned long flags; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci if (sources & GRCAN_IRQ_TXAHBERR) { 72462306a36Sopenharmony_ci txrx = "on tx "; 72562306a36Sopenharmony_ci stats->tx_errors++; 72662306a36Sopenharmony_ci } else if (sources & GRCAN_IRQ_RXAHBERR) { 72762306a36Sopenharmony_ci txrx = "on rx "; 72862306a36Sopenharmony_ci stats->rx_errors++; 72962306a36Sopenharmony_ci } 73062306a36Sopenharmony_ci netdev_err(dev, "Fatal AHB bus error %s- halting device\n", 73162306a36Sopenharmony_ci txrx); 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci /* Prevent anything to be enabled again and halt device */ 73662306a36Sopenharmony_ci priv->closing = true; 73762306a36Sopenharmony_ci netif_stop_queue(dev); 73862306a36Sopenharmony_ci grcan_stop_hardware(dev); 73962306a36Sopenharmony_ci priv->can.state = CAN_STATE_STOPPED; 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 74262306a36Sopenharmony_ci } 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci /* Pass on error frame if something to report, 74562306a36Sopenharmony_ci * i.e. id contains some information 74662306a36Sopenharmony_ci */ 74762306a36Sopenharmony_ci if (cf.can_id) { 74862306a36Sopenharmony_ci struct can_frame *skb_cf; 74962306a36Sopenharmony_ci struct sk_buff *skb = alloc_can_err_skb(dev, &skb_cf); 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci if (skb == NULL) { 75262306a36Sopenharmony_ci netdev_dbg(dev, "could not allocate error frame\n"); 75362306a36Sopenharmony_ci return; 75462306a36Sopenharmony_ci } 75562306a36Sopenharmony_ci skb_cf->can_id |= cf.can_id; 75662306a36Sopenharmony_ci memcpy(skb_cf->data, cf.data, sizeof(cf.data)); 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci netif_rx(skb); 75962306a36Sopenharmony_ci } 76062306a36Sopenharmony_ci} 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_cistatic irqreturn_t grcan_interrupt(int irq, void *dev_id) 76362306a36Sopenharmony_ci{ 76462306a36Sopenharmony_ci struct net_device *dev = dev_id; 76562306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 76662306a36Sopenharmony_ci struct grcan_registers __iomem *regs = priv->regs; 76762306a36Sopenharmony_ci u32 sources, status; 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci /* Find out the source */ 77062306a36Sopenharmony_ci sources = grcan_read_reg(®s->pimsr); 77162306a36Sopenharmony_ci if (!sources) 77262306a36Sopenharmony_ci return IRQ_NONE; 77362306a36Sopenharmony_ci grcan_write_reg(®s->picr, sources); 77462306a36Sopenharmony_ci status = grcan_read_reg(®s->stat); 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci /* If we got TX progress, the device has not hanged, 77762306a36Sopenharmony_ci * so disable the hang timer 77862306a36Sopenharmony_ci */ 77962306a36Sopenharmony_ci if (priv->need_txbug_workaround && 78062306a36Sopenharmony_ci (sources & (GRCAN_IRQ_TX | GRCAN_IRQ_TXLOSS))) { 78162306a36Sopenharmony_ci del_timer(&priv->hang_timer); 78262306a36Sopenharmony_ci } 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci /* Frame(s) received or transmitted */ 78562306a36Sopenharmony_ci if (sources & (GRCAN_IRQ_TX | GRCAN_IRQ_RX)) { 78662306a36Sopenharmony_ci /* Disable tx/rx interrupts and schedule poll(). No need for 78762306a36Sopenharmony_ci * locking as interference from a running reset at worst leads 78862306a36Sopenharmony_ci * to an extra interrupt. 78962306a36Sopenharmony_ci */ 79062306a36Sopenharmony_ci grcan_clear_bits(®s->imr, GRCAN_IRQ_TX | GRCAN_IRQ_RX); 79162306a36Sopenharmony_ci napi_schedule(&priv->napi); 79262306a36Sopenharmony_ci } 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci /* (Potential) error conditions to take care of */ 79562306a36Sopenharmony_ci if (sources & GRCAN_IRQ_ERRORS) 79662306a36Sopenharmony_ci grcan_err(dev, sources, status); 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci return IRQ_HANDLED; 79962306a36Sopenharmony_ci} 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci/* Reset device and restart operations from where they were. 80262306a36Sopenharmony_ci * 80362306a36Sopenharmony_ci * This assumes that RXCTRL & RXCTRL is properly disabled and that RX 80462306a36Sopenharmony_ci * is not ONGOING (TX might be stuck in ONGOING due to a harwrware bug 80562306a36Sopenharmony_ci * for single shot) 80662306a36Sopenharmony_ci */ 80762306a36Sopenharmony_cistatic void grcan_running_reset(struct timer_list *t) 80862306a36Sopenharmony_ci{ 80962306a36Sopenharmony_ci struct grcan_priv *priv = from_timer(priv, t, rr_timer); 81062306a36Sopenharmony_ci struct net_device *dev = priv->dev; 81162306a36Sopenharmony_ci struct grcan_registers __iomem *regs = priv->regs; 81262306a36Sopenharmony_ci unsigned long flags; 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci /* This temporarily messes with eskbp, so we need to lock 81562306a36Sopenharmony_ci * priv->lock 81662306a36Sopenharmony_ci */ 81762306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci priv->resetting = false; 82062306a36Sopenharmony_ci del_timer(&priv->hang_timer); 82162306a36Sopenharmony_ci del_timer(&priv->rr_timer); 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci if (!priv->closing) { 82462306a36Sopenharmony_ci /* Save and reset - config register preserved by grcan_reset */ 82562306a36Sopenharmony_ci u32 imr = grcan_read_reg(®s->imr); 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci u32 txaddr = grcan_read_reg(®s->txaddr); 82862306a36Sopenharmony_ci u32 txsize = grcan_read_reg(®s->txsize); 82962306a36Sopenharmony_ci u32 txwr = grcan_read_reg(®s->txwr); 83062306a36Sopenharmony_ci u32 txrd = grcan_read_reg(®s->txrd); 83162306a36Sopenharmony_ci u32 eskbp = priv->eskbp; 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci u32 rxaddr = grcan_read_reg(®s->rxaddr); 83462306a36Sopenharmony_ci u32 rxsize = grcan_read_reg(®s->rxsize); 83562306a36Sopenharmony_ci u32 rxwr = grcan_read_reg(®s->rxwr); 83662306a36Sopenharmony_ci u32 rxrd = grcan_read_reg(®s->rxrd); 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci grcan_reset(dev); 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci /* Restore */ 84162306a36Sopenharmony_ci grcan_write_reg(®s->txaddr, txaddr); 84262306a36Sopenharmony_ci grcan_write_reg(®s->txsize, txsize); 84362306a36Sopenharmony_ci grcan_write_reg(®s->txwr, txwr); 84462306a36Sopenharmony_ci grcan_write_reg(®s->txrd, txrd); 84562306a36Sopenharmony_ci priv->eskbp = eskbp; 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci grcan_write_reg(®s->rxaddr, rxaddr); 84862306a36Sopenharmony_ci grcan_write_reg(®s->rxsize, rxsize); 84962306a36Sopenharmony_ci grcan_write_reg(®s->rxwr, rxwr); 85062306a36Sopenharmony_ci grcan_write_reg(®s->rxrd, rxrd); 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci /* Turn on device again */ 85362306a36Sopenharmony_ci grcan_write_reg(®s->imr, imr); 85462306a36Sopenharmony_ci priv->can.state = CAN_STATE_ERROR_ACTIVE; 85562306a36Sopenharmony_ci grcan_write_reg(®s->txctrl, GRCAN_TXCTRL_ENABLE 85662306a36Sopenharmony_ci | (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT 85762306a36Sopenharmony_ci ? GRCAN_TXCTRL_SINGLE : 0)); 85862306a36Sopenharmony_ci grcan_write_reg(®s->rxctrl, GRCAN_RXCTRL_ENABLE); 85962306a36Sopenharmony_ci grcan_write_reg(®s->ctrl, GRCAN_CTRL_ENABLE); 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci /* Start queue if there is size and listen-onle mode is not 86262306a36Sopenharmony_ci * enabled 86362306a36Sopenharmony_ci */ 86462306a36Sopenharmony_ci if (grcan_txspace(priv->dma.tx.size, txwr, priv->eskbp) && 86562306a36Sopenharmony_ci !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) 86662306a36Sopenharmony_ci netif_wake_queue(dev); 86762306a36Sopenharmony_ci } 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci netdev_err(dev, "Device reset and restored\n"); 87262306a36Sopenharmony_ci} 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci/* Waiting time in usecs corresponding to the transmission of three maximum 87562306a36Sopenharmony_ci * sized can frames in the given bitrate (in bits/sec). Waiting for this amount 87662306a36Sopenharmony_ci * of time makes sure that the can controller have time to finish sending or 87762306a36Sopenharmony_ci * receiving a frame with a good margin. 87862306a36Sopenharmony_ci * 87962306a36Sopenharmony_ci * usecs/sec * number of frames * bits/frame / bits/sec 88062306a36Sopenharmony_ci */ 88162306a36Sopenharmony_cistatic inline u32 grcan_ongoing_wait_usecs(__u32 bitrate) 88262306a36Sopenharmony_ci{ 88362306a36Sopenharmony_ci return 1000000 * 3 * GRCAN_EFF_FRAME_MAX_BITS / bitrate; 88462306a36Sopenharmony_ci} 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci/* Set timer so that it will not fire until after a period in which the can 88762306a36Sopenharmony_ci * controller have a good margin to finish transmitting a frame unless it has 88862306a36Sopenharmony_ci * hanged 88962306a36Sopenharmony_ci */ 89062306a36Sopenharmony_cistatic inline void grcan_reset_timer(struct timer_list *timer, __u32 bitrate) 89162306a36Sopenharmony_ci{ 89262306a36Sopenharmony_ci u32 wait_jiffies = usecs_to_jiffies(grcan_ongoing_wait_usecs(bitrate)); 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci mod_timer(timer, jiffies + wait_jiffies); 89562306a36Sopenharmony_ci} 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci/* Disable channels and schedule a running reset */ 89862306a36Sopenharmony_cistatic void grcan_initiate_running_reset(struct timer_list *t) 89962306a36Sopenharmony_ci{ 90062306a36Sopenharmony_ci struct grcan_priv *priv = from_timer(priv, t, hang_timer); 90162306a36Sopenharmony_ci struct net_device *dev = priv->dev; 90262306a36Sopenharmony_ci struct grcan_registers __iomem *regs = priv->regs; 90362306a36Sopenharmony_ci unsigned long flags; 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci netdev_err(dev, "Device seems hanged - reset scheduled\n"); 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci /* The main body of this function must never be executed again 91062306a36Sopenharmony_ci * until after an execution of grcan_running_reset 91162306a36Sopenharmony_ci */ 91262306a36Sopenharmony_ci if (!priv->resetting && !priv->closing) { 91362306a36Sopenharmony_ci priv->resetting = true; 91462306a36Sopenharmony_ci netif_stop_queue(dev); 91562306a36Sopenharmony_ci grcan_clear_bits(®s->txctrl, GRCAN_TXCTRL_ENABLE); 91662306a36Sopenharmony_ci grcan_clear_bits(®s->rxctrl, GRCAN_RXCTRL_ENABLE); 91762306a36Sopenharmony_ci grcan_reset_timer(&priv->rr_timer, priv->can.bittiming.bitrate); 91862306a36Sopenharmony_ci } 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 92162306a36Sopenharmony_ci} 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_cistatic void grcan_free_dma_buffers(struct net_device *dev) 92462306a36Sopenharmony_ci{ 92562306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 92662306a36Sopenharmony_ci struct grcan_dma *dma = &priv->dma; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci dma_free_coherent(priv->ofdev_dev, dma->base_size, dma->base_buf, 92962306a36Sopenharmony_ci dma->base_handle); 93062306a36Sopenharmony_ci memset(dma, 0, sizeof(*dma)); 93162306a36Sopenharmony_ci} 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_cistatic int grcan_allocate_dma_buffers(struct net_device *dev, 93462306a36Sopenharmony_ci size_t tsize, size_t rsize) 93562306a36Sopenharmony_ci{ 93662306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 93762306a36Sopenharmony_ci struct grcan_dma *dma = &priv->dma; 93862306a36Sopenharmony_ci struct grcan_dma_buffer *large = rsize > tsize ? &dma->rx : &dma->tx; 93962306a36Sopenharmony_ci struct grcan_dma_buffer *small = rsize > tsize ? &dma->tx : &dma->rx; 94062306a36Sopenharmony_ci size_t shift; 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci /* Need a whole number of GRCAN_BUFFER_ALIGNMENT for the large, 94362306a36Sopenharmony_ci * i.e. first buffer 94462306a36Sopenharmony_ci */ 94562306a36Sopenharmony_ci size_t maxs = max(tsize, rsize); 94662306a36Sopenharmony_ci size_t lsize = ALIGN(maxs, GRCAN_BUFFER_ALIGNMENT); 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci /* Put the small buffer after that */ 94962306a36Sopenharmony_ci size_t ssize = min(tsize, rsize); 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_ci /* Extra GRCAN_BUFFER_ALIGNMENT to allow for alignment */ 95262306a36Sopenharmony_ci dma->base_size = lsize + ssize + GRCAN_BUFFER_ALIGNMENT; 95362306a36Sopenharmony_ci dma->base_buf = dma_alloc_coherent(priv->ofdev_dev, 95462306a36Sopenharmony_ci dma->base_size, 95562306a36Sopenharmony_ci &dma->base_handle, 95662306a36Sopenharmony_ci GFP_KERNEL); 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci if (!dma->base_buf) 95962306a36Sopenharmony_ci return -ENOMEM; 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci dma->tx.size = tsize; 96262306a36Sopenharmony_ci dma->rx.size = rsize; 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci large->handle = ALIGN(dma->base_handle, GRCAN_BUFFER_ALIGNMENT); 96562306a36Sopenharmony_ci small->handle = large->handle + lsize; 96662306a36Sopenharmony_ci shift = large->handle - dma->base_handle; 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci large->buf = dma->base_buf + shift; 96962306a36Sopenharmony_ci small->buf = large->buf + lsize; 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci return 0; 97262306a36Sopenharmony_ci} 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci/* priv->lock *must* be held when calling this function */ 97562306a36Sopenharmony_cistatic int grcan_start(struct net_device *dev) 97662306a36Sopenharmony_ci{ 97762306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 97862306a36Sopenharmony_ci struct grcan_registers __iomem *regs = priv->regs; 97962306a36Sopenharmony_ci u32 confop, txctrl; 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci grcan_reset(dev); 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci grcan_write_reg(®s->txaddr, priv->dma.tx.handle); 98462306a36Sopenharmony_ci grcan_write_reg(®s->txsize, priv->dma.tx.size); 98562306a36Sopenharmony_ci /* regs->txwr, regs->txrd and priv->eskbp already set to 0 by reset */ 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci grcan_write_reg(®s->rxaddr, priv->dma.rx.handle); 98862306a36Sopenharmony_ci grcan_write_reg(®s->rxsize, priv->dma.rx.size); 98962306a36Sopenharmony_ci /* regs->rxwr and regs->rxrd already set to 0 by reset */ 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci /* Enable interrupts */ 99262306a36Sopenharmony_ci grcan_read_reg(®s->pir); 99362306a36Sopenharmony_ci grcan_write_reg(®s->imr, GRCAN_IRQ_DEFAULT); 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci /* Enable interfaces, channels and device */ 99662306a36Sopenharmony_ci confop = GRCAN_CONF_ABORT 99762306a36Sopenharmony_ci | (priv->config.enable0 ? GRCAN_CONF_ENABLE0 : 0) 99862306a36Sopenharmony_ci | (priv->config.enable1 ? GRCAN_CONF_ENABLE1 : 0) 99962306a36Sopenharmony_ci | (priv->config.select ? GRCAN_CONF_SELECT : 0) 100062306a36Sopenharmony_ci | (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY ? 100162306a36Sopenharmony_ci GRCAN_CONF_SILENT : 0) 100262306a36Sopenharmony_ci | (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES ? 100362306a36Sopenharmony_ci GRCAN_CONF_SAM : 0); 100462306a36Sopenharmony_ci grcan_write_bits(®s->conf, confop, GRCAN_CONF_OPERATION); 100562306a36Sopenharmony_ci txctrl = GRCAN_TXCTRL_ENABLE 100662306a36Sopenharmony_ci | (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT 100762306a36Sopenharmony_ci ? GRCAN_TXCTRL_SINGLE : 0); 100862306a36Sopenharmony_ci grcan_write_reg(®s->txctrl, txctrl); 100962306a36Sopenharmony_ci grcan_write_reg(®s->rxctrl, GRCAN_RXCTRL_ENABLE); 101062306a36Sopenharmony_ci grcan_write_reg(®s->ctrl, GRCAN_CTRL_ENABLE); 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci priv->can.state = CAN_STATE_ERROR_ACTIVE; 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci return 0; 101562306a36Sopenharmony_ci} 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_cistatic int grcan_set_mode(struct net_device *dev, enum can_mode mode) 101862306a36Sopenharmony_ci{ 101962306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 102062306a36Sopenharmony_ci unsigned long flags; 102162306a36Sopenharmony_ci int err = 0; 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci if (mode == CAN_MODE_START) { 102462306a36Sopenharmony_ci /* This might be called to restart the device to recover from 102562306a36Sopenharmony_ci * bus off errors 102662306a36Sopenharmony_ci */ 102762306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 102862306a36Sopenharmony_ci if (priv->closing || priv->resetting) { 102962306a36Sopenharmony_ci err = -EBUSY; 103062306a36Sopenharmony_ci } else { 103162306a36Sopenharmony_ci netdev_info(dev, "Restarting device\n"); 103262306a36Sopenharmony_ci grcan_start(dev); 103362306a36Sopenharmony_ci if (!(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) 103462306a36Sopenharmony_ci netif_wake_queue(dev); 103562306a36Sopenharmony_ci } 103662306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 103762306a36Sopenharmony_ci return err; 103862306a36Sopenharmony_ci } 103962306a36Sopenharmony_ci return -EOPNOTSUPP; 104062306a36Sopenharmony_ci} 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_cistatic int grcan_open(struct net_device *dev) 104362306a36Sopenharmony_ci{ 104462306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 104562306a36Sopenharmony_ci struct grcan_dma *dma = &priv->dma; 104662306a36Sopenharmony_ci unsigned long flags; 104762306a36Sopenharmony_ci int err; 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci /* Allocate memory */ 105062306a36Sopenharmony_ci err = grcan_allocate_dma_buffers(dev, priv->config.txsize, 105162306a36Sopenharmony_ci priv->config.rxsize); 105262306a36Sopenharmony_ci if (err) { 105362306a36Sopenharmony_ci netdev_err(dev, "could not allocate DMA buffers\n"); 105462306a36Sopenharmony_ci return err; 105562306a36Sopenharmony_ci } 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci priv->echo_skb = kcalloc(dma->tx.size, sizeof(*priv->echo_skb), 105862306a36Sopenharmony_ci GFP_KERNEL); 105962306a36Sopenharmony_ci if (!priv->echo_skb) { 106062306a36Sopenharmony_ci err = -ENOMEM; 106162306a36Sopenharmony_ci goto exit_free_dma_buffers; 106262306a36Sopenharmony_ci } 106362306a36Sopenharmony_ci priv->can.echo_skb_max = dma->tx.size; 106462306a36Sopenharmony_ci priv->can.echo_skb = priv->echo_skb; 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci /* Get can device up */ 106762306a36Sopenharmony_ci err = open_candev(dev); 106862306a36Sopenharmony_ci if (err) 106962306a36Sopenharmony_ci goto exit_free_echo_skb; 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci err = request_irq(dev->irq, grcan_interrupt, IRQF_SHARED, 107262306a36Sopenharmony_ci dev->name, dev); 107362306a36Sopenharmony_ci if (err) 107462306a36Sopenharmony_ci goto exit_close_candev; 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci napi_enable(&priv->napi); 107962306a36Sopenharmony_ci grcan_start(dev); 108062306a36Sopenharmony_ci if (!(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) 108162306a36Sopenharmony_ci netif_start_queue(dev); 108262306a36Sopenharmony_ci priv->resetting = false; 108362306a36Sopenharmony_ci priv->closing = false; 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci return 0; 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_ciexit_close_candev: 109062306a36Sopenharmony_ci close_candev(dev); 109162306a36Sopenharmony_ciexit_free_echo_skb: 109262306a36Sopenharmony_ci kfree(priv->echo_skb); 109362306a36Sopenharmony_ciexit_free_dma_buffers: 109462306a36Sopenharmony_ci grcan_free_dma_buffers(dev); 109562306a36Sopenharmony_ci return err; 109662306a36Sopenharmony_ci} 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_cistatic int grcan_close(struct net_device *dev) 109962306a36Sopenharmony_ci{ 110062306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 110162306a36Sopenharmony_ci unsigned long flags; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci napi_disable(&priv->napi); 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci priv->closing = true; 110862306a36Sopenharmony_ci if (priv->need_txbug_workaround) { 110962306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 111062306a36Sopenharmony_ci del_timer_sync(&priv->hang_timer); 111162306a36Sopenharmony_ci del_timer_sync(&priv->rr_timer); 111262306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 111362306a36Sopenharmony_ci } 111462306a36Sopenharmony_ci netif_stop_queue(dev); 111562306a36Sopenharmony_ci grcan_stop_hardware(dev); 111662306a36Sopenharmony_ci priv->can.state = CAN_STATE_STOPPED; 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci free_irq(dev->irq, dev); 112162306a36Sopenharmony_ci close_candev(dev); 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ci grcan_free_dma_buffers(dev); 112462306a36Sopenharmony_ci priv->can.echo_skb_max = 0; 112562306a36Sopenharmony_ci priv->can.echo_skb = NULL; 112662306a36Sopenharmony_ci kfree(priv->echo_skb); 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci return 0; 112962306a36Sopenharmony_ci} 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_cistatic void grcan_transmit_catch_up(struct net_device *dev) 113262306a36Sopenharmony_ci{ 113362306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 113462306a36Sopenharmony_ci unsigned long flags; 113562306a36Sopenharmony_ci int work_done; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ci work_done = catch_up_echo_skb(dev, -1, true); 114062306a36Sopenharmony_ci if (work_done) { 114162306a36Sopenharmony_ci if (!priv->resetting && !priv->closing && 114262306a36Sopenharmony_ci !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) 114362306a36Sopenharmony_ci netif_wake_queue(dev); 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci /* With napi we don't get TX interrupts for a while, 114662306a36Sopenharmony_ci * so prevent a running reset while catching up 114762306a36Sopenharmony_ci */ 114862306a36Sopenharmony_ci if (priv->need_txbug_workaround) 114962306a36Sopenharmony_ci del_timer(&priv->hang_timer); 115062306a36Sopenharmony_ci } 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 115362306a36Sopenharmony_ci} 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_cistatic int grcan_receive(struct net_device *dev, int budget) 115662306a36Sopenharmony_ci{ 115762306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 115862306a36Sopenharmony_ci struct grcan_registers __iomem *regs = priv->regs; 115962306a36Sopenharmony_ci struct grcan_dma *dma = &priv->dma; 116062306a36Sopenharmony_ci struct net_device_stats *stats = &dev->stats; 116162306a36Sopenharmony_ci struct can_frame *cf; 116262306a36Sopenharmony_ci struct sk_buff *skb; 116362306a36Sopenharmony_ci u32 wr, rd, startrd; 116462306a36Sopenharmony_ci u32 *slot; 116562306a36Sopenharmony_ci u32 i, rtr, eff, j, shift; 116662306a36Sopenharmony_ci int work_done = 0; 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci rd = grcan_read_reg(®s->rxrd); 116962306a36Sopenharmony_ci startrd = rd; 117062306a36Sopenharmony_ci for (work_done = 0; work_done < budget; work_done++) { 117162306a36Sopenharmony_ci /* Check for packet to receive */ 117262306a36Sopenharmony_ci wr = grcan_read_reg(®s->rxwr); 117362306a36Sopenharmony_ci if (rd == wr) 117462306a36Sopenharmony_ci break; 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci /* Take care of packet */ 117762306a36Sopenharmony_ci skb = alloc_can_skb(dev, &cf); 117862306a36Sopenharmony_ci if (skb == NULL) { 117962306a36Sopenharmony_ci netdev_err(dev, 118062306a36Sopenharmony_ci "dropping frame: skb allocation failed\n"); 118162306a36Sopenharmony_ci stats->rx_dropped++; 118262306a36Sopenharmony_ci continue; 118362306a36Sopenharmony_ci } 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci slot = dma->rx.buf + rd; 118662306a36Sopenharmony_ci eff = slot[0] & GRCAN_MSG_IDE; 118762306a36Sopenharmony_ci rtr = slot[0] & GRCAN_MSG_RTR; 118862306a36Sopenharmony_ci if (eff) { 118962306a36Sopenharmony_ci cf->can_id = ((slot[0] & GRCAN_MSG_EID) 119062306a36Sopenharmony_ci >> GRCAN_MSG_EID_BIT); 119162306a36Sopenharmony_ci cf->can_id |= CAN_EFF_FLAG; 119262306a36Sopenharmony_ci } else { 119362306a36Sopenharmony_ci cf->can_id = ((slot[0] & GRCAN_MSG_BID) 119462306a36Sopenharmony_ci >> GRCAN_MSG_BID_BIT); 119562306a36Sopenharmony_ci } 119662306a36Sopenharmony_ci cf->len = can_cc_dlc2len((slot[1] & GRCAN_MSG_DLC) 119762306a36Sopenharmony_ci >> GRCAN_MSG_DLC_BIT); 119862306a36Sopenharmony_ci if (rtr) { 119962306a36Sopenharmony_ci cf->can_id |= CAN_RTR_FLAG; 120062306a36Sopenharmony_ci } else { 120162306a36Sopenharmony_ci for (i = 0; i < cf->len; i++) { 120262306a36Sopenharmony_ci j = GRCAN_MSG_DATA_SLOT_INDEX(i); 120362306a36Sopenharmony_ci shift = GRCAN_MSG_DATA_SHIFT(i); 120462306a36Sopenharmony_ci cf->data[i] = (u8)(slot[j] >> shift); 120562306a36Sopenharmony_ci } 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci stats->rx_bytes += cf->len; 120862306a36Sopenharmony_ci } 120962306a36Sopenharmony_ci stats->rx_packets++; 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci netif_receive_skb(skb); 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_ci rd = grcan_ring_add(rd, GRCAN_MSG_SIZE, dma->rx.size); 121462306a36Sopenharmony_ci } 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci /* Make sure everything is read before allowing hardware to 121762306a36Sopenharmony_ci * use the memory 121862306a36Sopenharmony_ci */ 121962306a36Sopenharmony_ci mb(); 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci /* Update read pointer - no need to check for ongoing */ 122262306a36Sopenharmony_ci if (likely(rd != startrd)) 122362306a36Sopenharmony_ci grcan_write_reg(®s->rxrd, rd); 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci return work_done; 122662306a36Sopenharmony_ci} 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_cistatic int grcan_poll(struct napi_struct *napi, int budget) 122962306a36Sopenharmony_ci{ 123062306a36Sopenharmony_ci struct grcan_priv *priv = container_of(napi, struct grcan_priv, napi); 123162306a36Sopenharmony_ci struct net_device *dev = priv->dev; 123262306a36Sopenharmony_ci struct grcan_registers __iomem *regs = priv->regs; 123362306a36Sopenharmony_ci unsigned long flags; 123462306a36Sopenharmony_ci int work_done; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci work_done = grcan_receive(dev, budget); 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci grcan_transmit_catch_up(dev); 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci if (work_done < budget) { 124162306a36Sopenharmony_ci napi_complete(napi); 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_ci /* Guarantee no interference with a running reset that otherwise 124462306a36Sopenharmony_ci * could turn off interrupts. 124562306a36Sopenharmony_ci */ 124662306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci /* Enable tx and rx interrupts again. No need to check 124962306a36Sopenharmony_ci * priv->closing as napi_disable in grcan_close is waiting for 125062306a36Sopenharmony_ci * scheduled napi calls to finish. 125162306a36Sopenharmony_ci */ 125262306a36Sopenharmony_ci grcan_set_bits(®s->imr, GRCAN_IRQ_TX | GRCAN_IRQ_RX); 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 125562306a36Sopenharmony_ci } 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_ci return work_done; 125862306a36Sopenharmony_ci} 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci/* Work tx bug by waiting while for the risky situation to clear. If that fails, 126162306a36Sopenharmony_ci * drop a frame in one-shot mode or indicate a busy device otherwise. 126262306a36Sopenharmony_ci * 126362306a36Sopenharmony_ci * Returns 0 on successful wait. Otherwise it sets *netdev_tx_status to the 126462306a36Sopenharmony_ci * value that should be returned by grcan_start_xmit when aborting the xmit. 126562306a36Sopenharmony_ci */ 126662306a36Sopenharmony_cistatic int grcan_txbug_workaround(struct net_device *dev, struct sk_buff *skb, 126762306a36Sopenharmony_ci u32 txwr, u32 oneshotmode, 126862306a36Sopenharmony_ci netdev_tx_t *netdev_tx_status) 126962306a36Sopenharmony_ci{ 127062306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 127162306a36Sopenharmony_ci struct grcan_registers __iomem *regs = priv->regs; 127262306a36Sopenharmony_ci struct grcan_dma *dma = &priv->dma; 127362306a36Sopenharmony_ci int i; 127462306a36Sopenharmony_ci unsigned long flags; 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci /* Wait a while for ongoing to be cleared or read pointer to catch up to 127762306a36Sopenharmony_ci * write pointer. The latter is needed due to a bug in older versions of 127862306a36Sopenharmony_ci * GRCAN in which ONGOING is not cleared properly one-shot mode when a 127962306a36Sopenharmony_ci * transmission fails. 128062306a36Sopenharmony_ci */ 128162306a36Sopenharmony_ci for (i = 0; i < GRCAN_SHORTWAIT_USECS; i++) { 128262306a36Sopenharmony_ci udelay(1); 128362306a36Sopenharmony_ci if (!grcan_read_bits(®s->txctrl, GRCAN_TXCTRL_ONGOING) || 128462306a36Sopenharmony_ci grcan_read_reg(®s->txrd) == txwr) { 128562306a36Sopenharmony_ci return 0; 128662306a36Sopenharmony_ci } 128762306a36Sopenharmony_ci } 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci /* Clean up, in case the situation was not resolved */ 129062306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 129162306a36Sopenharmony_ci if (!priv->resetting && !priv->closing) { 129262306a36Sopenharmony_ci /* Queue might have been stopped earlier in grcan_start_xmit */ 129362306a36Sopenharmony_ci if (grcan_txspace(dma->tx.size, txwr, priv->eskbp)) 129462306a36Sopenharmony_ci netif_wake_queue(dev); 129562306a36Sopenharmony_ci /* Set a timer to resolve a hanged tx controller */ 129662306a36Sopenharmony_ci if (!timer_pending(&priv->hang_timer)) 129762306a36Sopenharmony_ci grcan_reset_timer(&priv->hang_timer, 129862306a36Sopenharmony_ci priv->can.bittiming.bitrate); 129962306a36Sopenharmony_ci } 130062306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci if (oneshotmode) { 130362306a36Sopenharmony_ci /* In one-shot mode we should never end up here because 130462306a36Sopenharmony_ci * then the interrupt handler increases txrd on TXLOSS, 130562306a36Sopenharmony_ci * but it is consistent with one-shot mode to drop the 130662306a36Sopenharmony_ci * frame in this case. 130762306a36Sopenharmony_ci */ 130862306a36Sopenharmony_ci kfree_skb(skb); 130962306a36Sopenharmony_ci *netdev_tx_status = NETDEV_TX_OK; 131062306a36Sopenharmony_ci } else { 131162306a36Sopenharmony_ci /* In normal mode the socket-can transmission queue get 131262306a36Sopenharmony_ci * to keep the frame so that it can be retransmitted 131362306a36Sopenharmony_ci * later 131462306a36Sopenharmony_ci */ 131562306a36Sopenharmony_ci *netdev_tx_status = NETDEV_TX_BUSY; 131662306a36Sopenharmony_ci } 131762306a36Sopenharmony_ci return -EBUSY; 131862306a36Sopenharmony_ci} 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci/* Notes on the tx cyclic buffer handling: 132162306a36Sopenharmony_ci * 132262306a36Sopenharmony_ci * regs->txwr - the next slot for the driver to put data to be sent 132362306a36Sopenharmony_ci * regs->txrd - the next slot for the device to read data 132462306a36Sopenharmony_ci * priv->eskbp - the next slot for the driver to call can_put_echo_skb for 132562306a36Sopenharmony_ci * 132662306a36Sopenharmony_ci * grcan_start_xmit can enter more messages as long as regs->txwr does 132762306a36Sopenharmony_ci * not reach priv->eskbp (within 1 message gap) 132862306a36Sopenharmony_ci * 132962306a36Sopenharmony_ci * The device sends messages until regs->txrd reaches regs->txwr 133062306a36Sopenharmony_ci * 133162306a36Sopenharmony_ci * The interrupt calls handler calls can_put_echo_skb until 133262306a36Sopenharmony_ci * priv->eskbp reaches regs->txrd 133362306a36Sopenharmony_ci */ 133462306a36Sopenharmony_cistatic netdev_tx_t grcan_start_xmit(struct sk_buff *skb, 133562306a36Sopenharmony_ci struct net_device *dev) 133662306a36Sopenharmony_ci{ 133762306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 133862306a36Sopenharmony_ci struct grcan_registers __iomem *regs = priv->regs; 133962306a36Sopenharmony_ci struct grcan_dma *dma = &priv->dma; 134062306a36Sopenharmony_ci struct can_frame *cf = (struct can_frame *)skb->data; 134162306a36Sopenharmony_ci u32 id, txwr, txrd, space, txctrl; 134262306a36Sopenharmony_ci int slotindex; 134362306a36Sopenharmony_ci u32 *slot; 134462306a36Sopenharmony_ci u32 i, rtr, eff, dlc, tmp, err; 134562306a36Sopenharmony_ci int j, shift; 134662306a36Sopenharmony_ci unsigned long flags; 134762306a36Sopenharmony_ci u32 oneshotmode = priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT; 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci if (can_dev_dropped_skb(dev, skb)) 135062306a36Sopenharmony_ci return NETDEV_TX_OK; 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci /* Trying to transmit in silent mode will generate error interrupts, but 135362306a36Sopenharmony_ci * this should never happen - the queue should not have been started. 135462306a36Sopenharmony_ci */ 135562306a36Sopenharmony_ci if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) 135662306a36Sopenharmony_ci return NETDEV_TX_BUSY; 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci /* Reads of priv->eskbp and shut-downs of the queue needs to 135962306a36Sopenharmony_ci * be atomic towards the updates to priv->eskbp and wake-ups 136062306a36Sopenharmony_ci * of the queue in the interrupt handler. 136162306a36Sopenharmony_ci */ 136262306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci txwr = grcan_read_reg(®s->txwr); 136562306a36Sopenharmony_ci space = grcan_txspace(dma->tx.size, txwr, priv->eskbp); 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci slotindex = txwr / GRCAN_MSG_SIZE; 136862306a36Sopenharmony_ci slot = dma->tx.buf + txwr; 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci if (unlikely(space == 1)) 137162306a36Sopenharmony_ci netif_stop_queue(dev); 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 137462306a36Sopenharmony_ci /* End of critical section*/ 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci /* This should never happen. If circular buffer is full, the 137762306a36Sopenharmony_ci * netif_stop_queue should have been stopped already. 137862306a36Sopenharmony_ci */ 137962306a36Sopenharmony_ci if (unlikely(!space)) { 138062306a36Sopenharmony_ci netdev_err(dev, "No buffer space, but queue is non-stopped.\n"); 138162306a36Sopenharmony_ci return NETDEV_TX_BUSY; 138262306a36Sopenharmony_ci } 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci /* Convert and write CAN message to DMA buffer */ 138562306a36Sopenharmony_ci eff = cf->can_id & CAN_EFF_FLAG; 138662306a36Sopenharmony_ci rtr = cf->can_id & CAN_RTR_FLAG; 138762306a36Sopenharmony_ci id = cf->can_id & (eff ? CAN_EFF_MASK : CAN_SFF_MASK); 138862306a36Sopenharmony_ci dlc = cf->len; 138962306a36Sopenharmony_ci if (eff) 139062306a36Sopenharmony_ci tmp = (id << GRCAN_MSG_EID_BIT) & GRCAN_MSG_EID; 139162306a36Sopenharmony_ci else 139262306a36Sopenharmony_ci tmp = (id << GRCAN_MSG_BID_BIT) & GRCAN_MSG_BID; 139362306a36Sopenharmony_ci slot[0] = (eff ? GRCAN_MSG_IDE : 0) | (rtr ? GRCAN_MSG_RTR : 0) | tmp; 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci slot[1] = ((dlc << GRCAN_MSG_DLC_BIT) & GRCAN_MSG_DLC); 139662306a36Sopenharmony_ci slot[2] = 0; 139762306a36Sopenharmony_ci slot[3] = 0; 139862306a36Sopenharmony_ci for (i = 0; i < dlc; i++) { 139962306a36Sopenharmony_ci j = GRCAN_MSG_DATA_SLOT_INDEX(i); 140062306a36Sopenharmony_ci shift = GRCAN_MSG_DATA_SHIFT(i); 140162306a36Sopenharmony_ci slot[j] |= cf->data[i] << shift; 140262306a36Sopenharmony_ci } 140362306a36Sopenharmony_ci 140462306a36Sopenharmony_ci /* Checking that channel has not been disabled. These cases 140562306a36Sopenharmony_ci * should never happen 140662306a36Sopenharmony_ci */ 140762306a36Sopenharmony_ci txctrl = grcan_read_reg(®s->txctrl); 140862306a36Sopenharmony_ci if (!(txctrl & GRCAN_TXCTRL_ENABLE)) 140962306a36Sopenharmony_ci netdev_err(dev, "tx channel spuriously disabled\n"); 141062306a36Sopenharmony_ci 141162306a36Sopenharmony_ci if (oneshotmode && !(txctrl & GRCAN_TXCTRL_SINGLE)) 141262306a36Sopenharmony_ci netdev_err(dev, "one-shot mode spuriously disabled\n"); 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci /* Bug workaround for old version of grcan where updating txwr 141562306a36Sopenharmony_ci * in the same clock cycle as the controller updates txrd to 141662306a36Sopenharmony_ci * the current txwr could hang the can controller 141762306a36Sopenharmony_ci */ 141862306a36Sopenharmony_ci if (priv->need_txbug_workaround) { 141962306a36Sopenharmony_ci txrd = grcan_read_reg(®s->txrd); 142062306a36Sopenharmony_ci if (unlikely(grcan_ring_sub(txwr, txrd, dma->tx.size) == 1)) { 142162306a36Sopenharmony_ci netdev_tx_t txstatus; 142262306a36Sopenharmony_ci 142362306a36Sopenharmony_ci err = grcan_txbug_workaround(dev, skb, txwr, 142462306a36Sopenharmony_ci oneshotmode, &txstatus); 142562306a36Sopenharmony_ci if (err) 142662306a36Sopenharmony_ci return txstatus; 142762306a36Sopenharmony_ci } 142862306a36Sopenharmony_ci } 142962306a36Sopenharmony_ci 143062306a36Sopenharmony_ci /* Prepare skb for echoing. This must be after the bug workaround above 143162306a36Sopenharmony_ci * as ownership of the skb is passed on by calling can_put_echo_skb. 143262306a36Sopenharmony_ci * Returning NETDEV_TX_BUSY or accessing skb or cf after a call to 143362306a36Sopenharmony_ci * can_put_echo_skb would be an error unless other measures are 143462306a36Sopenharmony_ci * taken. 143562306a36Sopenharmony_ci */ 143662306a36Sopenharmony_ci can_put_echo_skb(skb, dev, slotindex, 0); 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_ci /* Make sure everything is written before allowing hardware to 143962306a36Sopenharmony_ci * read from the memory 144062306a36Sopenharmony_ci */ 144162306a36Sopenharmony_ci wmb(); 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_ci /* Update write pointer to start transmission */ 144462306a36Sopenharmony_ci grcan_write_reg(®s->txwr, 144562306a36Sopenharmony_ci grcan_ring_add(txwr, GRCAN_MSG_SIZE, dma->tx.size)); 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci return NETDEV_TX_OK; 144862306a36Sopenharmony_ci} 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci/* ========== Setting up sysfs interface and module parameters ========== */ 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci#define GRCAN_NOT_BOOL(unsigned_val) ((unsigned_val) > 1) 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_ci#define GRCAN_MODULE_PARAM(name, mtype, valcheckf, desc) \ 145562306a36Sopenharmony_ci static void grcan_sanitize_##name(struct platform_device *pd) \ 145662306a36Sopenharmony_ci { \ 145762306a36Sopenharmony_ci struct grcan_device_config grcan_default_config \ 145862306a36Sopenharmony_ci = GRCAN_DEFAULT_DEVICE_CONFIG; \ 145962306a36Sopenharmony_ci if (valcheckf(grcan_module_config.name)) { \ 146062306a36Sopenharmony_ci dev_err(&pd->dev, \ 146162306a36Sopenharmony_ci "Invalid module parameter value for " \ 146262306a36Sopenharmony_ci #name " - setting default\n"); \ 146362306a36Sopenharmony_ci grcan_module_config.name = \ 146462306a36Sopenharmony_ci grcan_default_config.name; \ 146562306a36Sopenharmony_ci } \ 146662306a36Sopenharmony_ci } \ 146762306a36Sopenharmony_ci module_param_named(name, grcan_module_config.name, \ 146862306a36Sopenharmony_ci mtype, 0444); \ 146962306a36Sopenharmony_ci MODULE_PARM_DESC(name, desc) 147062306a36Sopenharmony_ci 147162306a36Sopenharmony_ci#define GRCAN_CONFIG_ATTR(name, desc) \ 147262306a36Sopenharmony_ci static ssize_t grcan_store_##name(struct device *sdev, \ 147362306a36Sopenharmony_ci struct device_attribute *att, \ 147462306a36Sopenharmony_ci const char *buf, \ 147562306a36Sopenharmony_ci size_t count) \ 147662306a36Sopenharmony_ci { \ 147762306a36Sopenharmony_ci struct net_device *dev = to_net_dev(sdev); \ 147862306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); \ 147962306a36Sopenharmony_ci u8 val; \ 148062306a36Sopenharmony_ci int ret; \ 148162306a36Sopenharmony_ci if (dev->flags & IFF_UP) \ 148262306a36Sopenharmony_ci return -EBUSY; \ 148362306a36Sopenharmony_ci ret = kstrtou8(buf, 0, &val); \ 148462306a36Sopenharmony_ci if (ret < 0 || val > 1) \ 148562306a36Sopenharmony_ci return -EINVAL; \ 148662306a36Sopenharmony_ci priv->config.name = val; \ 148762306a36Sopenharmony_ci return count; \ 148862306a36Sopenharmony_ci } \ 148962306a36Sopenharmony_ci static ssize_t grcan_show_##name(struct device *sdev, \ 149062306a36Sopenharmony_ci struct device_attribute *att, \ 149162306a36Sopenharmony_ci char *buf) \ 149262306a36Sopenharmony_ci { \ 149362306a36Sopenharmony_ci struct net_device *dev = to_net_dev(sdev); \ 149462306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); \ 149562306a36Sopenharmony_ci return sprintf(buf, "%d\n", priv->config.name); \ 149662306a36Sopenharmony_ci } \ 149762306a36Sopenharmony_ci static DEVICE_ATTR(name, 0644, \ 149862306a36Sopenharmony_ci grcan_show_##name, \ 149962306a36Sopenharmony_ci grcan_store_##name); \ 150062306a36Sopenharmony_ci GRCAN_MODULE_PARAM(name, ushort, GRCAN_NOT_BOOL, desc) 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_ci/* The following configuration options are made available both via module 150362306a36Sopenharmony_ci * parameters and writable sysfs files. See the chapter about GRCAN in the 150462306a36Sopenharmony_ci * documentation for the GRLIB VHDL library for further details. 150562306a36Sopenharmony_ci */ 150662306a36Sopenharmony_ciGRCAN_CONFIG_ATTR(enable0, 150762306a36Sopenharmony_ci "Configuration of physical interface 0. Determines\n" \ 150862306a36Sopenharmony_ci "the \"Enable 0\" bit of the configuration register.\n" \ 150962306a36Sopenharmony_ci "Format: 0 | 1\nDefault: 0\n"); 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ciGRCAN_CONFIG_ATTR(enable1, 151262306a36Sopenharmony_ci "Configuration of physical interface 1. Determines\n" \ 151362306a36Sopenharmony_ci "the \"Enable 1\" bit of the configuration register.\n" \ 151462306a36Sopenharmony_ci "Format: 0 | 1\nDefault: 0\n"); 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ciGRCAN_CONFIG_ATTR(select, 151762306a36Sopenharmony_ci "Select which physical interface to use.\n" \ 151862306a36Sopenharmony_ci "Format: 0 | 1\nDefault: 0\n"); 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_ci/* The tx and rx buffer size configuration options are only available via module 152162306a36Sopenharmony_ci * parameters. 152262306a36Sopenharmony_ci */ 152362306a36Sopenharmony_ciGRCAN_MODULE_PARAM(txsize, uint, GRCAN_INVALID_BUFFER_SIZE, 152462306a36Sopenharmony_ci "Sets the size of the tx buffer.\n" \ 152562306a36Sopenharmony_ci "Format: <unsigned int> where (txsize & ~0x1fffc0) == 0\n" \ 152662306a36Sopenharmony_ci "Default: 1024\n"); 152762306a36Sopenharmony_ciGRCAN_MODULE_PARAM(rxsize, uint, GRCAN_INVALID_BUFFER_SIZE, 152862306a36Sopenharmony_ci "Sets the size of the rx buffer.\n" \ 152962306a36Sopenharmony_ci "Format: <unsigned int> where (size & ~0x1fffc0) == 0\n" \ 153062306a36Sopenharmony_ci "Default: 1024\n"); 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci/* Function that makes sure that configuration done using 153362306a36Sopenharmony_ci * module parameters are set to valid values 153462306a36Sopenharmony_ci */ 153562306a36Sopenharmony_cistatic void grcan_sanitize_module_config(struct platform_device *ofdev) 153662306a36Sopenharmony_ci{ 153762306a36Sopenharmony_ci grcan_sanitize_enable0(ofdev); 153862306a36Sopenharmony_ci grcan_sanitize_enable1(ofdev); 153962306a36Sopenharmony_ci grcan_sanitize_select(ofdev); 154062306a36Sopenharmony_ci grcan_sanitize_txsize(ofdev); 154162306a36Sopenharmony_ci grcan_sanitize_rxsize(ofdev); 154262306a36Sopenharmony_ci} 154362306a36Sopenharmony_ci 154462306a36Sopenharmony_cistatic const struct attribute *const sysfs_grcan_attrs[] = { 154562306a36Sopenharmony_ci /* Config attrs */ 154662306a36Sopenharmony_ci &dev_attr_enable0.attr, 154762306a36Sopenharmony_ci &dev_attr_enable1.attr, 154862306a36Sopenharmony_ci &dev_attr_select.attr, 154962306a36Sopenharmony_ci NULL, 155062306a36Sopenharmony_ci}; 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_cistatic const struct attribute_group sysfs_grcan_group = { 155362306a36Sopenharmony_ci .name = "grcan", 155462306a36Sopenharmony_ci .attrs = (struct attribute **)sysfs_grcan_attrs, 155562306a36Sopenharmony_ci}; 155662306a36Sopenharmony_ci 155762306a36Sopenharmony_ci/* ========== Setting up the driver ========== */ 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_cistatic const struct net_device_ops grcan_netdev_ops = { 156062306a36Sopenharmony_ci .ndo_open = grcan_open, 156162306a36Sopenharmony_ci .ndo_stop = grcan_close, 156262306a36Sopenharmony_ci .ndo_start_xmit = grcan_start_xmit, 156362306a36Sopenharmony_ci .ndo_change_mtu = can_change_mtu, 156462306a36Sopenharmony_ci}; 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_cistatic const struct ethtool_ops grcan_ethtool_ops = { 156762306a36Sopenharmony_ci .get_ts_info = ethtool_op_get_ts_info, 156862306a36Sopenharmony_ci}; 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_cistatic int grcan_setup_netdev(struct platform_device *ofdev, 157162306a36Sopenharmony_ci void __iomem *base, 157262306a36Sopenharmony_ci int irq, u32 ambafreq, bool txbug) 157362306a36Sopenharmony_ci{ 157462306a36Sopenharmony_ci struct net_device *dev; 157562306a36Sopenharmony_ci struct grcan_priv *priv; 157662306a36Sopenharmony_ci struct grcan_registers __iomem *regs; 157762306a36Sopenharmony_ci int err; 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ci dev = alloc_candev(sizeof(struct grcan_priv), 0); 158062306a36Sopenharmony_ci if (!dev) 158162306a36Sopenharmony_ci return -ENOMEM; 158262306a36Sopenharmony_ci 158362306a36Sopenharmony_ci dev->irq = irq; 158462306a36Sopenharmony_ci dev->flags |= IFF_ECHO; 158562306a36Sopenharmony_ci dev->netdev_ops = &grcan_netdev_ops; 158662306a36Sopenharmony_ci dev->ethtool_ops = &grcan_ethtool_ops; 158762306a36Sopenharmony_ci dev->sysfs_groups[0] = &sysfs_grcan_group; 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci priv = netdev_priv(dev); 159062306a36Sopenharmony_ci memcpy(&priv->config, &grcan_module_config, 159162306a36Sopenharmony_ci sizeof(struct grcan_device_config)); 159262306a36Sopenharmony_ci priv->dev = dev; 159362306a36Sopenharmony_ci priv->ofdev_dev = &ofdev->dev; 159462306a36Sopenharmony_ci priv->regs = base; 159562306a36Sopenharmony_ci priv->can.bittiming_const = &grcan_bittiming_const; 159662306a36Sopenharmony_ci priv->can.do_set_bittiming = grcan_set_bittiming; 159762306a36Sopenharmony_ci priv->can.do_set_mode = grcan_set_mode; 159862306a36Sopenharmony_ci priv->can.do_get_berr_counter = grcan_get_berr_counter; 159962306a36Sopenharmony_ci priv->can.clock.freq = ambafreq; 160062306a36Sopenharmony_ci priv->can.ctrlmode_supported = 160162306a36Sopenharmony_ci CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_ONE_SHOT; 160262306a36Sopenharmony_ci priv->need_txbug_workaround = txbug; 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci /* Discover if triple sampling is supported by hardware */ 160562306a36Sopenharmony_ci regs = priv->regs; 160662306a36Sopenharmony_ci grcan_set_bits(®s->ctrl, GRCAN_CTRL_RESET); 160762306a36Sopenharmony_ci grcan_set_bits(®s->conf, GRCAN_CONF_SAM); 160862306a36Sopenharmony_ci if (grcan_read_bits(®s->conf, GRCAN_CONF_SAM)) { 160962306a36Sopenharmony_ci priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; 161062306a36Sopenharmony_ci dev_dbg(&ofdev->dev, "Hardware supports triple-sampling\n"); 161162306a36Sopenharmony_ci } 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_ci spin_lock_init(&priv->lock); 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci if (priv->need_txbug_workaround) { 161662306a36Sopenharmony_ci timer_setup(&priv->rr_timer, grcan_running_reset, 0); 161762306a36Sopenharmony_ci timer_setup(&priv->hang_timer, grcan_initiate_running_reset, 0); 161862306a36Sopenharmony_ci } 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci netif_napi_add_weight(dev, &priv->napi, grcan_poll, GRCAN_NAPI_WEIGHT); 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci SET_NETDEV_DEV(dev, &ofdev->dev); 162362306a36Sopenharmony_ci dev_info(&ofdev->dev, "regs=0x%p, irq=%d, clock=%d\n", 162462306a36Sopenharmony_ci priv->regs, dev->irq, priv->can.clock.freq); 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_ci err = register_candev(dev); 162762306a36Sopenharmony_ci if (err) 162862306a36Sopenharmony_ci goto exit_free_candev; 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ci platform_set_drvdata(ofdev, dev); 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci /* Reset device to allow bit-timing to be set. No need to call 163362306a36Sopenharmony_ci * grcan_reset at this stage. That is done in grcan_open. 163462306a36Sopenharmony_ci */ 163562306a36Sopenharmony_ci grcan_write_reg(®s->ctrl, GRCAN_CTRL_RESET); 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ci return 0; 163862306a36Sopenharmony_ciexit_free_candev: 163962306a36Sopenharmony_ci free_candev(dev); 164062306a36Sopenharmony_ci return err; 164162306a36Sopenharmony_ci} 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_cistatic int grcan_probe(struct platform_device *ofdev) 164462306a36Sopenharmony_ci{ 164562306a36Sopenharmony_ci struct device_node *np = ofdev->dev.of_node; 164662306a36Sopenharmony_ci struct device_node *sysid_parent; 164762306a36Sopenharmony_ci u32 sysid, ambafreq; 164862306a36Sopenharmony_ci int irq, err; 164962306a36Sopenharmony_ci void __iomem *base; 165062306a36Sopenharmony_ci bool txbug = true; 165162306a36Sopenharmony_ci 165262306a36Sopenharmony_ci /* Compare GRLIB version number with the first that does not 165362306a36Sopenharmony_ci * have the tx bug (see start_xmit) 165462306a36Sopenharmony_ci */ 165562306a36Sopenharmony_ci sysid_parent = of_find_node_by_path("/ambapp0"); 165662306a36Sopenharmony_ci if (sysid_parent) { 165762306a36Sopenharmony_ci err = of_property_read_u32(sysid_parent, "systemid", &sysid); 165862306a36Sopenharmony_ci if (!err && ((sysid & GRLIB_VERSION_MASK) >= 165962306a36Sopenharmony_ci GRCAN_TXBUG_SAFE_GRLIB_VERSION)) 166062306a36Sopenharmony_ci txbug = false; 166162306a36Sopenharmony_ci of_node_put(sysid_parent); 166262306a36Sopenharmony_ci } 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci err = of_property_read_u32(np, "freq", &ambafreq); 166562306a36Sopenharmony_ci if (err) { 166662306a36Sopenharmony_ci dev_err(&ofdev->dev, "unable to fetch \"freq\" property\n"); 166762306a36Sopenharmony_ci goto exit_error; 166862306a36Sopenharmony_ci } 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci base = devm_platform_ioremap_resource(ofdev, 0); 167162306a36Sopenharmony_ci if (IS_ERR(base)) { 167262306a36Sopenharmony_ci err = PTR_ERR(base); 167362306a36Sopenharmony_ci goto exit_error; 167462306a36Sopenharmony_ci } 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_ci irq = irq_of_parse_and_map(np, GRCAN_IRQIX_IRQ); 167762306a36Sopenharmony_ci if (!irq) { 167862306a36Sopenharmony_ci dev_err(&ofdev->dev, "no irq found\n"); 167962306a36Sopenharmony_ci err = -ENODEV; 168062306a36Sopenharmony_ci goto exit_error; 168162306a36Sopenharmony_ci } 168262306a36Sopenharmony_ci 168362306a36Sopenharmony_ci grcan_sanitize_module_config(ofdev); 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci err = grcan_setup_netdev(ofdev, base, irq, ambafreq, txbug); 168662306a36Sopenharmony_ci if (err) 168762306a36Sopenharmony_ci goto exit_dispose_irq; 168862306a36Sopenharmony_ci 168962306a36Sopenharmony_ci return 0; 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ciexit_dispose_irq: 169262306a36Sopenharmony_ci irq_dispose_mapping(irq); 169362306a36Sopenharmony_ciexit_error: 169462306a36Sopenharmony_ci dev_err(&ofdev->dev, 169562306a36Sopenharmony_ci "%s socket CAN driver initialization failed with error %d\n", 169662306a36Sopenharmony_ci DRV_NAME, err); 169762306a36Sopenharmony_ci return err; 169862306a36Sopenharmony_ci} 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_cistatic void grcan_remove(struct platform_device *ofdev) 170162306a36Sopenharmony_ci{ 170262306a36Sopenharmony_ci struct net_device *dev = platform_get_drvdata(ofdev); 170362306a36Sopenharmony_ci struct grcan_priv *priv = netdev_priv(dev); 170462306a36Sopenharmony_ci 170562306a36Sopenharmony_ci unregister_candev(dev); /* Will in turn call grcan_close */ 170662306a36Sopenharmony_ci 170762306a36Sopenharmony_ci irq_dispose_mapping(dev->irq); 170862306a36Sopenharmony_ci netif_napi_del(&priv->napi); 170962306a36Sopenharmony_ci free_candev(dev); 171062306a36Sopenharmony_ci} 171162306a36Sopenharmony_ci 171262306a36Sopenharmony_cistatic const struct of_device_id grcan_match[] = { 171362306a36Sopenharmony_ci {.name = "GAISLER_GRCAN"}, 171462306a36Sopenharmony_ci {.name = "01_03d"}, 171562306a36Sopenharmony_ci {.name = "GAISLER_GRHCAN"}, 171662306a36Sopenharmony_ci {.name = "01_034"}, 171762306a36Sopenharmony_ci {}, 171862306a36Sopenharmony_ci}; 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, grcan_match); 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_cistatic struct platform_driver grcan_driver = { 172362306a36Sopenharmony_ci .driver = { 172462306a36Sopenharmony_ci .name = DRV_NAME, 172562306a36Sopenharmony_ci .of_match_table = grcan_match, 172662306a36Sopenharmony_ci }, 172762306a36Sopenharmony_ci .probe = grcan_probe, 172862306a36Sopenharmony_ci .remove_new = grcan_remove, 172962306a36Sopenharmony_ci}; 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_cimodule_platform_driver(grcan_driver); 173262306a36Sopenharmony_ci 173362306a36Sopenharmony_ciMODULE_AUTHOR("Aeroflex Gaisler AB."); 173462306a36Sopenharmony_ciMODULE_DESCRIPTION("Socket CAN driver for Aeroflex Gaisler GRCAN"); 173562306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1736