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