xref: /netbsd/sys/arch/arm/sunxi/sun4i_emac.c (revision 4a65ab8c)
1 /* $NetBSD: sun4i_emac.c,v 1.15 2022/09/18 02:32:14 thorpej Exp $ */
2 
3 /*-
4  * Copyright (c) 2013-2017 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Matt Thomas of 3am Software Foundry and Jared McNeill.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 
34 __KERNEL_RCSID(1, "$NetBSD: sun4i_emac.c,v 1.15 2022/09/18 02:32:14 thorpej Exp $");
35 
36 #include <sys/param.h>
37 #include <sys/bus.h>
38 #include <sys/device.h>
39 #include <sys/intr.h>
40 #include <sys/ioctl.h>
41 #include <sys/mutex.h>
42 #include <sys/rndsource.h>
43 #include <sys/kernel.h>
44 #include <sys/systm.h>
45 
46 #include <net/bpf.h>
47 #include <net/if.h>
48 #include <net/if_dl.h>
49 #include <net/if_ether.h>
50 #include <net/if_media.h>
51 
52 #include <dev/mii/miivar.h>
53 
54 #include <dev/fdt/fdtvar.h>
55 
56 #include <arm/sunxi/sunxi_sramc.h>
57 
58 #define	EMAC_IFNAME	"emac%d"
59 
60 #define	EMAC_CTL_REG		0x00
61 #define	 EMAC_CTL_RX_EN			__BIT(2)
62 #define	 EMAC_CTL_TX_EN			__BIT(1)
63 #define	 EMAC_CTL_RST			__BIT(0)
64 #define	EMAC_TX_MODE_REG	0x04
65 #define	 EMAC_TX_MODE_DMA		__BIT(1)
66 #define	 EMAC_TX_MODE_ABF_ENA		__BIT(0)
67 #define	EMAC_TX_FLOW_REG	0x08
68 #define	EMAC_TX_CTL0_REG	0x0c
69 #define	EMAC_TX_CTL1_REG	0x10
70 #define	EMAC_TX_CTL_REG(n)	(EMAC_TX_CTL0_REG+4*(n))
71 #define	 EMAC_TX_CTL_START		__BIT(0)
72 #define	EMAC_TX_INS_REG		0x14
73 #define	EMAC_TX_PL0_REG		0x18
74 #define	EMAC_TX_PL1_REG		0x1c
75 #define	EMAC_TX_PL_REG(n)	(EMAC_TX_PL0_REG+4*(n))
76 #define	EMAC_TX_STA_REG		0x20
77 #define	EMAC_TX_IO_DATA0_REG	0x24
78 #define	EMAC_TX_IO_DATA1_REG	0x28
79 #define	EMAC_TX_IO_DATA_REG(n)	(EMAC_TX_IO_DATA0_REG+4*(n))
80 #define	EMAC_TX_TSVL0_REG	0x2c
81 #define	EMAC_TX_TSVH0_REG	0x30
82 #define	EMAC_TX_TSVL1_REG	0x34
83 #define	EMAC_TX_TSVH1_REG	0x38
84 #define	EMAC_RX_CTL_REG		0x3c
85 #define	 EMAC_RX_CTL_SA_IF		__BIT(25)
86 #define	 EMAC_RX_CTL_SA			__BIT(24)
87 #define	 EMAC_RX_CTL_BC0		__BIT(22)
88 #define	 EMAC_RX_CTL_MHF		__BIT(21)
89 #define	 EMAC_RX_CTL_MC0		__BIT(20)
90 #define	 EMAC_RX_CTL_DAF		__BIT(17)
91 #define	 EMAC_RX_CTL_UCAD		__BIT(16)
92 #define	 EMAC_RX_CTL_POR		__BIT(8)
93 #define	 EMAC_RX_CTL_PLE		__BIT(7)
94 #define	 EMAC_RX_CTL_PCRCE		__BIT(6)
95 #define	 EMAC_RX_CTL_PCF		__BIT(5)
96 #define	 EMAC_RX_CTL_PROMISC		__BIT(4)
97 #define	 EMAC_RX_CTL_FIFO_RESET		__BIT(3)
98 #define	 EMAC_RX_CTL_DMA		__BIT(2)
99 #define	 EMAC_RX_CTL_DRQ_MODE		__BIT(1)
100 #define	 EMAC_RX_CTL_START		__BIT(0)
101 #define	EMAC_RX_HASH0_REG	0x40
102 #define	EMAC_RX_HASH1_REG	0x44
103 #define	EMAC_RX_STA_REG		0x48
104 #define	 EMAC_RX_STA_PKTOK		__BIT(7)
105 #define	 EMAC_RX_STA_ALNERR		__BIT(6)
106 #define	 EMAC_RX_STA_LENERR		__BIT(5)
107 #define	 EMAC_RX_STA_CRCERR		__BIT(4)
108 #define	EMAC_RX_IO_DATA_REG	0x4c
109 #define	EMAC_RX_FBC_REG		0x50
110 #define	EMAC_INT_CTL_REG	0x54
111 #define	EMAC_INT_STA_REG	0x58
112 #define	 EMAC_INT_RX			__BIT(8)
113 #define	 EMAC_INT_TX1			__BIT(1)
114 #define	 EMAC_INT_TX0			__BIT(0)
115 #define	 EMAC_INT_ENABLE		\
116 		(EMAC_INT_RX | EMAC_INT_TX1 | EMAC_INT_TX0)
117 #define	EMAC_MAC_CTL0_REG	0x5c
118 #define	 EMAC_MAC_CTL0_SOFT_RESET	__BIT(15)
119 #define	 EMAC_MAC_CTL0_TFC		__BIT(3)
120 #define	 EMAC_MAC_CTL0_RFC		__BIT(2)
121 #define	EMAC_MAC_CTL1_REG	0x60
122 #define	 EMAC_MAC_CTL1_ED		__BIT(15)
123 #define	 EMAC_MAC_CTL1_NB		__BIT(13)
124 #define	 EMAC_MAC_CTL1_BNB		__BIT(12)
125 #define	 EMAC_MAC_CTL1_LPE		__BIT(9)
126 #define	 EMAC_MAC_CTL1_PRE		__BIT(8)
127 #define	 EMAC_MAC_CTL1_ADP		__BIT(7)
128 #define	 EMAC_MAC_CTL1_VC		__BIT(6)
129 #define	 EMAC_MAC_CTL1_PC		__BIT(5)
130 #define	 EMAC_MAC_CTL1_CRC		__BIT(4)
131 #define	 EMAC_MAC_CTL1_DCRC		__BIT(3)
132 #define	 EMAC_MAC_CTL1_HF		__BIT(2)
133 #define	 EMAC_MAC_CTL1_FLC		__BIT(1)
134 #define	 EMAC_MAC_CTL1_FD		__BIT(0)
135 #define	EMAC_MAC_IPGT_REG	0x64
136 #define	 EMAC_MAC_IPGT_FD		0x15
137 #define	EMAC_MAC_IPGR_REG	0x68
138 #define	 EMAC_MAC_IPGR_IPG1		__BITS(15,8)
139 #define	 EMAC_MAC_IPGR_IPG2		__BITS(7,0)
140 #define	EMAC_MAC_CLRT_REG	0x6c
141 #define	 EMAC_MAC_CLRT_CW		__BITS(15,8)
142 #define	 EMAC_MAC_CLRT_RM		__BITS(7,0)
143 #define	EMAC_MAC_MAXF_REG	0x70
144 #define	EMAC_MAC_SUPP_REG	0x74
145 #define	 EMAC_MAC_SUPP_100M		__BIT(8)
146 #define	EMAC_MAC_TEST_REG	0x78
147 #define	EMAC_MAC_MCFG_REG	0x7c
148 #define	 EMAC_MAC_MCFG_CLK		__BITS(5,2)
149 #define	EMAC_MAC_MCMD_REG	0x80
150 #define	EMAC_MAC_MADR_REG	0x84
151 #define	EMAC_MAC_MWTD_REG	0x88
152 #define	EMAC_MAC_MRDD_REG	0x8c
153 #define	EMAC_MAC_MIND_REG	0x90
154 #define	EMAC_MAC_SSRR_REG	0x94
155 #define	EMAC_MAC_A0_REG		0x98
156 #define	EMAC_MAC_A1_REG		0x9c
157 #define	EMAC_MAC_A2_REG		0xa0
158 
159 #define	EMAC_RXHDR_STS			__BITS(31,16)
160 #define	EMAC_RXHDR_LEN			__BITS(15,0)
161 
162 #define	EMAC_RX_MAGIC		0x0143414d	/* M A C \001 */
163 
164 #define	EMAC_TXBUF_SIZE		4096
165 
166 static int sun4i_emac_match(device_t, cfdata_t, void *);
167 static void sun4i_emac_attach(device_t, device_t, void *);
168 
169 static int sun4i_emac_intr(void *);
170 static void sun4i_emac_tick(void *);
171 
172 static int sun4i_emac_miibus_read_reg(device_t, int, int, uint16_t *);
173 static int sun4i_emac_miibus_write_reg(device_t, int, int, uint16_t);
174 static void sun4i_emac_miibus_statchg(struct ifnet *);
175 
176 static void sun4i_emac_ifstart(struct ifnet *);
177 static int sun4i_emac_ifioctl(struct ifnet *, u_long, void *);
178 static int sun4i_emac_ifinit(struct ifnet *);
179 static void sun4i_emac_ifstop(struct ifnet *, int);
180 static void sun4i_emac_ifwatchdog(struct ifnet *);
181 
182 struct sun4i_emac_softc;
183 static void sun4i_emac_rx_hash(struct sun4i_emac_softc *);
184 
185 struct sun4i_emac_softc {
186 	device_t sc_dev;
187 	int sc_phandle;
188 	bus_space_tag_t sc_bst;
189 	bus_space_handle_t sc_bsh;
190 	bus_dma_tag_t sc_dmat;
191 	struct ethercom sc_ec;
192 	struct mii_data sc_mii;
193 	krndsource_t sc_rnd_source;	/* random source */
194 	kmutex_t sc_intr_lock;
195 	uint8_t sc_tx_active;
196 	callout_t sc_stat_ch;
197 	void *sc_ih;
198 	uint32_t sc_txbuf[EMAC_TXBUF_SIZE/4];
199 };
200 
201 static const struct device_compatible_entry compat_data[] = {
202 	{ .compat = "allwinner,sun4i-a10-emac" },
203 	DEVICE_COMPAT_EOL
204 };
205 
206 CFATTACH_DECL_NEW(sun4i_emac, sizeof(struct sun4i_emac_softc),
207 	sun4i_emac_match, sun4i_emac_attach, NULL, NULL);
208 
209 static inline uint32_t
sun4i_emac_read(struct sun4i_emac_softc * sc,bus_size_t o)210 sun4i_emac_read(struct sun4i_emac_softc *sc, bus_size_t o)
211 {
212 	return bus_space_read_4(sc->sc_bst, sc->sc_bsh, o);
213 }
214 
215 static inline void
sun4i_emac_write(struct sun4i_emac_softc * sc,bus_size_t o,uint32_t v)216 sun4i_emac_write(struct sun4i_emac_softc *sc, bus_size_t o, uint32_t v)
217 {
218 	return bus_space_write_4(sc->sc_bst, sc->sc_bsh, o, v);
219 }
220 
221 static inline void
sun4i_emac_clear_set(struct sun4i_emac_softc * sc,bus_size_t o,uint32_t c,uint32_t s)222 sun4i_emac_clear_set(struct sun4i_emac_softc *sc, bus_size_t o, uint32_t c,
223     uint32_t s)
224 {
225 	uint32_t v = bus_space_read_4(sc->sc_bst, sc->sc_bsh, o);
226 	return bus_space_write_4(sc->sc_bst, sc->sc_bsh, o, (v & ~c) | s);
227 }
228 
229 static int
sun4i_emac_match(device_t parent,cfdata_t cf,void * aux)230 sun4i_emac_match(device_t parent, cfdata_t cf, void *aux)
231 {
232 	struct fdt_attach_args * const faa = aux;
233 
234 	return of_compatible_match(faa->faa_phandle, compat_data);
235 }
236 
237 static void
sun4i_emac_attach(device_t parent,device_t self,void * aux)238 sun4i_emac_attach(device_t parent, device_t self, void *aux)
239 {
240 	struct sun4i_emac_softc * const sc = device_private(self);
241 	struct fdt_attach_args * const faa = aux;
242 	struct ifnet * const ifp = &sc->sc_ec.ec_if;
243 	struct mii_data * const mii = &sc->sc_mii;
244 	const int phandle = faa->faa_phandle;
245 	char enaddr[ETHER_ADDR_LEN];
246 	const uint8_t *local_addr;
247 	char intrstr[128];
248 	struct clk *clk;
249 	bus_addr_t addr;
250 	bus_size_t size;
251 	int len;
252 
253 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
254 		aprint_error(": cannot get registers\n");
255 		return;
256 	}
257 
258 	if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
259 		aprint_error(": cannot decode interrupt\n");
260 		return;
261 	}
262 
263 	clk = fdtbus_clock_get_index(phandle, 0);
264 	if (clk == NULL) {
265 		aprint_error(": cannot acquire clock\n");
266 		return;
267 	}
268 	if (clk_enable(clk) != 0) {
269 		aprint_error(": cannot enable clock\n");
270 		return;
271 	}
272 
273 	if (sunxi_sramc_claim(phandle) != 0) {
274 		aprint_error(": cannot map SRAM to EMAC\n");
275 		return;
276 	}
277 
278 	sc->sc_dev = self;
279 	sc->sc_phandle = phandle;
280 	sc->sc_ec.ec_mii = mii;
281 	sc->sc_bst = faa->faa_bst;
282 	if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
283 		aprint_error(": cannot map registers\n");
284 		return;
285 	}
286 	sc->sc_dmat = faa->faa_dmat;
287 
288 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_NET);
289 	callout_init(&sc->sc_stat_ch, 0);
290 	callout_setfunc(&sc->sc_stat_ch, sun4i_emac_tick, sc);
291 
292 	aprint_naive("\n");
293 	aprint_normal(": 10/100 Ethernet Controller\n");
294 
295 	/*
296 	 * Disable and then clear all interrupts
297 	 */
298 	sun4i_emac_write(sc, EMAC_INT_CTL_REG, 0);
299 	sun4i_emac_write(sc, EMAC_INT_STA_REG,
300 	    sun4i_emac_read(sc, EMAC_INT_STA_REG));
301 
302 	sc->sc_ih = fdtbus_intr_establish_xname(phandle, 0, IPL_NET, 0,
303 	    sun4i_emac_intr, sc, device_xname(self));
304 	if (sc->sc_ih == NULL) {
305 		aprint_error_dev(self, "failed to establish interrupt on %s\n",
306 		    intrstr);
307 		return;
308 	}
309 	aprint_normal_dev(self, "interrupting on %s\n", intrstr);
310 
311 	local_addr = fdtbus_get_prop(phandle, "local-mac-address", &len);
312 	if (local_addr && len == ETHER_ADDR_LEN) {
313 		memcpy(enaddr, local_addr, ETHER_ADDR_LEN);
314 
315 		uint32_t a1 = ((uint32_t)enaddr[0] << 16) |
316 			      ((uint32_t)enaddr[1] << 8) |
317 			       (uint32_t)enaddr[2];
318 		uint32_t a0 = ((uint32_t)enaddr[3] << 16) |
319 			      ((uint32_t)enaddr[4] << 8) |
320 			       (uint32_t)enaddr[5];
321 
322 		sun4i_emac_write(sc, EMAC_MAC_A1_REG, a1);
323 		sun4i_emac_write(sc, EMAC_MAC_A0_REG, a0);
324 	}
325 
326 	uint32_t a1 = sun4i_emac_read(sc, EMAC_MAC_A1_REG);
327 	uint32_t a0 = sun4i_emac_read(sc, EMAC_MAC_A0_REG);
328 	if (a0 != 0 || a1 != 0) {
329 		enaddr[0] = a1 >> 16;
330 		enaddr[1] = a1 >>  8;
331 		enaddr[2] = a1 >>  0;
332 		enaddr[3] = a0 >> 16;
333 		enaddr[4] = a0 >>  8;
334 		enaddr[5] = a0 >>  0;
335 	}
336 	aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(enaddr));
337 
338 	snprintf(ifp->if_xname, IFNAMSIZ, EMAC_IFNAME, device_unit(self));
339 	ifp->if_softc = sc;
340 	ifp->if_capabilities = 0;
341 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
342 	ifp->if_start = sun4i_emac_ifstart;
343 	ifp->if_ioctl = sun4i_emac_ifioctl;
344 	ifp->if_init = sun4i_emac_ifinit;
345 	ifp->if_stop = sun4i_emac_ifstop;
346 	ifp->if_watchdog = sun4i_emac_ifwatchdog;
347 	IFQ_SET_READY(&ifp->if_snd);
348 
349 	/* 802.1Q VLAN-sized frames are supported */
350 	sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_MTU;
351 
352 	ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus);
353 
354 	mii->mii_ifp = ifp;
355 	mii->mii_readreg = sun4i_emac_miibus_read_reg;
356 	mii->mii_writereg = sun4i_emac_miibus_write_reg;
357 	mii->mii_statchg = sun4i_emac_miibus_statchg;
358 
359 	mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0);
360 
361 	if (LIST_EMPTY(&mii->mii_phys)) {
362 		aprint_error_dev(self, "no PHY found!\n");
363 		ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_MANUAL, 0, NULL);
364 		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_MANUAL);
365 	} else {
366 		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
367 	}
368 
369 	/*
370 	 * Attach the interface.
371 	 */
372 	if_attach(ifp);
373 	if_deferred_start_init(ifp, NULL);
374 	ether_ifattach(ifp, enaddr);
375 	rnd_attach_source(&sc->sc_rnd_source, device_xname(self),
376 	    RND_TYPE_NET, RND_FLAG_DEFAULT);
377 }
378 
379 static inline void
sun4i_emac_int_enable(struct sun4i_emac_softc * sc)380 sun4i_emac_int_enable(struct sun4i_emac_softc *sc)
381 {
382 	sun4i_emac_clear_set(sc, EMAC_INT_CTL_REG, 0,
383 	    EMAC_INT_ENABLE);
384 	sun4i_emac_write(sc, EMAC_INT_STA_REG,
385 	    sun4i_emac_read(sc, EMAC_INT_STA_REG));
386 }
387 
388 int
sun4i_emac_miibus_read_reg(device_t self,int phy,int reg,uint16_t * val)389 sun4i_emac_miibus_read_reg(device_t self, int phy, int reg, uint16_t *val)
390 {
391 	struct sun4i_emac_softc * const sc = device_private(self);
392 	int retry = 100;
393 	int rv = 0;
394 
395 	sun4i_emac_write(sc, EMAC_MAC_MADR_REG, (phy << 8) | reg);
396 	sun4i_emac_write(sc, EMAC_MAC_MCMD_REG, 1);
397 
398 	while (--retry > 0 && (sun4i_emac_read(sc, EMAC_MAC_MIND_REG) & 1) != 0)
399 		delay(1000);
400 	if (retry == 0) {
401 		device_printf(self, "PHY read timeout\n");
402 		rv = ETIMEDOUT;
403 	}
404 
405 	sun4i_emac_write(sc, EMAC_MAC_MCMD_REG, 0);
406 	*val = sun4i_emac_read(sc, EMAC_MAC_MRDD_REG) & 0xffff;
407 
408 	return rv;
409 }
410 
411 int
sun4i_emac_miibus_write_reg(device_t self,int phy,int reg,uint16_t val)412 sun4i_emac_miibus_write_reg(device_t self, int phy, int reg, uint16_t val)
413 {
414 	struct sun4i_emac_softc * const sc = device_private(self);
415 	int retry = 100;
416 	int rv = 0;
417 
418 	sun4i_emac_write(sc, EMAC_MAC_MADR_REG, (phy << 8) | reg);
419 	sun4i_emac_write(sc, EMAC_MAC_MCMD_REG, 1);
420 
421 	while (--retry > 0 && (sun4i_emac_read(sc, EMAC_MAC_MIND_REG) & 1) != 0)
422 		delay(1000);
423 	if (retry == 0) {
424 		device_printf(self, "PHY write timeout\n");
425 		rv = ETIMEDOUT;
426 	}
427 
428 	sun4i_emac_write(sc, EMAC_MAC_MCMD_REG, 0);
429 	sun4i_emac_write(sc, EMAC_MAC_MWTD_REG, val);
430 
431 	return rv;
432 }
433 
434 void
sun4i_emac_miibus_statchg(struct ifnet * ifp)435 sun4i_emac_miibus_statchg(struct ifnet *ifp)
436 {
437 	struct sun4i_emac_softc * const sc = ifp->if_softc;
438 	struct mii_data * const mii = &sc->sc_mii;
439 	const u_int media = mii->mii_media_active;
440 
441 	/*
442 	 * Set MII interface based on the speed
443 	 * negotiated by the PHY.
444 	 */
445 	switch (IFM_SUBTYPE(media)) {
446 	case IFM_10_T:
447 		sun4i_emac_clear_set(sc, EMAC_MAC_SUPP_REG,
448 		    EMAC_MAC_SUPP_100M, 0);
449 		break;
450 	case IFM_100_TX:
451 		sun4i_emac_clear_set(sc, EMAC_MAC_SUPP_REG,
452 		    0, EMAC_MAC_SUPP_100M);
453 		break;
454 	}
455 
456 	const bool link = (IFM_SUBTYPE(media) & (IFM_10_T | IFM_100_TX)) != 0;
457 	if (link) {
458 		if (media & IFM_FDX) {
459 			sun4i_emac_clear_set(sc, EMAC_MAC_CTL1_REG,
460 			    0, EMAC_MAC_CTL1_FD);
461 		} else {
462 			sun4i_emac_clear_set(sc, EMAC_MAC_CTL1_REG,
463 			    EMAC_MAC_CTL1_FD, 0);
464 		}
465 	}
466 }
467 
468 static void
sun4i_emac_tick(void * softc)469 sun4i_emac_tick(void *softc)
470 {
471 	struct sun4i_emac_softc * const sc = softc;
472 	struct mii_data * const mii = &sc->sc_mii;
473 	int s;
474 
475 	s = splnet();
476 	mii_tick(mii);
477 	callout_schedule(&sc->sc_stat_ch, hz);
478 	splx(s);
479 }
480 
481 static inline void
sun4i_emac_rxfifo_flush(struct sun4i_emac_softc * sc)482 sun4i_emac_rxfifo_flush(struct sun4i_emac_softc *sc)
483 {
484 	sun4i_emac_clear_set(sc, EMAC_CTL_REG, EMAC_CTL_RX_EN, 0);
485 
486 	sun4i_emac_clear_set(sc, EMAC_RX_CTL_REG, 0, EMAC_RX_CTL_FIFO_RESET);
487 
488 	for (;;) {
489 		uint32_t v0 = sun4i_emac_read(sc, EMAC_RX_CTL_REG);
490 		if ((v0 & EMAC_RX_CTL_FIFO_RESET) == 0)
491 			break;
492 	}
493 
494 	sun4i_emac_clear_set(sc, EMAC_CTL_REG, 0, EMAC_CTL_RX_EN);
495 }
496 
497 static void
sun4i_emac_rxfifo_consume(struct sun4i_emac_softc * sc,size_t len)498 sun4i_emac_rxfifo_consume(struct sun4i_emac_softc *sc, size_t len)
499 {
500 	for (len = (len + 3) >> 2; len > 0; len--) {
501 		(void) sun4i_emac_read(sc, EMAC_RX_IO_DATA_REG);
502 	}
503 }
504 
505 static void
sun4i_emac_rxfifo_transfer(struct sun4i_emac_softc * sc,struct mbuf * m)506 sun4i_emac_rxfifo_transfer(struct sun4i_emac_softc *sc, struct mbuf *m)
507 {
508 	uint32_t *dp32 = mtod(m, uint32_t *);
509 	const int len = roundup2(m->m_len, 4);
510 
511 	bus_space_read_multi_4(sc->sc_bst, sc->sc_bsh,
512 	    EMAC_RX_IO_DATA_REG, dp32, len / 4);
513 }
514 
515 static struct mbuf *
sun4i_emac_mgethdr(struct sun4i_emac_softc * sc,size_t rxlen)516 sun4i_emac_mgethdr(struct sun4i_emac_softc *sc, size_t rxlen)
517 {
518 	struct mbuf *m = m_gethdr(M_DONTWAIT, MT_DATA);
519 
520 	if (m == NULL) {
521 		return NULL;
522 	}
523 	if (rxlen + 2 > MHLEN) {
524 		MCLGET(m, M_DONTWAIT);
525 		if ((m->m_flags & M_EXT) == 0) {
526 			m_free(m);
527 			return NULL;
528 		}
529 	}
530 
531 	m_adj(m, 2);
532 	m->m_len = rxlen;
533 	m->m_pkthdr.len = rxlen;
534 	m_set_rcvif(m, &sc->sc_ec.ec_if);
535 	m->m_flags |= M_HASFCS;
536 
537 	return m;
538 }
539 
540 static void
sun4i_emac_if_input(struct sun4i_emac_softc * sc,struct mbuf * m)541 sun4i_emac_if_input(struct sun4i_emac_softc *sc, struct mbuf *m)
542 {
543 	struct ifnet * const ifp = &sc->sc_ec.ec_if;
544 
545 	if_percpuq_enqueue(ifp->if_percpuq, m);
546 }
547 
548 static void
sun4i_emac_rx_intr(struct sun4i_emac_softc * sc)549 sun4i_emac_rx_intr(struct sun4i_emac_softc *sc)
550 {
551 	for (;;) {
552 		uint32_t rx_count = sun4i_emac_read(sc, EMAC_RX_FBC_REG);
553 		struct mbuf *m;
554 
555 		if (rx_count == 0) {
556 			rx_count = sun4i_emac_read(sc, EMAC_RX_FBC_REG);
557 			if (rx_count == 0)
558 				return;
559 		}
560 
561 		uint32_t v = sun4i_emac_read(sc, EMAC_RX_IO_DATA_REG);
562 		if (v != EMAC_RX_MAGIC) {
563 			sun4i_emac_rxfifo_flush(sc);
564 			return;
565 		}
566 
567 		uint32_t rxhdr = sun4i_emac_read(sc, EMAC_RX_IO_DATA_REG);
568 		uint32_t rxlen = __SHIFTOUT(rxhdr, EMAC_RXHDR_LEN);
569 		uint32_t rxsts = __SHIFTOUT(rxhdr, EMAC_RXHDR_STS);
570 
571 		if (rxlen < ETHER_MIN_LEN || (rxsts & EMAC_RX_STA_PKTOK) == 0) {
572 			if_statinc(&sc->sc_ec.ec_if, if_ierrors);
573 			continue;
574 		}
575 
576 		m = sun4i_emac_mgethdr(sc, rxlen);
577 		if (m == NULL) {
578 			if_statinc(&sc->sc_ec.ec_if, if_ierrors);
579 			sun4i_emac_rxfifo_consume(sc, rxlen);
580 			return;
581 		}
582 
583 		sun4i_emac_rxfifo_transfer(sc, m);
584 		sun4i_emac_if_input(sc, m);
585 	}
586 }
587 
588 static int
sun4i_emac_txfifo_transfer(struct sun4i_emac_softc * sc,struct mbuf * m,u_int slot)589 sun4i_emac_txfifo_transfer(struct sun4i_emac_softc *sc, struct mbuf *m, u_int slot)
590 {
591 	bus_size_t const io_data_reg = EMAC_TX_IO_DATA_REG(0);
592 	const int len = m->m_pkthdr.len;
593 	uint32_t *pktdata;
594 
595 	KASSERT(len > 0 && len <= sizeof(sc->sc_txbuf));
596 
597 	if (m->m_next != NULL) {
598 		m_copydata(m, 0, len, sc->sc_txbuf);
599 		pktdata = sc->sc_txbuf;
600 	} else {
601 		pktdata = mtod(m, uint32_t *);
602 	}
603 
604 	bus_space_write_multi_4(sc->sc_bst, sc->sc_bsh, io_data_reg,
605 	    pktdata, roundup2(len, 4) / 4);
606 
607 	return len;
608 }
609 
610 static void
sun4i_emac_tx_enqueue(struct sun4i_emac_softc * sc,struct mbuf * m,u_int slot)611 sun4i_emac_tx_enqueue(struct sun4i_emac_softc *sc, struct mbuf *m, u_int slot)
612 {
613 	struct ifnet * const ifp = &sc->sc_ec.ec_if;
614 
615 	sun4i_emac_write(sc, EMAC_TX_INS_REG, slot);
616 
617 	const int len = sun4i_emac_txfifo_transfer(sc, m, slot);
618 
619 	bus_size_t const pl_reg = EMAC_TX_PL_REG(slot);
620 	bus_size_t const ctl_reg = EMAC_TX_CTL_REG(slot);
621 
622 	sun4i_emac_write(sc, pl_reg, len);
623 	sun4i_emac_clear_set(sc, ctl_reg, 0, EMAC_TX_CTL_START);
624 
625 	bpf_mtap(ifp, m, BPF_D_OUT);
626 
627 	m_freem(m);
628 }
629 
630 static void
sun4i_emac_tx_intr(struct sun4i_emac_softc * sc,u_int slot)631 sun4i_emac_tx_intr(struct sun4i_emac_softc *sc, u_int slot)
632 {
633 	sc->sc_tx_active &= ~__BIT(slot);
634 }
635 
636 int
sun4i_emac_intr(void * arg)637 sun4i_emac_intr(void *arg)
638 {
639 	struct sun4i_emac_softc * const sc = arg;
640 	struct ifnet * const ifp = &sc->sc_ec.ec_if;
641 
642 	mutex_enter(&sc->sc_intr_lock);
643 
644 	uint32_t sts = sun4i_emac_read(sc, EMAC_INT_STA_REG);
645 	sun4i_emac_write(sc, EMAC_INT_STA_REG, sts);
646 	rnd_add_uint32(&sc->sc_rnd_source, sts);
647 
648 	if (sts & EMAC_INT_RX) {
649 		sun4i_emac_rx_intr(sc);
650 	}
651 	if (sts & EMAC_INT_TX0) {
652 		sun4i_emac_tx_intr(sc, 0);
653 	}
654 	if (sts & EMAC_INT_TX1) {
655 		sun4i_emac_tx_intr(sc, 1);
656 	}
657 	if (sts & (EMAC_INT_TX0 | EMAC_INT_TX1)) {
658 		if (sc->sc_tx_active == 0)
659 			ifp->if_timer = 0;
660 		if_schedule_deferred_start(ifp);
661 	}
662 
663 	mutex_exit(&sc->sc_intr_lock);
664 
665 	return 1;
666 }
667 
668 void
sun4i_emac_ifstart(struct ifnet * ifp)669 sun4i_emac_ifstart(struct ifnet *ifp)
670 {
671 	struct sun4i_emac_softc * const sc = ifp->if_softc;
672 
673 	mutex_enter(&sc->sc_intr_lock);
674 
675 	if ((sc->sc_tx_active & 1) == 0) {
676 		struct mbuf *m;
677 		IFQ_DEQUEUE(&ifp->if_snd, m);
678 		if (m == NULL) {
679 			mutex_exit(&sc->sc_intr_lock);
680 			return;
681 		}
682 		sun4i_emac_tx_enqueue(sc, m, 0);
683 		sc->sc_tx_active |= 1;
684 	}
685 
686 	if ((sc->sc_tx_active & 2) == 0) {
687 		struct mbuf *m;
688 		IFQ_DEQUEUE(&ifp->if_snd, m);
689 		if (m == NULL) {
690 			mutex_exit(&sc->sc_intr_lock);
691 			return;
692 		}
693 		sun4i_emac_tx_enqueue(sc, m, 1);
694 		sc->sc_tx_active |= 2;
695 	}
696 
697 	ifp->if_timer = 5;
698 
699 	mutex_exit(&sc->sc_intr_lock);
700 }
701 
702 
703 static int
sun4i_emac_ifioctl(struct ifnet * ifp,u_long cmd,void * data)704 sun4i_emac_ifioctl(struct ifnet *ifp, u_long cmd, void *data)
705 {
706 	struct sun4i_emac_softc * const sc = ifp->if_softc;
707 	int error;
708 
709 	switch (cmd) {
710 	default:
711 		if ((error = ether_ioctl(ifp, cmd, data)) != ENETRESET)
712 			break;
713 		error = 0;
714 		if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI)
715 			break;
716 		if (ifp->if_flags & IFF_RUNNING) {
717 			/*
718 			 * Multicast list has changed; set the hardware filter
719 			 * accordingly.
720 			 */
721 			mutex_enter(&sc->sc_intr_lock);
722 			sun4i_emac_ifstop(ifp, 0);
723 			error = sun4i_emac_ifinit(ifp);
724 			mutex_exit(&sc->sc_intr_lock);
725 		}
726 		break;
727 	}
728 
729 	return error;
730 }
731 
732 static void
sun4i_emac_ifstop(struct ifnet * ifp,int discard)733 sun4i_emac_ifstop(struct ifnet *ifp, int discard)
734 {
735 	struct sun4i_emac_softc * const sc = ifp->if_softc;
736 	struct mii_data * const mii = &sc->sc_mii;
737 
738 	KASSERT(mutex_owned(&sc->sc_intr_lock));
739 
740 	callout_stop(&sc->sc_stat_ch);
741 	mii_down(mii);
742 
743 	sun4i_emac_write(sc, EMAC_INT_CTL_REG, 0);
744 	sun4i_emac_write(sc, EMAC_INT_STA_REG,
745 	    sun4i_emac_read(sc, EMAC_INT_STA_REG));
746 
747 	sun4i_emac_clear_set(sc, EMAC_CTL_REG,
748 	    EMAC_CTL_RST | EMAC_CTL_TX_EN | EMAC_CTL_RX_EN, 0);
749 
750 	ifp->if_flags &= ~IFF_RUNNING;
751 	ifp->if_timer = 0;
752 }
753 
754 int
sun4i_emac_ifinit(struct ifnet * ifp)755 sun4i_emac_ifinit(struct ifnet *ifp)
756 {
757 	struct sun4i_emac_softc * const sc = ifp->if_softc;
758 	struct mii_data * const mii = &sc->sc_mii;
759 
760 	sun4i_emac_clear_set(sc, EMAC_RX_CTL_REG,
761 	    0, EMAC_RX_CTL_FIFO_RESET);
762 
763 	delay(1);
764 
765 	sun4i_emac_clear_set(sc, EMAC_MAC_CTL0_REG,
766 	    EMAC_MAC_CTL0_SOFT_RESET, 0);
767 
768 	sun4i_emac_clear_set(sc, EMAC_MAC_MCFG_REG,
769 	    EMAC_MAC_MCFG_CLK, __SHIFTIN(0xd, EMAC_MAC_MCFG_CLK));
770 
771 	sun4i_emac_write(sc, EMAC_RX_FBC_REG, 0);
772 
773 	sun4i_emac_write(sc, EMAC_INT_CTL_REG, 0);
774 	sun4i_emac_write(sc, EMAC_INT_STA_REG,
775 	    sun4i_emac_read(sc, EMAC_INT_STA_REG));
776 
777 	delay(1);
778 
779 	sun4i_emac_clear_set(sc, EMAC_TX_MODE_REG,
780 	    EMAC_TX_MODE_DMA, EMAC_TX_MODE_ABF_ENA);
781 
782 	sun4i_emac_clear_set(sc, EMAC_MAC_CTL0_REG,
783 	    0, EMAC_MAC_CTL0_TFC | EMAC_MAC_CTL0_RFC);
784 
785 	sun4i_emac_clear_set(sc, EMAC_RX_CTL_REG,
786 	    EMAC_RX_CTL_DMA, 0);
787 
788 	sun4i_emac_clear_set(sc, EMAC_MAC_CTL1_REG,
789 	    0,
790 	    EMAC_MAC_CTL1_FLC | EMAC_MAC_CTL1_CRC |
791 	    EMAC_MAC_CTL1_PC);
792 
793 	sun4i_emac_write(sc, EMAC_MAC_IPGT_REG, EMAC_MAC_IPGT_FD);
794 	sun4i_emac_write(sc, EMAC_MAC_IPGR_REG,
795 	    __SHIFTIN(0x0c, EMAC_MAC_IPGR_IPG1) |
796 	    __SHIFTIN(0x12, EMAC_MAC_IPGR_IPG2));
797 
798 	sun4i_emac_write(sc, EMAC_MAC_CLRT_REG,
799 	    __SHIFTIN(0x0f, EMAC_MAC_CLRT_RM) |
800 	    __SHIFTIN(0x37, EMAC_MAC_CLRT_CW));
801 
802 	sun4i_emac_write(sc, EMAC_MAC_MAXF_REG, 0x600);
803 
804 	sun4i_emac_rx_hash(sc);
805 
806 	sun4i_emac_int_enable(sc);
807 
808 	ifp->if_flags |= IFF_RUNNING;
809 
810 	/* Enable RX/TX */
811 	sun4i_emac_clear_set(sc, EMAC_CTL_REG,
812 	    0, EMAC_CTL_RST | EMAC_CTL_TX_EN | EMAC_CTL_RX_EN);
813 
814 	mii_mediachg(mii);
815 	callout_schedule(&sc->sc_stat_ch, hz);
816 
817 	return 0;
818 }
819 
820 static void
sun4i_emac_ifwatchdog(struct ifnet * ifp)821 sun4i_emac_ifwatchdog(struct ifnet *ifp)
822 {
823 	struct sun4i_emac_softc * const sc = ifp->if_softc;
824 
825 	device_printf(sc->sc_dev, "device timeout\n");
826 
827 	if_statinc(ifp, if_oerrors);
828 	sun4i_emac_ifinit(ifp);
829 	sun4i_emac_ifstart(ifp);
830 }
831 
832 static void
sun4i_emac_rx_hash(struct sun4i_emac_softc * sc)833 sun4i_emac_rx_hash(struct sun4i_emac_softc *sc)
834 {
835 	struct ethercom *ec = &sc->sc_ec;
836 	struct ifnet * const ifp = &ec->ec_if;
837 	struct ether_multistep step;
838 	struct ether_multi *enm;
839 	uint32_t hash[2];
840 	uint32_t rxctl;
841 
842 	rxctl = sun4i_emac_read(sc, EMAC_RX_CTL_REG);
843 	rxctl &= ~EMAC_RX_CTL_MHF;
844 	rxctl |= EMAC_RX_CTL_UCAD;
845 	rxctl |= EMAC_RX_CTL_DAF;
846 	rxctl |= EMAC_RX_CTL_MC0;
847 	rxctl |= EMAC_RX_CTL_BC0;
848 	rxctl |= EMAC_RX_CTL_POR;
849 
850 	hash[0] = hash[1] = ~0;
851 	if (ifp->if_flags & IFF_PROMISC) {
852 		ifp->if_flags |= IFF_ALLMULTI;
853 		rxctl |= EMAC_RX_CTL_PROMISC;
854 	} else {
855 		rxctl &= ~EMAC_RX_CTL_PROMISC;
856 	}
857 
858 	if ((ifp->if_flags & IFF_PROMISC) == 0) {
859 		hash[0] = hash[1] = 0;
860 
861 		ETHER_LOCK(ec);
862 		ETHER_FIRST_MULTI(step, ec, enm);
863 		while (enm != NULL) {
864 			if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
865 			    ETHER_ADDR_LEN)) {
866 				ETHER_UNLOCK(ec);
867 				/*
868 				 * We must listen to a range of multicast
869 				 * addresses. For now, just accept all
870 				 * multicasts, rather than trying to set only
871 				 * those filter bits needed to match the range.
872 				 * (At this time, the only use of address
873 				 * ranges is for IP multicast routing, for
874 				 * which the range is big enough to require all
875 				 * bits set.)
876 				 */
877 				hash[0] = hash[1] = ~0;
878 				ifp->if_flags |= IFF_ALLMULTI;
879 				goto done;
880 			}
881 
882 			u_int crc = ether_crc32_be(enm->enm_addrlo,
883 			    ETHER_ADDR_LEN);
884 
885 			/* Just want the 6 most significant bits. */
886 			crc >>= 26;
887 
888 			/* Set the corresponding bit in the filter. */
889 			hash[crc >> 5] |= __BIT(crc & 31);
890 			ETHER_NEXT_MULTI(step, enm);
891 		}
892 		ETHER_UNLOCK(ec);
893 		ifp->if_flags &= ~IFF_ALLMULTI;
894 		rxctl |= EMAC_RX_CTL_MHF;
895 	}
896 
897 done:
898 
899 	sun4i_emac_write(sc, EMAC_RX_HASH0_REG, hash[0]);
900 	sun4i_emac_write(sc, EMAC_RX_HASH1_REG, hash[1]);
901 
902 	sun4i_emac_write(sc, EMAC_RX_CTL_REG, rxctl);
903 }
904