xref: /OK3568_Linux_fs/kernel/drivers/net/can/sun4i_can.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * sun4i_can.c - CAN bus controller driver for Allwinner SUN4I&SUN7I based SoCs
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2013 Peter Chen
5*4882a593Smuzhiyun  * Copyright (C) 2015 Gerhard Bertelsmann
6*4882a593Smuzhiyun  * All rights reserved.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Parts of this software are based on (derived from) the SJA1000 code by:
9*4882a593Smuzhiyun  *   Copyright (C) 2014 Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
10*4882a593Smuzhiyun  *   Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com>
11*4882a593Smuzhiyun  *   Copyright (C) 2002-2007 Volkswagen Group Electronic Research
12*4882a593Smuzhiyun  *   Copyright (C) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33,
13*4882a593Smuzhiyun  *   38106 Braunschweig, GERMANY
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * Redistribution and use in source and binary forms, with or without
16*4882a593Smuzhiyun  * modification, are permitted provided that the following conditions
17*4882a593Smuzhiyun  * are met:
18*4882a593Smuzhiyun  * 1. Redistributions of source code must retain the above copyright
19*4882a593Smuzhiyun  *    notice, this list of conditions and the following disclaimer.
20*4882a593Smuzhiyun  * 2. Redistributions in binary form must reproduce the above copyright
21*4882a593Smuzhiyun  *    notice, this list of conditions and the following disclaimer in the
22*4882a593Smuzhiyun  *    documentation and/or other materials provided with the distribution.
23*4882a593Smuzhiyun  * 3. Neither the name of Volkswagen nor the names of its contributors
24*4882a593Smuzhiyun  *    may be used to endorse or promote products derived from this software
25*4882a593Smuzhiyun  *    without specific prior written permission.
26*4882a593Smuzhiyun  *
27*4882a593Smuzhiyun  * Alternatively, provided that this notice is retained in full, this
28*4882a593Smuzhiyun  * software may be distributed under the terms of the GNU General
29*4882a593Smuzhiyun  * Public License ("GPL") version 2, in which case the provisions of the
30*4882a593Smuzhiyun  * GPL apply INSTEAD OF those given above.
31*4882a593Smuzhiyun  *
32*4882a593Smuzhiyun  * The provided data structures and external interfaces from this code
33*4882a593Smuzhiyun  * are not restricted to be used by modules with a GPL compatible license.
34*4882a593Smuzhiyun  *
35*4882a593Smuzhiyun  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36*4882a593Smuzhiyun  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37*4882a593Smuzhiyun  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38*4882a593Smuzhiyun  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39*4882a593Smuzhiyun  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40*4882a593Smuzhiyun  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41*4882a593Smuzhiyun  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42*4882a593Smuzhiyun  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43*4882a593Smuzhiyun  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44*4882a593Smuzhiyun  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45*4882a593Smuzhiyun  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46*4882a593Smuzhiyun  * DAMAGE.
47*4882a593Smuzhiyun  *
48*4882a593Smuzhiyun  */
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun #include <linux/netdevice.h>
51*4882a593Smuzhiyun #include <linux/can.h>
52*4882a593Smuzhiyun #include <linux/can/dev.h>
53*4882a593Smuzhiyun #include <linux/can/error.h>
54*4882a593Smuzhiyun #include <linux/can/led.h>
55*4882a593Smuzhiyun #include <linux/clk.h>
56*4882a593Smuzhiyun #include <linux/delay.h>
57*4882a593Smuzhiyun #include <linux/interrupt.h>
58*4882a593Smuzhiyun #include <linux/init.h>
59*4882a593Smuzhiyun #include <linux/io.h>
60*4882a593Smuzhiyun #include <linux/module.h>
61*4882a593Smuzhiyun #include <linux/of.h>
62*4882a593Smuzhiyun #include <linux/of_device.h>
63*4882a593Smuzhiyun #include <linux/platform_device.h>
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun #define DRV_NAME "sun4i_can"
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun /* Registers address (physical base address 0x01C2BC00) */
68*4882a593Smuzhiyun #define SUN4I_REG_MSEL_ADDR	0x0000	/* CAN Mode Select */
69*4882a593Smuzhiyun #define SUN4I_REG_CMD_ADDR	0x0004	/* CAN Command */
70*4882a593Smuzhiyun #define SUN4I_REG_STA_ADDR	0x0008	/* CAN Status */
71*4882a593Smuzhiyun #define SUN4I_REG_INT_ADDR	0x000c	/* CAN Interrupt Flag */
72*4882a593Smuzhiyun #define SUN4I_REG_INTEN_ADDR	0x0010	/* CAN Interrupt Enable */
73*4882a593Smuzhiyun #define SUN4I_REG_BTIME_ADDR	0x0014	/* CAN Bus Timing 0 */
74*4882a593Smuzhiyun #define SUN4I_REG_TEWL_ADDR	0x0018	/* CAN Tx Error Warning Limit */
75*4882a593Smuzhiyun #define SUN4I_REG_ERRC_ADDR	0x001c	/* CAN Error Counter */
76*4882a593Smuzhiyun #define SUN4I_REG_RMCNT_ADDR	0x0020	/* CAN Receive Message Counter */
77*4882a593Smuzhiyun #define SUN4I_REG_RBUFSA_ADDR	0x0024	/* CAN Receive Buffer Start Address */
78*4882a593Smuzhiyun #define SUN4I_REG_BUF0_ADDR	0x0040	/* CAN Tx/Rx Buffer 0 */
79*4882a593Smuzhiyun #define SUN4I_REG_BUF1_ADDR	0x0044	/* CAN Tx/Rx Buffer 1 */
80*4882a593Smuzhiyun #define SUN4I_REG_BUF2_ADDR	0x0048	/* CAN Tx/Rx Buffer 2 */
81*4882a593Smuzhiyun #define SUN4I_REG_BUF3_ADDR	0x004c	/* CAN Tx/Rx Buffer 3 */
82*4882a593Smuzhiyun #define SUN4I_REG_BUF4_ADDR	0x0050	/* CAN Tx/Rx Buffer 4 */
83*4882a593Smuzhiyun #define SUN4I_REG_BUF5_ADDR	0x0054	/* CAN Tx/Rx Buffer 5 */
84*4882a593Smuzhiyun #define SUN4I_REG_BUF6_ADDR	0x0058	/* CAN Tx/Rx Buffer 6 */
85*4882a593Smuzhiyun #define SUN4I_REG_BUF7_ADDR	0x005c	/* CAN Tx/Rx Buffer 7 */
86*4882a593Smuzhiyun #define SUN4I_REG_BUF8_ADDR	0x0060	/* CAN Tx/Rx Buffer 8 */
87*4882a593Smuzhiyun #define SUN4I_REG_BUF9_ADDR	0x0064	/* CAN Tx/Rx Buffer 9 */
88*4882a593Smuzhiyun #define SUN4I_REG_BUF10_ADDR	0x0068	/* CAN Tx/Rx Buffer 10 */
89*4882a593Smuzhiyun #define SUN4I_REG_BUF11_ADDR	0x006c	/* CAN Tx/Rx Buffer 11 */
90*4882a593Smuzhiyun #define SUN4I_REG_BUF12_ADDR	0x0070	/* CAN Tx/Rx Buffer 12 */
91*4882a593Smuzhiyun #define SUN4I_REG_ACPC_ADDR	0x0040	/* CAN Acceptance Code 0 */
92*4882a593Smuzhiyun #define SUN4I_REG_ACPM_ADDR	0x0044	/* CAN Acceptance Mask 0 */
93*4882a593Smuzhiyun #define SUN4I_REG_RBUF_RBACK_START_ADDR	0x0180	/* CAN transmit buffer start */
94*4882a593Smuzhiyun #define SUN4I_REG_RBUF_RBACK_END_ADDR	0x01b0	/* CAN transmit buffer end */
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun /* Controller Register Description */
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun /* mode select register (r/w)
99*4882a593Smuzhiyun  * offset:0x0000 default:0x0000_0001
100*4882a593Smuzhiyun  */
101*4882a593Smuzhiyun #define SUN4I_MSEL_SLEEP_MODE		(0x01 << 4) /* write in reset mode */
102*4882a593Smuzhiyun #define SUN4I_MSEL_WAKE_UP		(0x00 << 4)
103*4882a593Smuzhiyun #define SUN4I_MSEL_SINGLE_FILTER	(0x01 << 3) /* write in reset mode */
104*4882a593Smuzhiyun #define SUN4I_MSEL_DUAL_FILTERS		(0x00 << 3)
105*4882a593Smuzhiyun #define SUN4I_MSEL_LOOPBACK_MODE	BIT(2)
106*4882a593Smuzhiyun #define SUN4I_MSEL_LISTEN_ONLY_MODE	BIT(1)
107*4882a593Smuzhiyun #define SUN4I_MSEL_RESET_MODE		BIT(0)
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun /* command register (w)
110*4882a593Smuzhiyun  * offset:0x0004 default:0x0000_0000
111*4882a593Smuzhiyun  */
112*4882a593Smuzhiyun #define SUN4I_CMD_BUS_OFF_REQ	BIT(5)
113*4882a593Smuzhiyun #define SUN4I_CMD_SELF_RCV_REQ	BIT(4)
114*4882a593Smuzhiyun #define SUN4I_CMD_CLEAR_OR_FLAG	BIT(3)
115*4882a593Smuzhiyun #define SUN4I_CMD_RELEASE_RBUF	BIT(2)
116*4882a593Smuzhiyun #define SUN4I_CMD_ABORT_REQ	BIT(1)
117*4882a593Smuzhiyun #define SUN4I_CMD_TRANS_REQ	BIT(0)
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun /* status register (r)
120*4882a593Smuzhiyun  * offset:0x0008 default:0x0000_003c
121*4882a593Smuzhiyun  */
122*4882a593Smuzhiyun #define SUN4I_STA_BIT_ERR	(0x00 << 22)
123*4882a593Smuzhiyun #define SUN4I_STA_FORM_ERR	(0x01 << 22)
124*4882a593Smuzhiyun #define SUN4I_STA_STUFF_ERR	(0x02 << 22)
125*4882a593Smuzhiyun #define SUN4I_STA_OTHER_ERR	(0x03 << 22)
126*4882a593Smuzhiyun #define SUN4I_STA_MASK_ERR	(0x03 << 22)
127*4882a593Smuzhiyun #define SUN4I_STA_ERR_DIR	BIT(21)
128*4882a593Smuzhiyun #define SUN4I_STA_ERR_SEG_CODE	(0x1f << 16)
129*4882a593Smuzhiyun #define SUN4I_STA_START		(0x03 << 16)
130*4882a593Smuzhiyun #define SUN4I_STA_ID28_21	(0x02 << 16)
131*4882a593Smuzhiyun #define SUN4I_STA_ID20_18	(0x06 << 16)
132*4882a593Smuzhiyun #define SUN4I_STA_SRTR		(0x04 << 16)
133*4882a593Smuzhiyun #define SUN4I_STA_IDE		(0x05 << 16)
134*4882a593Smuzhiyun #define SUN4I_STA_ID17_13	(0x07 << 16)
135*4882a593Smuzhiyun #define SUN4I_STA_ID12_5	(0x0f << 16)
136*4882a593Smuzhiyun #define SUN4I_STA_ID4_0		(0x0e << 16)
137*4882a593Smuzhiyun #define SUN4I_STA_RTR		(0x0c << 16)
138*4882a593Smuzhiyun #define SUN4I_STA_RB1		(0x0d << 16)
139*4882a593Smuzhiyun #define SUN4I_STA_RB0		(0x09 << 16)
140*4882a593Smuzhiyun #define SUN4I_STA_DLEN		(0x0b << 16)
141*4882a593Smuzhiyun #define SUN4I_STA_DATA_FIELD	(0x0a << 16)
142*4882a593Smuzhiyun #define SUN4I_STA_CRC_SEQUENCE	(0x08 << 16)
143*4882a593Smuzhiyun #define SUN4I_STA_CRC_DELIMITER	(0x18 << 16)
144*4882a593Smuzhiyun #define SUN4I_STA_ACK		(0x19 << 16)
145*4882a593Smuzhiyun #define SUN4I_STA_ACK_DELIMITER	(0x1b << 16)
146*4882a593Smuzhiyun #define SUN4I_STA_END		(0x1a << 16)
147*4882a593Smuzhiyun #define SUN4I_STA_INTERMISSION	(0x12 << 16)
148*4882a593Smuzhiyun #define SUN4I_STA_ACTIVE_ERROR	(0x11 << 16)
149*4882a593Smuzhiyun #define SUN4I_STA_PASSIVE_ERROR	(0x16 << 16)
150*4882a593Smuzhiyun #define SUN4I_STA_TOLERATE_DOMINANT_BITS	(0x13 << 16)
151*4882a593Smuzhiyun #define SUN4I_STA_ERROR_DELIMITER	(0x17 << 16)
152*4882a593Smuzhiyun #define SUN4I_STA_OVERLOAD	(0x1c << 16)
153*4882a593Smuzhiyun #define SUN4I_STA_BUS_OFF	BIT(7)
154*4882a593Smuzhiyun #define SUN4I_STA_ERR_STA	BIT(6)
155*4882a593Smuzhiyun #define SUN4I_STA_TRANS_BUSY	BIT(5)
156*4882a593Smuzhiyun #define SUN4I_STA_RCV_BUSY	BIT(4)
157*4882a593Smuzhiyun #define SUN4I_STA_TRANS_OVER	BIT(3)
158*4882a593Smuzhiyun #define SUN4I_STA_TBUF_RDY	BIT(2)
159*4882a593Smuzhiyun #define SUN4I_STA_DATA_ORUN	BIT(1)
160*4882a593Smuzhiyun #define SUN4I_STA_RBUF_RDY	BIT(0)
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun /* interrupt register (r)
163*4882a593Smuzhiyun  * offset:0x000c default:0x0000_0000
164*4882a593Smuzhiyun  */
165*4882a593Smuzhiyun #define SUN4I_INT_BUS_ERR	BIT(7)
166*4882a593Smuzhiyun #define SUN4I_INT_ARB_LOST	BIT(6)
167*4882a593Smuzhiyun #define SUN4I_INT_ERR_PASSIVE	BIT(5)
168*4882a593Smuzhiyun #define SUN4I_INT_WAKEUP	BIT(4)
169*4882a593Smuzhiyun #define SUN4I_INT_DATA_OR	BIT(3)
170*4882a593Smuzhiyun #define SUN4I_INT_ERR_WRN	BIT(2)
171*4882a593Smuzhiyun #define SUN4I_INT_TBUF_VLD	BIT(1)
172*4882a593Smuzhiyun #define SUN4I_INT_RBUF_VLD	BIT(0)
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun /* interrupt enable register (r/w)
175*4882a593Smuzhiyun  * offset:0x0010 default:0x0000_0000
176*4882a593Smuzhiyun  */
177*4882a593Smuzhiyun #define SUN4I_INTEN_BERR	BIT(7)
178*4882a593Smuzhiyun #define SUN4I_INTEN_ARB_LOST	BIT(6)
179*4882a593Smuzhiyun #define SUN4I_INTEN_ERR_PASSIVE	BIT(5)
180*4882a593Smuzhiyun #define SUN4I_INTEN_WAKEUP	BIT(4)
181*4882a593Smuzhiyun #define SUN4I_INTEN_OR		BIT(3)
182*4882a593Smuzhiyun #define SUN4I_INTEN_ERR_WRN	BIT(2)
183*4882a593Smuzhiyun #define SUN4I_INTEN_TX		BIT(1)
184*4882a593Smuzhiyun #define SUN4I_INTEN_RX		BIT(0)
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun /* error code */
187*4882a593Smuzhiyun #define SUN4I_ERR_INRCV		(0x1 << 5)
188*4882a593Smuzhiyun #define SUN4I_ERR_INTRANS	(0x0 << 5)
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun /* filter mode */
191*4882a593Smuzhiyun #define SUN4I_FILTER_CLOSE	0
192*4882a593Smuzhiyun #define SUN4I_SINGLE_FLTER_MODE	1
193*4882a593Smuzhiyun #define SUN4I_DUAL_FILTER_MODE	2
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun /* message buffer flags */
196*4882a593Smuzhiyun #define SUN4I_MSG_EFF_FLAG	BIT(7)
197*4882a593Smuzhiyun #define SUN4I_MSG_RTR_FLAG	BIT(6)
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun /* max. number of interrupts handled in ISR */
200*4882a593Smuzhiyun #define SUN4I_CAN_MAX_IRQ	20
201*4882a593Smuzhiyun #define SUN4I_MODE_MAX_RETRIES	100
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun struct sun4ican_priv {
204*4882a593Smuzhiyun 	struct can_priv can;
205*4882a593Smuzhiyun 	void __iomem *base;
206*4882a593Smuzhiyun 	struct clk *clk;
207*4882a593Smuzhiyun 	spinlock_t cmdreg_lock;	/* lock for concurrent cmd register writes */
208*4882a593Smuzhiyun };
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun static const struct can_bittiming_const sun4ican_bittiming_const = {
211*4882a593Smuzhiyun 	.name = DRV_NAME,
212*4882a593Smuzhiyun 	.tseg1_min = 1,
213*4882a593Smuzhiyun 	.tseg1_max = 16,
214*4882a593Smuzhiyun 	.tseg2_min = 1,
215*4882a593Smuzhiyun 	.tseg2_max = 8,
216*4882a593Smuzhiyun 	.sjw_max = 4,
217*4882a593Smuzhiyun 	.brp_min = 1,
218*4882a593Smuzhiyun 	.brp_max = 64,
219*4882a593Smuzhiyun 	.brp_inc = 1,
220*4882a593Smuzhiyun };
221*4882a593Smuzhiyun 
sun4i_can_write_cmdreg(struct sun4ican_priv * priv,u8 val)222*4882a593Smuzhiyun static void sun4i_can_write_cmdreg(struct sun4ican_priv *priv, u8 val)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	unsigned long flags;
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	spin_lock_irqsave(&priv->cmdreg_lock, flags);
227*4882a593Smuzhiyun 	writel(val, priv->base + SUN4I_REG_CMD_ADDR);
228*4882a593Smuzhiyun 	spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun 
set_normal_mode(struct net_device * dev)231*4882a593Smuzhiyun static int set_normal_mode(struct net_device *dev)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun 	struct sun4ican_priv *priv = netdev_priv(dev);
234*4882a593Smuzhiyun 	int retry = SUN4I_MODE_MAX_RETRIES;
235*4882a593Smuzhiyun 	u32 mod_reg_val = 0;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	do {
238*4882a593Smuzhiyun 		mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR);
239*4882a593Smuzhiyun 		mod_reg_val &= ~SUN4I_MSEL_RESET_MODE;
240*4882a593Smuzhiyun 		writel(mod_reg_val, priv->base + SUN4I_REG_MSEL_ADDR);
241*4882a593Smuzhiyun 	} while (retry-- && (mod_reg_val & SUN4I_MSEL_RESET_MODE));
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	if (readl(priv->base + SUN4I_REG_MSEL_ADDR) & SUN4I_MSEL_RESET_MODE) {
244*4882a593Smuzhiyun 		netdev_err(dev,
245*4882a593Smuzhiyun 			   "setting controller into normal mode failed!\n");
246*4882a593Smuzhiyun 		return -ETIMEDOUT;
247*4882a593Smuzhiyun 	}
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	return 0;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun 
set_reset_mode(struct net_device * dev)252*4882a593Smuzhiyun static int set_reset_mode(struct net_device *dev)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun 	struct sun4ican_priv *priv = netdev_priv(dev);
255*4882a593Smuzhiyun 	int retry = SUN4I_MODE_MAX_RETRIES;
256*4882a593Smuzhiyun 	u32 mod_reg_val = 0;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	do {
259*4882a593Smuzhiyun 		mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR);
260*4882a593Smuzhiyun 		mod_reg_val |= SUN4I_MSEL_RESET_MODE;
261*4882a593Smuzhiyun 		writel(mod_reg_val, priv->base + SUN4I_REG_MSEL_ADDR);
262*4882a593Smuzhiyun 	} while (retry-- && !(mod_reg_val & SUN4I_MSEL_RESET_MODE));
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	if (!(readl(priv->base + SUN4I_REG_MSEL_ADDR) &
265*4882a593Smuzhiyun 	      SUN4I_MSEL_RESET_MODE)) {
266*4882a593Smuzhiyun 		netdev_err(dev, "setting controller into reset mode failed!\n");
267*4882a593Smuzhiyun 		return -ETIMEDOUT;
268*4882a593Smuzhiyun 	}
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	return 0;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun /* bittiming is called in reset_mode only */
sun4ican_set_bittiming(struct net_device * dev)274*4882a593Smuzhiyun static int sun4ican_set_bittiming(struct net_device *dev)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun 	struct sun4ican_priv *priv = netdev_priv(dev);
277*4882a593Smuzhiyun 	struct can_bittiming *bt = &priv->can.bittiming;
278*4882a593Smuzhiyun 	u32 cfg;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	cfg = ((bt->brp - 1) & 0x3FF) |
281*4882a593Smuzhiyun 	     (((bt->sjw - 1) & 0x3) << 14) |
282*4882a593Smuzhiyun 	     (((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) << 16) |
283*4882a593Smuzhiyun 	     (((bt->phase_seg2 - 1) & 0x7) << 20);
284*4882a593Smuzhiyun 	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
285*4882a593Smuzhiyun 		cfg |= 0x800000;
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	netdev_dbg(dev, "setting BITTIMING=0x%08x\n", cfg);
288*4882a593Smuzhiyun 	writel(cfg, priv->base + SUN4I_REG_BTIME_ADDR);
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	return 0;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun 
sun4ican_get_berr_counter(const struct net_device * dev,struct can_berr_counter * bec)293*4882a593Smuzhiyun static int sun4ican_get_berr_counter(const struct net_device *dev,
294*4882a593Smuzhiyun 				     struct can_berr_counter *bec)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun 	struct sun4ican_priv *priv = netdev_priv(dev);
297*4882a593Smuzhiyun 	u32 errors;
298*4882a593Smuzhiyun 	int err;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	err = clk_prepare_enable(priv->clk);
301*4882a593Smuzhiyun 	if (err) {
302*4882a593Smuzhiyun 		netdev_err(dev, "could not enable clock\n");
303*4882a593Smuzhiyun 		return err;
304*4882a593Smuzhiyun 	}
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	errors = readl(priv->base + SUN4I_REG_ERRC_ADDR);
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	bec->txerr = errors & 0xFF;
309*4882a593Smuzhiyun 	bec->rxerr = (errors >> 16) & 0xFF;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	clk_disable_unprepare(priv->clk);
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	return 0;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun 
sun4i_can_start(struct net_device * dev)316*4882a593Smuzhiyun static int sun4i_can_start(struct net_device *dev)
317*4882a593Smuzhiyun {
318*4882a593Smuzhiyun 	struct sun4ican_priv *priv = netdev_priv(dev);
319*4882a593Smuzhiyun 	int err;
320*4882a593Smuzhiyun 	u32 mod_reg_val;
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	/* we need to enter the reset mode */
323*4882a593Smuzhiyun 	err = set_reset_mode(dev);
324*4882a593Smuzhiyun 	if (err) {
325*4882a593Smuzhiyun 		netdev_err(dev, "could not enter reset mode\n");
326*4882a593Smuzhiyun 		return err;
327*4882a593Smuzhiyun 	}
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	/* set filters - we accept all */
330*4882a593Smuzhiyun 	writel(0x00000000, priv->base + SUN4I_REG_ACPC_ADDR);
331*4882a593Smuzhiyun 	writel(0xFFFFFFFF, priv->base + SUN4I_REG_ACPM_ADDR);
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	/* clear error counters and error code capture */
334*4882a593Smuzhiyun 	writel(0, priv->base + SUN4I_REG_ERRC_ADDR);
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	/* enable interrupts */
337*4882a593Smuzhiyun 	if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
338*4882a593Smuzhiyun 		writel(0xFF, priv->base + SUN4I_REG_INTEN_ADDR);
339*4882a593Smuzhiyun 	else
340*4882a593Smuzhiyun 		writel(0xFF & ~SUN4I_INTEN_BERR,
341*4882a593Smuzhiyun 		       priv->base + SUN4I_REG_INTEN_ADDR);
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	/* enter the selected mode */
344*4882a593Smuzhiyun 	mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR);
345*4882a593Smuzhiyun 	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
346*4882a593Smuzhiyun 		mod_reg_val |= SUN4I_MSEL_LOOPBACK_MODE;
347*4882a593Smuzhiyun 	else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
348*4882a593Smuzhiyun 		mod_reg_val |= SUN4I_MSEL_LISTEN_ONLY_MODE;
349*4882a593Smuzhiyun 	writel(mod_reg_val, priv->base + SUN4I_REG_MSEL_ADDR);
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	err = sun4ican_set_bittiming(dev);
352*4882a593Smuzhiyun 	if (err)
353*4882a593Smuzhiyun 		return err;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	/* we are ready to enter the normal mode */
356*4882a593Smuzhiyun 	err = set_normal_mode(dev);
357*4882a593Smuzhiyun 	if (err) {
358*4882a593Smuzhiyun 		netdev_err(dev, "could not enter normal mode\n");
359*4882a593Smuzhiyun 		return err;
360*4882a593Smuzhiyun 	}
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	return 0;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun 
sun4i_can_stop(struct net_device * dev)367*4882a593Smuzhiyun static int sun4i_can_stop(struct net_device *dev)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun 	struct sun4ican_priv *priv = netdev_priv(dev);
370*4882a593Smuzhiyun 	int err;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	priv->can.state = CAN_STATE_STOPPED;
373*4882a593Smuzhiyun 	/* we need to enter reset mode */
374*4882a593Smuzhiyun 	err = set_reset_mode(dev);
375*4882a593Smuzhiyun 	if (err) {
376*4882a593Smuzhiyun 		netdev_err(dev, "could not enter reset mode\n");
377*4882a593Smuzhiyun 		return err;
378*4882a593Smuzhiyun 	}
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	/* disable all interrupts */
381*4882a593Smuzhiyun 	writel(0, priv->base + SUN4I_REG_INTEN_ADDR);
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	return 0;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun 
sun4ican_set_mode(struct net_device * dev,enum can_mode mode)386*4882a593Smuzhiyun static int sun4ican_set_mode(struct net_device *dev, enum can_mode mode)
387*4882a593Smuzhiyun {
388*4882a593Smuzhiyun 	int err;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	switch (mode) {
391*4882a593Smuzhiyun 	case CAN_MODE_START:
392*4882a593Smuzhiyun 		err = sun4i_can_start(dev);
393*4882a593Smuzhiyun 		if (err) {
394*4882a593Smuzhiyun 			netdev_err(dev, "starting CAN controller failed!\n");
395*4882a593Smuzhiyun 			return err;
396*4882a593Smuzhiyun 		}
397*4882a593Smuzhiyun 		if (netif_queue_stopped(dev))
398*4882a593Smuzhiyun 			netif_wake_queue(dev);
399*4882a593Smuzhiyun 		break;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	default:
402*4882a593Smuzhiyun 		return -EOPNOTSUPP;
403*4882a593Smuzhiyun 	}
404*4882a593Smuzhiyun 	return 0;
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun /* transmit a CAN message
408*4882a593Smuzhiyun  * message layout in the sk_buff should be like this:
409*4882a593Smuzhiyun  * xx xx xx xx         ff         ll 00 11 22 33 44 55 66 77
410*4882a593Smuzhiyun  * [ can_id ] [flags] [len] [can data (up to 8 bytes]
411*4882a593Smuzhiyun  */
sun4ican_start_xmit(struct sk_buff * skb,struct net_device * dev)412*4882a593Smuzhiyun static netdev_tx_t sun4ican_start_xmit(struct sk_buff *skb, struct net_device *dev)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun 	struct sun4ican_priv *priv = netdev_priv(dev);
415*4882a593Smuzhiyun 	struct can_frame *cf = (struct can_frame *)skb->data;
416*4882a593Smuzhiyun 	u8 dlc;
417*4882a593Smuzhiyun 	u32 dreg, msg_flag_n;
418*4882a593Smuzhiyun 	canid_t id;
419*4882a593Smuzhiyun 	int i;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	if (can_dropped_invalid_skb(dev, skb))
422*4882a593Smuzhiyun 		return NETDEV_TX_OK;
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	netif_stop_queue(dev);
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	id = cf->can_id;
427*4882a593Smuzhiyun 	dlc = cf->can_dlc;
428*4882a593Smuzhiyun 	msg_flag_n = dlc;
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	if (id & CAN_RTR_FLAG)
431*4882a593Smuzhiyun 		msg_flag_n |= SUN4I_MSG_RTR_FLAG;
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	if (id & CAN_EFF_FLAG) {
434*4882a593Smuzhiyun 		msg_flag_n |= SUN4I_MSG_EFF_FLAG;
435*4882a593Smuzhiyun 		dreg = SUN4I_REG_BUF5_ADDR;
436*4882a593Smuzhiyun 		writel((id >> 21) & 0xFF, priv->base + SUN4I_REG_BUF1_ADDR);
437*4882a593Smuzhiyun 		writel((id >> 13) & 0xFF, priv->base + SUN4I_REG_BUF2_ADDR);
438*4882a593Smuzhiyun 		writel((id >> 5)  & 0xFF, priv->base + SUN4I_REG_BUF3_ADDR);
439*4882a593Smuzhiyun 		writel((id << 3)  & 0xF8, priv->base + SUN4I_REG_BUF4_ADDR);
440*4882a593Smuzhiyun 	} else {
441*4882a593Smuzhiyun 		dreg = SUN4I_REG_BUF3_ADDR;
442*4882a593Smuzhiyun 		writel((id >> 3) & 0xFF, priv->base + SUN4I_REG_BUF1_ADDR);
443*4882a593Smuzhiyun 		writel((id << 5) & 0xE0, priv->base + SUN4I_REG_BUF2_ADDR);
444*4882a593Smuzhiyun 	}
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	for (i = 0; i < dlc; i++)
447*4882a593Smuzhiyun 		writel(cf->data[i], priv->base + (dreg + i * 4));
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	writel(msg_flag_n, priv->base + SUN4I_REG_BUF0_ADDR);
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	can_put_echo_skb(skb, dev, 0);
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
454*4882a593Smuzhiyun 		sun4i_can_write_cmdreg(priv, SUN4I_CMD_SELF_RCV_REQ);
455*4882a593Smuzhiyun 	else
456*4882a593Smuzhiyun 		sun4i_can_write_cmdreg(priv, SUN4I_CMD_TRANS_REQ);
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 	return NETDEV_TX_OK;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun 
sun4i_can_rx(struct net_device * dev)461*4882a593Smuzhiyun static void sun4i_can_rx(struct net_device *dev)
462*4882a593Smuzhiyun {
463*4882a593Smuzhiyun 	struct sun4ican_priv *priv = netdev_priv(dev);
464*4882a593Smuzhiyun 	struct net_device_stats *stats = &dev->stats;
465*4882a593Smuzhiyun 	struct can_frame *cf;
466*4882a593Smuzhiyun 	struct sk_buff *skb;
467*4882a593Smuzhiyun 	u8 fi;
468*4882a593Smuzhiyun 	u32 dreg;
469*4882a593Smuzhiyun 	canid_t id;
470*4882a593Smuzhiyun 	int i;
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 	/* create zero'ed CAN frame buffer */
473*4882a593Smuzhiyun 	skb = alloc_can_skb(dev, &cf);
474*4882a593Smuzhiyun 	if (!skb)
475*4882a593Smuzhiyun 		return;
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	fi = readl(priv->base + SUN4I_REG_BUF0_ADDR);
478*4882a593Smuzhiyun 	cf->can_dlc = get_can_dlc(fi & 0x0F);
479*4882a593Smuzhiyun 	if (fi & SUN4I_MSG_EFF_FLAG) {
480*4882a593Smuzhiyun 		dreg = SUN4I_REG_BUF5_ADDR;
481*4882a593Smuzhiyun 		id = (readl(priv->base + SUN4I_REG_BUF1_ADDR) << 21) |
482*4882a593Smuzhiyun 		     (readl(priv->base + SUN4I_REG_BUF2_ADDR) << 13) |
483*4882a593Smuzhiyun 		     (readl(priv->base + SUN4I_REG_BUF3_ADDR) << 5)  |
484*4882a593Smuzhiyun 		    ((readl(priv->base + SUN4I_REG_BUF4_ADDR) >> 3)  & 0x1f);
485*4882a593Smuzhiyun 		id |= CAN_EFF_FLAG;
486*4882a593Smuzhiyun 	} else {
487*4882a593Smuzhiyun 		dreg = SUN4I_REG_BUF3_ADDR;
488*4882a593Smuzhiyun 		id = (readl(priv->base + SUN4I_REG_BUF1_ADDR) << 3) |
489*4882a593Smuzhiyun 		    ((readl(priv->base + SUN4I_REG_BUF2_ADDR) >> 5) & 0x7);
490*4882a593Smuzhiyun 	}
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	/* remote frame ? */
493*4882a593Smuzhiyun 	if (fi & SUN4I_MSG_RTR_FLAG)
494*4882a593Smuzhiyun 		id |= CAN_RTR_FLAG;
495*4882a593Smuzhiyun 	else
496*4882a593Smuzhiyun 		for (i = 0; i < cf->can_dlc; i++)
497*4882a593Smuzhiyun 			cf->data[i] = readl(priv->base + dreg + i * 4);
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	cf->can_id = id;
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	sun4i_can_write_cmdreg(priv, SUN4I_CMD_RELEASE_RBUF);
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 	stats->rx_packets++;
504*4882a593Smuzhiyun 	stats->rx_bytes += cf->can_dlc;
505*4882a593Smuzhiyun 	netif_rx(skb);
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	can_led_event(dev, CAN_LED_EVENT_RX);
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun 
sun4i_can_err(struct net_device * dev,u8 isrc,u8 status)510*4882a593Smuzhiyun static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun 	struct sun4ican_priv *priv = netdev_priv(dev);
513*4882a593Smuzhiyun 	struct net_device_stats *stats = &dev->stats;
514*4882a593Smuzhiyun 	struct can_frame *cf;
515*4882a593Smuzhiyun 	struct sk_buff *skb;
516*4882a593Smuzhiyun 	enum can_state state = priv->can.state;
517*4882a593Smuzhiyun 	enum can_state rx_state, tx_state;
518*4882a593Smuzhiyun 	unsigned int rxerr, txerr, errc;
519*4882a593Smuzhiyun 	u32 ecc, alc;
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	/* we don't skip if alloc fails because we want the stats anyhow */
522*4882a593Smuzhiyun 	skb = alloc_can_err_skb(dev, &cf);
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun 	errc = readl(priv->base + SUN4I_REG_ERRC_ADDR);
525*4882a593Smuzhiyun 	rxerr = (errc >> 16) & 0xFF;
526*4882a593Smuzhiyun 	txerr = errc & 0xFF;
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	if (isrc & SUN4I_INT_DATA_OR) {
529*4882a593Smuzhiyun 		/* data overrun interrupt */
530*4882a593Smuzhiyun 		netdev_dbg(dev, "data overrun interrupt\n");
531*4882a593Smuzhiyun 		if (likely(skb)) {
532*4882a593Smuzhiyun 			cf->can_id |= CAN_ERR_CRTL;
533*4882a593Smuzhiyun 			cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
534*4882a593Smuzhiyun 		}
535*4882a593Smuzhiyun 		stats->rx_over_errors++;
536*4882a593Smuzhiyun 		stats->rx_errors++;
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 		/* reset the CAN IP by entering reset mode
539*4882a593Smuzhiyun 		 * ignoring timeout error
540*4882a593Smuzhiyun 		 */
541*4882a593Smuzhiyun 		set_reset_mode(dev);
542*4882a593Smuzhiyun 		set_normal_mode(dev);
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun 		/* clear bit */
545*4882a593Smuzhiyun 		sun4i_can_write_cmdreg(priv, SUN4I_CMD_CLEAR_OR_FLAG);
546*4882a593Smuzhiyun 	}
547*4882a593Smuzhiyun 	if (isrc & SUN4I_INT_ERR_WRN) {
548*4882a593Smuzhiyun 		/* error warning interrupt */
549*4882a593Smuzhiyun 		netdev_dbg(dev, "error warning interrupt\n");
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 		if (status & SUN4I_STA_BUS_OFF)
552*4882a593Smuzhiyun 			state = CAN_STATE_BUS_OFF;
553*4882a593Smuzhiyun 		else if (status & SUN4I_STA_ERR_STA)
554*4882a593Smuzhiyun 			state = CAN_STATE_ERROR_WARNING;
555*4882a593Smuzhiyun 		else
556*4882a593Smuzhiyun 			state = CAN_STATE_ERROR_ACTIVE;
557*4882a593Smuzhiyun 	}
558*4882a593Smuzhiyun 	if (skb && state != CAN_STATE_BUS_OFF) {
559*4882a593Smuzhiyun 		cf->data[6] = txerr;
560*4882a593Smuzhiyun 		cf->data[7] = rxerr;
561*4882a593Smuzhiyun 	}
562*4882a593Smuzhiyun 	if (isrc & SUN4I_INT_BUS_ERR) {
563*4882a593Smuzhiyun 		/* bus error interrupt */
564*4882a593Smuzhiyun 		netdev_dbg(dev, "bus error interrupt\n");
565*4882a593Smuzhiyun 		priv->can.can_stats.bus_error++;
566*4882a593Smuzhiyun 		stats->rx_errors++;
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 		if (likely(skb)) {
569*4882a593Smuzhiyun 			ecc = readl(priv->base + SUN4I_REG_STA_ADDR);
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 			cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 			switch (ecc & SUN4I_STA_MASK_ERR) {
574*4882a593Smuzhiyun 			case SUN4I_STA_BIT_ERR:
575*4882a593Smuzhiyun 				cf->data[2] |= CAN_ERR_PROT_BIT;
576*4882a593Smuzhiyun 				break;
577*4882a593Smuzhiyun 			case SUN4I_STA_FORM_ERR:
578*4882a593Smuzhiyun 				cf->data[2] |= CAN_ERR_PROT_FORM;
579*4882a593Smuzhiyun 				break;
580*4882a593Smuzhiyun 			case SUN4I_STA_STUFF_ERR:
581*4882a593Smuzhiyun 				cf->data[2] |= CAN_ERR_PROT_STUFF;
582*4882a593Smuzhiyun 				break;
583*4882a593Smuzhiyun 			default:
584*4882a593Smuzhiyun 				cf->data[3] = (ecc & SUN4I_STA_ERR_SEG_CODE)
585*4882a593Smuzhiyun 					       >> 16;
586*4882a593Smuzhiyun 				break;
587*4882a593Smuzhiyun 			}
588*4882a593Smuzhiyun 			/* error occurred during transmission? */
589*4882a593Smuzhiyun 			if ((ecc & SUN4I_STA_ERR_DIR) == 0)
590*4882a593Smuzhiyun 				cf->data[2] |= CAN_ERR_PROT_TX;
591*4882a593Smuzhiyun 		}
592*4882a593Smuzhiyun 	}
593*4882a593Smuzhiyun 	if (isrc & SUN4I_INT_ERR_PASSIVE) {
594*4882a593Smuzhiyun 		/* error passive interrupt */
595*4882a593Smuzhiyun 		netdev_dbg(dev, "error passive interrupt\n");
596*4882a593Smuzhiyun 		if (state == CAN_STATE_ERROR_PASSIVE)
597*4882a593Smuzhiyun 			state = CAN_STATE_ERROR_WARNING;
598*4882a593Smuzhiyun 		else
599*4882a593Smuzhiyun 			state = CAN_STATE_ERROR_PASSIVE;
600*4882a593Smuzhiyun 	}
601*4882a593Smuzhiyun 	if (isrc & SUN4I_INT_ARB_LOST) {
602*4882a593Smuzhiyun 		/* arbitration lost interrupt */
603*4882a593Smuzhiyun 		netdev_dbg(dev, "arbitration lost interrupt\n");
604*4882a593Smuzhiyun 		alc = readl(priv->base + SUN4I_REG_STA_ADDR);
605*4882a593Smuzhiyun 		priv->can.can_stats.arbitration_lost++;
606*4882a593Smuzhiyun 		if (likely(skb)) {
607*4882a593Smuzhiyun 			cf->can_id |= CAN_ERR_LOSTARB;
608*4882a593Smuzhiyun 			cf->data[0] = (alc >> 8) & 0x1f;
609*4882a593Smuzhiyun 		}
610*4882a593Smuzhiyun 	}
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 	if (state != priv->can.state) {
613*4882a593Smuzhiyun 		tx_state = txerr >= rxerr ? state : 0;
614*4882a593Smuzhiyun 		rx_state = txerr <= rxerr ? state : 0;
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun 		if (likely(skb))
617*4882a593Smuzhiyun 			can_change_state(dev, cf, tx_state, rx_state);
618*4882a593Smuzhiyun 		else
619*4882a593Smuzhiyun 			priv->can.state = state;
620*4882a593Smuzhiyun 		if (state == CAN_STATE_BUS_OFF)
621*4882a593Smuzhiyun 			can_bus_off(dev);
622*4882a593Smuzhiyun 	}
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun 	if (likely(skb)) {
625*4882a593Smuzhiyun 		stats->rx_packets++;
626*4882a593Smuzhiyun 		stats->rx_bytes += cf->can_dlc;
627*4882a593Smuzhiyun 		netif_rx(skb);
628*4882a593Smuzhiyun 	} else {
629*4882a593Smuzhiyun 		return -ENOMEM;
630*4882a593Smuzhiyun 	}
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 	return 0;
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun 
sun4i_can_interrupt(int irq,void * dev_id)635*4882a593Smuzhiyun static irqreturn_t sun4i_can_interrupt(int irq, void *dev_id)
636*4882a593Smuzhiyun {
637*4882a593Smuzhiyun 	struct net_device *dev = (struct net_device *)dev_id;
638*4882a593Smuzhiyun 	struct sun4ican_priv *priv = netdev_priv(dev);
639*4882a593Smuzhiyun 	struct net_device_stats *stats = &dev->stats;
640*4882a593Smuzhiyun 	u8 isrc, status;
641*4882a593Smuzhiyun 	int n = 0;
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	while ((isrc = readl(priv->base + SUN4I_REG_INT_ADDR)) &&
644*4882a593Smuzhiyun 	       (n < SUN4I_CAN_MAX_IRQ)) {
645*4882a593Smuzhiyun 		n++;
646*4882a593Smuzhiyun 		status = readl(priv->base + SUN4I_REG_STA_ADDR);
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 		if (isrc & SUN4I_INT_WAKEUP)
649*4882a593Smuzhiyun 			netdev_warn(dev, "wakeup interrupt\n");
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 		if (isrc & SUN4I_INT_TBUF_VLD) {
652*4882a593Smuzhiyun 			/* transmission complete interrupt */
653*4882a593Smuzhiyun 			stats->tx_bytes +=
654*4882a593Smuzhiyun 			    readl(priv->base +
655*4882a593Smuzhiyun 				  SUN4I_REG_RBUF_RBACK_START_ADDR) & 0xf;
656*4882a593Smuzhiyun 			stats->tx_packets++;
657*4882a593Smuzhiyun 			can_get_echo_skb(dev, 0);
658*4882a593Smuzhiyun 			netif_wake_queue(dev);
659*4882a593Smuzhiyun 			can_led_event(dev, CAN_LED_EVENT_TX);
660*4882a593Smuzhiyun 		}
661*4882a593Smuzhiyun 		if ((isrc & SUN4I_INT_RBUF_VLD) &&
662*4882a593Smuzhiyun 		    !(isrc & SUN4I_INT_DATA_OR)) {
663*4882a593Smuzhiyun 			/* receive interrupt - don't read if overrun occurred */
664*4882a593Smuzhiyun 			while (status & SUN4I_STA_RBUF_RDY) {
665*4882a593Smuzhiyun 				/* RX buffer is not empty */
666*4882a593Smuzhiyun 				sun4i_can_rx(dev);
667*4882a593Smuzhiyun 				status = readl(priv->base + SUN4I_REG_STA_ADDR);
668*4882a593Smuzhiyun 			}
669*4882a593Smuzhiyun 		}
670*4882a593Smuzhiyun 		if (isrc &
671*4882a593Smuzhiyun 		    (SUN4I_INT_DATA_OR | SUN4I_INT_ERR_WRN | SUN4I_INT_BUS_ERR |
672*4882a593Smuzhiyun 		     SUN4I_INT_ERR_PASSIVE | SUN4I_INT_ARB_LOST)) {
673*4882a593Smuzhiyun 			/* error interrupt */
674*4882a593Smuzhiyun 			if (sun4i_can_err(dev, isrc, status))
675*4882a593Smuzhiyun 				netdev_err(dev, "can't allocate buffer - clearing pending interrupts\n");
676*4882a593Smuzhiyun 		}
677*4882a593Smuzhiyun 		/* clear interrupts */
678*4882a593Smuzhiyun 		writel(isrc, priv->base + SUN4I_REG_INT_ADDR);
679*4882a593Smuzhiyun 		readl(priv->base + SUN4I_REG_INT_ADDR);
680*4882a593Smuzhiyun 	}
681*4882a593Smuzhiyun 	if (n >= SUN4I_CAN_MAX_IRQ)
682*4882a593Smuzhiyun 		netdev_dbg(dev, "%d messages handled in ISR", n);
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun 	return (n) ? IRQ_HANDLED : IRQ_NONE;
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun 
sun4ican_open(struct net_device * dev)687*4882a593Smuzhiyun static int sun4ican_open(struct net_device *dev)
688*4882a593Smuzhiyun {
689*4882a593Smuzhiyun 	struct sun4ican_priv *priv = netdev_priv(dev);
690*4882a593Smuzhiyun 	int err;
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	/* common open */
693*4882a593Smuzhiyun 	err = open_candev(dev);
694*4882a593Smuzhiyun 	if (err)
695*4882a593Smuzhiyun 		return err;
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun 	/* register interrupt handler */
698*4882a593Smuzhiyun 	err = request_irq(dev->irq, sun4i_can_interrupt, 0, dev->name, dev);
699*4882a593Smuzhiyun 	if (err) {
700*4882a593Smuzhiyun 		netdev_err(dev, "request_irq err: %d\n", err);
701*4882a593Smuzhiyun 		goto exit_irq;
702*4882a593Smuzhiyun 	}
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun 	/* turn on clocking for CAN peripheral block */
705*4882a593Smuzhiyun 	err = clk_prepare_enable(priv->clk);
706*4882a593Smuzhiyun 	if (err) {
707*4882a593Smuzhiyun 		netdev_err(dev, "could not enable CAN peripheral clock\n");
708*4882a593Smuzhiyun 		goto exit_clock;
709*4882a593Smuzhiyun 	}
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun 	err = sun4i_can_start(dev);
712*4882a593Smuzhiyun 	if (err) {
713*4882a593Smuzhiyun 		netdev_err(dev, "could not start CAN peripheral\n");
714*4882a593Smuzhiyun 		goto exit_can_start;
715*4882a593Smuzhiyun 	}
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun 	can_led_event(dev, CAN_LED_EVENT_OPEN);
718*4882a593Smuzhiyun 	netif_start_queue(dev);
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun 	return 0;
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun exit_can_start:
723*4882a593Smuzhiyun 	clk_disable_unprepare(priv->clk);
724*4882a593Smuzhiyun exit_clock:
725*4882a593Smuzhiyun 	free_irq(dev->irq, dev);
726*4882a593Smuzhiyun exit_irq:
727*4882a593Smuzhiyun 	close_candev(dev);
728*4882a593Smuzhiyun 	return err;
729*4882a593Smuzhiyun }
730*4882a593Smuzhiyun 
sun4ican_close(struct net_device * dev)731*4882a593Smuzhiyun static int sun4ican_close(struct net_device *dev)
732*4882a593Smuzhiyun {
733*4882a593Smuzhiyun 	struct sun4ican_priv *priv = netdev_priv(dev);
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun 	netif_stop_queue(dev);
736*4882a593Smuzhiyun 	sun4i_can_stop(dev);
737*4882a593Smuzhiyun 	clk_disable_unprepare(priv->clk);
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	free_irq(dev->irq, dev);
740*4882a593Smuzhiyun 	close_candev(dev);
741*4882a593Smuzhiyun 	can_led_event(dev, CAN_LED_EVENT_STOP);
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun 	return 0;
744*4882a593Smuzhiyun }
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun static const struct net_device_ops sun4ican_netdev_ops = {
747*4882a593Smuzhiyun 	.ndo_open = sun4ican_open,
748*4882a593Smuzhiyun 	.ndo_stop = sun4ican_close,
749*4882a593Smuzhiyun 	.ndo_start_xmit = sun4ican_start_xmit,
750*4882a593Smuzhiyun };
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun static const struct of_device_id sun4ican_of_match[] = {
753*4882a593Smuzhiyun 	{.compatible = "allwinner,sun4i-a10-can"},
754*4882a593Smuzhiyun 	{},
755*4882a593Smuzhiyun };
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, sun4ican_of_match);
758*4882a593Smuzhiyun 
sun4ican_remove(struct platform_device * pdev)759*4882a593Smuzhiyun static int sun4ican_remove(struct platform_device *pdev)
760*4882a593Smuzhiyun {
761*4882a593Smuzhiyun 	struct net_device *dev = platform_get_drvdata(pdev);
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun 	unregister_netdev(dev);
764*4882a593Smuzhiyun 	free_candev(dev);
765*4882a593Smuzhiyun 
766*4882a593Smuzhiyun 	return 0;
767*4882a593Smuzhiyun }
768*4882a593Smuzhiyun 
sun4ican_probe(struct platform_device * pdev)769*4882a593Smuzhiyun static int sun4ican_probe(struct platform_device *pdev)
770*4882a593Smuzhiyun {
771*4882a593Smuzhiyun 	struct device_node *np = pdev->dev.of_node;
772*4882a593Smuzhiyun 	struct clk *clk;
773*4882a593Smuzhiyun 	void __iomem *addr;
774*4882a593Smuzhiyun 	int err, irq;
775*4882a593Smuzhiyun 	struct net_device *dev;
776*4882a593Smuzhiyun 	struct sun4ican_priv *priv;
777*4882a593Smuzhiyun 
778*4882a593Smuzhiyun 	clk = of_clk_get(np, 0);
779*4882a593Smuzhiyun 	if (IS_ERR(clk)) {
780*4882a593Smuzhiyun 		dev_err(&pdev->dev, "unable to request clock\n");
781*4882a593Smuzhiyun 		err = -ENODEV;
782*4882a593Smuzhiyun 		goto exit;
783*4882a593Smuzhiyun 	}
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun 	irq = platform_get_irq(pdev, 0);
786*4882a593Smuzhiyun 	if (irq < 0) {
787*4882a593Smuzhiyun 		err = -ENODEV;
788*4882a593Smuzhiyun 		goto exit;
789*4882a593Smuzhiyun 	}
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun 	addr = devm_platform_ioremap_resource(pdev, 0);
792*4882a593Smuzhiyun 	if (IS_ERR(addr)) {
793*4882a593Smuzhiyun 		err = PTR_ERR(addr);
794*4882a593Smuzhiyun 		goto exit;
795*4882a593Smuzhiyun 	}
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun 	dev = alloc_candev(sizeof(struct sun4ican_priv), 1);
798*4882a593Smuzhiyun 	if (!dev) {
799*4882a593Smuzhiyun 		dev_err(&pdev->dev,
800*4882a593Smuzhiyun 			"could not allocate memory for CAN device\n");
801*4882a593Smuzhiyun 		err = -ENOMEM;
802*4882a593Smuzhiyun 		goto exit;
803*4882a593Smuzhiyun 	}
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun 	dev->netdev_ops = &sun4ican_netdev_ops;
806*4882a593Smuzhiyun 	dev->irq = irq;
807*4882a593Smuzhiyun 	dev->flags |= IFF_ECHO;
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun 	priv = netdev_priv(dev);
810*4882a593Smuzhiyun 	priv->can.clock.freq = clk_get_rate(clk);
811*4882a593Smuzhiyun 	priv->can.bittiming_const = &sun4ican_bittiming_const;
812*4882a593Smuzhiyun 	priv->can.do_set_mode = sun4ican_set_mode;
813*4882a593Smuzhiyun 	priv->can.do_get_berr_counter = sun4ican_get_berr_counter;
814*4882a593Smuzhiyun 	priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING |
815*4882a593Smuzhiyun 				       CAN_CTRLMODE_LISTENONLY |
816*4882a593Smuzhiyun 				       CAN_CTRLMODE_LOOPBACK |
817*4882a593Smuzhiyun 				       CAN_CTRLMODE_3_SAMPLES;
818*4882a593Smuzhiyun 	priv->base = addr;
819*4882a593Smuzhiyun 	priv->clk = clk;
820*4882a593Smuzhiyun 	spin_lock_init(&priv->cmdreg_lock);
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun 	platform_set_drvdata(pdev, dev);
823*4882a593Smuzhiyun 	SET_NETDEV_DEV(dev, &pdev->dev);
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun 	err = register_candev(dev);
826*4882a593Smuzhiyun 	if (err) {
827*4882a593Smuzhiyun 		dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
828*4882a593Smuzhiyun 			DRV_NAME, err);
829*4882a593Smuzhiyun 		goto exit_free;
830*4882a593Smuzhiyun 	}
831*4882a593Smuzhiyun 	devm_can_led_init(dev);
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun 	dev_info(&pdev->dev, "device registered (base=%p, irq=%d)\n",
834*4882a593Smuzhiyun 		 priv->base, dev->irq);
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun 	return 0;
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun exit_free:
839*4882a593Smuzhiyun 	free_candev(dev);
840*4882a593Smuzhiyun exit:
841*4882a593Smuzhiyun 	return err;
842*4882a593Smuzhiyun }
843*4882a593Smuzhiyun 
844*4882a593Smuzhiyun static struct platform_driver sun4i_can_driver = {
845*4882a593Smuzhiyun 	.driver = {
846*4882a593Smuzhiyun 		.name = DRV_NAME,
847*4882a593Smuzhiyun 		.of_match_table = sun4ican_of_match,
848*4882a593Smuzhiyun 	},
849*4882a593Smuzhiyun 	.probe = sun4ican_probe,
850*4882a593Smuzhiyun 	.remove = sun4ican_remove,
851*4882a593Smuzhiyun };
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun module_platform_driver(sun4i_can_driver);
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun MODULE_AUTHOR("Peter Chen <xingkongcp@gmail.com>");
856*4882a593Smuzhiyun MODULE_AUTHOR("Gerhard Bertelsmann <info@gerhard-bertelsmann.de>");
857*4882a593Smuzhiyun MODULE_LICENSE("Dual BSD/GPL");
858*4882a593Smuzhiyun MODULE_DESCRIPTION("CAN driver for Allwinner SoCs (A10/A20)");
859