xref: /openbmc/linux/drivers/net/can/c_can/c_can_main.c (revision 278002edb19bce2c628fafb0af936e77000f3a5b)
12722ac98SDario Binacchi /*
22722ac98SDario Binacchi  * CAN bus driver for Bosch C_CAN controller
32722ac98SDario Binacchi  *
42722ac98SDario Binacchi  * Copyright (C) 2010 ST Microelectronics
52722ac98SDario Binacchi  * Bhupesh Sharma <bhupesh.sharma@st.com>
62722ac98SDario Binacchi  *
72722ac98SDario Binacchi  * Borrowed heavily from the C_CAN driver originally written by:
82722ac98SDario Binacchi  * Copyright (C) 2007
92722ac98SDario Binacchi  * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer@pengutronix.de>
102722ac98SDario Binacchi  * - Simon Kallweit, intefo AG <simon.kallweit@intefo.ch>
112722ac98SDario Binacchi  *
122722ac98SDario Binacchi  * TX and RX NAPI implementation has been borrowed from at91 CAN driver
132722ac98SDario Binacchi  * written by:
142722ac98SDario Binacchi  * Copyright
152722ac98SDario Binacchi  * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de>
162722ac98SDario Binacchi  * (C) 2008, 2009 by Marc Kleine-Budde <kernel@pengutronix.de>
172722ac98SDario Binacchi  *
182722ac98SDario Binacchi  * Bosch C_CAN controller is compliant to CAN protocol version 2.0 part A and B.
192722ac98SDario Binacchi  * Bosch C_CAN user manual can be obtained from:
202722ac98SDario Binacchi  * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/c_can/
212722ac98SDario Binacchi  * users_manual_c_can.pdf
222722ac98SDario Binacchi  *
232722ac98SDario Binacchi  * This file is licensed under the terms of the GNU General Public
242722ac98SDario Binacchi  * License version 2. This program is licensed "as is" without any
252722ac98SDario Binacchi  * warranty of any kind, whether express or implied.
262722ac98SDario Binacchi  */
272722ac98SDario Binacchi 
282722ac98SDario Binacchi #include <linux/kernel.h>
292722ac98SDario Binacchi #include <linux/module.h>
302722ac98SDario Binacchi #include <linux/interrupt.h>
312722ac98SDario Binacchi #include <linux/delay.h>
322722ac98SDario Binacchi #include <linux/netdevice.h>
332722ac98SDario Binacchi #include <linux/if_arp.h>
342722ac98SDario Binacchi #include <linux/if_ether.h>
352722ac98SDario Binacchi #include <linux/list.h>
362722ac98SDario Binacchi #include <linux/io.h>
372722ac98SDario Binacchi #include <linux/pm_runtime.h>
382722ac98SDario Binacchi #include <linux/pinctrl/consumer.h>
392722ac98SDario Binacchi 
402722ac98SDario Binacchi #include <linux/can.h>
412722ac98SDario Binacchi #include <linux/can/dev.h>
422722ac98SDario Binacchi #include <linux/can/error.h>
432722ac98SDario Binacchi 
442722ac98SDario Binacchi #include "c_can.h"
452722ac98SDario Binacchi 
462722ac98SDario Binacchi /* Number of interface registers */
472722ac98SDario Binacchi #define IF_ENUM_REG_LEN		11
482722ac98SDario Binacchi #define C_CAN_IFACE(reg, iface)	(C_CAN_IF1_##reg + (iface) * IF_ENUM_REG_LEN)
492722ac98SDario Binacchi 
502722ac98SDario Binacchi /* control extension register D_CAN specific */
512722ac98SDario Binacchi #define CONTROL_EX_PDR		BIT(8)
522722ac98SDario Binacchi 
532722ac98SDario Binacchi /* control register */
542722ac98SDario Binacchi #define CONTROL_SWR		BIT(15)
552722ac98SDario Binacchi #define CONTROL_TEST		BIT(7)
562722ac98SDario Binacchi #define CONTROL_CCE		BIT(6)
572722ac98SDario Binacchi #define CONTROL_DISABLE_AR	BIT(5)
582722ac98SDario Binacchi #define CONTROL_ENABLE_AR	(0 << 5)
592722ac98SDario Binacchi #define CONTROL_EIE		BIT(3)
602722ac98SDario Binacchi #define CONTROL_SIE		BIT(2)
612722ac98SDario Binacchi #define CONTROL_IE		BIT(1)
622722ac98SDario Binacchi #define CONTROL_INIT		BIT(0)
632722ac98SDario Binacchi 
642722ac98SDario Binacchi #define CONTROL_IRQMSK		(CONTROL_EIE | CONTROL_IE | CONTROL_SIE)
652722ac98SDario Binacchi 
662722ac98SDario Binacchi /* test register */
672722ac98SDario Binacchi #define TEST_RX			BIT(7)
682722ac98SDario Binacchi #define TEST_TX1		BIT(6)
692722ac98SDario Binacchi #define TEST_TX2		BIT(5)
702722ac98SDario Binacchi #define TEST_LBACK		BIT(4)
712722ac98SDario Binacchi #define TEST_SILENT		BIT(3)
722722ac98SDario Binacchi #define TEST_BASIC		BIT(2)
732722ac98SDario Binacchi 
742722ac98SDario Binacchi /* status register */
752722ac98SDario Binacchi #define STATUS_PDA		BIT(10)
762722ac98SDario Binacchi #define STATUS_BOFF		BIT(7)
772722ac98SDario Binacchi #define STATUS_EWARN		BIT(6)
782722ac98SDario Binacchi #define STATUS_EPASS		BIT(5)
792722ac98SDario Binacchi #define STATUS_RXOK		BIT(4)
802722ac98SDario Binacchi #define STATUS_TXOK		BIT(3)
812722ac98SDario Binacchi 
822722ac98SDario Binacchi /* error counter register */
832722ac98SDario Binacchi #define ERR_CNT_TEC_MASK	0xff
842722ac98SDario Binacchi #define ERR_CNT_TEC_SHIFT	0
852722ac98SDario Binacchi #define ERR_CNT_REC_SHIFT	8
862722ac98SDario Binacchi #define ERR_CNT_REC_MASK	(0x7f << ERR_CNT_REC_SHIFT)
872722ac98SDario Binacchi #define ERR_CNT_RP_SHIFT	15
882722ac98SDario Binacchi #define ERR_CNT_RP_MASK		(0x1 << ERR_CNT_RP_SHIFT)
892722ac98SDario Binacchi 
902722ac98SDario Binacchi /* bit-timing register */
912722ac98SDario Binacchi #define BTR_BRP_MASK		0x3f
922722ac98SDario Binacchi #define BTR_BRP_SHIFT		0
932722ac98SDario Binacchi #define BTR_SJW_SHIFT		6
942722ac98SDario Binacchi #define BTR_SJW_MASK		(0x3 << BTR_SJW_SHIFT)
952722ac98SDario Binacchi #define BTR_TSEG1_SHIFT		8
962722ac98SDario Binacchi #define BTR_TSEG1_MASK		(0xf << BTR_TSEG1_SHIFT)
972722ac98SDario Binacchi #define BTR_TSEG2_SHIFT		12
982722ac98SDario Binacchi #define BTR_TSEG2_MASK		(0x7 << BTR_TSEG2_SHIFT)
992722ac98SDario Binacchi 
1002722ac98SDario Binacchi /* interrupt register */
1012722ac98SDario Binacchi #define INT_STS_PENDING		0x8000
1022722ac98SDario Binacchi 
1032722ac98SDario Binacchi /* brp extension register */
1042722ac98SDario Binacchi #define BRP_EXT_BRPE_MASK	0x0f
1052722ac98SDario Binacchi #define BRP_EXT_BRPE_SHIFT	0
1062722ac98SDario Binacchi 
1072722ac98SDario Binacchi /* IFx command request */
1082722ac98SDario Binacchi #define IF_COMR_BUSY		BIT(15)
1092722ac98SDario Binacchi 
1102722ac98SDario Binacchi /* IFx command mask */
1112722ac98SDario Binacchi #define IF_COMM_WR		BIT(7)
1122722ac98SDario Binacchi #define IF_COMM_MASK		BIT(6)
1132722ac98SDario Binacchi #define IF_COMM_ARB		BIT(5)
1142722ac98SDario Binacchi #define IF_COMM_CONTROL		BIT(4)
1152722ac98SDario Binacchi #define IF_COMM_CLR_INT_PND	BIT(3)
1162722ac98SDario Binacchi #define IF_COMM_TXRQST		BIT(2)
1172722ac98SDario Binacchi #define IF_COMM_CLR_NEWDAT	IF_COMM_TXRQST
1182722ac98SDario Binacchi #define IF_COMM_DATAA		BIT(1)
1192722ac98SDario Binacchi #define IF_COMM_DATAB		BIT(0)
1202722ac98SDario Binacchi 
1212722ac98SDario Binacchi /* TX buffer setup */
1222722ac98SDario Binacchi #define IF_COMM_TX		(IF_COMM_ARB | IF_COMM_CONTROL | \
1232722ac98SDario Binacchi 				 IF_COMM_TXRQST |		 \
1242722ac98SDario Binacchi 				 IF_COMM_DATAA | IF_COMM_DATAB)
1252722ac98SDario Binacchi 
1262722ac98SDario Binacchi /* For the low buffers we clear the interrupt bit, but keep newdat */
1272722ac98SDario Binacchi #define IF_COMM_RCV_LOW		(IF_COMM_MASK | IF_COMM_ARB | \
1282722ac98SDario Binacchi 				 IF_COMM_CONTROL | IF_COMM_CLR_INT_PND | \
1292722ac98SDario Binacchi 				 IF_COMM_DATAA | IF_COMM_DATAB)
1302722ac98SDario Binacchi 
1312722ac98SDario Binacchi /* For the high buffers we clear the interrupt bit and newdat */
1322722ac98SDario Binacchi #define IF_COMM_RCV_HIGH	(IF_COMM_RCV_LOW | IF_COMM_CLR_NEWDAT)
1332722ac98SDario Binacchi 
1342722ac98SDario Binacchi /* Receive setup of message objects */
1352722ac98SDario Binacchi #define IF_COMM_RCV_SETUP	(IF_COMM_MASK | IF_COMM_ARB | IF_COMM_CONTROL)
1362722ac98SDario Binacchi 
1372722ac98SDario Binacchi /* Invalidation of message objects */
1382722ac98SDario Binacchi #define IF_COMM_INVAL		(IF_COMM_ARB | IF_COMM_CONTROL)
1392722ac98SDario Binacchi 
1402722ac98SDario Binacchi /* IFx arbitration */
1412722ac98SDario Binacchi #define IF_ARB_MSGVAL		BIT(31)
1422722ac98SDario Binacchi #define IF_ARB_MSGXTD		BIT(30)
1432722ac98SDario Binacchi #define IF_ARB_TRANSMIT		BIT(29)
1442722ac98SDario Binacchi 
1452722ac98SDario Binacchi /* IFx message control */
1462722ac98SDario Binacchi #define IF_MCONT_NEWDAT		BIT(15)
1472722ac98SDario Binacchi #define IF_MCONT_MSGLST		BIT(14)
1482722ac98SDario Binacchi #define IF_MCONT_INTPND		BIT(13)
1492722ac98SDario Binacchi #define IF_MCONT_UMASK		BIT(12)
1502722ac98SDario Binacchi #define IF_MCONT_TXIE		BIT(11)
1512722ac98SDario Binacchi #define IF_MCONT_RXIE		BIT(10)
1522722ac98SDario Binacchi #define IF_MCONT_RMTEN		BIT(9)
1532722ac98SDario Binacchi #define IF_MCONT_TXRQST		BIT(8)
1542722ac98SDario Binacchi #define IF_MCONT_EOB		BIT(7)
1552722ac98SDario Binacchi #define IF_MCONT_DLC_MASK	0xf
1562722ac98SDario Binacchi 
1572722ac98SDario Binacchi #define IF_MCONT_RCV		(IF_MCONT_RXIE | IF_MCONT_UMASK)
1582722ac98SDario Binacchi #define IF_MCONT_RCV_EOB	(IF_MCONT_RCV | IF_MCONT_EOB)
1592722ac98SDario Binacchi 
1602722ac98SDario Binacchi #define IF_MCONT_TX		(IF_MCONT_TXIE | IF_MCONT_EOB)
1612722ac98SDario Binacchi 
16205cb2ba4SMarc Kleine-Budde /* Use IF1 in NAPI path and IF2 in TX path */
16305cb2ba4SMarc Kleine-Budde #define IF_NAPI			0
1642722ac98SDario Binacchi #define IF_TX			1
1652722ac98SDario Binacchi 
1662722ac98SDario Binacchi /* minimum timeout for checking BUSY status */
1672722ac98SDario Binacchi #define MIN_TIMEOUT_VALUE	6
1682722ac98SDario Binacchi 
1692722ac98SDario Binacchi /* Wait for ~1 sec for INIT bit */
1702722ac98SDario Binacchi #define INIT_WAIT_MS		1000
1712722ac98SDario Binacchi 
1722722ac98SDario Binacchi /* c_can lec values */
1732722ac98SDario Binacchi enum c_can_lec_type {
1742722ac98SDario Binacchi 	LEC_NO_ERROR = 0,
1752722ac98SDario Binacchi 	LEC_STUFF_ERROR,
1762722ac98SDario Binacchi 	LEC_FORM_ERROR,
1772722ac98SDario Binacchi 	LEC_ACK_ERROR,
1782722ac98SDario Binacchi 	LEC_BIT1_ERROR,
1792722ac98SDario Binacchi 	LEC_BIT0_ERROR,
1802722ac98SDario Binacchi 	LEC_CRC_ERROR,
1812722ac98SDario Binacchi 	LEC_UNUSED,
1822722ac98SDario Binacchi 	LEC_MASK = LEC_UNUSED,
1832722ac98SDario Binacchi };
1842722ac98SDario Binacchi 
1852722ac98SDario Binacchi /* c_can error types:
1862722ac98SDario Binacchi  * Bus errors (BUS_OFF, ERROR_WARNING, ERROR_PASSIVE) are supported
1872722ac98SDario Binacchi  */
1882722ac98SDario Binacchi enum c_can_bus_error_types {
1892722ac98SDario Binacchi 	C_CAN_NO_ERROR = 0,
1902722ac98SDario Binacchi 	C_CAN_BUS_OFF,
1912722ac98SDario Binacchi 	C_CAN_ERROR_WARNING,
1922722ac98SDario Binacchi 	C_CAN_ERROR_PASSIVE,
1932722ac98SDario Binacchi };
1942722ac98SDario Binacchi 
1952722ac98SDario Binacchi static const struct can_bittiming_const c_can_bittiming_const = {
1962722ac98SDario Binacchi 	.name = KBUILD_MODNAME,
1972722ac98SDario Binacchi 	.tseg1_min = 2,		/* Time segment 1 = prop_seg + phase_seg1 */
1982722ac98SDario Binacchi 	.tseg1_max = 16,
1992722ac98SDario Binacchi 	.tseg2_min = 1,		/* Time segment 2 = phase_seg2 */
2002722ac98SDario Binacchi 	.tseg2_max = 8,
2012722ac98SDario Binacchi 	.sjw_max = 4,
2022722ac98SDario Binacchi 	.brp_min = 1,
2032722ac98SDario Binacchi 	.brp_max = 1024,	/* 6-bit BRP field + 4-bit BRPE field*/
2042722ac98SDario Binacchi 	.brp_inc = 1,
2052722ac98SDario Binacchi };
2062722ac98SDario Binacchi 
c_can_pm_runtime_get_sync(const struct c_can_priv * priv)2072722ac98SDario Binacchi static inline void c_can_pm_runtime_get_sync(const struct c_can_priv *priv)
2082722ac98SDario Binacchi {
2092722ac98SDario Binacchi 	if (priv->device)
2102722ac98SDario Binacchi 		pm_runtime_get_sync(priv->device);
2112722ac98SDario Binacchi }
2122722ac98SDario Binacchi 
c_can_pm_runtime_put_sync(const struct c_can_priv * priv)2132722ac98SDario Binacchi static inline void c_can_pm_runtime_put_sync(const struct c_can_priv *priv)
2142722ac98SDario Binacchi {
2152722ac98SDario Binacchi 	if (priv->device)
2162722ac98SDario Binacchi 		pm_runtime_put_sync(priv->device);
2172722ac98SDario Binacchi }
2182722ac98SDario Binacchi 
c_can_reset_ram(const struct c_can_priv * priv,bool enable)2192722ac98SDario Binacchi static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable)
2202722ac98SDario Binacchi {
2212722ac98SDario Binacchi 	if (priv->raminit)
2222722ac98SDario Binacchi 		priv->raminit(priv, enable);
2232722ac98SDario Binacchi }
2242722ac98SDario Binacchi 
c_can_irq_control(struct c_can_priv * priv,bool enable)2252722ac98SDario Binacchi static void c_can_irq_control(struct c_can_priv *priv, bool enable)
2262722ac98SDario Binacchi {
2272722ac98SDario Binacchi 	u32 ctrl = priv->read_reg(priv,	C_CAN_CTRL_REG) & ~CONTROL_IRQMSK;
2282722ac98SDario Binacchi 
2292722ac98SDario Binacchi 	if (enable)
2302722ac98SDario Binacchi 		ctrl |= CONTROL_IRQMSK;
2312722ac98SDario Binacchi 
2322722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_CTRL_REG, ctrl);
2332722ac98SDario Binacchi }
2342722ac98SDario Binacchi 
c_can_obj_update(struct net_device * dev,int iface,u32 cmd,u32 obj)2352722ac98SDario Binacchi static void c_can_obj_update(struct net_device *dev, int iface, u32 cmd, u32 obj)
2362722ac98SDario Binacchi {
2372722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
2382722ac98SDario Binacchi 	int cnt, reg = C_CAN_IFACE(COMREQ_REG, iface);
2392722ac98SDario Binacchi 
2402722ac98SDario Binacchi 	priv->write_reg32(priv, reg, (cmd << 16) | obj);
2412722ac98SDario Binacchi 
2422722ac98SDario Binacchi 	for (cnt = MIN_TIMEOUT_VALUE; cnt; cnt--) {
2432722ac98SDario Binacchi 		if (!(priv->read_reg(priv, reg) & IF_COMR_BUSY))
2442722ac98SDario Binacchi 			return;
2452722ac98SDario Binacchi 		udelay(1);
2462722ac98SDario Binacchi 	}
2472722ac98SDario Binacchi 	netdev_err(dev, "Updating object timed out\n");
2482722ac98SDario Binacchi }
2492722ac98SDario Binacchi 
c_can_object_get(struct net_device * dev,int iface,u32 obj,u32 cmd)2502722ac98SDario Binacchi static inline void c_can_object_get(struct net_device *dev, int iface,
2512722ac98SDario Binacchi 				    u32 obj, u32 cmd)
2522722ac98SDario Binacchi {
2532722ac98SDario Binacchi 	c_can_obj_update(dev, iface, cmd, obj);
2542722ac98SDario Binacchi }
2552722ac98SDario Binacchi 
c_can_object_put(struct net_device * dev,int iface,u32 obj,u32 cmd)2562722ac98SDario Binacchi static inline void c_can_object_put(struct net_device *dev, int iface,
2572722ac98SDario Binacchi 				    u32 obj, u32 cmd)
2582722ac98SDario Binacchi {
2592722ac98SDario Binacchi 	c_can_obj_update(dev, iface, cmd | IF_COMM_WR, obj);
2602722ac98SDario Binacchi }
2612722ac98SDario Binacchi 
2622722ac98SDario Binacchi /* Note: According to documentation clearing TXIE while MSGVAL is set
2632722ac98SDario Binacchi  * is not allowed, but works nicely on C/DCAN. And that lowers the I/O
2642722ac98SDario Binacchi  * load significantly.
2652722ac98SDario Binacchi  */
c_can_inval_tx_object(struct net_device * dev,int iface,int obj)2662722ac98SDario Binacchi static void c_can_inval_tx_object(struct net_device *dev, int iface, int obj)
2672722ac98SDario Binacchi {
2682722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
2692722ac98SDario Binacchi 
2702722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0);
2712722ac98SDario Binacchi 	c_can_object_put(dev, iface, obj, IF_COMM_INVAL);
2722722ac98SDario Binacchi }
2732722ac98SDario Binacchi 
c_can_inval_msg_object(struct net_device * dev,int iface,int obj)2742722ac98SDario Binacchi static void c_can_inval_msg_object(struct net_device *dev, int iface, int obj)
2752722ac98SDario Binacchi {
2762722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
2772722ac98SDario Binacchi 
2782722ac98SDario Binacchi 	priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), 0);
2792722ac98SDario Binacchi 	c_can_inval_tx_object(dev, iface, obj);
2802722ac98SDario Binacchi }
2812722ac98SDario Binacchi 
c_can_setup_tx_object(struct net_device * dev,int iface,struct can_frame * frame,int idx)2822722ac98SDario Binacchi static void c_can_setup_tx_object(struct net_device *dev, int iface,
2832722ac98SDario Binacchi 				  struct can_frame *frame, int idx)
2842722ac98SDario Binacchi {
2852722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
2862722ac98SDario Binacchi 	u16 ctrl = IF_MCONT_TX | frame->len;
2872722ac98SDario Binacchi 	bool rtr = frame->can_id & CAN_RTR_FLAG;
2882722ac98SDario Binacchi 	u32 arb = IF_ARB_MSGVAL;
2892722ac98SDario Binacchi 	int i;
2902722ac98SDario Binacchi 
2912722ac98SDario Binacchi 	if (frame->can_id & CAN_EFF_FLAG) {
2922722ac98SDario Binacchi 		arb |= frame->can_id & CAN_EFF_MASK;
2932722ac98SDario Binacchi 		arb |= IF_ARB_MSGXTD;
2942722ac98SDario Binacchi 	} else {
2952722ac98SDario Binacchi 		arb |= (frame->can_id & CAN_SFF_MASK) << 18;
2962722ac98SDario Binacchi 	}
2972722ac98SDario Binacchi 
2982722ac98SDario Binacchi 	if (!rtr)
2992722ac98SDario Binacchi 		arb |= IF_ARB_TRANSMIT;
3002722ac98SDario Binacchi 
3012722ac98SDario Binacchi 	/* If we change the DIR bit, we need to invalidate the buffer
3022722ac98SDario Binacchi 	 * first, i.e. clear the MSGVAL flag in the arbiter.
3032722ac98SDario Binacchi 	 */
3042722ac98SDario Binacchi 	if (rtr != (bool)test_bit(idx, &priv->tx_dir)) {
3052722ac98SDario Binacchi 		u32 obj = idx + priv->msg_obj_tx_first;
3062722ac98SDario Binacchi 
3072722ac98SDario Binacchi 		c_can_inval_msg_object(dev, iface, obj);
3082722ac98SDario Binacchi 		change_bit(idx, &priv->tx_dir);
3092722ac98SDario Binacchi 	}
3102722ac98SDario Binacchi 
3112722ac98SDario Binacchi 	priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), arb);
3122722ac98SDario Binacchi 
3132722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl);
3142722ac98SDario Binacchi 
3152722ac98SDario Binacchi 	if (priv->type == BOSCH_D_CAN) {
3162722ac98SDario Binacchi 		u32 data = 0, dreg = C_CAN_IFACE(DATA1_REG, iface);
3172722ac98SDario Binacchi 
3182722ac98SDario Binacchi 		for (i = 0; i < frame->len; i += 4, dreg += 2) {
3192722ac98SDario Binacchi 			data = (u32)frame->data[i];
3202722ac98SDario Binacchi 			data |= (u32)frame->data[i + 1] << 8;
3212722ac98SDario Binacchi 			data |= (u32)frame->data[i + 2] << 16;
3222722ac98SDario Binacchi 			data |= (u32)frame->data[i + 3] << 24;
3232722ac98SDario Binacchi 			priv->write_reg32(priv, dreg, data);
3242722ac98SDario Binacchi 		}
3252722ac98SDario Binacchi 	} else {
3262722ac98SDario Binacchi 		for (i = 0; i < frame->len; i += 2) {
3272722ac98SDario Binacchi 			priv->write_reg(priv,
3282722ac98SDario Binacchi 					C_CAN_IFACE(DATA1_REG, iface) + i / 2,
3292722ac98SDario Binacchi 					frame->data[i] |
3302722ac98SDario Binacchi 					(frame->data[i + 1] << 8));
3312722ac98SDario Binacchi 		}
3322722ac98SDario Binacchi 	}
3332722ac98SDario Binacchi }
3342722ac98SDario Binacchi 
c_can_handle_lost_msg_obj(struct net_device * dev,int iface,int objno,u32 ctrl)3352722ac98SDario Binacchi static int c_can_handle_lost_msg_obj(struct net_device *dev,
3362722ac98SDario Binacchi 				     int iface, int objno, u32 ctrl)
3372722ac98SDario Binacchi {
3382722ac98SDario Binacchi 	struct net_device_stats *stats = &dev->stats;
3392722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
3402722ac98SDario Binacchi 	struct can_frame *frame;
3412722ac98SDario Binacchi 	struct sk_buff *skb;
3422722ac98SDario Binacchi 
3432722ac98SDario Binacchi 	ctrl &= ~(IF_MCONT_MSGLST | IF_MCONT_INTPND | IF_MCONT_NEWDAT);
3442722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl);
3452722ac98SDario Binacchi 	c_can_object_put(dev, iface, objno, IF_COMM_CONTROL);
3462722ac98SDario Binacchi 
3472722ac98SDario Binacchi 	stats->rx_errors++;
3482722ac98SDario Binacchi 	stats->rx_over_errors++;
3492722ac98SDario Binacchi 
3502722ac98SDario Binacchi 	/* create an error msg */
3512722ac98SDario Binacchi 	skb = alloc_can_err_skb(dev, &frame);
3522722ac98SDario Binacchi 	if (unlikely(!skb))
3532722ac98SDario Binacchi 		return 0;
3542722ac98SDario Binacchi 
3552722ac98SDario Binacchi 	frame->can_id |= CAN_ERR_CRTL;
3562722ac98SDario Binacchi 	frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
3572722ac98SDario Binacchi 
3582722ac98SDario Binacchi 	netif_receive_skb(skb);
3592722ac98SDario Binacchi 	return 1;
3602722ac98SDario Binacchi }
3612722ac98SDario Binacchi 
c_can_read_msg_object(struct net_device * dev,int iface,u32 ctrl)3622722ac98SDario Binacchi static int c_can_read_msg_object(struct net_device *dev, int iface, u32 ctrl)
3632722ac98SDario Binacchi {
3642722ac98SDario Binacchi 	struct net_device_stats *stats = &dev->stats;
3652722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
3662722ac98SDario Binacchi 	struct can_frame *frame;
3672722ac98SDario Binacchi 	struct sk_buff *skb;
3682722ac98SDario Binacchi 	u32 arb, data;
3692722ac98SDario Binacchi 
3702722ac98SDario Binacchi 	skb = alloc_can_skb(dev, &frame);
3712722ac98SDario Binacchi 	if (!skb) {
3722722ac98SDario Binacchi 		stats->rx_dropped++;
3732722ac98SDario Binacchi 		return -ENOMEM;
3742722ac98SDario Binacchi 	}
3752722ac98SDario Binacchi 
3762722ac98SDario Binacchi 	frame->len = can_cc_dlc2len(ctrl & 0x0F);
3772722ac98SDario Binacchi 
3782722ac98SDario Binacchi 	arb = priv->read_reg32(priv, C_CAN_IFACE(ARB1_REG, iface));
3792722ac98SDario Binacchi 
3802722ac98SDario Binacchi 	if (arb & IF_ARB_MSGXTD)
3812722ac98SDario Binacchi 		frame->can_id = (arb & CAN_EFF_MASK) | CAN_EFF_FLAG;
3822722ac98SDario Binacchi 	else
3832722ac98SDario Binacchi 		frame->can_id = (arb >> 18) & CAN_SFF_MASK;
3842722ac98SDario Binacchi 
3852722ac98SDario Binacchi 	if (arb & IF_ARB_TRANSMIT) {
3862722ac98SDario Binacchi 		frame->can_id |= CAN_RTR_FLAG;
3872722ac98SDario Binacchi 	} else {
3882722ac98SDario Binacchi 		int i, dreg = C_CAN_IFACE(DATA1_REG, iface);
3892722ac98SDario Binacchi 
3902722ac98SDario Binacchi 		if (priv->type == BOSCH_D_CAN) {
3912722ac98SDario Binacchi 			for (i = 0; i < frame->len; i += 4, dreg += 2) {
3922722ac98SDario Binacchi 				data = priv->read_reg32(priv, dreg);
3932722ac98SDario Binacchi 				frame->data[i] = data;
3942722ac98SDario Binacchi 				frame->data[i + 1] = data >> 8;
3952722ac98SDario Binacchi 				frame->data[i + 2] = data >> 16;
3962722ac98SDario Binacchi 				frame->data[i + 3] = data >> 24;
3972722ac98SDario Binacchi 			}
3982722ac98SDario Binacchi 		} else {
3992722ac98SDario Binacchi 			for (i = 0; i < frame->len; i += 2, dreg++) {
4002722ac98SDario Binacchi 				data = priv->read_reg(priv, dreg);
4012722ac98SDario Binacchi 				frame->data[i] = data;
4022722ac98SDario Binacchi 				frame->data[i + 1] = data >> 8;
4032722ac98SDario Binacchi 			}
4042722ac98SDario Binacchi 		}
4052722ac98SDario Binacchi 
4062722ac98SDario Binacchi 		stats->rx_bytes += frame->len;
4078e674ca7SVincent Mailhol 	}
4088e674ca7SVincent Mailhol 	stats->rx_packets++;
4092722ac98SDario Binacchi 
4102722ac98SDario Binacchi 	netif_receive_skb(skb);
4112722ac98SDario Binacchi 	return 0;
4122722ac98SDario Binacchi }
4132722ac98SDario Binacchi 
c_can_setup_receive_object(struct net_device * dev,int iface,u32 obj,u32 mask,u32 id,u32 mcont)4142722ac98SDario Binacchi static void c_can_setup_receive_object(struct net_device *dev, int iface,
4152722ac98SDario Binacchi 				       u32 obj, u32 mask, u32 id, u32 mcont)
4162722ac98SDario Binacchi {
4172722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
4182722ac98SDario Binacchi 
4192722ac98SDario Binacchi 	mask |= BIT(29);
4202722ac98SDario Binacchi 	priv->write_reg32(priv, C_CAN_IFACE(MASK1_REG, iface), mask);
4212722ac98SDario Binacchi 
4222722ac98SDario Binacchi 	id |= IF_ARB_MSGVAL;
4232722ac98SDario Binacchi 	priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), id);
4242722ac98SDario Binacchi 
4252722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), mcont);
4262722ac98SDario Binacchi 	c_can_object_put(dev, iface, obj, IF_COMM_RCV_SETUP);
4272722ac98SDario Binacchi }
4282722ac98SDario Binacchi 
c_can_tx_busy(const struct c_can_priv * priv,const struct c_can_tx_ring * tx_ring)42928e86e9aSDario Binacchi static bool c_can_tx_busy(const struct c_can_priv *priv,
43028e86e9aSDario Binacchi 			  const struct c_can_tx_ring *tx_ring)
43128e86e9aSDario Binacchi {
43281d192c2SMarc Kleine-Budde 	if (c_can_get_tx_free(priv, tx_ring) > 0)
43328e86e9aSDario Binacchi 		return false;
43428e86e9aSDario Binacchi 
43528e86e9aSDario Binacchi 	netif_stop_queue(priv->dev);
43628e86e9aSDario Binacchi 
43728e86e9aSDario Binacchi 	/* Memory barrier before checking tx_free (head and tail) */
43828e86e9aSDario Binacchi 	smp_mb();
43928e86e9aSDario Binacchi 
44081d192c2SMarc Kleine-Budde 	if (c_can_get_tx_free(priv, tx_ring) == 0) {
44128e86e9aSDario Binacchi 		netdev_dbg(priv->dev,
44228e86e9aSDario Binacchi 			   "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, len=%d).\n",
44328e86e9aSDario Binacchi 			   tx_ring->head, tx_ring->tail,
44428e86e9aSDario Binacchi 			   tx_ring->head - tx_ring->tail);
44528e86e9aSDario Binacchi 		return true;
44628e86e9aSDario Binacchi 	}
44728e86e9aSDario Binacchi 
44828e86e9aSDario Binacchi 	netif_start_queue(priv->dev);
44928e86e9aSDario Binacchi 	return false;
45028e86e9aSDario Binacchi }
45128e86e9aSDario Binacchi 
c_can_start_xmit(struct sk_buff * skb,struct net_device * dev)4522722ac98SDario Binacchi static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
4532722ac98SDario Binacchi 				    struct net_device *dev)
4542722ac98SDario Binacchi {
4552722ac98SDario Binacchi 	struct can_frame *frame = (struct can_frame *)skb->data;
4562722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
45728e86e9aSDario Binacchi 	struct c_can_tx_ring *tx_ring = &priv->tx;
458387da6bcSDario Binacchi 	u32 idx, obj, cmd = IF_COMM_TX;
4592722ac98SDario Binacchi 
460ae64438bSOliver Hartkopp 	if (can_dev_dropped_skb(dev, skb))
4612722ac98SDario Binacchi 		return NETDEV_TX_OK;
46228e86e9aSDario Binacchi 
46328e86e9aSDario Binacchi 	if (c_can_tx_busy(priv, tx_ring))
46428e86e9aSDario Binacchi 		return NETDEV_TX_BUSY;
46528e86e9aSDario Binacchi 
46628e86e9aSDario Binacchi 	idx = c_can_get_tx_head(tx_ring);
46728e86e9aSDario Binacchi 	tx_ring->head++;
46881d192c2SMarc Kleine-Budde 	if (c_can_get_tx_free(priv, tx_ring) == 0)
46928e86e9aSDario Binacchi 		netif_stop_queue(dev);
47028e86e9aSDario Binacchi 
471387da6bcSDario Binacchi 	if (idx < c_can_get_tx_tail(tx_ring))
472387da6bcSDario Binacchi 		cmd &= ~IF_COMM_TXRQST; /* Cache the message */
4732722ac98SDario Binacchi 
4742722ac98SDario Binacchi 	/* Store the message in the interface so we can call
4752722ac98SDario Binacchi 	 * can_put_echo_skb(). We must do this before we enable
4762722ac98SDario Binacchi 	 * transmit as we might race against do_tx().
4772722ac98SDario Binacchi 	 */
4782722ac98SDario Binacchi 	c_can_setup_tx_object(dev, IF_TX, frame, idx);
4792722ac98SDario Binacchi 	can_put_echo_skb(skb, dev, idx, 0);
480387da6bcSDario Binacchi 	obj = idx + priv->msg_obj_tx_first;
481387da6bcSDario Binacchi 	c_can_object_put(dev, IF_TX, obj, cmd);
4822722ac98SDario Binacchi 
4832722ac98SDario Binacchi 	return NETDEV_TX_OK;
4842722ac98SDario Binacchi }
4852722ac98SDario Binacchi 
c_can_wait_for_ctrl_init(struct net_device * dev,struct c_can_priv * priv,u32 init)4862722ac98SDario Binacchi static int c_can_wait_for_ctrl_init(struct net_device *dev,
4872722ac98SDario Binacchi 				    struct c_can_priv *priv, u32 init)
4882722ac98SDario Binacchi {
4892722ac98SDario Binacchi 	int retry = 0;
4902722ac98SDario Binacchi 
4912722ac98SDario Binacchi 	while (init != (priv->read_reg(priv, C_CAN_CTRL_REG) & CONTROL_INIT)) {
4922722ac98SDario Binacchi 		udelay(10);
4932722ac98SDario Binacchi 		if (retry++ > 1000) {
4942722ac98SDario Binacchi 			netdev_err(dev, "CCTRL: set CONTROL_INIT failed\n");
4952722ac98SDario Binacchi 			return -EIO;
4962722ac98SDario Binacchi 		}
4972722ac98SDario Binacchi 	}
4982722ac98SDario Binacchi 	return 0;
4992722ac98SDario Binacchi }
5002722ac98SDario Binacchi 
c_can_set_bittiming(struct net_device * dev)5012722ac98SDario Binacchi static int c_can_set_bittiming(struct net_device *dev)
5022722ac98SDario Binacchi {
5032722ac98SDario Binacchi 	unsigned int reg_btr, reg_brpe, ctrl_save;
5042722ac98SDario Binacchi 	u8 brp, brpe, sjw, tseg1, tseg2;
5052722ac98SDario Binacchi 	u32 ten_bit_brp;
5062722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
5072722ac98SDario Binacchi 	const struct can_bittiming *bt = &priv->can.bittiming;
5082722ac98SDario Binacchi 	int res;
5092722ac98SDario Binacchi 
5102722ac98SDario Binacchi 	/* c_can provides a 6-bit brp and 4-bit brpe fields */
5112722ac98SDario Binacchi 	ten_bit_brp = bt->brp - 1;
5122722ac98SDario Binacchi 	brp = ten_bit_brp & BTR_BRP_MASK;
5132722ac98SDario Binacchi 	brpe = ten_bit_brp >> 6;
5142722ac98SDario Binacchi 
5152722ac98SDario Binacchi 	sjw = bt->sjw - 1;
5162722ac98SDario Binacchi 	tseg1 = bt->prop_seg + bt->phase_seg1 - 1;
5172722ac98SDario Binacchi 	tseg2 = bt->phase_seg2 - 1;
5182722ac98SDario Binacchi 	reg_btr = brp | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) |
5192722ac98SDario Binacchi 			(tseg2 << BTR_TSEG2_SHIFT);
5202722ac98SDario Binacchi 	reg_brpe = brpe & BRP_EXT_BRPE_MASK;
5212722ac98SDario Binacchi 
5222722ac98SDario Binacchi 	netdev_info(dev,
5232722ac98SDario Binacchi 		    "setting BTR=%04x BRPE=%04x\n", reg_btr, reg_brpe);
5242722ac98SDario Binacchi 
5252722ac98SDario Binacchi 	ctrl_save = priv->read_reg(priv, C_CAN_CTRL_REG);
5262722ac98SDario Binacchi 	ctrl_save &= ~CONTROL_INIT;
5272722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_CCE | CONTROL_INIT);
5282722ac98SDario Binacchi 	res = c_can_wait_for_ctrl_init(dev, priv, CONTROL_INIT);
5292722ac98SDario Binacchi 	if (res)
5302722ac98SDario Binacchi 		return res;
5312722ac98SDario Binacchi 
5322722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_BTR_REG, reg_btr);
5332722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_BRPEXT_REG, reg_brpe);
5342722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_CTRL_REG, ctrl_save);
5352722ac98SDario Binacchi 
5362722ac98SDario Binacchi 	return c_can_wait_for_ctrl_init(dev, priv, 0);
5372722ac98SDario Binacchi }
5382722ac98SDario Binacchi 
5392722ac98SDario Binacchi /* Configure C_CAN message objects for Tx and Rx purposes:
5402722ac98SDario Binacchi  * C_CAN provides a total of 32 message objects that can be configured
5412722ac98SDario Binacchi  * either for Tx or Rx purposes. Here the first 16 message objects are used as
5422722ac98SDario Binacchi  * a reception FIFO. The end of reception FIFO is signified by the EoB bit
5432722ac98SDario Binacchi  * being SET. The remaining 16 message objects are kept aside for Tx purposes.
5442722ac98SDario Binacchi  * See user guide document for further details on configuring message
5452722ac98SDario Binacchi  * objects.
5462722ac98SDario Binacchi  */
c_can_configure_msg_objects(struct net_device * dev)5472722ac98SDario Binacchi static void c_can_configure_msg_objects(struct net_device *dev)
5482722ac98SDario Binacchi {
5492722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
5502722ac98SDario Binacchi 	int i;
5512722ac98SDario Binacchi 
5522722ac98SDario Binacchi 	/* first invalidate all message objects */
5532722ac98SDario Binacchi 	for (i = priv->msg_obj_rx_first; i <= priv->msg_obj_num; i++)
55405cb2ba4SMarc Kleine-Budde 		c_can_inval_msg_object(dev, IF_NAPI, i);
5552722ac98SDario Binacchi 
5562722ac98SDario Binacchi 	/* setup receive message objects */
5572722ac98SDario Binacchi 	for (i = priv->msg_obj_rx_first; i < priv->msg_obj_rx_last; i++)
55805cb2ba4SMarc Kleine-Budde 		c_can_setup_receive_object(dev, IF_NAPI, i, 0, 0, IF_MCONT_RCV);
5592722ac98SDario Binacchi 
56005cb2ba4SMarc Kleine-Budde 	c_can_setup_receive_object(dev, IF_NAPI, priv->msg_obj_rx_last, 0, 0,
5612722ac98SDario Binacchi 				   IF_MCONT_RCV_EOB);
5622722ac98SDario Binacchi }
5632722ac98SDario Binacchi 
c_can_software_reset(struct net_device * dev)5642722ac98SDario Binacchi static int c_can_software_reset(struct net_device *dev)
5652722ac98SDario Binacchi {
5662722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
5672722ac98SDario Binacchi 	int retry = 0;
5682722ac98SDario Binacchi 
5692722ac98SDario Binacchi 	if (priv->type != BOSCH_D_CAN)
5702722ac98SDario Binacchi 		return 0;
5712722ac98SDario Binacchi 
5722722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_SWR | CONTROL_INIT);
5732722ac98SDario Binacchi 	while (priv->read_reg(priv, C_CAN_CTRL_REG) & CONTROL_SWR) {
5742722ac98SDario Binacchi 		msleep(20);
5752722ac98SDario Binacchi 		if (retry++ > 100) {
5762722ac98SDario Binacchi 			netdev_err(dev, "CCTRL: software reset failed\n");
5772722ac98SDario Binacchi 			return -EIO;
5782722ac98SDario Binacchi 		}
5792722ac98SDario Binacchi 	}
5802722ac98SDario Binacchi 
5812722ac98SDario Binacchi 	return 0;
5822722ac98SDario Binacchi }
5832722ac98SDario Binacchi 
5842722ac98SDario Binacchi /* Configure C_CAN chip:
5852722ac98SDario Binacchi  * - enable/disable auto-retransmission
5862722ac98SDario Binacchi  * - set operating mode
5872722ac98SDario Binacchi  * - configure message objects
5882722ac98SDario Binacchi  */
c_can_chip_config(struct net_device * dev)5892722ac98SDario Binacchi static int c_can_chip_config(struct net_device *dev)
5902722ac98SDario Binacchi {
5912722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
59228e86e9aSDario Binacchi 	struct c_can_tx_ring *tx_ring = &priv->tx;
5932722ac98SDario Binacchi 	int err;
5942722ac98SDario Binacchi 
5952722ac98SDario Binacchi 	err = c_can_software_reset(dev);
5962722ac98SDario Binacchi 	if (err)
5972722ac98SDario Binacchi 		return err;
5982722ac98SDario Binacchi 
5992722ac98SDario Binacchi 	/* enable automatic retransmission */
6002722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR);
6012722ac98SDario Binacchi 
6022722ac98SDario Binacchi 	if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) &&
6032722ac98SDario Binacchi 	    (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) {
6042722ac98SDario Binacchi 		/* loopback + silent mode : useful for hot self-test */
6052722ac98SDario Binacchi 		priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
6062722ac98SDario Binacchi 		priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK | TEST_SILENT);
6072722ac98SDario Binacchi 	} else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
6082722ac98SDario Binacchi 		/* loopback mode : useful for self-test function */
6092722ac98SDario Binacchi 		priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
6102722ac98SDario Binacchi 		priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK);
6112722ac98SDario Binacchi 	} else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
6122722ac98SDario Binacchi 		/* silent mode : bus-monitoring mode */
6132722ac98SDario Binacchi 		priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
6142722ac98SDario Binacchi 		priv->write_reg(priv, C_CAN_TEST_REG, TEST_SILENT);
6152722ac98SDario Binacchi 	}
6162722ac98SDario Binacchi 
6172722ac98SDario Binacchi 	/* configure message objects */
6182722ac98SDario Binacchi 	c_can_configure_msg_objects(dev);
6192722ac98SDario Binacchi 
6202722ac98SDario Binacchi 	/* set a `lec` value so that we can check for updates later */
6212722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
6222722ac98SDario Binacchi 
6232722ac98SDario Binacchi 	/* Clear all internal status */
62428e86e9aSDario Binacchi 	tx_ring->head = 0;
62528e86e9aSDario Binacchi 	tx_ring->tail = 0;
6262722ac98SDario Binacchi 	priv->tx_dir = 0;
6272722ac98SDario Binacchi 
6282722ac98SDario Binacchi 	/* set bittiming params */
6292722ac98SDario Binacchi 	return c_can_set_bittiming(dev);
6302722ac98SDario Binacchi }
6312722ac98SDario Binacchi 
c_can_start(struct net_device * dev)6322722ac98SDario Binacchi static int c_can_start(struct net_device *dev)
6332722ac98SDario Binacchi {
6342722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
6352722ac98SDario Binacchi 	int err;
6362722ac98SDario Binacchi 	struct pinctrl *p;
6372722ac98SDario Binacchi 
6382722ac98SDario Binacchi 	/* basic c_can configuration */
6392722ac98SDario Binacchi 	err = c_can_chip_config(dev);
6402722ac98SDario Binacchi 	if (err)
6412722ac98SDario Binacchi 		return err;
6422722ac98SDario Binacchi 
6432722ac98SDario Binacchi 	/* Setup the command for new messages */
6442722ac98SDario Binacchi 	priv->comm_rcv_high = priv->type != BOSCH_D_CAN ?
6452722ac98SDario Binacchi 		IF_COMM_RCV_LOW : IF_COMM_RCV_HIGH;
6462722ac98SDario Binacchi 
6472722ac98SDario Binacchi 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
6482722ac98SDario Binacchi 
6492722ac98SDario Binacchi 	/* Attempt to use "active" if available else use "default" */
6502722ac98SDario Binacchi 	p = pinctrl_get_select(priv->device, "active");
6512722ac98SDario Binacchi 	if (!IS_ERR(p))
6522722ac98SDario Binacchi 		pinctrl_put(p);
6532722ac98SDario Binacchi 	else
6542722ac98SDario Binacchi 		pinctrl_pm_select_default_state(priv->device);
6552722ac98SDario Binacchi 
6562722ac98SDario Binacchi 	return 0;
6572722ac98SDario Binacchi }
6582722ac98SDario Binacchi 
c_can_stop(struct net_device * dev)6592722ac98SDario Binacchi static void c_can_stop(struct net_device *dev)
6602722ac98SDario Binacchi {
6612722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
6622722ac98SDario Binacchi 
6632722ac98SDario Binacchi 	c_can_irq_control(priv, false);
6642722ac98SDario Binacchi 
6652722ac98SDario Binacchi 	/* put ctrl to init on stop to end ongoing transmission */
6662722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_INIT);
6672722ac98SDario Binacchi 
6682722ac98SDario Binacchi 	/* deactivate pins */
6692722ac98SDario Binacchi 	pinctrl_pm_select_sleep_state(dev->dev.parent);
6702722ac98SDario Binacchi 	priv->can.state = CAN_STATE_STOPPED;
6712722ac98SDario Binacchi }
6722722ac98SDario Binacchi 
c_can_set_mode(struct net_device * dev,enum can_mode mode)6732722ac98SDario Binacchi static int c_can_set_mode(struct net_device *dev, enum can_mode mode)
6742722ac98SDario Binacchi {
6752722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
6762722ac98SDario Binacchi 	int err;
6772722ac98SDario Binacchi 
6782722ac98SDario Binacchi 	switch (mode) {
6792722ac98SDario Binacchi 	case CAN_MODE_START:
6802722ac98SDario Binacchi 		err = c_can_start(dev);
6812722ac98SDario Binacchi 		if (err)
6822722ac98SDario Binacchi 			return err;
6832722ac98SDario Binacchi 		netif_wake_queue(dev);
6842722ac98SDario Binacchi 		c_can_irq_control(priv, true);
6852722ac98SDario Binacchi 		break;
6862722ac98SDario Binacchi 	default:
6872722ac98SDario Binacchi 		return -EOPNOTSUPP;
6882722ac98SDario Binacchi 	}
6892722ac98SDario Binacchi 
6902722ac98SDario Binacchi 	return 0;
6912722ac98SDario Binacchi }
6922722ac98SDario Binacchi 
__c_can_get_berr_counter(const struct net_device * dev,struct can_berr_counter * bec)6932722ac98SDario Binacchi static int __c_can_get_berr_counter(const struct net_device *dev,
6942722ac98SDario Binacchi 				    struct can_berr_counter *bec)
6952722ac98SDario Binacchi {
6962722ac98SDario Binacchi 	unsigned int reg_err_counter;
6972722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
6982722ac98SDario Binacchi 
6992722ac98SDario Binacchi 	reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG);
7002722ac98SDario Binacchi 	bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >>
7012722ac98SDario Binacchi 				ERR_CNT_REC_SHIFT;
7022722ac98SDario Binacchi 	bec->txerr = reg_err_counter & ERR_CNT_TEC_MASK;
7032722ac98SDario Binacchi 
7042722ac98SDario Binacchi 	return 0;
7052722ac98SDario Binacchi }
7062722ac98SDario Binacchi 
c_can_get_berr_counter(const struct net_device * dev,struct can_berr_counter * bec)7072722ac98SDario Binacchi static int c_can_get_berr_counter(const struct net_device *dev,
7082722ac98SDario Binacchi 				  struct can_berr_counter *bec)
7092722ac98SDario Binacchi {
7102722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
7112722ac98SDario Binacchi 	int err;
7122722ac98SDario Binacchi 
7132722ac98SDario Binacchi 	c_can_pm_runtime_get_sync(priv);
7142722ac98SDario Binacchi 	err = __c_can_get_berr_counter(dev, bec);
7152722ac98SDario Binacchi 	c_can_pm_runtime_put_sync(priv);
7162722ac98SDario Binacchi 
7172722ac98SDario Binacchi 	return err;
7182722ac98SDario Binacchi }
7192722ac98SDario Binacchi 
c_can_do_tx(struct net_device * dev)7202722ac98SDario Binacchi static void c_can_do_tx(struct net_device *dev)
7212722ac98SDario Binacchi {
7222722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
72328e86e9aSDario Binacchi 	struct c_can_tx_ring *tx_ring = &priv->tx;
7242722ac98SDario Binacchi 	struct net_device_stats *stats = &dev->stats;
72528e86e9aSDario Binacchi 	u32 idx, obj, pkts = 0, bytes = 0, pend;
726387da6bcSDario Binacchi 	u8 tail;
7272722ac98SDario Binacchi 
7282722ac98SDario Binacchi 	if (priv->msg_obj_tx_last > 32)
7292722ac98SDario Binacchi 		pend = priv->read_reg32(priv, C_CAN_INTPND3_REG);
7302722ac98SDario Binacchi 	else
7312722ac98SDario Binacchi 		pend = priv->read_reg(priv, C_CAN_INTPND2_REG);
7322722ac98SDario Binacchi 
7332722ac98SDario Binacchi 	while ((idx = ffs(pend))) {
7342722ac98SDario Binacchi 		idx--;
7352722ac98SDario Binacchi 		pend &= ~BIT(idx);
7362722ac98SDario Binacchi 		obj = idx + priv->msg_obj_tx_first;
7372722ac98SDario Binacchi 
73805cb2ba4SMarc Kleine-Budde 		/* We use IF_NAPI interface instead of IF_TX because we
7392722ac98SDario Binacchi 		 * are called from c_can_poll(), which runs inside
740236de85fSMarc Kleine-Budde 		 * NAPI. We are not transmitting.
7412722ac98SDario Binacchi 		 */
74205cb2ba4SMarc Kleine-Budde 		c_can_inval_tx_object(dev, IF_NAPI, obj);
743cc4b08c3SVincent Mailhol 		bytes += can_get_echo_skb(dev, idx, NULL);
7442722ac98SDario Binacchi 		pkts++;
7452722ac98SDario Binacchi 	}
7462722ac98SDario Binacchi 
747a54cdbbaSDario Binacchi 	if (!pkts)
748a54cdbbaSDario Binacchi 		return;
749a54cdbbaSDario Binacchi 
75028e86e9aSDario Binacchi 	tx_ring->tail += pkts;
75181d192c2SMarc Kleine-Budde 	if (c_can_get_tx_free(priv, tx_ring)) {
75228e86e9aSDario Binacchi 		/* Make sure that anybody stopping the queue after
75328e86e9aSDario Binacchi 		 * this sees the new tx_ring->tail.
75428e86e9aSDario Binacchi 		 */
75528e86e9aSDario Binacchi 		smp_mb();
75628e86e9aSDario Binacchi 		netif_wake_queue(priv->dev);
75728e86e9aSDario Binacchi 	}
7582722ac98SDario Binacchi 
7592722ac98SDario Binacchi 	stats->tx_bytes += bytes;
7602722ac98SDario Binacchi 	stats->tx_packets += pkts;
761387da6bcSDario Binacchi 
762387da6bcSDario Binacchi 	tail = c_can_get_tx_tail(tx_ring);
76381d192c2SMarc Kleine-Budde 	if (priv->type == BOSCH_D_CAN && tail == 0) {
764387da6bcSDario Binacchi 		u8 head = c_can_get_tx_head(tx_ring);
765387da6bcSDario Binacchi 
766387da6bcSDario Binacchi 		/* Start transmission for all cached messages */
767387da6bcSDario Binacchi 		for (idx = tail; idx < head; idx++) {
768387da6bcSDario Binacchi 			obj = idx + priv->msg_obj_tx_first;
769387da6bcSDario Binacchi 			c_can_object_put(dev, IF_NAPI, obj, IF_COMM_TXRQST);
770387da6bcSDario Binacchi 		}
771387da6bcSDario Binacchi 	}
7722722ac98SDario Binacchi }
7732722ac98SDario Binacchi 
7742722ac98SDario Binacchi /* If we have a gap in the pending bits, that means we either
7752722ac98SDario Binacchi  * raced with the hardware or failed to readout all upper
7762722ac98SDario Binacchi  * objects in the last run due to quota limit.
7772722ac98SDario Binacchi  */
c_can_adjust_pending(u32 pend,u32 rx_mask)7782722ac98SDario Binacchi static u32 c_can_adjust_pending(u32 pend, u32 rx_mask)
7792722ac98SDario Binacchi {
7802722ac98SDario Binacchi 	u32 weight, lasts;
7812722ac98SDario Binacchi 
7822722ac98SDario Binacchi 	if (pend == rx_mask)
7832722ac98SDario Binacchi 		return pend;
7842722ac98SDario Binacchi 
7852722ac98SDario Binacchi 	/* If the last set bit is larger than the number of pending
7862722ac98SDario Binacchi 	 * bits we have a gap.
7872722ac98SDario Binacchi 	 */
7882722ac98SDario Binacchi 	weight = hweight32(pend);
7892722ac98SDario Binacchi 	lasts = fls(pend);
7902722ac98SDario Binacchi 
7912722ac98SDario Binacchi 	/* If the bits are linear, nothing to do */
7922722ac98SDario Binacchi 	if (lasts == weight)
7932722ac98SDario Binacchi 		return pend;
7942722ac98SDario Binacchi 
7952722ac98SDario Binacchi 	/* Find the first set bit after the gap. We walk backwards
7962722ac98SDario Binacchi 	 * from the last set bit.
7972722ac98SDario Binacchi 	 */
7982722ac98SDario Binacchi 	for (lasts--; pend & BIT(lasts - 1); lasts--)
7992722ac98SDario Binacchi 		;
8002722ac98SDario Binacchi 
8012722ac98SDario Binacchi 	return pend & ~GENMASK(lasts - 1, 0);
8022722ac98SDario Binacchi }
8032722ac98SDario Binacchi 
c_can_rx_object_get(struct net_device * dev,struct c_can_priv * priv,u32 obj)8042722ac98SDario Binacchi static inline void c_can_rx_object_get(struct net_device *dev,
8052722ac98SDario Binacchi 				       struct c_can_priv *priv, u32 obj)
8062722ac98SDario Binacchi {
80705cb2ba4SMarc Kleine-Budde 	c_can_object_get(dev, IF_NAPI, obj, priv->comm_rcv_high);
8082722ac98SDario Binacchi }
8092722ac98SDario Binacchi 
c_can_rx_finalize(struct net_device * dev,struct c_can_priv * priv,u32 obj)8102722ac98SDario Binacchi static inline void c_can_rx_finalize(struct net_device *dev,
8112722ac98SDario Binacchi 				     struct c_can_priv *priv, u32 obj)
8122722ac98SDario Binacchi {
8132722ac98SDario Binacchi 	if (priv->type != BOSCH_D_CAN)
81405cb2ba4SMarc Kleine-Budde 		c_can_object_get(dev, IF_NAPI, obj, IF_COMM_CLR_NEWDAT);
8152722ac98SDario Binacchi }
8162722ac98SDario Binacchi 
c_can_read_objects(struct net_device * dev,struct c_can_priv * priv,u32 pend,int quota)8172722ac98SDario Binacchi static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
8182722ac98SDario Binacchi 			      u32 pend, int quota)
8192722ac98SDario Binacchi {
8202722ac98SDario Binacchi 	u32 pkts = 0, ctrl, obj;
8212722ac98SDario Binacchi 
8222722ac98SDario Binacchi 	while ((obj = ffs(pend)) && quota > 0) {
8232722ac98SDario Binacchi 		pend &= ~BIT(obj - 1);
8242722ac98SDario Binacchi 
8252722ac98SDario Binacchi 		c_can_rx_object_get(dev, priv, obj);
82605cb2ba4SMarc Kleine-Budde 		ctrl = priv->read_reg(priv, C_CAN_IFACE(MSGCTRL_REG, IF_NAPI));
8272722ac98SDario Binacchi 
8282722ac98SDario Binacchi 		if (ctrl & IF_MCONT_MSGLST) {
82905cb2ba4SMarc Kleine-Budde 			int n;
83005cb2ba4SMarc Kleine-Budde 
83105cb2ba4SMarc Kleine-Budde 			n = c_can_handle_lost_msg_obj(dev, IF_NAPI, obj, ctrl);
8322722ac98SDario Binacchi 
8332722ac98SDario Binacchi 			pkts += n;
8342722ac98SDario Binacchi 			quota -= n;
8352722ac98SDario Binacchi 			continue;
8362722ac98SDario Binacchi 		}
8372722ac98SDario Binacchi 
8382722ac98SDario Binacchi 		/* This really should not happen, but this covers some
8392722ac98SDario Binacchi 		 * odd HW behaviour. Do not remove that unless you
8402722ac98SDario Binacchi 		 * want to brick your machine.
8412722ac98SDario Binacchi 		 */
8422722ac98SDario Binacchi 		if (!(ctrl & IF_MCONT_NEWDAT))
8432722ac98SDario Binacchi 			continue;
8442722ac98SDario Binacchi 
8452722ac98SDario Binacchi 		/* read the data from the message object */
84605cb2ba4SMarc Kleine-Budde 		c_can_read_msg_object(dev, IF_NAPI, ctrl);
8472722ac98SDario Binacchi 
8482722ac98SDario Binacchi 		c_can_rx_finalize(dev, priv, obj);
8492722ac98SDario Binacchi 
8502722ac98SDario Binacchi 		pkts++;
8512722ac98SDario Binacchi 		quota--;
8522722ac98SDario Binacchi 	}
8532722ac98SDario Binacchi 
8542722ac98SDario Binacchi 	return pkts;
8552722ac98SDario Binacchi }
8562722ac98SDario Binacchi 
c_can_get_pending(struct c_can_priv * priv)8572722ac98SDario Binacchi static inline u32 c_can_get_pending(struct c_can_priv *priv)
8582722ac98SDario Binacchi {
8592722ac98SDario Binacchi 	u32 pend;
8602722ac98SDario Binacchi 
8612722ac98SDario Binacchi 	if (priv->msg_obj_rx_last > 16)
8622722ac98SDario Binacchi 		pend = priv->read_reg32(priv, C_CAN_NEWDAT1_REG);
8632722ac98SDario Binacchi 	else
8642722ac98SDario Binacchi 		pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG);
8652722ac98SDario Binacchi 
8662722ac98SDario Binacchi 	return pend;
8672722ac98SDario Binacchi }
8682722ac98SDario Binacchi 
8692722ac98SDario Binacchi /* theory of operation:
8702722ac98SDario Binacchi  *
8712722ac98SDario Binacchi  * c_can core saves a received CAN message into the first free message
8722722ac98SDario Binacchi  * object it finds free (starting with the lowest). Bits NEWDAT and
8732722ac98SDario Binacchi  * INTPND are set for this message object indicating that a new message
8742722ac98SDario Binacchi  * has arrived.
8752722ac98SDario Binacchi  *
8762722ac98SDario Binacchi  * We clear the newdat bit right away.
8772722ac98SDario Binacchi  *
8782722ac98SDario Binacchi  * This can result in packet reordering when the readout is slow.
8792722ac98SDario Binacchi  */
c_can_do_rx_poll(struct net_device * dev,int quota)8802722ac98SDario Binacchi static int c_can_do_rx_poll(struct net_device *dev, int quota)
8812722ac98SDario Binacchi {
8822722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
8832722ac98SDario Binacchi 	u32 pkts = 0, pend = 0, toread, n;
8842722ac98SDario Binacchi 
8852722ac98SDario Binacchi 	while (quota > 0) {
8862722ac98SDario Binacchi 		if (!pend) {
8872722ac98SDario Binacchi 			pend = c_can_get_pending(priv);
8882722ac98SDario Binacchi 			if (!pend)
8892722ac98SDario Binacchi 				break;
8902722ac98SDario Binacchi 			/* If the pending field has a gap, handle the
8912722ac98SDario Binacchi 			 * bits above the gap first.
8922722ac98SDario Binacchi 			 */
8932722ac98SDario Binacchi 			toread = c_can_adjust_pending(pend,
8942722ac98SDario Binacchi 						      priv->msg_obj_rx_mask);
8952722ac98SDario Binacchi 		} else {
8962722ac98SDario Binacchi 			toread = pend;
8972722ac98SDario Binacchi 		}
8982722ac98SDario Binacchi 		/* Remove the bits from pend */
8992722ac98SDario Binacchi 		pend &= ~toread;
9002722ac98SDario Binacchi 		/* Read the objects */
9012722ac98SDario Binacchi 		n = c_can_read_objects(dev, priv, toread, quota);
9022722ac98SDario Binacchi 		pkts += n;
9032722ac98SDario Binacchi 		quota -= n;
9042722ac98SDario Binacchi 	}
9052722ac98SDario Binacchi 
9062722ac98SDario Binacchi 	return pkts;
9072722ac98SDario Binacchi }
9082722ac98SDario Binacchi 
c_can_handle_state_change(struct net_device * dev,enum c_can_bus_error_types error_type)9092722ac98SDario Binacchi static int c_can_handle_state_change(struct net_device *dev,
9102722ac98SDario Binacchi 				     enum c_can_bus_error_types error_type)
9112722ac98SDario Binacchi {
9122722ac98SDario Binacchi 	unsigned int reg_err_counter;
9132722ac98SDario Binacchi 	unsigned int rx_err_passive;
9142722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
9152722ac98SDario Binacchi 	struct can_frame *cf;
9162722ac98SDario Binacchi 	struct sk_buff *skb;
9172722ac98SDario Binacchi 	struct can_berr_counter bec;
9182722ac98SDario Binacchi 
9192722ac98SDario Binacchi 	switch (error_type) {
9202722ac98SDario Binacchi 	case C_CAN_NO_ERROR:
9212722ac98SDario Binacchi 		priv->can.state = CAN_STATE_ERROR_ACTIVE;
9222722ac98SDario Binacchi 		break;
9232722ac98SDario Binacchi 	case C_CAN_ERROR_WARNING:
9242722ac98SDario Binacchi 		/* error warning state */
9252722ac98SDario Binacchi 		priv->can.can_stats.error_warning++;
9262722ac98SDario Binacchi 		priv->can.state = CAN_STATE_ERROR_WARNING;
9272722ac98SDario Binacchi 		break;
9282722ac98SDario Binacchi 	case C_CAN_ERROR_PASSIVE:
9292722ac98SDario Binacchi 		/* error passive state */
9302722ac98SDario Binacchi 		priv->can.can_stats.error_passive++;
9312722ac98SDario Binacchi 		priv->can.state = CAN_STATE_ERROR_PASSIVE;
9322722ac98SDario Binacchi 		break;
9332722ac98SDario Binacchi 	case C_CAN_BUS_OFF:
9342722ac98SDario Binacchi 		/* bus-off state */
9352722ac98SDario Binacchi 		priv->can.state = CAN_STATE_BUS_OFF;
9362722ac98SDario Binacchi 		priv->can.can_stats.bus_off++;
9372722ac98SDario Binacchi 		break;
9382722ac98SDario Binacchi 	default:
9392722ac98SDario Binacchi 		break;
9402722ac98SDario Binacchi 	}
9412722ac98SDario Binacchi 
9422722ac98SDario Binacchi 	/* propagate the error condition to the CAN stack */
9432722ac98SDario Binacchi 	skb = alloc_can_err_skb(dev, &cf);
9442722ac98SDario Binacchi 	if (unlikely(!skb))
9452722ac98SDario Binacchi 		return 0;
9462722ac98SDario Binacchi 
9472722ac98SDario Binacchi 	__c_can_get_berr_counter(dev, &bec);
9482722ac98SDario Binacchi 	reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG);
9492722ac98SDario Binacchi 	rx_err_passive = (reg_err_counter & ERR_CNT_RP_MASK) >>
9502722ac98SDario Binacchi 				ERR_CNT_RP_SHIFT;
9512722ac98SDario Binacchi 
9522722ac98SDario Binacchi 	switch (error_type) {
9532722ac98SDario Binacchi 	case C_CAN_NO_ERROR:
9543e5c291cSVincent Mailhol 		cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
9552722ac98SDario Binacchi 		cf->data[1] = CAN_ERR_CRTL_ACTIVE;
9562722ac98SDario Binacchi 		cf->data[6] = bec.txerr;
9572722ac98SDario Binacchi 		cf->data[7] = bec.rxerr;
9582722ac98SDario Binacchi 		break;
9592722ac98SDario Binacchi 	case C_CAN_ERROR_WARNING:
9602722ac98SDario Binacchi 		/* error warning state */
9613e5c291cSVincent Mailhol 		cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
9622722ac98SDario Binacchi 		cf->data[1] = (bec.txerr > bec.rxerr) ?
9632722ac98SDario Binacchi 			CAN_ERR_CRTL_TX_WARNING :
9642722ac98SDario Binacchi 			CAN_ERR_CRTL_RX_WARNING;
9652722ac98SDario Binacchi 		cf->data[6] = bec.txerr;
9662722ac98SDario Binacchi 		cf->data[7] = bec.rxerr;
9672722ac98SDario Binacchi 
9682722ac98SDario Binacchi 		break;
9692722ac98SDario Binacchi 	case C_CAN_ERROR_PASSIVE:
9702722ac98SDario Binacchi 		/* error passive state */
9713e5c291cSVincent Mailhol 		cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
9722722ac98SDario Binacchi 		if (rx_err_passive)
9732722ac98SDario Binacchi 			cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
9742722ac98SDario Binacchi 		if (bec.txerr > 127)
9752722ac98SDario Binacchi 			cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
9762722ac98SDario Binacchi 
9772722ac98SDario Binacchi 		cf->data[6] = bec.txerr;
9782722ac98SDario Binacchi 		cf->data[7] = bec.rxerr;
9792722ac98SDario Binacchi 		break;
9802722ac98SDario Binacchi 	case C_CAN_BUS_OFF:
9812722ac98SDario Binacchi 		/* bus-off state */
9822722ac98SDario Binacchi 		cf->can_id |= CAN_ERR_BUSOFF;
9832722ac98SDario Binacchi 		can_bus_off(dev);
9842722ac98SDario Binacchi 		break;
9852722ac98SDario Binacchi 	default:
9862722ac98SDario Binacchi 		break;
9872722ac98SDario Binacchi 	}
9882722ac98SDario Binacchi 
9892722ac98SDario Binacchi 	netif_receive_skb(skb);
9902722ac98SDario Binacchi 
9912722ac98SDario Binacchi 	return 1;
9922722ac98SDario Binacchi }
9932722ac98SDario Binacchi 
c_can_handle_bus_err(struct net_device * dev,enum c_can_lec_type lec_type)9942722ac98SDario Binacchi static int c_can_handle_bus_err(struct net_device *dev,
9952722ac98SDario Binacchi 				enum c_can_lec_type lec_type)
9962722ac98SDario Binacchi {
9972722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
9982722ac98SDario Binacchi 	struct net_device_stats *stats = &dev->stats;
9992722ac98SDario Binacchi 	struct can_frame *cf;
10002722ac98SDario Binacchi 	struct sk_buff *skb;
10012722ac98SDario Binacchi 
10022722ac98SDario Binacchi 	/* early exit if no lec update or no error.
10032722ac98SDario Binacchi 	 * no lec update means that no CAN bus event has been detected
10042722ac98SDario Binacchi 	 * since CPU wrote 0x7 value to status reg.
10052722ac98SDario Binacchi 	 */
10062722ac98SDario Binacchi 	if (lec_type == LEC_UNUSED || lec_type == LEC_NO_ERROR)
10072722ac98SDario Binacchi 		return 0;
10082722ac98SDario Binacchi 
10092722ac98SDario Binacchi 	if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING))
10102722ac98SDario Binacchi 		return 0;
10112722ac98SDario Binacchi 
10122722ac98SDario Binacchi 	/* common for all type of bus errors */
10132722ac98SDario Binacchi 	priv->can.can_stats.bus_error++;
10142722ac98SDario Binacchi 
10152722ac98SDario Binacchi 	/* propagate the error condition to the CAN stack */
10162722ac98SDario Binacchi 	skb = alloc_can_err_skb(dev, &cf);
10172722ac98SDario Binacchi 
10182722ac98SDario Binacchi 	/* check for 'last error code' which tells us the
10192722ac98SDario Binacchi 	 * type of the last error to occur on the CAN bus
10202722ac98SDario Binacchi 	 */
1021*c146df82SDario Binacchi 	if (likely(skb))
10222722ac98SDario Binacchi 		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
10232722ac98SDario Binacchi 
10242722ac98SDario Binacchi 	switch (lec_type) {
10252722ac98SDario Binacchi 	case LEC_STUFF_ERROR:
10262722ac98SDario Binacchi 		netdev_dbg(dev, "stuff error\n");
1027*c146df82SDario Binacchi 		if (likely(skb))
10282722ac98SDario Binacchi 			cf->data[2] |= CAN_ERR_PROT_STUFF;
1029f32fc3beSDario Binacchi 		stats->rx_errors++;
10302722ac98SDario Binacchi 		break;
10312722ac98SDario Binacchi 	case LEC_FORM_ERROR:
10322722ac98SDario Binacchi 		netdev_dbg(dev, "form error\n");
1033*c146df82SDario Binacchi 		if (likely(skb))
10342722ac98SDario Binacchi 			cf->data[2] |= CAN_ERR_PROT_FORM;
1035f32fc3beSDario Binacchi 		stats->rx_errors++;
10362722ac98SDario Binacchi 		break;
10372722ac98SDario Binacchi 	case LEC_ACK_ERROR:
10382722ac98SDario Binacchi 		netdev_dbg(dev, "ack error\n");
1039*c146df82SDario Binacchi 		if (likely(skb))
10402722ac98SDario Binacchi 			cf->data[3] = CAN_ERR_PROT_LOC_ACK;
1041f32fc3beSDario Binacchi 		stats->tx_errors++;
10422722ac98SDario Binacchi 		break;
10432722ac98SDario Binacchi 	case LEC_BIT1_ERROR:
10442722ac98SDario Binacchi 		netdev_dbg(dev, "bit1 error\n");
1045*c146df82SDario Binacchi 		if (likely(skb))
10462722ac98SDario Binacchi 			cf->data[2] |= CAN_ERR_PROT_BIT1;
1047f32fc3beSDario Binacchi 		stats->tx_errors++;
10482722ac98SDario Binacchi 		break;
10492722ac98SDario Binacchi 	case LEC_BIT0_ERROR:
10502722ac98SDario Binacchi 		netdev_dbg(dev, "bit0 error\n");
1051*c146df82SDario Binacchi 		if (likely(skb))
10522722ac98SDario Binacchi 			cf->data[2] |= CAN_ERR_PROT_BIT0;
1053f32fc3beSDario Binacchi 		stats->tx_errors++;
10542722ac98SDario Binacchi 		break;
10552722ac98SDario Binacchi 	case LEC_CRC_ERROR:
10562722ac98SDario Binacchi 		netdev_dbg(dev, "CRC error\n");
1057*c146df82SDario Binacchi 		if (likely(skb))
10582722ac98SDario Binacchi 			cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
1059f32fc3beSDario Binacchi 		stats->rx_errors++;
10602722ac98SDario Binacchi 		break;
10612722ac98SDario Binacchi 	default:
10622722ac98SDario Binacchi 		break;
10632722ac98SDario Binacchi 	}
10642722ac98SDario Binacchi 
1065*c146df82SDario Binacchi 	if (unlikely(!skb))
1066*c146df82SDario Binacchi 		return 0;
1067*c146df82SDario Binacchi 
10682722ac98SDario Binacchi 	netif_receive_skb(skb);
10692722ac98SDario Binacchi 	return 1;
10702722ac98SDario Binacchi }
10712722ac98SDario Binacchi 
c_can_poll(struct napi_struct * napi,int quota)10722722ac98SDario Binacchi static int c_can_poll(struct napi_struct *napi, int quota)
10732722ac98SDario Binacchi {
10742722ac98SDario Binacchi 	struct net_device *dev = napi->dev;
10752722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
10762722ac98SDario Binacchi 	u16 curr, last = priv->last_status;
10772722ac98SDario Binacchi 	int work_done = 0;
10782722ac98SDario Binacchi 
10792722ac98SDario Binacchi 	/* Only read the status register if a status interrupt was pending */
10802722ac98SDario Binacchi 	if (atomic_xchg(&priv->sie_pending, 0)) {
10812722ac98SDario Binacchi 		priv->last_status = priv->read_reg(priv, C_CAN_STS_REG);
10822722ac98SDario Binacchi 		curr = priv->last_status;
10832722ac98SDario Binacchi 		/* Ack status on C_CAN. D_CAN is self clearing */
10842722ac98SDario Binacchi 		if (priv->type != BOSCH_D_CAN)
10852722ac98SDario Binacchi 			priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
10862722ac98SDario Binacchi 	} else {
10872722ac98SDario Binacchi 		/* no change detected ... */
10882722ac98SDario Binacchi 		curr = last;
10892722ac98SDario Binacchi 	}
10902722ac98SDario Binacchi 
10912722ac98SDario Binacchi 	/* handle state changes */
10922722ac98SDario Binacchi 	if ((curr & STATUS_EWARN) && (!(last & STATUS_EWARN))) {
10932722ac98SDario Binacchi 		netdev_dbg(dev, "entered error warning state\n");
10942722ac98SDario Binacchi 		work_done += c_can_handle_state_change(dev, C_CAN_ERROR_WARNING);
10952722ac98SDario Binacchi 	}
10962722ac98SDario Binacchi 
10972722ac98SDario Binacchi 	if ((curr & STATUS_EPASS) && (!(last & STATUS_EPASS))) {
10982722ac98SDario Binacchi 		netdev_dbg(dev, "entered error passive state\n");
10992722ac98SDario Binacchi 		work_done += c_can_handle_state_change(dev, C_CAN_ERROR_PASSIVE);
11002722ac98SDario Binacchi 	}
11012722ac98SDario Binacchi 
11022722ac98SDario Binacchi 	if ((curr & STATUS_BOFF) && (!(last & STATUS_BOFF))) {
11032722ac98SDario Binacchi 		netdev_dbg(dev, "entered bus off state\n");
11042722ac98SDario Binacchi 		work_done += c_can_handle_state_change(dev, C_CAN_BUS_OFF);
11052722ac98SDario Binacchi 		goto end;
11062722ac98SDario Binacchi 	}
11072722ac98SDario Binacchi 
11082722ac98SDario Binacchi 	/* handle bus recovery events */
11092722ac98SDario Binacchi 	if ((!(curr & STATUS_BOFF)) && (last & STATUS_BOFF)) {
11102722ac98SDario Binacchi 		netdev_dbg(dev, "left bus off state\n");
11112722ac98SDario Binacchi 		work_done += c_can_handle_state_change(dev, C_CAN_ERROR_PASSIVE);
11122722ac98SDario Binacchi 	}
11132722ac98SDario Binacchi 
11142722ac98SDario Binacchi 	if ((!(curr & STATUS_EPASS)) && (last & STATUS_EPASS)) {
11152722ac98SDario Binacchi 		netdev_dbg(dev, "left error passive state\n");
11162722ac98SDario Binacchi 		work_done += c_can_handle_state_change(dev, C_CAN_ERROR_WARNING);
11172722ac98SDario Binacchi 	}
11182722ac98SDario Binacchi 
11192722ac98SDario Binacchi 	if ((!(curr & STATUS_EWARN)) && (last & STATUS_EWARN)) {
11202722ac98SDario Binacchi 		netdev_dbg(dev, "left error warning state\n");
11212722ac98SDario Binacchi 		work_done += c_can_handle_state_change(dev, C_CAN_NO_ERROR);
11222722ac98SDario Binacchi 	}
11232722ac98SDario Binacchi 
11242722ac98SDario Binacchi 	/* handle lec errors on the bus */
11252722ac98SDario Binacchi 	work_done += c_can_handle_bus_err(dev, curr & LEC_MASK);
11262722ac98SDario Binacchi 
11272722ac98SDario Binacchi 	/* Handle Tx/Rx events. We do this unconditionally */
11282722ac98SDario Binacchi 	work_done += c_can_do_rx_poll(dev, (quota - work_done));
11292722ac98SDario Binacchi 	c_can_do_tx(dev);
11302722ac98SDario Binacchi 
11312722ac98SDario Binacchi end:
11322722ac98SDario Binacchi 	if (work_done < quota) {
11332722ac98SDario Binacchi 		napi_complete_done(napi, work_done);
11342722ac98SDario Binacchi 		/* enable all IRQs if we are not in bus off state */
11352722ac98SDario Binacchi 		if (priv->can.state != CAN_STATE_BUS_OFF)
11362722ac98SDario Binacchi 			c_can_irq_control(priv, true);
11372722ac98SDario Binacchi 	}
11382722ac98SDario Binacchi 
11392722ac98SDario Binacchi 	return work_done;
11402722ac98SDario Binacchi }
11412722ac98SDario Binacchi 
c_can_isr(int irq,void * dev_id)11422722ac98SDario Binacchi static irqreturn_t c_can_isr(int irq, void *dev_id)
11432722ac98SDario Binacchi {
11442722ac98SDario Binacchi 	struct net_device *dev = (struct net_device *)dev_id;
11452722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
11462722ac98SDario Binacchi 	int reg_int;
11472722ac98SDario Binacchi 
11482722ac98SDario Binacchi 	reg_int = priv->read_reg(priv, C_CAN_INT_REG);
11492722ac98SDario Binacchi 	if (!reg_int)
11502722ac98SDario Binacchi 		return IRQ_NONE;
11512722ac98SDario Binacchi 
11522722ac98SDario Binacchi 	/* save for later use */
11532722ac98SDario Binacchi 	if (reg_int & INT_STS_PENDING)
11542722ac98SDario Binacchi 		atomic_set(&priv->sie_pending, 1);
11552722ac98SDario Binacchi 
11562722ac98SDario Binacchi 	/* disable all interrupts and schedule the NAPI */
11572722ac98SDario Binacchi 	c_can_irq_control(priv, false);
11582722ac98SDario Binacchi 	napi_schedule(&priv->napi);
11592722ac98SDario Binacchi 
11602722ac98SDario Binacchi 	return IRQ_HANDLED;
11612722ac98SDario Binacchi }
11622722ac98SDario Binacchi 
c_can_open(struct net_device * dev)11632722ac98SDario Binacchi static int c_can_open(struct net_device *dev)
11642722ac98SDario Binacchi {
11652722ac98SDario Binacchi 	int err;
11662722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
11672722ac98SDario Binacchi 
11682722ac98SDario Binacchi 	c_can_pm_runtime_get_sync(priv);
11692722ac98SDario Binacchi 	c_can_reset_ram(priv, true);
11702722ac98SDario Binacchi 
11712722ac98SDario Binacchi 	/* open the can device */
11722722ac98SDario Binacchi 	err = open_candev(dev);
11732722ac98SDario Binacchi 	if (err) {
11742722ac98SDario Binacchi 		netdev_err(dev, "failed to open can device\n");
11752722ac98SDario Binacchi 		goto exit_open_fail;
11762722ac98SDario Binacchi 	}
11772722ac98SDario Binacchi 
11782722ac98SDario Binacchi 	/* register interrupt handler */
11792722ac98SDario Binacchi 	err = request_irq(dev->irq, &c_can_isr, IRQF_SHARED, dev->name,
11802722ac98SDario Binacchi 			  dev);
11812722ac98SDario Binacchi 	if (err < 0) {
11822722ac98SDario Binacchi 		netdev_err(dev, "failed to request interrupt\n");
11832722ac98SDario Binacchi 		goto exit_irq_fail;
11842722ac98SDario Binacchi 	}
11852722ac98SDario Binacchi 
11862722ac98SDario Binacchi 	/* start the c_can controller */
11872722ac98SDario Binacchi 	err = c_can_start(dev);
11882722ac98SDario Binacchi 	if (err)
11892722ac98SDario Binacchi 		goto exit_start_fail;
11902722ac98SDario Binacchi 
11912722ac98SDario Binacchi 	napi_enable(&priv->napi);
11922722ac98SDario Binacchi 	/* enable status change, error and module interrupts */
11932722ac98SDario Binacchi 	c_can_irq_control(priv, true);
11942722ac98SDario Binacchi 	netif_start_queue(dev);
11952722ac98SDario Binacchi 
11962722ac98SDario Binacchi 	return 0;
11972722ac98SDario Binacchi 
11982722ac98SDario Binacchi exit_start_fail:
11992722ac98SDario Binacchi 	free_irq(dev->irq, dev);
12002722ac98SDario Binacchi exit_irq_fail:
12012722ac98SDario Binacchi 	close_candev(dev);
12022722ac98SDario Binacchi exit_open_fail:
12032722ac98SDario Binacchi 	c_can_reset_ram(priv, false);
12042722ac98SDario Binacchi 	c_can_pm_runtime_put_sync(priv);
12052722ac98SDario Binacchi 	return err;
12062722ac98SDario Binacchi }
12072722ac98SDario Binacchi 
c_can_close(struct net_device * dev)12082722ac98SDario Binacchi static int c_can_close(struct net_device *dev)
12092722ac98SDario Binacchi {
12102722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
12112722ac98SDario Binacchi 
12122722ac98SDario Binacchi 	netif_stop_queue(dev);
12132722ac98SDario Binacchi 	napi_disable(&priv->napi);
12142722ac98SDario Binacchi 	c_can_stop(dev);
12152722ac98SDario Binacchi 	free_irq(dev->irq, dev);
12162722ac98SDario Binacchi 	close_candev(dev);
12172722ac98SDario Binacchi 
12182722ac98SDario Binacchi 	c_can_reset_ram(priv, false);
12192722ac98SDario Binacchi 	c_can_pm_runtime_put_sync(priv);
12202722ac98SDario Binacchi 
12212722ac98SDario Binacchi 	return 0;
12222722ac98SDario Binacchi }
12232722ac98SDario Binacchi 
alloc_c_can_dev(int msg_obj_num)12242722ac98SDario Binacchi struct net_device *alloc_c_can_dev(int msg_obj_num)
12252722ac98SDario Binacchi {
12262722ac98SDario Binacchi 	struct net_device *dev;
12272722ac98SDario Binacchi 	struct c_can_priv *priv;
12282722ac98SDario Binacchi 	int msg_obj_tx_num = msg_obj_num / 2;
12292722ac98SDario Binacchi 
1230cc4b08c3SVincent Mailhol 	dev = alloc_candev(sizeof(*priv), msg_obj_tx_num);
12312722ac98SDario Binacchi 	if (!dev)
12322722ac98SDario Binacchi 		return NULL;
12332722ac98SDario Binacchi 
12342722ac98SDario Binacchi 	priv = netdev_priv(dev);
12352722ac98SDario Binacchi 	priv->msg_obj_num = msg_obj_num;
12362722ac98SDario Binacchi 	priv->msg_obj_rx_num = msg_obj_num - msg_obj_tx_num;
12372722ac98SDario Binacchi 	priv->msg_obj_rx_first = 1;
12382722ac98SDario Binacchi 	priv->msg_obj_rx_last =
12392722ac98SDario Binacchi 		priv->msg_obj_rx_first + priv->msg_obj_rx_num - 1;
12402722ac98SDario Binacchi 	priv->msg_obj_rx_mask = GENMASK(priv->msg_obj_rx_num - 1, 0);
12412722ac98SDario Binacchi 
12422722ac98SDario Binacchi 	priv->msg_obj_tx_num = msg_obj_tx_num;
12432722ac98SDario Binacchi 	priv->msg_obj_tx_first = priv->msg_obj_rx_last + 1;
12442722ac98SDario Binacchi 	priv->msg_obj_tx_last =
12452722ac98SDario Binacchi 		priv->msg_obj_tx_first + priv->msg_obj_tx_num - 1;
12462722ac98SDario Binacchi 
124728e86e9aSDario Binacchi 	priv->tx.head = 0;
124828e86e9aSDario Binacchi 	priv->tx.tail = 0;
124928e86e9aSDario Binacchi 	priv->tx.obj_num = msg_obj_tx_num;
125028e86e9aSDario Binacchi 
1251caf6b7f8SJakub Kicinski 	netif_napi_add_weight(dev, &priv->napi, c_can_poll,
1252caf6b7f8SJakub Kicinski 			      priv->msg_obj_rx_num);
12532722ac98SDario Binacchi 
12542722ac98SDario Binacchi 	priv->dev = dev;
12552722ac98SDario Binacchi 	priv->can.bittiming_const = &c_can_bittiming_const;
12562722ac98SDario Binacchi 	priv->can.do_set_mode = c_can_set_mode;
12572722ac98SDario Binacchi 	priv->can.do_get_berr_counter = c_can_get_berr_counter;
12582722ac98SDario Binacchi 	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
12592722ac98SDario Binacchi 					CAN_CTRLMODE_LISTENONLY |
12602722ac98SDario Binacchi 					CAN_CTRLMODE_BERR_REPORTING;
12612722ac98SDario Binacchi 
12622722ac98SDario Binacchi 	return dev;
12632722ac98SDario Binacchi }
12642722ac98SDario Binacchi EXPORT_SYMBOL_GPL(alloc_c_can_dev);
12652722ac98SDario Binacchi 
12662722ac98SDario Binacchi #ifdef CONFIG_PM
c_can_power_down(struct net_device * dev)12672722ac98SDario Binacchi int c_can_power_down(struct net_device *dev)
12682722ac98SDario Binacchi {
12692722ac98SDario Binacchi 	u32 val;
12702722ac98SDario Binacchi 	unsigned long time_out;
12712722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
12722722ac98SDario Binacchi 
12732722ac98SDario Binacchi 	if (!(dev->flags & IFF_UP))
12742722ac98SDario Binacchi 		return 0;
12752722ac98SDario Binacchi 
12762722ac98SDario Binacchi 	WARN_ON(priv->type != BOSCH_D_CAN);
12772722ac98SDario Binacchi 
12782722ac98SDario Binacchi 	/* set PDR value so the device goes to power down mode */
12792722ac98SDario Binacchi 	val = priv->read_reg(priv, C_CAN_CTRL_EX_REG);
12802722ac98SDario Binacchi 	val |= CONTROL_EX_PDR;
12812722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_CTRL_EX_REG, val);
12822722ac98SDario Binacchi 
12832722ac98SDario Binacchi 	/* Wait for the PDA bit to get set */
12842722ac98SDario Binacchi 	time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS);
12852722ac98SDario Binacchi 	while (!(priv->read_reg(priv, C_CAN_STS_REG) & STATUS_PDA) &&
12862722ac98SDario Binacchi 	       time_after(time_out, jiffies))
12872722ac98SDario Binacchi 		cpu_relax();
12882722ac98SDario Binacchi 
12892722ac98SDario Binacchi 	if (time_after(jiffies, time_out))
12902722ac98SDario Binacchi 		return -ETIMEDOUT;
12912722ac98SDario Binacchi 
12922722ac98SDario Binacchi 	c_can_stop(dev);
12932722ac98SDario Binacchi 
12942722ac98SDario Binacchi 	c_can_reset_ram(priv, false);
12952722ac98SDario Binacchi 	c_can_pm_runtime_put_sync(priv);
12962722ac98SDario Binacchi 
12972722ac98SDario Binacchi 	return 0;
12982722ac98SDario Binacchi }
12992722ac98SDario Binacchi EXPORT_SYMBOL_GPL(c_can_power_down);
13002722ac98SDario Binacchi 
c_can_power_up(struct net_device * dev)13012722ac98SDario Binacchi int c_can_power_up(struct net_device *dev)
13022722ac98SDario Binacchi {
13032722ac98SDario Binacchi 	u32 val;
13042722ac98SDario Binacchi 	unsigned long time_out;
13052722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
13062722ac98SDario Binacchi 	int ret;
13072722ac98SDario Binacchi 
13082722ac98SDario Binacchi 	if (!(dev->flags & IFF_UP))
13092722ac98SDario Binacchi 		return 0;
13102722ac98SDario Binacchi 
13112722ac98SDario Binacchi 	WARN_ON(priv->type != BOSCH_D_CAN);
13122722ac98SDario Binacchi 
13132722ac98SDario Binacchi 	c_can_pm_runtime_get_sync(priv);
13142722ac98SDario Binacchi 	c_can_reset_ram(priv, true);
13152722ac98SDario Binacchi 
13162722ac98SDario Binacchi 	/* Clear PDR and INIT bits */
13172722ac98SDario Binacchi 	val = priv->read_reg(priv, C_CAN_CTRL_EX_REG);
13182722ac98SDario Binacchi 	val &= ~CONTROL_EX_PDR;
13192722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_CTRL_EX_REG, val);
13202722ac98SDario Binacchi 	val = priv->read_reg(priv, C_CAN_CTRL_REG);
13212722ac98SDario Binacchi 	val &= ~CONTROL_INIT;
13222722ac98SDario Binacchi 	priv->write_reg(priv, C_CAN_CTRL_REG, val);
13232722ac98SDario Binacchi 
13242722ac98SDario Binacchi 	/* Wait for the PDA bit to get clear */
13252722ac98SDario Binacchi 	time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS);
13262722ac98SDario Binacchi 	while ((priv->read_reg(priv, C_CAN_STS_REG) & STATUS_PDA) &&
13272722ac98SDario Binacchi 	       time_after(time_out, jiffies))
13282722ac98SDario Binacchi 		cpu_relax();
13292722ac98SDario Binacchi 
13302722ac98SDario Binacchi 	if (time_after(jiffies, time_out)) {
13312722ac98SDario Binacchi 		ret = -ETIMEDOUT;
13322722ac98SDario Binacchi 		goto err_out;
13332722ac98SDario Binacchi 	}
13342722ac98SDario Binacchi 
13352722ac98SDario Binacchi 	ret = c_can_start(dev);
13362722ac98SDario Binacchi 	if (ret)
13372722ac98SDario Binacchi 		goto err_out;
13382722ac98SDario Binacchi 
13392722ac98SDario Binacchi 	c_can_irq_control(priv, true);
13402722ac98SDario Binacchi 
13412722ac98SDario Binacchi 	return 0;
13422722ac98SDario Binacchi 
13432722ac98SDario Binacchi err_out:
13442722ac98SDario Binacchi 	c_can_reset_ram(priv, false);
13452722ac98SDario Binacchi 	c_can_pm_runtime_put_sync(priv);
13462722ac98SDario Binacchi 
13472722ac98SDario Binacchi 	return ret;
13482722ac98SDario Binacchi }
13492722ac98SDario Binacchi EXPORT_SYMBOL_GPL(c_can_power_up);
13502722ac98SDario Binacchi #endif
13512722ac98SDario Binacchi 
free_c_can_dev(struct net_device * dev)13522722ac98SDario Binacchi void free_c_can_dev(struct net_device *dev)
13532722ac98SDario Binacchi {
13542722ac98SDario Binacchi 	struct c_can_priv *priv = netdev_priv(dev);
13552722ac98SDario Binacchi 
13562722ac98SDario Binacchi 	netif_napi_del(&priv->napi);
13572722ac98SDario Binacchi 	free_candev(dev);
13582722ac98SDario Binacchi }
13592722ac98SDario Binacchi EXPORT_SYMBOL_GPL(free_c_can_dev);
13602722ac98SDario Binacchi 
13612722ac98SDario Binacchi static const struct net_device_ops c_can_netdev_ops = {
13622722ac98SDario Binacchi 	.ndo_open = c_can_open,
13632722ac98SDario Binacchi 	.ndo_stop = c_can_close,
13642722ac98SDario Binacchi 	.ndo_start_xmit = c_can_start_xmit,
13652722ac98SDario Binacchi 	.ndo_change_mtu = can_change_mtu,
13662722ac98SDario Binacchi };
13672722ac98SDario Binacchi 
register_c_can_dev(struct net_device * dev)13682722ac98SDario Binacchi int register_c_can_dev(struct net_device *dev)
13692722ac98SDario Binacchi {
13702722ac98SDario Binacchi 	/* Deactivate pins to prevent DRA7 DCAN IP from being
13712722ac98SDario Binacchi 	 * stuck in transition when module is disabled.
13722722ac98SDario Binacchi 	 * Pins are activated in c_can_start() and deactivated
13732722ac98SDario Binacchi 	 * in c_can_stop()
13742722ac98SDario Binacchi 	 */
13752722ac98SDario Binacchi 	pinctrl_pm_select_sleep_state(dev->dev.parent);
13762722ac98SDario Binacchi 
13772722ac98SDario Binacchi 	dev->flags |= IFF_ECHO;	/* we support local echo */
13782722ac98SDario Binacchi 	dev->netdev_ops = &c_can_netdev_ops;
13790ccb3e0bSVincent Mailhol 	dev->ethtool_ops = &c_can_ethtool_ops;
13802722ac98SDario Binacchi 
13816c1e423aSOliver Hartkopp 	return register_candev(dev);
13822722ac98SDario Binacchi }
13832722ac98SDario Binacchi EXPORT_SYMBOL_GPL(register_c_can_dev);
13842722ac98SDario Binacchi 
unregister_c_can_dev(struct net_device * dev)13852722ac98SDario Binacchi void unregister_c_can_dev(struct net_device *dev)
13862722ac98SDario Binacchi {
13872722ac98SDario Binacchi 	unregister_candev(dev);
13882722ac98SDario Binacchi }
13892722ac98SDario Binacchi EXPORT_SYMBOL_GPL(unregister_c_can_dev);
13902722ac98SDario Binacchi 
13912722ac98SDario Binacchi MODULE_AUTHOR("Bhupesh Sharma <bhupesh.sharma@st.com>");
13922722ac98SDario Binacchi MODULE_LICENSE("GPL v2");
13932722ac98SDario Binacchi MODULE_DESCRIPTION("CAN bus driver for Bosch C_CAN controller");
1394