Remove building with NOCRYPTO option
[minix3.git] / minix / drivers / net / lan8710a / lan8710a.c
blobf25a0fb477d6d68a58a0ffa1457b13e39a6f5e58
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"
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);
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);
28 static void lan8710a_phy_write(u32_t reg, u32_t value);
29 static u32_t lan8710a_phy_read(u32_t reg);
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);
36 /* Local variables */
37 static lan8710a_t lan8710a_state;
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
49 /*============================================================================*
50 * main *
51 *============================================================================*/
52 int
53 main(int argc, char *argv[])
55 struct machine machine;
57 env_setargs(argc, argv);
59 sys_getmachine(&machine);
60 if (BOARD_IS_BB(machine.board_id))
61 netdriver_task(&lan8710a_table);
63 return EXIT_SUCCESS;
66 /*============================================================================*
67 * lan8710a_init *
68 *============================================================================*/
69 static int
70 lan8710a_init(unsigned int instance, netdriver_addr_t * addr, uint32_t * caps,
71 unsigned int * ticks)
73 /* Initialize the ethernet driver. */
75 /* Clear state. */
76 memset(&lan8710a_state, 0, sizeof(lan8710a_state));
78 /* Initialize driver. */
79 lan8710a_map_regs();
81 lan8710a_init_hw(addr, instance);
83 *caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
84 *ticks = sys_hz(); /* update statistics once a second */
85 return OK;
88 /*============================================================================*
89 * lan8710a_enable_interrupt *
90 *============================================================================*/
91 static void
92 lan8710a_enable_interrupt(int interrupt)
94 int r;
96 if (interrupt & RX_INT) {
97 if ((r = sys_irqenable(&lan8710a_state.irq_rx_hook)) != OK) {
98 panic("sys_irqenable failed: %d", r);
101 if (interrupt & TX_INT) {
102 if ((r = sys_irqenable(&lan8710a_state.irq_tx_hook)) != OK) {
103 panic("sys_irqenable failed: %d", r);
108 /*============================================================================*
109 * lan8710a_intr *
110 *============================================================================*/
111 static void
112 lan8710a_intr(unsigned int mask)
114 u32_t dma_status;
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;
121 /* Handle interrupts. */
122 if (rx_stat) {
123 cp = lan8710a_reg_read(CPDMA_STRAM_RX_CP(0));
125 netdriver_recv();
127 lan8710a_reg_write(CPDMA_STRAM_RX_CP(0), cp);
128 lan8710a_reg_write(CPDMA_EOI_VECTOR, RX_INT);
130 if (tx_stat) {
131 cp = lan8710a_reg_read(CPDMA_STRAM_TX_CP(0));
133 /* Disabling channels, where Tx interrupt occurred */
134 lan8710a_reg_set(CPDMA_TX_INTMASK_CLEAR, tx_stat);
136 netdriver_send();
138 lan8710a_reg_write(CPDMA_STRAM_TX_CP(0), cp);
139 lan8710a_reg_write(CPDMA_EOI_VECTOR, TX_INT);
142 dma_status = lan8710a_reg_read(CPDMA_STATUS);
144 if (dma_status & CPDMA_ERROR) {
145 LAN8710A_DEBUG_PRINT(("CPDMA error: 0x%X, reset", dma_status));
146 lan8710a_dma_reset_init();
149 /* Re-enable Rx interrupt. */
150 if (mask & (1 << RX_INT))
151 lan8710a_enable_interrupt(RX_INT);
153 /* Re-enable Tx interrupt. */
154 if (mask & (1 << TX_INT))
155 lan8710a_enable_interrupt(TX_INT);
158 /*============================================================================*
159 * lan8710a_init_addr *
160 *============================================================================*/
161 static void
162 lan8710a_init_addr(netdriver_addr_t * addr, unsigned int instance)
164 static char eakey[]= LAN8710A_ENVVAR "#_EA";
165 static char eafmt[]= "x:x:x:x:x:x";
166 int i;
167 long v;
170 * Do we have a user defined ethernet address?
172 eakey[sizeof(LAN8710A_ENVVAR)-1] = '0' + instance;
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;
180 if (i == 6)
181 return;
184 * No; get the address from the chip itself.
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;
194 /*============================================================================*
195 * lan8710a_map_regs *
196 *============================================================================*/
197 static void
198 lan8710a_map_regs(void)
200 struct minix_mem_range mr;
201 mr.mr_base = CM_PER_BASE_ADR;
202 mr.mr_limit = CM_PER_BASE_ADR + MEMORY_LIMIT;
204 if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
205 panic("Unable to request permission to map memory");
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");
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");
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");
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");
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");
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");
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");
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");
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");
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");
258 mr.mr_base = BEGINNING_DESC_MEM;
259 mr.mr_limit = BEGINNING_DESC_MEM + DESC_MEMORY_LIMIT;
261 if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
262 panic("Unable to request permission to map memory");
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");
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");
277 mr.mr_base = CPSW_STATS_BASE_ADR;
278 mr.mr_limit = CPSW_STATS_BASE_ADR + CPSW_STATS_MEM_LIMIT;
280 if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
281 panic("Unable to request permission to map memory");
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");
290 /*============================================================================*
291 * lan8710a_update_stats *
292 *============================================================================*/
293 static void
294 lan8710a_update_stats(void)
296 uint32_t val;
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.
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);
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);
311 val = lan8710a_reg_read(CPSW_STAT_RX_OVERSIZE);
312 lan8710a_reg_write(CPSW_STAT_RX_OVERSIZE, val);
313 netdriver_stat_ierror(val);
315 val = lan8710a_reg_read(CPSW_STAT_COLLISIONS);
316 lan8710a_reg_write(CPSW_STAT_COLLISIONS, val);
317 netdriver_stat_coll(val);
320 /*============================================================================*
321 * lan8710a_tick *
322 *============================================================================*/
323 static void
324 lan8710a_tick(void)
327 /* Update statistics. */
328 lan8710a_update_stats();
331 /*============================================================================*
332 * lan8710a_stop *
333 *============================================================================*/
334 static void
335 lan8710a_stop(void)
337 /* Reset hardware. */
338 lan8710a_reset_hw();
341 /*============================================================================*
342 * lan8710a_dma_config_tx *
343 *============================================================================*/
344 static void
345 lan8710a_dma_config_tx(u8_t desc_idx)
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;
352 if (i == TX_DMA_CHANNELS) {
353 panic("There are no free TX DMA channels.");
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);
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);
367 /*============================================================================*
368 * lan8710a_dma_reset_init *
369 *============================================================================*/
370 static void
371 lan8710a_dma_reset_init(void)
373 int i;
374 lan8710a_reg_write(CPDMA_SOFT_RESET, SOFT_RESET);
375 while ((lan8710a_reg_read(CPDMA_SOFT_RESET) & SOFT_RESET));
378 * Initialize the HDPs (Header Description Pointers) and
379 * CPs (Completion Pointers) to NULL.
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);
388 lan8710a_reg_write(CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
389 lan8710a_reg_write(CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
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 */
395 /* Enabling first channel Rx interrupt */
396 lan8710a_reg_set(CPDMA_RX_INTMASK_SET, CPDMA_FIRST_CHAN_INT);
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.
403 lan8710a_reg_write(CPDMA_STRAM_RX_HDP(0),
404 (u32_t)lan8710a_state.rx_desc_phy);
406 lan8710a_state.rx_desc_idx = 0;
407 lan8710a_state.tx_desc_idx = 0;
410 /*============================================================================*
411 * lan8710a_init_desc *
412 *============================================================================*/
413 static void
414 lan8710a_init_desc(void)
416 lan8710a_desc_t *p_rx_desc;
417 lan8710a_desc_t *p_tx_desc;
418 phys_bytes buf_phys_addr;
419 u8_t i;
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.");
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));
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))));
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");
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));
454 lan8710a_state.rx_desc_idx = 0;
455 lan8710a_state.tx_desc_idx = 0;
458 /*============================================================================*
459 * lan8710a_init_hw *
460 *============================================================================*/
461 static int
462 lan8710a_init_hw(netdriver_addr_t * addr, unsigned int instance)
464 int r, i;
467 * Set the interrupt handler and policy. Do not automatically
468 * re-enable interrupts. Return the IRQ line number on interrupts.
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);
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);
481 /* Reset hardware. */
482 lan8710a_reset_hw();
485 * Select the Interface (GMII/RGMII/MII) Mode in the Control Module.
486 * Port1 GMII/MII Mode, Port2 not used.
488 lan8710a_reg_write(GMII_SEL, (GMII2_SEL_BIT1 | GMII2_SEL_BIT0));
491 * Configure pads (PIN muxing) as per the Interface Selected using the
492 * appropriate pin muxing conf_xxx registers in the Control Module.
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
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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));
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));
610 * Configure the ALE.
611 * Enabling Ale.
612 * All packets received on ports 1 are
613 * sent to the host (only to the host).
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);
623 * Configure CPSW_SL Register
624 * Full duplex mode.
626 lan8710a_reg_write(CPSW_SL_MACCONTROL(1), CPSW_SL_FULLDUPLEX);
628 /* Initialize MDIO Protocol */
629 lan8710a_init_mdio();
631 /* Getting MAC Address */
632 lan8710a_init_addr(addr, instance);
634 /* Initialize descriptors */
635 lan8710a_init_desc();
637 /* Reset and initialize CPDMA */
638 lan8710a_dma_reset_init();
641 * Configure the Interrupts.
642 * Routing all channel Rx int to RX_PULSE signal.
644 lan8710a_reg_set(CPSW_WR_C0_RX_EN, CPSW_FIRST_CHAN_INT);
647 * Enabling LAN8710A Auto-negotiation
649 lan8710a_phy_write(LAN8710A_CTRL_REG, LAN8710A_AUTO_NEG);
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;
658 micro_delay(1666666);
661 /* GMII RX and TX release from reset. */
662 lan8710a_reg_set(CPSW_SL_MACCONTROL(1), CPSW_SL_GMII_EN);
664 /* Enable interrupts. */
665 lan8710a_enable_interrupt(RX_INT | TX_INT);
667 return TRUE;
670 /*============================================================================*
671 * lan8710a_init_mdio *
672 *============================================================================*/
673 static void
674 lan8710a_init_mdio(void)
676 u16_t address = 0;
677 u32_t r;
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 */
687 while (!(r = lan8710a_reg_read(MDIOALIVE)));
689 /* Get PHY address */
690 while (r >>= 1) {
691 ++address;
693 lan8710a_state.phy_address = address;
695 /* Setup appropiate address in MDIOUSERPHYSEL0 */
696 lan8710a_reg_set(MDIOUSERPHYSEL0, address);
699 /*============================================================================*
700 * lan8710a_send *
701 *============================================================================*/
702 static int
703 lan8710a_send(struct netdriver_data * data, size_t size)
705 lan8710a_t *e = &lan8710a_state;
706 lan8710a_desc_t *p_tx_desc;
707 u8_t *buf;
709 /* setup descriptors */
710 p_tx_desc = &(e->tx_desc[e->tx_desc_idx]);
713 * Check if descriptor is available for host and suspend if not.
715 if (LAN8710A_DESC_FLAG_OWN & p_tx_desc->pkt_len_flags)
716 return SUSPEND;
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);
723 return OK;
726 /* virtual address of buffer */
727 buf = e->p_tx_buf + e->tx_desc_idx * LAN8710A_IOBUF_SIZE;
729 netdriver_copyin(data, 0, buf, size);
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;
741 /* setup DMA transfer */
742 lan8710a_dma_config_tx(e->tx_desc_idx);
744 e->tx_desc_idx++;
745 if (LAN8710A_NUM_TX_DESC == e->tx_desc_idx)
746 e->tx_desc_idx = 0;
748 return OK;
751 /*============================================================================*
752 * lan8710a_recv *
753 *============================================================================*/
754 static ssize_t
755 lan8710a_recv(struct netdriver_data * data, size_t max)
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;
764 * Only handle one packet at a time.
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;
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]);
780 if (0 == (LAN8710A_DESC_FLAG_SOP & p_rx_desc->pkt_len_flags)) {
781 /* SOP was not found */
782 return SUSPEND;
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..
790 size = 0;
791 off = 0;
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;
797 /* Truncate packets that are too large. */
798 if (chunk > max - size)
799 chunk = max - size;
801 if (chunk > 0) {
802 netdriver_copyout(data, size, buf, chunk);
804 size += chunk;
807 flags = p_rx_desc->pkt_len_flags;
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;
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]);
819 /* if EOP flag is set -> stop processing */
820 if (flags & LAN8710A_DESC_FLAG_EOP)
821 break;
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
829 off = p_rx_desc->buffer_length_off >> 16;
832 return size;
835 /*============================================================================*
836 * lan8710a_phy_write *
837 *============================================================================*/
838 static void
839 lan8710a_phy_write(u32_t reg, u32_t value)
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);
854 /* Waiting for writing completion */
855 while (lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO);
859 /*============================================================================*
860 * lan8710a_phy_read *
861 *============================================================================*/
862 static u32_t
863 lan8710a_phy_read(u32_t reg)
865 u32_t value = 0xFFFFFFFF;
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);
879 /* Waiting for reading completion */
880 while ((lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO)
881 && !(lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_ACK));
883 /* Reading data */
884 value = lan8710a_reg_read(MDIOUSERACCESS0) & 0xFFFF;
886 return value;
889 /*============================================================================*
890 * lan8710a_reset_hw *
891 *============================================================================*/
892 static void
893 lan8710a_reset_hw(void)
895 /* Assert a Device Reset signal. */
896 lan8710a_phy_write(LAN8710A_CTRL_REG, LAN8710A_SOFT_RESET);
898 /* Waiting for reset completion. */
899 while (lan8710a_phy_read(LAN8710A_CTRL_REG) & LAN8710A_SOFT_RESET);
902 /*============================================================================*
903 * lan8710a_reg_read *
904 *============================================================================*/
905 static u32_t
906 lan8710a_reg_read(volatile u32_t *reg)
908 u32_t value;
910 /* Read from memory mapped register. */
911 value = *reg;
913 /* Return the result. */
914 return value;
917 /*============================================================================*
918 * lan8710a_reg_write *
919 *============================================================================*/
920 static void
921 lan8710a_reg_write(volatile u32_t *reg, u32_t value)
923 /* Write to memory mapped register. */
924 *reg = value;
927 /*============================================================================*
928 * lan8710a_reg_set *
929 *============================================================================*/
930 static void
931 lan8710a_reg_set(volatile u32_t *reg, u32_t value)
933 u32_t data;
935 /* First read the current value. */
936 data = lan8710a_reg_read(reg);
938 /* Set value, and write back. */
939 lan8710a_reg_write(reg, data | value);
942 /*============================================================================*
943 * lan8710a_reg_unset *
944 *============================================================================*/
945 static void
946 lan8710a_reg_unset(volatile u32_t *reg, u32_t value)
948 u32_t data;
950 /* First read the current value. */
951 data = lan8710a_reg_read(reg);
953 /* Unset value, and write back. */
954 lan8710a_reg_write(reg, data & ~value);