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