xref: /minix/minix/drivers/net/lan8710a/lan8710a.c (revision 9f988b79)
1 #include <minix/drivers.h>
2 #include <minix/netdriver.h>
3 #include <minix/board.h>
4 #include <sys/mman.h>
5 #include "assert.h"
6 #include "lan8710a.h"
7 #include "lan8710a_reg.h"
8 
9 /* Local functions */
10 static int lan8710a_init(unsigned int instance, ether_addr_t *addr);
11 static void lan8710a_stop(void);
12 static ssize_t lan8710a_recv(struct netdriver_data *data, size_t max);
13 static int lan8710a_send(struct netdriver_data *data, size_t size);
14 static void lan8710a_stat(eth_stat_t *stat);
15 static void lan8710a_intr(unsigned int mask);
16 
17 static void lan8710a_enable_interrupt(int interrupt);
18 static void lan8710a_map_regs(void);
19 static void lan8710a_dma_config_tx(u8_t desc_idx);
20 static void lan8710a_dma_reset_init(void);
21 static void lan8710a_init_addr(ether_addr_t *addr);
22 static void lan8710a_init_desc(void);
23 static void lan8710a_init_mdio(void);
24 static int lan8710a_init_hw(ether_addr_t *addr);
25 static void lan8710a_reset_hw(void);
26 
27 static void lan8710a_phy_write(u32_t reg, u32_t value);
28 static u32_t lan8710a_phy_read(u32_t reg);
29 
30 static u32_t lan8710a_reg_read(volatile u32_t *reg);
31 static void lan8710a_reg_write(volatile u32_t *reg, u32_t value);
32 static void lan8710a_reg_set(volatile u32_t *reg, u32_t value);
33 static void lan8710a_reg_unset(volatile u32_t *reg, u32_t value);
34 
35 /* Local variables */
36 static lan8710a_t lan8710a_state;
37 
38 static const struct netdriver lan8710a_table = {
39 	.ndr_init	= lan8710a_init,
40 	.ndr_stop	= lan8710a_stop,
41 	.ndr_recv	= lan8710a_recv,
42 	.ndr_send	= lan8710a_send,
43 	.ndr_stat	= lan8710a_stat,
44 	.ndr_intr	= lan8710a_intr
45 };
46 
47 /*============================================================================*
48  *				main					      *
49  *============================================================================*/
50 int
51 main(int argc, char *argv[])
52 {
53 	struct machine machine;
54 
55 	env_setargs(argc, argv);
56 
57 	sys_getmachine(&machine);
58 	if (BOARD_IS_BB(machine.board_id))
59 		netdriver_task(&lan8710a_table);
60 
61 	return EXIT_SUCCESS;
62 }
63 
64 /*============================================================================*
65  *				lan8710a_init				      *
66  *============================================================================*/
67 static int
68 lan8710a_init(unsigned int instance, ether_addr_t * addr)
69 {
70 	/* Initialize the ethernet driver. */
71 
72 	/* Clear state. */
73 	memset(&lan8710a_state, 0, sizeof(lan8710a_state));
74 
75 	strlcpy(lan8710a_state.name, "lan8710a#0", LAN8710A_NAME_LEN);
76 	lan8710a_state.name[9] += instance;
77 	lan8710a_state.instance = instance;
78 
79 	/* Initialize driver. */
80 	lan8710a_map_regs();
81 
82 	lan8710a_init_hw(addr);
83 
84 	return OK;
85 }
86 
87 /*============================================================================*
88  *				lan8710a_enable_interrupt		      *
89  *============================================================================*/
90 static void
91 lan8710a_enable_interrupt(int interrupt)
92 {
93 	int r;
94 
95 	if (interrupt & RX_INT) {
96 		if ((r = sys_irqenable(&lan8710a_state.irq_rx_hook)) != OK) {
97 			panic("sys_irqenable failed: %d", r);
98 		}
99 	}
100 	if (interrupt & TX_INT) {
101 		if ((r = sys_irqenable(&lan8710a_state.irq_tx_hook)) != OK) {
102 			panic("sys_irqenable failed: %d", r);
103 		}
104 	}
105 }
106 
107 /*============================================================================*
108  *				lan8710a_intr				      *
109  *============================================================================*/
110 static void
111 lan8710a_intr(unsigned int mask)
112 {
113 	u32_t dma_status;
114 
115 	/* Check the card for interrupt reason(s). */
116 	u32_t rx_stat = lan8710a_reg_read(CPSW_WR_C0_RX_STAT);
117 	u32_t tx_stat = lan8710a_reg_read(CPSW_WR_C0_TX_STAT);
118 	u32_t cp;
119 
120 	/* Handle interrupts. */
121 	if (rx_stat) {
122 		cp = lan8710a_reg_read(CPDMA_STRAM_RX_CP(0));
123 
124 		netdriver_recv();
125 
126 		lan8710a_reg_write(CPDMA_STRAM_RX_CP(0), cp);
127 		lan8710a_reg_write(CPDMA_EOI_VECTOR, RX_INT);
128 	}
129 	if (tx_stat) {
130 		cp = lan8710a_reg_read(CPDMA_STRAM_TX_CP(0));
131 
132 		/* Disabling channels, where Tx interrupt occurred */
133 		lan8710a_reg_set(CPDMA_TX_INTMASK_CLEAR, tx_stat);
134 
135 		netdriver_send();
136 
137 		lan8710a_reg_write(CPDMA_STRAM_TX_CP(0), cp);
138 		lan8710a_reg_write(CPDMA_EOI_VECTOR, TX_INT);
139 	}
140 
141 	dma_status = lan8710a_reg_read(CPDMA_STATUS);
142 
143 	if (dma_status & CPDMA_ERROR) {
144 		LAN8710A_DEBUG_PRINT(("CPDMA error: 0x%X, reset", dma_status));
145 		lan8710a_dma_reset_init();
146 	}
147 
148 	/* Re-enable Rx interrupt. */
149 	if (mask & (1 << RX_INT))
150 		lan8710a_enable_interrupt(RX_INT);
151 
152 	/* Re-enable Tx interrupt. */
153 	if (mask & (1 << TX_INT))
154 		lan8710a_enable_interrupt(TX_INT);
155 }
156 
157 /*============================================================================*
158  *				lan8710a_init_addr			      *
159  *============================================================================*/
160 static void
161 lan8710a_init_addr(ether_addr_t * addr)
162 {
163 	static char eakey[]= LAN8710A_ENVVAR "#_EA";
164 	static char eafmt[]= "x:x:x:x:x:x";
165 	int i;
166 	long v;
167 
168 	/*
169 	 * Do we have a user defined ethernet address?
170 	 */
171 	eakey[sizeof(LAN8710A_ENVVAR)-1] = '0' + lan8710a_state.instance;
172 
173 	for (i= 0; i < 6; i++) {
174 		if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
175 			break;
176 		else
177 			addr->ea_addr[i] = v;
178 	}
179 	if (i == 6)
180 		return;
181 
182 	/*
183 	 * No; get the address from the chip itself.
184 	 */
185 	addr->ea_addr[0] = lan8710a_reg_read(CTRL_MAC_ID0_HI) & 0xFF;
186 	addr->ea_addr[1] = (lan8710a_reg_read(CTRL_MAC_ID0_HI) >> 8) & 0xFF;
187 	addr->ea_addr[2] = (lan8710a_reg_read(CTRL_MAC_ID0_HI) >> 16) & 0xFF;
188 	addr->ea_addr[3] = (lan8710a_reg_read(CTRL_MAC_ID0_HI) >> 24) & 0xFF;
189 	addr->ea_addr[4] = lan8710a_reg_read(CTRL_MAC_ID0_LO) & 0xFF;
190 	addr->ea_addr[5] = (lan8710a_reg_read(CTRL_MAC_ID0_LO) >> 8) & 0xFF;
191 }
192 
193 /*============================================================================*
194  *				lan8710a_map_regs			      *
195  *============================================================================*/
196 static void
197 lan8710a_map_regs(void)
198 {
199 	struct minix_mem_range mr;
200 	mr.mr_base = CM_PER_BASE_ADR;
201 	mr.mr_limit = CM_PER_BASE_ADR + MEMORY_LIMIT;
202 
203 	if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
204 		panic("Unable to request permission to map memory");
205 	}
206 	lan8710a_state.regs_cp_per =
207 		(vir_bytes)vm_map_phys(SELF, (void *)CM_PER_BASE_ADR, 512);
208 	if ((void *)lan8710a_state.regs_cp_per == MAP_FAILED) {
209 		panic("lan8710a_state.regs_cp_per: vm_map_phys failed");
210 	}
211 	lan8710a_state.regs_cpdma_stram =
212 		(vir_bytes)vm_map_phys(SELF, (void *)CPDMA_STRAM_BASE_ADR, 512);
213 	if ((void *)lan8710a_state.regs_cpdma_stram == MAP_FAILED) {
214 		panic("lan8710a_state.regs_cpdma_stram: vm_map_phys failed");
215 	}
216 	lan8710a_state.regs_cpsw_cpdma =
217 		(vir_bytes)vm_map_phys(SELF, (void *)CPSW_CPDMA_BASE_ADR, 512);
218 	if ((void *)lan8710a_state.regs_cpsw_cpdma == MAP_FAILED) {
219 		panic("lan8710a_state.regs_cpsw_cpdma: vm_map_phys failed");
220 	}
221 	lan8710a_state.regs_cpsw_ale =
222 		(vir_bytes)vm_map_phys(SELF, (void *)CPSW_ALE_BASE_ADR, 256);
223 	if ((void *)lan8710a_state.regs_cpsw_ale == MAP_FAILED) {
224 		panic("lan8710a_state.regs_cpsw_ale: vm_map_phys failed");
225 	}
226 	lan8710a_state.regs_cpsw_sl =
227 		(vir_bytes)vm_map_phys(SELF, (void *)CPSW_SL_BASE_ADR, 512);
228 	if ((void *)lan8710a_state.regs_cpsw_sl == MAP_FAILED) {
229 		panic("lan8710a_state.regs_cpsw_sl: vm_map_phys failed");
230 	}
231 	lan8710a_state.regs_cpsw_ss =
232 		(vir_bytes)vm_map_phys(SELF, (void *)CPSW_SS_BASE_ADR, 512);
233 	if ((void *)lan8710a_state.regs_cpsw_ss == MAP_FAILED) {
234 		panic("lan8710a_state.regs_cpsw_ss: vm_map_phys failed");
235 	}
236 	lan8710a_state.regs_cpsw_wr =
237 		(vir_bytes)vm_map_phys(SELF, (void *)CPSW_WR_BASE_ADR, 512);
238 	if ((void *)lan8710a_state.regs_cpsw_wr == MAP_FAILED) {
239 		panic("lan8710a_state.regs_cpsw_wr: vm_map_phys failed");
240 	}
241 	lan8710a_state.regs_ctrl_mod =
242 		(vir_bytes)vm_map_phys(SELF, (void *)CTRL_MOD_BASE_ADR, 2560);
243 	if ((void *)lan8710a_state.regs_ctrl_mod == MAP_FAILED) {
244 		panic("lan8710a_state.regs_ctrl_mod: vm_map_phys failed");
245 	}
246 	lan8710a_state.regs_intc =
247 		(vir_bytes)vm_map_phys(SELF, (void *)INTC_BASE_ADR, 512);
248 	if ((void *)lan8710a_state.regs_intc == MAP_FAILED) {
249 		panic("lan8710a_state.regs_intc: vm_map_phys failed");
250 	}
251 	lan8710a_state.regs_mdio =
252 		(vir_bytes)vm_map_phys(SELF, (void *)MDIO_BASE_ADDR, 512);
253 	if ((void *)lan8710a_state.regs_mdio == MAP_FAILED) {
254 		panic("lan8710a_state.regs_mdio: vm_map_phys failed");
255 	}
256 
257 	mr.mr_base = BEGINNING_DESC_MEM;
258 	mr.mr_limit = BEGINNING_DESC_MEM + DESC_MEMORY_LIMIT;
259 
260 	if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
261 		panic("Unable to request permission to map memory");
262 	}
263 	lan8710a_state.rx_desc_phy = BEGINNING_RX_DESC_MEM;
264 	lan8710a_state.tx_desc_phy = BEGINNING_TX_DESC_MEM;
265 	lan8710a_state.rx_desc = (lan8710a_desc_t *)vm_map_phys(SELF,
266 				(void *)lan8710a_state.rx_desc_phy, 1024);
267 	if ((void *)lan8710a_state.rx_desc == MAP_FAILED) {
268 		panic("lan8710a_state.rx_desc: vm_map_phys failed");
269 	}
270 	lan8710a_state.tx_desc = (lan8710a_desc_t *)vm_map_phys(SELF,
271 				(void *)lan8710a_state.tx_desc_phy, 1024);
272 	if ((void *)lan8710a_state.tx_desc == MAP_FAILED) {
273 		panic("lan8710a_state.tx_desc: vm_map_phys failed");
274 	}
275 
276 	mr.mr_base = CPSW_STATS_BASE_ADR;
277 	mr.mr_limit = CPSW_STATS_BASE_ADR + CPSW_STATS_MEM_LIMIT;
278 
279 	if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
280 		panic("Unable to request permission to map memory");
281 	}
282 	lan8710a_state.regs_cpsw_stats =
283 		(vir_bytes)vm_map_phys(SELF, (void *)CPSW_STATS_BASE_ADR, 256);
284 	if ((void *)lan8710a_state.regs_cpsw_stats == MAP_FAILED) {
285 		panic("lan8710a_state.regs_cpsw_stats: vm_map_phys failed");
286 	}
287 }
288 
289 /*============================================================================*
290  *				lan8710a_stat				      *
291  *============================================================================*/
292 static void
293 lan8710a_stat(eth_stat_t * stat)
294 {
295 	stat->ets_recvErr   = lan8710a_reg_read(CPSW_STAT_RX_CRC_ERR)
296 				+ lan8710a_reg_read(CPSW_STAT_RX_AGNCD_ERR)
297 				+ lan8710a_reg_read(CPSW_STAT_RX_OVERSIZE);
298 	stat->ets_sendErr   = 0;
299 	stat->ets_OVW       = 0;
300 	stat->ets_CRCerr    = lan8710a_reg_read(CPSW_STAT_RX_CRC_ERR);
301 	stat->ets_frameAll  = lan8710a_reg_read(CPSW_STAT_RX_AGNCD_ERR);
302 	stat->ets_missedP   = 0;
303 	stat->ets_packetR   = lan8710a_reg_read(CPSW_STAT_RX_GOOD);
304 	stat->ets_packetT   = lan8710a_reg_read(CPSW_STAT_TX_GOOD);
305 	stat->ets_collision = lan8710a_reg_read(CPSW_STAT_COLLISIONS);
306 	stat->ets_transAb   = 0;
307 	stat->ets_carrSense = lan8710a_reg_read(CPSW_STAT_CARR_SENS_ERR);
308 	stat->ets_fifoUnder = lan8710a_reg_read(CPSW_STAT_TX_UNDERRUN);
309 	stat->ets_fifoOver  = lan8710a_reg_read(CPSW_STAT_RX_OVERRUN);
310 	stat->ets_CDheartbeat = 0;
311 	stat->ets_OWC = 0;
312 }
313 
314 /*============================================================================*
315  *				lan8710a_stop				      *
316  *============================================================================*/
317 static void
318 lan8710a_stop(void)
319 {
320 	/* Reset hardware. */
321 	lan8710a_reset_hw();
322 }
323 
324 /*============================================================================*
325  *				lan8710a_dma_config_tx			      *
326  *============================================================================*/
327 static void
328 lan8710a_dma_config_tx(u8_t desc_idx)
329 {
330 	phys_bytes phys_addr;
331 	int i;
332 	for (i = 0; i < TX_DMA_CHANNELS; ++i) {
333 		if (!lan8710a_reg_read(CPDMA_STRAM_TX_HDP(i))) break;
334 	}
335 	if (i == TX_DMA_CHANNELS) {
336 		panic("There are no free TX DMA channels.");
337 	}
338 
339 	/* Enabling only one channel Tx interrupt */
340 	lan8710a_reg_write(CPDMA_TX_INTMASK_SET, 1 << i);
341 	/* Routing only one channel Tx int to TX_PULSE signal */
342 	lan8710a_reg_write(CPSW_WR_C0_TX_EN, 1 << i);
343 
344 	/* Setting HDP */
345 	phys_addr = lan8710a_state.tx_desc_phy +
346 					(desc_idx * sizeof(lan8710a_desc_t));
347 	lan8710a_reg_write(CPDMA_STRAM_TX_HDP(i), (u32_t)phys_addr);
348 }
349 
350 /*============================================================================*
351  *				lan8710a_dma_reset_init			      *
352  *============================================================================*/
353 static void
354 lan8710a_dma_reset_init(void)
355 {
356 	int i;
357 	lan8710a_reg_write(CPDMA_SOFT_RESET, SOFT_RESET);
358 	while ((lan8710a_reg_read(CPDMA_SOFT_RESET) & SOFT_RESET));
359 
360 	/*
361 	 * Initialize the HDPs (Header Description Pointers) and
362 	 * CPs (Completion Pointers) to NULL.
363 	 */
364 	for (i = 0; i < DMA_MAX_CHANNELS; ++i) {
365 		lan8710a_reg_write(CPDMA_STRAM_TX_HDP(i), 0);
366 		lan8710a_reg_write(CPDMA_STRAM_RX_HDP(i), 0);
367 		lan8710a_reg_write(CPDMA_STRAM_TX_CP(i), 0);
368 		lan8710a_reg_write(CPDMA_STRAM_RX_CP(i), 0);
369 	}
370 
371 	lan8710a_reg_write(CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
372 	lan8710a_reg_write(CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
373 
374 	/* Configure the CPDMA controller. */
375 	lan8710a_reg_set(CPDMA_RX_CONTROL, CPDMA_RX_EN); /* RX Enabled */
376 	lan8710a_reg_set(CPDMA_TX_CONTROL, CPDMA_TX_EN); /* TX Enabled */
377 
378 	/* Enabling first channel Rx interrupt */
379 	lan8710a_reg_set(CPDMA_RX_INTMASK_SET, CPDMA_FIRST_CHAN_INT);
380 
381 	/*
382 	 * Writing the address of the first buffer descriptor in the queue
383 	 * (nonzero value)to the channel�s head descriptor pointer in the
384 	 * channel�s Rx DMA state.
385 	 */
386 	lan8710a_reg_write(CPDMA_STRAM_RX_HDP(0),
387 			  (u32_t)lan8710a_state.rx_desc_phy);
388 
389 	lan8710a_state.rx_desc_idx = 0;
390 	lan8710a_state.tx_desc_idx = 0;
391 }
392 
393 /*============================================================================*
394  *				lan8710a_init_desc			      *
395  *============================================================================*/
396 static void
397 lan8710a_init_desc(void)
398 {
399 	lan8710a_desc_t *p_rx_desc;
400 	lan8710a_desc_t *p_tx_desc;
401 	phys_bytes   buf_phys_addr;
402 	u8_t *p_buf;
403 	u8_t i;
404 
405 	/* Attempt to allocate. */
406 	if ((lan8710a_state.p_rx_buf = alloc_contig((LAN8710A_NUM_RX_DESC
407 			* LAN8710A_IOBUF_SIZE), AC_ALIGN4K,
408 			&buf_phys_addr)) == NULL) {
409 		panic("failed to allocate RX buffers.");
410 	}
411 	p_buf = lan8710a_state.p_rx_buf;
412 	for (i = 0; i < LAN8710A_NUM_RX_DESC; i++) {
413 		p_rx_desc = &(lan8710a_state.rx_desc[i]);
414 		memset(p_rx_desc, 0x0, sizeof(lan8710a_desc_t));
415 		p_rx_desc->pkt_len_flags = LAN8710A_DESC_FLAG_OWN;
416 		p_rx_desc->buffer_length_off = LAN8710A_IOBUF_SIZE;
417 		p_rx_desc->buffer_pointer = (u32_t)(buf_phys_addr +
418 						(i * LAN8710A_IOBUF_SIZE));
419 
420 		p_rx_desc->next_pointer =
421 		   (u32_t)((i == (LAN8710A_NUM_RX_DESC - 1)) ?
422 			   (lan8710a_state.rx_desc_phy) :
423 			   (lan8710a_state.rx_desc_phy +
424 			     ((i + 1) * sizeof(lan8710a_desc_t))));
425 	}
426 
427 	/* Attempt to allocate. */
428 	if ((lan8710a_state.p_tx_buf = alloc_contig((LAN8710A_NUM_TX_DESC
429 			* LAN8710A_IOBUF_SIZE), AC_ALIGN4K,
430 			&buf_phys_addr)) == NULL) {
431 		panic("failed to allocate TX buffers");
432 	}
433 	p_buf = lan8710a_state.p_tx_buf;
434 	for (i = 0; i < LAN8710A_NUM_TX_DESC; i++) {
435 		p_tx_desc = &(lan8710a_state.tx_desc[i]);
436 		memset(p_tx_desc, 0x0, sizeof(lan8710a_desc_t));
437 		p_tx_desc->buffer_pointer = (u32_t)(buf_phys_addr +
438 				(i * LAN8710A_IOBUF_SIZE));
439 	}
440 	lan8710a_state.rx_desc_idx = 0;
441 	lan8710a_state.tx_desc_idx = 0;
442 }
443 
444 /*============================================================================*
445  *				lan8710a_init_hw			      *
446  *============================================================================*/
447 static int
448 lan8710a_init_hw(ether_addr_t * addr)
449 {
450 	int r, i;
451 
452 	/*
453 	 * Set the interrupt handler and policy. Do not automatically
454 	 * re-enable interrupts. Return the IRQ line number on interrupts.
455 	 */
456 	lan8710a_state.irq_rx_hook = RX_INT;
457 	if ((r = sys_irqsetpolicy(LAN8710A_RX_INTR, 0,
458 					&lan8710a_state.irq_rx_hook)) != OK) {
459 		panic("sys_irqsetpolicy failed: %d", r);
460 	}
461 	lan8710a_state.irq_tx_hook = TX_INT;
462 	if ((r = sys_irqsetpolicy(LAN8710A_TX_INTR, 0,
463 					&lan8710a_state.irq_tx_hook)) != OK) {
464 		panic("sys_irqsetpolicy failed: %d", r);
465 	}
466 
467 	/* Reset hardware. */
468 	lan8710a_reset_hw();
469 
470 	/*
471 	 * Select the Interface (GMII/RGMII/MII) Mode in the Control Module.
472 	 * Port1 GMII/MII Mode, Port2 not used.
473 	 */
474 	lan8710a_reg_write(GMII_SEL, (GMII2_SEL_BIT1 | GMII2_SEL_BIT0));
475 
476 	/*
477 	 * Configure pads (PIN muxing) as per the Interface Selected using the
478 	 * appropriate pin muxing conf_xxx registers in the Control Module.
479 	 *
480 	 * CONF_MOD_SLEW_CTRL when 0 - Fast Mode, when 1 - Slow Mode
481 	 * CONF_MOD_RX_ACTIVE when 0 - Only output, when 1 - Also input
482 	 * CONF_MOD_PU_TYPESEL when 0 - Pull-down, when 1 - Pull-up
483 	 * CONF_MOD_PUDEN when 0 Pull* enabled, when 1 Pull* disabled
484 	 * CONF_MOD_MMODE_MII selects pin to work for MII interface
485 	 */
486 	lan8710a_reg_unset(CONF_MII1_COL, CONF_MOD_SLEW_CTRL);
487 	lan8710a_reg_set(CONF_MII1_COL, CONF_MOD_RX_ACTIVE);
488 	lan8710a_reg_set(CONF_MII1_COL, CONF_MOD_PU_TYPESEL);
489 	lan8710a_reg_unset(CONF_MII1_COL, CONF_MOD_PUDEN);
490 	lan8710a_reg_unset(CONF_MII1_COL, CONF_MOD_MMODE_MII);
491 
492 	lan8710a_reg_unset(CONF_MII1_CRS, CONF_MOD_SLEW_CTRL);
493 	lan8710a_reg_set(CONF_MII1_CRS, CONF_MOD_RX_ACTIVE);
494 	lan8710a_reg_set(CONF_MII1_CRS, CONF_MOD_PU_TYPESEL);
495 	lan8710a_reg_unset(CONF_MII1_CRS, CONF_MOD_PUDEN);
496 	lan8710a_reg_unset(CONF_MII1_CRS, CONF_MOD_MMODE_MII);
497 
498 	lan8710a_reg_unset(CONF_MII1_RX_ER, CONF_MOD_SLEW_CTRL);
499 	lan8710a_reg_set(CONF_MII1_RX_ER, CONF_MOD_RX_ACTIVE);
500 	lan8710a_reg_set(CONF_MII1_RX_ER, CONF_MOD_PU_TYPESEL);
501 	lan8710a_reg_unset(CONF_MII1_RX_ER, CONF_MOD_PUDEN);
502 	lan8710a_reg_unset(CONF_MII1_RX_ER, CONF_MOD_MMODE_MII);
503 
504 	lan8710a_reg_unset(CONF_MII1_TX_EN, CONF_MOD_SLEW_CTRL);
505 	lan8710a_reg_unset(CONF_MII1_TX_EN, CONF_MOD_RX_ACTIVE);
506 	lan8710a_reg_set(CONF_MII1_TX_EN, CONF_MOD_PUDEN);
507 	lan8710a_reg_unset(CONF_MII1_TX_EN, CONF_MOD_MMODE_MII);
508 
509 	lan8710a_reg_unset(CONF_MII1_RX_DV, CONF_MOD_SLEW_CTRL);
510 	lan8710a_reg_set(CONF_MII1_RX_DV, CONF_MOD_RX_ACTIVE);
511 	lan8710a_reg_set(CONF_MII1_RX_DV, CONF_MOD_PU_TYPESEL);
512 	lan8710a_reg_unset(CONF_MII1_RX_DV, CONF_MOD_PUDEN);
513 	lan8710a_reg_unset(CONF_MII1_RX_DV, CONF_MOD_MMODE_MII);
514 
515 	lan8710a_reg_unset(CONF_MII1_TXD3, CONF_MOD_SLEW_CTRL);
516 	lan8710a_reg_unset(CONF_MII1_TXD3, CONF_MOD_RX_ACTIVE);
517 	lan8710a_reg_set(CONF_MII1_TXD3, CONF_MOD_PUDEN);
518 	lan8710a_reg_unset(CONF_MII1_TXD3, CONF_MOD_MMODE_MII);
519 
520 	lan8710a_reg_unset(CONF_MII1_TXD2, CONF_MOD_SLEW_CTRL);
521 	lan8710a_reg_unset(CONF_MII1_TXD2, CONF_MOD_RX_ACTIVE);
522 	lan8710a_reg_set(CONF_MII1_TXD2, CONF_MOD_PUDEN);
523 	lan8710a_reg_unset(CONF_MII1_TXD2, CONF_MOD_MMODE_MII);
524 
525 	lan8710a_reg_unset(CONF_MII1_TXD1, CONF_MOD_SLEW_CTRL);
526 	lan8710a_reg_unset(CONF_MII1_TXD1, CONF_MOD_RX_ACTIVE);
527 	lan8710a_reg_set(CONF_MII1_TXD1, CONF_MOD_PUDEN);
528 	lan8710a_reg_unset(CONF_MII1_TXD1, CONF_MOD_MMODE_MII);
529 
530 	lan8710a_reg_unset(CONF_MII1_TXD0, CONF_MOD_SLEW_CTRL);
531 	lan8710a_reg_unset(CONF_MII1_TXD0, CONF_MOD_RX_ACTIVE);
532 	lan8710a_reg_set(CONF_MII1_TXD0, CONF_MOD_PUDEN);
533 	lan8710a_reg_unset(CONF_MII1_TXD0, CONF_MOD_MMODE_MII);
534 
535 	lan8710a_reg_unset(CONF_MII1_TX_CLK, CONF_MOD_SLEW_CTRL);
536 	lan8710a_reg_set(CONF_MII1_TX_CLK, CONF_MOD_RX_ACTIVE);
537 	lan8710a_reg_set(CONF_MII1_TX_CLK, CONF_MOD_PUDEN);
538 	lan8710a_reg_unset(CONF_MII1_TX_CLK, CONF_MOD_MMODE_MII);
539 
540 	lan8710a_reg_unset(CONF_MII1_RX_CLK, CONF_MOD_SLEW_CTRL);
541 	lan8710a_reg_set(CONF_MII1_RX_CLK, CONF_MOD_RX_ACTIVE);
542 	lan8710a_reg_set(CONF_MII1_RX_CLK, CONF_MOD_PUDEN);
543 	lan8710a_reg_unset(CONF_MII1_RX_CLK, CONF_MOD_MMODE_MII);
544 
545 	lan8710a_reg_unset(CONF_MII1_RXD3, CONF_MOD_SLEW_CTRL);
546 	lan8710a_reg_set(CONF_MII1_RXD3, CONF_MOD_RX_ACTIVE);
547 	lan8710a_reg_set(CONF_MII1_RXD3, CONF_MOD_PU_TYPESEL);
548 	lan8710a_reg_unset(CONF_MII1_RXD3, CONF_MOD_PUDEN);
549 	lan8710a_reg_unset(CONF_MII1_RXD3, CONF_MOD_MMODE_MII);
550 
551 	lan8710a_reg_unset(CONF_MII1_RXD2, CONF_MOD_SLEW_CTRL);
552 	lan8710a_reg_set(CONF_MII1_RXD2, CONF_MOD_RX_ACTIVE);
553 	lan8710a_reg_set(CONF_MII1_RXD2, CONF_MOD_PU_TYPESEL);
554 	lan8710a_reg_unset(CONF_MII1_RXD2, CONF_MOD_PUDEN);
555 	lan8710a_reg_unset(CONF_MII1_RXD2, CONF_MOD_MMODE_MII);
556 
557 	lan8710a_reg_unset(CONF_MII1_RXD1, CONF_MOD_SLEW_CTRL);
558 	lan8710a_reg_set(CONF_MII1_RXD1, CONF_MOD_RX_ACTIVE);
559 	lan8710a_reg_set(CONF_MII1_RXD1, CONF_MOD_PU_TYPESEL);
560 	lan8710a_reg_unset(CONF_MII1_RXD1, CONF_MOD_PUDEN);
561 	lan8710a_reg_unset(CONF_MII1_RXD1, CONF_MOD_MMODE_MII);
562 
563 	lan8710a_reg_unset(CONF_MII1_RXD0, CONF_MOD_SLEW_CTRL);
564 	lan8710a_reg_set(CONF_MII1_RXD0, CONF_MOD_RX_ACTIVE);
565 	lan8710a_reg_set(CONF_MII1_RXD0, CONF_MOD_PU_TYPESEL);
566 	lan8710a_reg_unset(CONF_MII1_RXD0, CONF_MOD_PUDEN);
567 	lan8710a_reg_unset(CONF_MII1_RXD0, CONF_MOD_MMODE_MII);
568 
569 	lan8710a_reg_unset(CONF_MDIO, CONF_MOD_SLEW_CTRL);
570 	lan8710a_reg_set(CONF_MDIO, CONF_MOD_RX_ACTIVE);
571 	lan8710a_reg_set(CONF_MDIO, CONF_MOD_PU_TYPESEL);
572 	lan8710a_reg_unset(CONF_MDIO, CONF_MOD_PUDEN);
573 	lan8710a_reg_unset(CONF_MDIO, CONF_MOD_MMODE_MII);
574 
575 	lan8710a_reg_unset(CONF_MDC, CONF_MOD_SLEW_CTRL);
576 	lan8710a_reg_unset(CONF_MDC, CONF_MOD_RX_ACTIVE);
577 	lan8710a_reg_set(CONF_MDC, CONF_MOD_PUDEN);
578 	lan8710a_reg_unset(CONF_MDC, CONF_MOD_MMODE_MII);
579 
580 	/* Apply soft reset to 3PSW Subsytem, CPSW_3G, CPGMAC_SL, and CPDMA. */
581 	lan8710a_reg_write(CPSW_SS_SOFT_RESET, SOFT_RESET);
582 	lan8710a_reg_write(CPSW_SL_SOFT_RESET(1), SOFT_RESET);
583 	lan8710a_reg_write(CPSW_SL_SOFT_RESET(2), SOFT_RESET);
584 
585 	/* Wait for software resets completion */
586 	while ((lan8710a_reg_read(CPSW_SS_SOFT_RESET) & SOFT_RESET) ||
587 		(lan8710a_reg_read(CPSW_SL_SOFT_RESET(1)) & SOFT_RESET) ||
588 		(lan8710a_reg_read(CPSW_SL_SOFT_RESET(2)) & SOFT_RESET));
589 
590 	/* Configure the Statistics Port Enable register. */
591 	/* Enable port 0 and 1 statistics. */
592 	lan8710a_reg_write(CPSW_SS_STAT_PORT_EN, (CPSW_P1_STAT_EN |
593 							CPSW_P0_STAT_EN));
594 
595 	/*
596 	 * Configure the ALE.
597 	 * Enabling Ale.
598 	 * All packets received on ports 1 are
599 	 * sent to the host (only to the host).
600 	 */
601 	lan8710a_reg_write(CPSW_ALE_CONTROL, (CPSW_ALE_ENABLE |
602 						CPSW_ALE_BYPASS));
603 	/* Port 0 (host) in forwarding mode. */
604 	lan8710a_reg_write(CPSW_ALE_PORTCTL0, CPSW_ALE_PORT_FWD);
605 	/* Port 1 in forwarding mode. */
606 	lan8710a_reg_write(CPSW_ALE_PORTCTL1, CPSW_ALE_PORT_FWD);
607 
608 	/*
609 	 * Configure CPSW_SL Register
610 	 * Full duplex mode.
611 	 */
612 	lan8710a_reg_write(CPSW_SL_MACCONTROL(1), CPSW_SL_FULLDUPLEX);
613 
614 	/* Initialize MDIO Protocol */
615 	lan8710a_init_mdio();
616 
617 	/* Getting MAC Address */
618 	lan8710a_init_addr(addr);
619 
620 	/* Initialize descriptors */
621 	lan8710a_init_desc();
622 
623 	/* Reset and initialize CPDMA */
624 	lan8710a_dma_reset_init();
625 
626 	/*
627 	 * Configure the Interrupts.
628 	 * Routing all channel Rx int to RX_PULSE signal.
629 	 */
630 	lan8710a_reg_set(CPSW_WR_C0_RX_EN, CPSW_FIRST_CHAN_INT);
631 
632 	/*
633 	 * Enabling LAN8710A Auto-negotiation
634 	 */
635 	lan8710a_phy_write(LAN8710A_CTRL_REG, LAN8710A_AUTO_NEG);
636 
637 	/* Waiting for auto-negotiaion completion. */
638 	for (i = 0; !(lan8710a_phy_read(LAN8710A_STATUS_REG) &
639 					LAN8710A_AUTO_NEG_COMPL); ++i) {
640 		if (i == 100) {
641 			LAN8710A_DEBUG_PRINT(("Autonegotiation failed"));
642 			break;
643 		}
644 		tickdelay(100);
645 	}
646 
647 	/* GMII RX and TX release from reset. */
648 	lan8710a_reg_set(CPSW_SL_MACCONTROL(1), CPSW_SL_GMII_EN);
649 
650 	/* Enable interrupts. */
651 	lan8710a_enable_interrupt(RX_INT | TX_INT);
652 
653 	return TRUE;
654 }
655 
656 /*============================================================================*
657  *				lan8710a_init_mdio			      *
658  *============================================================================*/
659 static void
660 lan8710a_init_mdio(void)
661 {
662 	u16_t address = 0;
663 	u32_t r;
664 
665 	/* Clearing MDIOCONTROL register */
666 	lan8710a_reg_write(MDIOCONTROL, 0);
667 	/* Configure the PREAMBLE and CLKDIV in the MDIO control register */
668 	lan8710a_reg_unset(MDIOCONTROL, MDIO_PREAMBLE); /* CLKDIV default */
669 	/* Enable sending MDIO frame preambles */
670 	lan8710a_reg_set(MDIOCONTROL, (MDCLK_DIVIDER | MDIO_ENABLE));
671 	/* Enable the MDIO module by setting the ENABLE bit in MDIOCONTROL */
672 
673 	while (!(r = lan8710a_reg_read(MDIOALIVE)));
674 
675 	/* Get PHY address */
676 	while (r >>= 1) {
677 		++address;
678 	}
679 	lan8710a_state.phy_address = address;
680 
681 	/* Setup appropiate address in MDIOUSERPHYSEL0 */
682 	lan8710a_reg_set(MDIOUSERPHYSEL0, address);
683 }
684 
685 /*============================================================================*
686  *				lan8710a_send				      *
687  *============================================================================*/
688 static int
689 lan8710a_send(struct netdriver_data * data, size_t size)
690 {
691 	lan8710a_t *e = &lan8710a_state;
692 	lan8710a_desc_t *p_tx_desc;
693 	u8_t *buf;
694 
695 	/* setup descriptors */
696 	p_tx_desc = &(e->tx_desc[e->tx_desc_idx]);
697 
698 	/*
699 	 * Check if descriptor is available for host and suspend if not.
700 	 */
701 	if (LAN8710A_DESC_FLAG_OWN & p_tx_desc->pkt_len_flags)
702 		return SUSPEND;
703 
704 	/* Drop packets that exceed the size of our transmission buffer. */
705 	if (size > LAN8710A_IOBUF_SIZE) {
706 		printf("%s: dropping large packet (%zu)\n", e->name, size);
707 
708 		return OK;
709 	}
710 
711 	/* virtual address of buffer */
712 	buf = e->p_tx_buf + e->tx_desc_idx * LAN8710A_IOBUF_SIZE;
713 
714 	netdriver_copyin(data, 0, buf, size);
715 
716 	/* set descriptor length */
717 	p_tx_desc->buffer_length_off = size;
718 	/* set flags */
719 	p_tx_desc->pkt_len_flags = (LAN8710A_DESC_FLAG_OWN |
720 					LAN8710A_DESC_FLAG_SOP |
721 					LAN8710A_DESC_FLAG_EOP |
722 					TX_DESC_TO_PORT1 |
723 					TX_DESC_TO_PORT_EN);
724 	p_tx_desc->pkt_len_flags |= size;
725 
726 	/* setup DMA transfer */
727 	lan8710a_dma_config_tx(e->tx_desc_idx);
728 
729 	e->tx_desc_idx++;
730 	if (LAN8710A_NUM_TX_DESC == e->tx_desc_idx)
731 		e->tx_desc_idx = 0;
732 
733 	return OK;
734 }
735 
736 /*============================================================================*
737  *				lan8710a_recv				      *
738  *============================================================================*/
739 static ssize_t
740 lan8710a_recv(struct netdriver_data * data, size_t max)
741 {
742 	lan8710a_t *e = &lan8710a_state;
743 	lan8710a_desc_t *p_rx_desc;
744 	u32_t flags;
745 	u8_t *buf;
746 	size_t off, size, chunk;
747 
748 	/*
749 	 * Only handle one packet at a time.
750 	 */
751 	p_rx_desc = &(e->rx_desc[e->rx_desc_idx]);
752 	/* find next OWN descriptor with SOP flag */
753 	while ((0 == (LAN8710A_DESC_FLAG_SOP & p_rx_desc->pkt_len_flags)) &&
754 	    (0 == (LAN8710A_DESC_FLAG_OWN & p_rx_desc->pkt_len_flags))) {
755 		p_rx_desc->buffer_length_off = LAN8710A_IOBUF_SIZE;
756 		/* set ownership of current descriptor to EMAC */
757 		p_rx_desc->pkt_len_flags = LAN8710A_DESC_FLAG_OWN;
758 
759 		e->rx_desc_idx++;
760 		if (LAN8710A_NUM_RX_DESC == e->rx_desc_idx)
761 			e->rx_desc_idx = 0;
762 		p_rx_desc = &(e->rx_desc[e->rx_desc_idx]);
763 	}
764 
765 	if (0 == (LAN8710A_DESC_FLAG_SOP & p_rx_desc->pkt_len_flags)) {
766 		/* SOP was not found */
767 		return SUSPEND;
768 	}
769 
770 	/*
771 	 * Copy data from descriptors, from SOP to EOP inclusive.
772 	 * TODO: make sure that the presence of a SOP slot implies the presence
773 	 * of an EOP slot, because we are not checking for ownership below..
774 	 */
775 	size = 0;
776 	off = 0;
777 
778 	for (;;) {
779 		buf = e->p_rx_buf + e->rx_desc_idx * LAN8710A_IOBUF_SIZE + off;
780 		chunk = p_rx_desc->buffer_length_off & 0xFFFF;
781 
782 		/* Truncate packets that are too large. */
783 		if (chunk > max - size)
784 			chunk = max - size;
785 
786 		if (chunk > 0) {
787 			netdriver_copyout(data, size, buf, chunk);
788 
789 			size += chunk;
790 		}
791 
792 		flags = p_rx_desc->pkt_len_flags;
793 
794 		/* Whole buffer move to the next descriptor */
795 		p_rx_desc->buffer_length_off = LAN8710A_IOBUF_SIZE;
796 		/* set ownership of current desc to EMAC */
797 		p_rx_desc->pkt_len_flags = LAN8710A_DESC_FLAG_OWN;
798 
799 		e->rx_desc_idx++;
800 		if (LAN8710A_NUM_RX_DESC == e->rx_desc_idx)
801 			e->rx_desc_idx = 0;
802 		p_rx_desc = &(e->rx_desc[e->rx_desc_idx]);
803 
804 		/* if EOP flag is set -> stop processing */
805 		if (flags & LAN8710A_DESC_FLAG_EOP)
806 			break;
807 
808 		/*
809 		 * TODO: the upper 16 bits of buffer_length_off are used *only*
810 		 * for descriptors *after* the first one; I'm retaining this
811 		 * behavior because I don't have the chip's spec, but it may be
812 		 * better to simplify/correct this behavior. --David
813 		 */
814 		off = p_rx_desc->buffer_length_off >> 16;
815 	}
816 
817 	return size;
818 }
819 
820 /*============================================================================*
821  *				lan8710a_phy_write			      *
822  *============================================================================*/
823 static void
824 lan8710a_phy_write(u32_t reg, u32_t value)
825 {
826 	if (!(lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO)) {
827 		/* Clearing MDIOUSERACCESS0 register */
828 		lan8710a_reg_write(MDIOUSERACCESS0, 0);
829 		/* Setting proper values in MDIOUSERACCESS0 */
830 		lan8710a_reg_set(MDIOUSERACCESS0, MDIO_WRITE);
831 		lan8710a_reg_set(MDIOUSERACCESS0, reg << MDIO_REGADR);
832 		lan8710a_reg_set(MDIOUSERACCESS0,
833 				lan8710a_state.phy_address << MDIO_PHYADR);
834 		/* Data written only 16 bits. */
835 		lan8710a_reg_set(MDIOUSERACCESS0,
836 		    (value & 0xFFFF) << MDIO_DATA);
837 		lan8710a_reg_set(MDIOUSERACCESS0, MDIO_GO);
838 
839 		/* Waiting for writing completion */
840 		while (lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO);
841 	}
842 }
843 
844 /*============================================================================*
845  *				lan8710a_phy_read			      *
846  *============================================================================*/
847 static u32_t
848 lan8710a_phy_read(u32_t reg)
849 {
850 	u32_t value = 0xFFFFFFFF;
851 
852 	if (!(lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO)) {
853 		/* Clearing MDIOUSERACCESS0 register */
854 		lan8710a_reg_write(MDIOUSERACCESS0, 0);
855 		/* Setting proper values in MDIOUSERACCESS0 */
856 		lan8710a_reg_unset(MDIOUSERACCESS0, MDIO_WRITE);
857 		/* Reg number must be 5 bit long */
858 		lan8710a_reg_set(MDIOUSERACCESS0, (reg & 0x1F) << MDIO_REGADR);
859 		/* Addr must be 5 bit long */
860 		lan8710a_reg_set(MDIOUSERACCESS0,
861 			(lan8710a_state.phy_address & 0x1F) << MDIO_PHYADR);
862 		lan8710a_reg_set(MDIOUSERACCESS0, MDIO_GO);
863 
864 		/* Waiting for reading completion */
865 		while ((lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO)
866 			&& !(lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_ACK));
867 
868 		/* Reading data */
869 		value = lan8710a_reg_read(MDIOUSERACCESS0) & 0xFFFF;
870 	}
871 	return value;
872 }
873 
874 /*============================================================================*
875  *				lan8710a_reset_hw			      *
876  *============================================================================*/
877 static void
878 lan8710a_reset_hw(void)
879 {
880 	/* Assert a Device Reset signal. */
881 	lan8710a_phy_write(LAN8710A_CTRL_REG, LAN8710A_SOFT_RESET);
882 
883 	/* Waiting for reset completion. */
884 	while (lan8710a_phy_read(LAN8710A_CTRL_REG) & LAN8710A_SOFT_RESET);
885 }
886 
887 /*============================================================================*
888  *				lan8710a_reg_read			      *
889  *============================================================================*/
890 static u32_t
891 lan8710a_reg_read(volatile u32_t *reg)
892 {
893 	u32_t value;
894 
895 	/* Read from memory mapped register. */
896 	value = *reg;
897 
898 	/* Return the result. */
899 	return value;
900 }
901 
902 /*============================================================================*
903  *				lan8710a_reg_write			      *
904  *============================================================================*/
905 static void
906 lan8710a_reg_write(volatile u32_t *reg, u32_t value)
907 {
908 	/* Write to memory mapped register. */
909 	*reg = value;
910 }
911 
912 /*============================================================================*
913  *				lan8710a_reg_set			      *
914  *============================================================================*/
915 static void
916 lan8710a_reg_set(volatile u32_t *reg, u32_t value)
917 {
918 	u32_t data;
919 
920 	/* First read the current value. */
921 	data = lan8710a_reg_read(reg);
922 
923 	/* Set value, and write back. */
924 	lan8710a_reg_write(reg, data | value);
925 }
926 
927 /*============================================================================*
928  *				lan8710a_reg_unset			      *
929  *============================================================================*/
930 static void
931 lan8710a_reg_unset(volatile u32_t *reg, u32_t value)
932 {
933 	u32_t data;
934 
935 	/* First read the current value. */
936 	data = lan8710a_reg_read(reg);
937 
938 	/* Unset value, and write back. */
939 	lan8710a_reg_write(reg, data & ~value);
940 }
941