<sys/ioccom.h>, <sys/ioctl.h>
[minix3.git] / drivers / lan8710a / lan8710a.c
blob69e37b9d74ba142f5fe4273caf597709e501b44f
1 #include <minix/drivers.h>
2 #include <minix/netdriver.h>
3 #include <net/gen/ether.h>
4 #include <net/gen/eth_io.h>
5 #include <minix/sysutil.h>
6 #include <minix/board.h>
7 #include "assert.h"
8 #include "lan8710a.h"
9 #include "lan8710a_reg.h"
11 /* Local functions */
12 static void lan8710a_readv_s(message *m, int from_int);
13 static void lan8710a_writev_s(message *m, int from_int);
14 static void lan8710a_conf(message *m);
15 static void lan8710a_getstat(message *m);
17 static void lan8710a_init(void);
18 static void lan8710a_enable_interrupt(int interrupt);
19 static void lan8710a_interrupt(message *m);
20 static void lan8710a_map_regs(void);
21 static void lan8710a_stop(void);
22 static void lan8710a_dma_config_tx(u8_t desc_idx);
23 static void lan8710a_dma_reset_init(void);
24 static void lan8710a_init_addr(void);
25 static void lan8710a_init_desc(void);
26 static void lan8710a_init_mdio(void);
27 static int lan8710a_init_hw(void);
28 static void lan8710a_reset_hw();
30 static void lan8710a_phy_write(u32_t reg, u32_t value);
31 static u32_t lan8710a_phy_read(u32_t reg);
33 static u32_t lan8710a_reg_read(volatile u32_t *reg);
34 static void lan8710a_reg_write(volatile u32_t *reg, u32_t value);
35 static void lan8710a_reg_set(volatile u32_t *reg, u32_t value);
36 static void lan8710a_reg_unset(volatile u32_t *reg, u32_t value);
38 static void mess_reply(message *req, message *reply);
39 static void reply(lan8710a_t *e);
41 /* Local variables */
42 static lan8710a_t lan8710a_state;
44 /* SEF functions and variables. */
45 static void sef_local_startup(void);
46 static int sef_cb_init_fresh(int type, sef_init_info_t *info);
47 static void sef_cb_signal_handler(int signal);
49 /*============================================================================*
50 * main *
51 *============================================================================*/
52 int
53 main(int argc, char *argv[])
56 /* Local variables */
57 message m;
58 int r;
59 int ipc_status;
60 struct machine machine ;
62 sys_getmachine(&machine);
63 if ( BOARD_IS_BB(machine.board_id)) {
65 /* SEF local startup */
66 env_setargs(argc, argv);
67 sef_local_startup();
69 /* Main driver loop */
70 for (;;) {
71 r = netdriver_receive(ANY, &m, &ipc_status);
72 if (r != OK) {
73 panic("netdriver_receive failed: %d", r);
76 if (is_ipc_notify(ipc_status)) {
77 switch (_ENDPOINT_P(m.m_source)) {
78 case HARDWARE:
79 lan8710a_interrupt(&m);
80 break;
82 } else {
83 switch (m.m_type) {
84 case DL_WRITEV_S:
85 lan8710a_writev_s(&m, FALSE);
86 break;
87 case DL_READV_S:
88 lan8710a_readv_s(&m, FALSE);
89 break;
90 case DL_CONF:
91 lan8710a_conf(&m);
92 break;
93 case DL_GETSTAT_S:
94 lan8710a_getstat(&m);
95 break;
96 default:
97 panic("Illegal message: %d", m.m_type);
102 return EXIT_SUCCESS;
105 /*============================================================================*
106 * sef_local_startup *
107 *============================================================================*/
108 static void
109 sef_local_startup()
111 /* Register init callbacks. */
112 sef_setcb_init_fresh(sef_cb_init_fresh);
113 sef_setcb_init_lu(sef_cb_init_fresh);
114 sef_setcb_init_restart(sef_cb_init_fresh);
116 /* Register live update callbacks. */
117 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
118 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree);
120 /* Register signal callbacks. */
121 sef_setcb_signal_handler(sef_cb_signal_handler);
123 /* Let SEF perform startup. */
124 sef_startup();
127 /*============================================================================*
128 * sef_cb_init_fresh *
129 *============================================================================*/
130 static int
131 sef_cb_init_fresh(int UNUSED( type), sef_init_info_t *UNUSED( info))
133 /* Initialize the ethernet driver. */
134 long v = 0;
136 /* Clear state. */
137 memset(&lan8710a_state, 0, sizeof(lan8710a_state));
139 /* Initialize driver. */
140 lan8710a_init();
142 /* Get instance of ethernet device */
143 env_parse("instance", "d", 0, &v, 0, 255);
144 lan8710a_state.instance = (int) v;
146 /* Announce we are up! */
147 netdriver_announce();
149 return OK;
152 /*============================================================================*
153 * sef_cb_signal_handler *
154 *============================================================================*/
155 static void
156 sef_cb_signal_handler(int signal)
158 /* Only check for termination signal, ignore anything else. */
159 if (signal != SIGTERM)
160 return;
162 lan8710a_stop();
165 /*============================================================================*
166 * lan8710a_enable_interrupt *
167 *============================================================================*/
168 static void
169 lan8710a_enable_interrupt(interrupt)
170 u8_t interrupt;
172 int r;
174 if (interrupt & RX_INT) {
175 if ((r = sys_irqenable(&lan8710a_state.irq_rx_hook)) != OK) {
176 panic("sys_irqenable failed: %d", r);
179 if (interrupt & TX_INT) {
180 if ((r = sys_irqenable(&lan8710a_state.irq_tx_hook)) != OK) {
181 panic("sys_irqenable failed: %d", r);
185 /*============================================================================*
186 * lan8710a_interrupt *
187 *============================================================================*/
188 static void
189 lan8710a_interrupt(m)
190 message *m;
192 lan8710a_t *e = &lan8710a_state;
193 u32_t dma_status;
195 /* Check the card for interrupt reason(s). */
196 u32_t rx_stat = lan8710a_reg_read(CPSW_WR_C0_RX_STAT);
197 u32_t tx_stat = lan8710a_reg_read(CPSW_WR_C0_TX_STAT);
198 u32_t cp;
200 /* Handle interrupts. */
201 if (rx_stat) {
202 cp = lan8710a_reg_read(CPDMA_STRAM_RX_CP(0));
204 lan8710a_readv_s(&(e->rx_message), TRUE);
206 lan8710a_reg_write(CPDMA_STRAM_RX_CP(0), cp);
207 lan8710a_reg_write(CPDMA_EOI_VECTOR, RX_INT);
209 if (tx_stat) {
210 cp = lan8710a_reg_read(CPDMA_STRAM_TX_CP(0));
212 /* Disabling channels, where Tx interrupt occurred */
213 lan8710a_reg_set(CPDMA_TX_INTMASK_CLEAR, tx_stat);
215 lan8710a_writev_s(&(e->tx_message), TRUE);
217 lan8710a_reg_write(CPDMA_STRAM_TX_CP(0), cp);
218 lan8710a_reg_write(CPDMA_EOI_VECTOR, TX_INT);
221 dma_status = lan8710a_reg_read(CPDMA_STATUS);
223 if (dma_status & CPDMA_ERROR) {
224 LAN8710A_DEBUG_PRINT(("CPDMA error: 0x%X, reset", dma_status));
225 lan8710a_dma_reset_init();
228 /* Re-enable Rx interrupt. */
229 if(m->m_notify.interrupts & (1 << RX_INT))
230 lan8710a_enable_interrupt(RX_INT);
232 /* Re-enable Tx interrupt. */
233 if(m->m_notify.interrupts & (1 << TX_INT))
234 lan8710a_enable_interrupt(TX_INT);
237 /*============================================================================*
238 * lan8710a_conf *
239 *============================================================================*/
240 static void
241 lan8710a_conf(m)
242 message *m;
244 message reply;
246 if (!(lan8710a_state.status & LAN8710A_ENABLED) &&
247 !(lan8710a_init_hw())) {
248 reply.m_type = DL_CONF_REPLY;
249 reply.DL_STAT = ENXIO;
250 mess_reply(m, &reply);
251 return;
253 /* Reply back to INET. */
254 reply.m_type = DL_CONF_REPLY;
255 reply.DL_STAT = OK;
256 *(ether_addr_t *) reply.DL_HWADDR = lan8710a_state.address;
257 mess_reply(m, &reply);
260 /*============================================================================*
261 * lan8710a_init *
262 *============================================================================*/
263 static void
264 lan8710a_init(void)
266 lan8710a_map_regs();
267 strlcpy(lan8710a_state.name, "lan8710a#0", LAN8710A_NAME_LEN);
268 lan8710a_state.name[9] += lan8710a_state.instance;
269 lan8710a_state.status |= LAN8710A_DETECTED;
271 if (!(lan8710a_state.status & LAN8710A_ENABLED) &&
272 !(lan8710a_init_hw())) {
273 return;
277 /*============================================================================*
278 * lan8710a_init_addr *
279 *============================================================================*/
280 static void
281 lan8710a_init_addr(void)
283 static char eakey[]= LAN8710A_ENVVAR "#_EA";
284 static char eafmt[]= "x:x:x:x:x:x";
285 int i;
286 long v;
289 * Do we have a user defined ethernet address?
291 eakey[sizeof(LAN8710A_ENVVAR)-1] = '0' + lan8710a_state.instance;
293 for (i= 0; i < 6; i++) {
294 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
295 break;
296 else
297 lan8710a_state.address.ea_addr[i] = v;
299 if (i != 6) {
300 lan8710a_state.address.ea_addr[0] =
301 (lan8710a_reg_read(CTRL_MAC_ID0_HI) & 0xFF);
302 lan8710a_state.address.ea_addr[1] =
303 ((lan8710a_reg_read(CTRL_MAC_ID0_HI) & 0xFF00) >> 8);
304 lan8710a_state.address.ea_addr[2] =
305 ((lan8710a_reg_read(CTRL_MAC_ID0_HI) & 0xFF0000) >> 16);
306 lan8710a_state.address.ea_addr[3] =
307 ((lan8710a_reg_read(CTRL_MAC_ID0_HI) & 0xFF000000) >> 24);
308 lan8710a_state.address.ea_addr[4] =
309 (lan8710a_reg_read(CTRL_MAC_ID0_LO) & 0xFF);
310 lan8710a_state.address.ea_addr[5] =
311 ((lan8710a_reg_read(CTRL_MAC_ID0_LO) & 0xFF00) >> 8);
315 /*============================================================================*
316 * lan8710a_map_regs *
317 *============================================================================*/
318 static void
319 lan8710a_map_regs(void)
321 struct minix_mem_range mr;
322 mr.mr_base = CM_PER_BASE_ADR;
323 mr.mr_limit = CM_PER_BASE_ADR + MEMORY_LIMIT;
325 if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
326 panic("Unable to request permission to map memory");
328 lan8710a_state.regs_cp_per =
329 (vir_bytes)vm_map_phys(SELF, (void *)CM_PER_BASE_ADR, 512);
330 if ((void *)lan8710a_state.regs_cp_per == MAP_FAILED) {
331 panic("lan8710a_state.regs_cp_per: vm_map_phys failed");
333 lan8710a_state.regs_cpdma_stram =
334 (vir_bytes)vm_map_phys(SELF, (void *)CPDMA_STRAM_BASE_ADR, 512);
335 if ((void *)lan8710a_state.regs_cpdma_stram == MAP_FAILED) {
336 panic("lan8710a_state.regs_cpdma_stram: vm_map_phys failed");
338 lan8710a_state.regs_cpsw_cpdma =
339 (vir_bytes)vm_map_phys(SELF, (void *)CPSW_CPDMA_BASE_ADR, 512);
340 if ((void *)lan8710a_state.regs_cpsw_cpdma == MAP_FAILED) {
341 panic("lan8710a_state.regs_cpsw_cpdma: vm_map_phys failed");
343 lan8710a_state.regs_cpsw_ale =
344 (vir_bytes)vm_map_phys(SELF, (void *)CPSW_ALE_BASE_ADR, 256);
345 if ((void *)lan8710a_state.regs_cpsw_ale == MAP_FAILED) {
346 panic("lan8710a_state.regs_cpsw_ale: vm_map_phys failed");
348 lan8710a_state.regs_cpsw_sl =
349 (vir_bytes)vm_map_phys(SELF, (void *)CPSW_SL_BASE_ADR, 512);
350 if ((void *)lan8710a_state.regs_cpsw_sl == MAP_FAILED) {
351 panic("lan8710a_state.regs_cpsw_sl: vm_map_phys failed");
353 lan8710a_state.regs_cpsw_ss =
354 (vir_bytes)vm_map_phys(SELF, (void *)CPSW_SS_BASE_ADR, 512);
355 if ((void *)lan8710a_state.regs_cpsw_ss == MAP_FAILED) {
356 panic("lan8710a_state.regs_cpsw_ss: vm_map_phys failed");
358 lan8710a_state.regs_cpsw_wr =
359 (vir_bytes)vm_map_phys(SELF, (void *)CPSW_WR_BASE_ADR, 512);
360 if ((void *)lan8710a_state.regs_cpsw_wr == MAP_FAILED) {
361 panic("lan8710a_state.regs_cpsw_wr: vm_map_phys failed");
363 lan8710a_state.regs_ctrl_mod =
364 (vir_bytes)vm_map_phys(SELF, (void *)CTRL_MOD_BASE_ADR, 2560);
365 if ((void *)lan8710a_state.regs_ctrl_mod == MAP_FAILED) {
366 panic("lan8710a_state.regs_ctrl_mod: vm_map_phys failed");
368 lan8710a_state.regs_intc =
369 (vir_bytes)vm_map_phys(SELF, (void *)INTC_BASE_ADR, 512);
370 if ((void *)lan8710a_state.regs_intc == MAP_FAILED) {
371 panic("lan8710a_state.regs_intc: vm_map_phys failed");
373 lan8710a_state.regs_mdio =
374 (vir_bytes)vm_map_phys(SELF, (void *)MDIO_BASE_ADDR, 512);
375 if ((void *)lan8710a_state.regs_mdio == MAP_FAILED) {
376 panic("lan8710a_state.regs_mdio: vm_map_phys failed");
379 mr.mr_base = BEGINNING_DESC_MEM;
380 mr.mr_limit = BEGINNING_DESC_MEM + DESC_MEMORY_LIMIT;
382 if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
383 panic("Unable to request permission to map memory");
385 lan8710a_state.rx_desc_phy = BEGINNING_RX_DESC_MEM;
386 lan8710a_state.tx_desc_phy = BEGINNING_TX_DESC_MEM;
387 lan8710a_state.rx_desc = (lan8710a_desc_t *)vm_map_phys(SELF,
388 (void *)lan8710a_state.rx_desc_phy, 1024);
389 if ((void *)lan8710a_state.rx_desc == MAP_FAILED) {
390 panic("lan8710a_state.rx_desc: vm_map_phys failed");
392 lan8710a_state.tx_desc = (lan8710a_desc_t *)vm_map_phys(SELF,
393 (void *)lan8710a_state.tx_desc_phy, 1024);
394 if ((void *)lan8710a_state.tx_desc == MAP_FAILED) {
395 panic("lan8710a_state.tx_desc: vm_map_phys failed");
398 mr.mr_base = CPSW_STATS_BASE_ADR;
399 mr.mr_limit = CPSW_STATS_BASE_ADR + CPSW_STATS_MEM_LIMIT;
401 if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
402 panic("Unable to request permission to map memory");
404 lan8710a_state.regs_cpsw_stats =
405 (vir_bytes)vm_map_phys(SELF, (void *)CPSW_STATS_BASE_ADR, 256);
406 if ((void *)lan8710a_state.regs_cpsw_stats == MAP_FAILED) {
407 panic("lan8710a_state.regs_cpsw_stats: vm_map_phys failed");
411 /*============================================================================*
412 * lan8710a_getstat *
413 *============================================================================*/
414 static void
415 lan8710a_getstat(mp)
416 message *mp;
418 int r;
419 eth_stat_t stats;
421 stats.ets_recvErr = lan8710a_reg_read(CPSW_STAT_RX_CRC_ERR)
422 + lan8710a_reg_read(CPSW_STAT_RX_AGNCD_ERR)
423 + lan8710a_reg_read(CPSW_STAT_RX_OVERSIZE);
424 stats.ets_sendErr = 0;
425 stats.ets_OVW = 0;
426 stats.ets_CRCerr = lan8710a_reg_read(CPSW_STAT_RX_CRC_ERR);
427 stats.ets_frameAll = lan8710a_reg_read(CPSW_STAT_RX_AGNCD_ERR);
428 stats.ets_missedP = 0;
429 stats.ets_packetR = lan8710a_reg_read(CPSW_STAT_RX_GOOD);
430 stats.ets_packetT = lan8710a_reg_read(CPSW_STAT_TX_GOOD);
431 stats.ets_collision = lan8710a_reg_read(CPSW_STAT_COLLISIONS);
432 stats.ets_transAb = 0;
433 stats.ets_carrSense = lan8710a_reg_read(CPSW_STAT_CARR_SENS_ERR);
434 stats.ets_fifoUnder = lan8710a_reg_read(CPSW_STAT_TX_UNDERRUN);
435 stats.ets_fifoOver = lan8710a_reg_read(CPSW_STAT_RX_OVERRUN);
436 stats.ets_CDheartbeat = 0;
437 stats.ets_OWC = 0;
439 sys_safecopyto(mp->m_source, mp->DL_GRANT, 0, (vir_bytes)&stats,
440 sizeof(stats));
441 mp->m_type = DL_STAT_REPLY;
443 if ((r=ipc_send(mp->m_source, mp)) != OK) {
444 panic("lan8710a_getstat: ipc_send() failed: %d", r);
448 /*============================================================================*
449 * lan8710a_stop *
450 *============================================================================*/
451 static void
452 lan8710a_stop(void)
454 /* Reset hardware. */
455 lan8710a_reset_hw();
457 /* Exit driver. */
458 exit(EXIT_SUCCESS);
461 /*============================================================================*
462 * lan8710a_dma_config_tx *
463 *============================================================================*/
464 static void
465 lan8710a_dma_config_tx(desc_idx)
466 u8_t desc_idx;
468 phys_bytes phys_addr;
469 int i;
470 for (i = 0; i < TX_DMA_CHANNELS; ++i) {
471 if (!lan8710a_reg_read(CPDMA_STRAM_TX_HDP(i))) break;
473 if (i == TX_DMA_CHANNELS) {
474 panic("There are no free TX DMA channels.");
477 /* Enabling only one channel Tx interrupt */
478 lan8710a_reg_write(CPDMA_TX_INTMASK_SET, 1 << i);
479 /* Routing only one channel Tx int to TX_PULSE signal */
480 lan8710a_reg_write(CPSW_WR_C0_TX_EN, 1 << i);
482 /* Setting HDP */
483 phys_addr = lan8710a_state.tx_desc_phy +
484 (desc_idx * sizeof(lan8710a_desc_t));
485 lan8710a_reg_write(CPDMA_STRAM_TX_HDP(i), (u32_t)phys_addr);
488 /*============================================================================*
489 * lan8710a_dma_reset_init *
490 *============================================================================*/
491 static void
492 lan8710a_dma_reset_init(void)
494 int i;
495 lan8710a_reg_write(CPDMA_SOFT_RESET, SOFT_RESET);
496 while ((lan8710a_reg_read(CPDMA_SOFT_RESET) & SOFT_RESET));
499 * Initialize the HDPs (Header Description Pointers) and
500 * CPs (Completion Pointers) to NULL.
502 for (i = 0; i < DMA_MAX_CHANNELS; ++i) {
503 lan8710a_reg_write(CPDMA_STRAM_TX_HDP(i), 0);
504 lan8710a_reg_write(CPDMA_STRAM_RX_HDP(i), 0);
505 lan8710a_reg_write(CPDMA_STRAM_TX_CP(i), 0);
506 lan8710a_reg_write(CPDMA_STRAM_RX_CP(i), 0);
509 lan8710a_reg_write(CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
510 lan8710a_reg_write(CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
512 /* Configure the CPDMA controller. */
513 lan8710a_reg_set(CPDMA_RX_CONTROL, CPDMA_RX_EN); /* RX Enabled */
514 lan8710a_reg_set(CPDMA_TX_CONTROL, CPDMA_TX_EN); /* TX Enabled */
516 /* Enabling first channel Rx interrupt */
517 lan8710a_reg_set(CPDMA_RX_INTMASK_SET, CPDMA_FIRST_CHAN_INT);
520 * Writing the address of the first buffer descriptor in the queue
521 * (nonzero value)to the channel’s head descriptor pointer in the
522 * channel’s Rx DMA state.
524 lan8710a_reg_write(CPDMA_STRAM_RX_HDP(0),
525 (u32_t)lan8710a_state.rx_desc_phy);
527 lan8710a_state.rx_desc_idx = 0;
528 lan8710a_state.tx_desc_idx = 0;
531 /*============================================================================*
532 * lan8710a_init_desc *
533 *============================================================================*/
534 static void
535 lan8710a_init_desc(void)
537 lan8710a_desc_t *p_rx_desc;
538 lan8710a_desc_t *p_tx_desc;
539 phys_bytes buf_phys_addr;
540 u8_t *p_buf;
541 u8_t i;
543 /* Attempt to allocate. */
544 if ((lan8710a_state.p_rx_buf = alloc_contig((LAN8710A_NUM_RX_DESC
545 * LAN8710A_IOBUF_SIZE), AC_ALIGN4K,
546 &buf_phys_addr)) == NULL) {
547 panic("failed to allocate RX buffers.");
549 p_buf = lan8710a_state.p_rx_buf;
550 for (i = 0; i < LAN8710A_NUM_RX_DESC; i++) {
551 p_rx_desc = &(lan8710a_state.rx_desc[i]);
552 memset(p_rx_desc, 0x0, sizeof(lan8710a_desc_t));
553 p_rx_desc->pkt_len_flags = LAN8710A_DESC_FLAG_OWN;
554 p_rx_desc->buffer_length_off = LAN8710A_IOBUF_SIZE;
555 p_rx_desc->buffer_pointer = (u32_t)(buf_phys_addr +
556 (i * LAN8710A_IOBUF_SIZE));
558 p_rx_desc->next_pointer =
559 (u32_t)((i == (LAN8710A_NUM_RX_DESC - 1)) ?
560 (lan8710a_state.rx_desc_phy) :
561 (lan8710a_state.rx_desc_phy +
562 ((i + 1) * sizeof(lan8710a_desc_t))));
565 /* Attempt to allocate. */
566 if ((lan8710a_state.p_tx_buf = alloc_contig((LAN8710A_NUM_TX_DESC
567 * LAN8710A_IOBUF_SIZE), AC_ALIGN4K,
568 &buf_phys_addr)) == NULL) {
569 panic("failed to allocate TX buffers");
571 p_buf = lan8710a_state.p_tx_buf;
572 for (i = 0; i < LAN8710A_NUM_TX_DESC; i++) {
573 p_tx_desc = &(lan8710a_state.tx_desc[i]);
574 memset(p_tx_desc, 0x0, sizeof(lan8710a_desc_t));
575 p_tx_desc->buffer_pointer = (u32_t)(buf_phys_addr +
576 (i * LAN8710A_IOBUF_SIZE));
578 lan8710a_state.rx_desc_idx = 0;
579 lan8710a_state.tx_desc_idx = 0;
582 /*============================================================================*
583 * lan8710a_init_hw *
584 *============================================================================*/
585 static int
586 lan8710a_init_hw(void)
588 int r, i;
590 lan8710a_state.status |= LAN8710A_ENABLED;
593 * Set the interrupt handler and policy. Do not automatically
594 * re-enable interrupts. Return the IRQ line number on interrupts.
596 lan8710a_state.irq_rx_hook = RX_INT;
597 if ((r = sys_irqsetpolicy(LAN8710A_RX_INTR, 0,
598 &lan8710a_state.irq_rx_hook)) != OK) {
599 panic("sys_irqsetpolicy failed: %d", r);
601 lan8710a_state.irq_tx_hook = TX_INT;
602 if ((r = sys_irqsetpolicy(LAN8710A_TX_INTR, 0,
603 &lan8710a_state.irq_tx_hook)) != OK) {
604 panic("sys_irqsetpolicy failed: %d", r);
607 /* Reset hardware. */
608 lan8710a_reset_hw();
611 * Select the Interface (GMII/RGMII/MII) Mode in the Control Module.
612 * Port1 GMII/MII Mode, Port2 not used.
614 lan8710a_reg_write(GMII_SEL, (GMII2_SEL_BIT1 | GMII2_SEL_BIT0));
617 * Configure pads (PIN muxing) as per the Interface Selected using the
618 * appropriate pin muxing conf_xxx registers in the Control Module.
620 * CONF_MOD_SLEW_CTRL when 0 - Fast Mode, when 1 - Slow Mode
621 * CONF_MOD_RX_ACTIVE when 0 - Only output, when 1 - Also input
622 * CONF_MOD_PU_TYPESEL when 0 - Pull-down, when 1 - Pull-up
623 * CONF_MOD_PUDEN when 0 Pull* enabled, when 1 Pull* disabled
624 * CONF_MOD_MMODE_MII selects pin to work for MII interface
626 lan8710a_reg_unset(CONF_MII1_COL, CONF_MOD_SLEW_CTRL);
627 lan8710a_reg_set(CONF_MII1_COL, CONF_MOD_RX_ACTIVE);
628 lan8710a_reg_set(CONF_MII1_COL, CONF_MOD_PU_TYPESEL);
629 lan8710a_reg_unset(CONF_MII1_COL, CONF_MOD_PUDEN);
630 lan8710a_reg_unset(CONF_MII1_COL, CONF_MOD_MMODE_MII);
632 lan8710a_reg_unset(CONF_MII1_CRS, CONF_MOD_SLEW_CTRL);
633 lan8710a_reg_set(CONF_MII1_CRS, CONF_MOD_RX_ACTIVE);
634 lan8710a_reg_set(CONF_MII1_CRS, CONF_MOD_PU_TYPESEL);
635 lan8710a_reg_unset(CONF_MII1_CRS, CONF_MOD_PUDEN);
636 lan8710a_reg_unset(CONF_MII1_CRS, CONF_MOD_MMODE_MII);
638 lan8710a_reg_unset(CONF_MII1_RX_ER, CONF_MOD_SLEW_CTRL);
639 lan8710a_reg_set(CONF_MII1_RX_ER, CONF_MOD_RX_ACTIVE);
640 lan8710a_reg_set(CONF_MII1_RX_ER, CONF_MOD_PU_TYPESEL);
641 lan8710a_reg_unset(CONF_MII1_RX_ER, CONF_MOD_PUDEN);
642 lan8710a_reg_unset(CONF_MII1_RX_ER, CONF_MOD_MMODE_MII);
644 lan8710a_reg_unset(CONF_MII1_TX_EN, CONF_MOD_SLEW_CTRL);
645 lan8710a_reg_unset(CONF_MII1_TX_EN, CONF_MOD_RX_ACTIVE);
646 lan8710a_reg_set(CONF_MII1_TX_EN, CONF_MOD_PUDEN);
647 lan8710a_reg_unset(CONF_MII1_TX_EN, CONF_MOD_MMODE_MII);
649 lan8710a_reg_unset(CONF_MII1_RX_DV, CONF_MOD_SLEW_CTRL);
650 lan8710a_reg_set(CONF_MII1_RX_DV, CONF_MOD_RX_ACTIVE);
651 lan8710a_reg_set(CONF_MII1_RX_DV, CONF_MOD_PU_TYPESEL);
652 lan8710a_reg_unset(CONF_MII1_RX_DV, CONF_MOD_PUDEN);
653 lan8710a_reg_unset(CONF_MII1_RX_DV, CONF_MOD_MMODE_MII);
655 lan8710a_reg_unset(CONF_MII1_TXD3, CONF_MOD_SLEW_CTRL);
656 lan8710a_reg_unset(CONF_MII1_TXD3, CONF_MOD_RX_ACTIVE);
657 lan8710a_reg_set(CONF_MII1_TXD3, CONF_MOD_PUDEN);
658 lan8710a_reg_unset(CONF_MII1_TXD3, CONF_MOD_MMODE_MII);
660 lan8710a_reg_unset(CONF_MII1_TXD2, CONF_MOD_SLEW_CTRL);
661 lan8710a_reg_unset(CONF_MII1_TXD2, CONF_MOD_RX_ACTIVE);
662 lan8710a_reg_set(CONF_MII1_TXD2, CONF_MOD_PUDEN);
663 lan8710a_reg_unset(CONF_MII1_TXD2, CONF_MOD_MMODE_MII);
665 lan8710a_reg_unset(CONF_MII1_TXD1, CONF_MOD_SLEW_CTRL);
666 lan8710a_reg_unset(CONF_MII1_TXD1, CONF_MOD_RX_ACTIVE);
667 lan8710a_reg_set(CONF_MII1_TXD1, CONF_MOD_PUDEN);
668 lan8710a_reg_unset(CONF_MII1_TXD1, CONF_MOD_MMODE_MII);
670 lan8710a_reg_unset(CONF_MII1_TXD0, CONF_MOD_SLEW_CTRL);
671 lan8710a_reg_unset(CONF_MII1_TXD0, CONF_MOD_RX_ACTIVE);
672 lan8710a_reg_set(CONF_MII1_TXD0, CONF_MOD_PUDEN);
673 lan8710a_reg_unset(CONF_MII1_TXD0, CONF_MOD_MMODE_MII);
675 lan8710a_reg_unset(CONF_MII1_TX_CLK, CONF_MOD_SLEW_CTRL);
676 lan8710a_reg_set(CONF_MII1_TX_CLK, CONF_MOD_RX_ACTIVE);
677 lan8710a_reg_set(CONF_MII1_TX_CLK, CONF_MOD_PUDEN);
678 lan8710a_reg_unset(CONF_MII1_TX_CLK, CONF_MOD_MMODE_MII);
680 lan8710a_reg_unset(CONF_MII1_RX_CLK, CONF_MOD_SLEW_CTRL);
681 lan8710a_reg_set(CONF_MII1_RX_CLK, CONF_MOD_RX_ACTIVE);
682 lan8710a_reg_set(CONF_MII1_RX_CLK, CONF_MOD_PUDEN);
683 lan8710a_reg_unset(CONF_MII1_RX_CLK, CONF_MOD_MMODE_MII);
685 lan8710a_reg_unset(CONF_MII1_RXD3, CONF_MOD_SLEW_CTRL);
686 lan8710a_reg_set(CONF_MII1_RXD3, CONF_MOD_RX_ACTIVE);
687 lan8710a_reg_set(CONF_MII1_RXD3, CONF_MOD_PU_TYPESEL);
688 lan8710a_reg_unset(CONF_MII1_RXD3, CONF_MOD_PUDEN);
689 lan8710a_reg_unset(CONF_MII1_RXD3, CONF_MOD_MMODE_MII);
691 lan8710a_reg_unset(CONF_MII1_RXD2, CONF_MOD_SLEW_CTRL);
692 lan8710a_reg_set(CONF_MII1_RXD2, CONF_MOD_RX_ACTIVE);
693 lan8710a_reg_set(CONF_MII1_RXD2, CONF_MOD_PU_TYPESEL);
694 lan8710a_reg_unset(CONF_MII1_RXD2, CONF_MOD_PUDEN);
695 lan8710a_reg_unset(CONF_MII1_RXD2, CONF_MOD_MMODE_MII);
697 lan8710a_reg_unset(CONF_MII1_RXD1, CONF_MOD_SLEW_CTRL);
698 lan8710a_reg_set(CONF_MII1_RXD1, CONF_MOD_RX_ACTIVE);
699 lan8710a_reg_set(CONF_MII1_RXD1, CONF_MOD_PU_TYPESEL);
700 lan8710a_reg_unset(CONF_MII1_RXD1, CONF_MOD_PUDEN);
701 lan8710a_reg_unset(CONF_MII1_RXD1, CONF_MOD_MMODE_MII);
703 lan8710a_reg_unset(CONF_MII1_RXD0, CONF_MOD_SLEW_CTRL);
704 lan8710a_reg_set(CONF_MII1_RXD0, CONF_MOD_RX_ACTIVE);
705 lan8710a_reg_set(CONF_MII1_RXD0, CONF_MOD_PU_TYPESEL);
706 lan8710a_reg_unset(CONF_MII1_RXD0, CONF_MOD_PUDEN);
707 lan8710a_reg_unset(CONF_MII1_RXD0, CONF_MOD_MMODE_MII);
709 lan8710a_reg_unset(CONF_MDIO, CONF_MOD_SLEW_CTRL);
710 lan8710a_reg_set(CONF_MDIO, CONF_MOD_RX_ACTIVE);
711 lan8710a_reg_set(CONF_MDIO, CONF_MOD_PU_TYPESEL);
712 lan8710a_reg_unset(CONF_MDIO, CONF_MOD_PUDEN);
713 lan8710a_reg_unset(CONF_MDIO, CONF_MOD_MMODE_MII);
715 lan8710a_reg_unset(CONF_MDC, CONF_MOD_SLEW_CTRL);
716 lan8710a_reg_unset(CONF_MDC, CONF_MOD_RX_ACTIVE);
717 lan8710a_reg_set(CONF_MDC, CONF_MOD_PUDEN);
718 lan8710a_reg_unset(CONF_MDC, CONF_MOD_MMODE_MII);
720 /* Apply soft reset to 3PSW Subsytem, CPSW_3G, CPGMAC_SL, and CPDMA. */
721 lan8710a_reg_write(CPSW_SS_SOFT_RESET, SOFT_RESET);
722 lan8710a_reg_write(CPSW_SL_SOFT_RESET(1), SOFT_RESET);
723 lan8710a_reg_write(CPSW_SL_SOFT_RESET(2), SOFT_RESET);
725 /* Wait for software resets completion */
726 while ((lan8710a_reg_read(CPSW_SS_SOFT_RESET) & SOFT_RESET) ||
727 (lan8710a_reg_read(CPSW_SL_SOFT_RESET(1)) & SOFT_RESET) ||
728 (lan8710a_reg_read(CPSW_SL_SOFT_RESET(2)) & SOFT_RESET));
730 /* Configure the Statistics Port Enable register. */
731 /* Enable port 0 and 1 statistics. */
732 lan8710a_reg_write(CPSW_SS_STAT_PORT_EN, (CPSW_P1_STAT_EN |
733 CPSW_P0_STAT_EN));
736 * Configure the ALE.
737 * Enabling Ale.
738 * All packets received on ports 1 are
739 * sent to the host (only to the host).
741 lan8710a_reg_write(CPSW_ALE_CONTROL, (CPSW_ALE_ENABLE |
742 CPSW_ALE_BYPASS));
743 /* Port 0 (host) in forwarding mode. */
744 lan8710a_reg_write(CPSW_ALE_PORTCTL0, CPSW_ALE_PORT_FWD);
745 /* Port 1 in forwarding mode. */
746 lan8710a_reg_write(CPSW_ALE_PORTCTL1, CPSW_ALE_PORT_FWD);
749 * Configure CPSW_SL Register
750 * Full duplex mode.
752 lan8710a_reg_write(CPSW_SL_MACCONTROL(1), CPSW_SL_FULLDUPLEX);
754 /* Initialize MDIO Protocol */
755 lan8710a_init_mdio();
757 /* Getting MAC Address */
758 lan8710a_init_addr();
760 /* Initialize descriptors */
761 lan8710a_init_desc();
763 /* Reset and initialize CPDMA */
764 lan8710a_dma_reset_init();
767 * Configure the Interrupts.
768 * Routing all channel Rx int to RX_PULSE signal.
770 lan8710a_reg_set(CPSW_WR_C0_RX_EN, CPSW_FIRST_CHAN_INT);
773 * Enabling LAN8710A Auto-negotiation
775 lan8710a_phy_write(LAN8710A_CTRL_REG, LAN8710A_AUTO_NEG);
777 /* Waiting for auto-negotiaion completion. */
778 for (i = 0; !(lan8710a_phy_read(LAN8710A_STATUS_REG) &
779 LAN8710A_AUTO_NEG_COMPL); ++i) {
780 if (i == 100) {
781 LAN8710A_DEBUG_PRINT(("Autonegotiation failed"));
782 break;
784 tickdelay(100);
787 /* GMII RX and TX release from reset. */
788 lan8710a_reg_set(CPSW_SL_MACCONTROL(1), CPSW_SL_GMII_EN);
790 /* Enable interrupts. */
791 lan8710a_enable_interrupt(RX_INT | TX_INT);
793 return TRUE;
796 /*============================================================================*
797 * lan8710a_init_mdio *
798 *============================================================================*/
799 static void
800 lan8710a_init_mdio(void)
802 u16_t address = 0;
803 u32_t r;
805 /* Clearing MDIOCONTROL register */
806 lan8710a_reg_write(MDIOCONTROL, 0);
807 /* Configure the PREAMBLE and CLKDIV in the MDIO control register */
808 lan8710a_reg_unset(MDIOCONTROL, MDIO_PREAMBLE); /* CLKDIV default */
809 /* Enable sending MDIO frame preambles */
810 lan8710a_reg_set(MDIOCONTROL, (MDCLK_DIVIDER | MDIO_ENABLE));
811 /* Enable the MDIO module by setting the ENABLE bit in MDIOCONTROL */
813 while (!(r = lan8710a_reg_read(MDIOALIVE)));
815 /* Get PHY address */
816 while (r >>= 1) {
817 ++address;
819 lan8710a_state.phy_address = address;
821 /* Setup appropiate address in MDIOUSERPHYSEL0 */
822 lan8710a_reg_set(MDIOUSERPHYSEL0, address);
825 /*============================================================================*
826 * lan8710a_writev_s *
827 *============================================================================*/
828 static void
829 lan8710a_writev_s(mp, from_int)
830 message *mp;
831 int from_int;
833 iovec_s_t iovec[LAN8710A_IOVEC_NR];
834 lan8710a_t *e = &lan8710a_state;
835 lan8710a_desc_t *p_tx_desc;
836 u8_t *p_buf;
837 int r, size, buf_data_len, i;
839 /* Are we called from the interrupt handler? */
840 if (!from_int) {
841 /* We cannot write twice simultaneously. */
842 assert(!(e->status & LAN8710A_WRITING));
844 /* Copy write message. */
845 e->tx_message = *mp;
846 e->client = mp->m_source;
847 e->status |= LAN8710A_WRITING;
849 /* verify vector count */
850 assert(mp->DL_COUNT > 0);
851 assert(mp->DL_COUNT < LAN8710A_IOVEC_NR);
854 * Copy the I/O vector table.
856 if ((r = sys_safecopyfrom(mp->m_source, mp->DL_GRANT, 0,
857 (vir_bytes) iovec,
858 mp->DL_COUNT * sizeof(iovec_s_t))) != OK) {
859 panic("sys_safecopyfrom() failed: %d", r);
861 /* setup descriptors */
862 p_tx_desc = &(e->tx_desc[e->tx_desc_idx]);
865 * Check if descriptor is available for host
866 * and drop the packet if not.
868 if (LAN8710A_DESC_FLAG_OWN & p_tx_desc->pkt_len_flags) {
869 panic("No available transmit descriptor.");
872 /* virtual address of buffer */
873 p_buf = e->p_tx_buf + e->tx_desc_idx * LAN8710A_IOBUF_SIZE;
874 buf_data_len = 0;
875 for (i = 0; i < mp->DL_COUNT; i++) {
876 if ((buf_data_len + iovec[i].iov_size)
877 > LAN8710A_IOBUF_SIZE) {
878 panic("packet too long");
881 /* copy data to buffer */
882 size = iovec[i].iov_size
883 < (LAN8710A_IOBUF_SIZE - buf_data_len) ?
884 iovec[i].iov_size
885 : (LAN8710A_IOBUF_SIZE - buf_data_len);
887 /* Copy bytes to TX queue buffers. */
888 if ((r = sys_safecopyfrom(mp->m_source,
889 iovec[i].iov_grant, 0,
890 (vir_bytes) p_buf, size)) != OK) {
891 panic("sys_safecopyfrom() failed: %d", r);
893 p_buf += size;
894 buf_data_len += size;
897 /* set descriptor length */
898 p_tx_desc->buffer_length_off = buf_data_len;
899 /* set flags */
900 p_tx_desc->pkt_len_flags = (LAN8710A_DESC_FLAG_OWN |
901 LAN8710A_DESC_FLAG_SOP |
902 LAN8710A_DESC_FLAG_EOP |
903 TX_DESC_TO_PORT1 |
904 TX_DESC_TO_PORT_EN);
905 p_tx_desc->pkt_len_flags |= buf_data_len;
907 /* setup DMA transfer */
908 lan8710a_dma_config_tx(e->tx_desc_idx);
910 e->tx_desc_idx++;
911 if (LAN8710A_NUM_TX_DESC == e->tx_desc_idx) {
912 e->tx_desc_idx = 0;
914 } else {
915 e->status |= LAN8710A_TRANSMIT;
917 reply(e);
920 /*============================================================================*
921 * lan8710a_readv_s *
922 *============================================================================*/
923 static void
924 lan8710a_readv_s(mp, from_int)
925 message *mp;
926 int from_int;
928 iovec_s_t iovec[LAN8710A_IOVEC_NR];
929 lan8710a_t *e = &lan8710a_state;
930 lan8710a_desc_t *p_rx_desc;
931 u32_t flags;
932 u8_t *p_buf;
933 u16_t pkt_data_len;
934 u16_t buf_bytes, buf_len;
935 int i, r, size;
937 /* Are we called from the interrupt handler? */
938 if (!from_int) {
939 e->rx_message = *mp;
940 e->client = mp->m_source;
941 e->status |= LAN8710A_READING;
942 e->rx_size = 0;
944 assert(e->rx_message.DL_COUNT > 0);
945 assert(e->rx_message.DL_COUNT < LAN8710A_IOVEC_NR);
947 if (e->status & LAN8710A_READING) {
949 * Copy the I/O vector table first.
951 if ((r = sys_safecopyfrom(e->rx_message.m_source,
952 e->rx_message.DL_GRANT, 0, (vir_bytes) iovec,
953 e->rx_message.DL_COUNT *
954 sizeof(iovec_s_t))) != OK) {
955 panic("sys_safecopyfrom() failed: %d", r);
959 * Only handle one packet at a time.
961 p_rx_desc = &(e->rx_desc[e->rx_desc_idx]);
962 /* find next OWN descriptor with SOP flag */
963 while ((0 == (LAN8710A_DESC_FLAG_SOP &
964 p_rx_desc->pkt_len_flags)) &&
965 (0 == (LAN8710A_DESC_FLAG_OWN &
966 p_rx_desc->pkt_len_flags))) {
967 p_rx_desc->buffer_length_off = LAN8710A_IOBUF_SIZE;
968 /* set ownership of current descriptor to EMAC */
969 p_rx_desc->pkt_len_flags = LAN8710A_DESC_FLAG_OWN;
971 e->rx_desc_idx++;
972 if (LAN8710A_NUM_RX_DESC == e->rx_desc_idx)
973 e->rx_desc_idx = 0;
974 p_rx_desc = &(e->rx_desc[e->rx_desc_idx]);
976 if (0 == (LAN8710A_DESC_FLAG_SOP & p_rx_desc->pkt_len_flags)) {
977 /* SOP was not found */
978 reply(e);
979 return;
983 * Copy to vector elements.
985 pkt_data_len = 0;
986 buf_bytes = 0;
987 p_buf = e->p_rx_buf + e->rx_desc_idx * LAN8710A_IOBUF_SIZE;
988 for (i = 0; i < e->rx_message.DL_COUNT; i++) {
989 buf_len = p_rx_desc->buffer_length_off & 0xFFFF;
990 if (buf_bytes == buf_len) {
991 /* Whole buffer move to the next descriptor */
992 p_rx_desc->buffer_length_off =
993 LAN8710A_IOBUF_SIZE;
994 /* set ownership of current desc to EMAC */
995 p_rx_desc->pkt_len_flags =
996 LAN8710A_DESC_FLAG_OWN;
997 buf_bytes = 0;
999 e->rx_desc_idx++;
1000 if (LAN8710A_NUM_RX_DESC == e->rx_desc_idx)
1001 e->rx_desc_idx = 0;
1002 p_rx_desc = &(e->rx_desc[e->rx_desc_idx]);
1003 p_buf = e->p_rx_buf + (e->rx_desc_idx *
1004 LAN8710A_IOBUF_SIZE) +
1005 (p_rx_desc->buffer_length_off >> 16);
1006 buf_len = p_rx_desc->buffer_length_off & 0xFFFF;
1008 size = iovec[i].iov_size < (buf_len - buf_bytes) ?
1009 iovec[i].iov_size :
1010 (buf_len - buf_bytes);
1012 if ((r = sys_safecopyto(e->rx_message.m_source,
1013 iovec[i].iov_grant, 0,
1014 (vir_bytes) p_buf,
1015 size)) != OK) {
1016 panic("sys_safecopyto() failed: %d", r);
1018 p_buf += size;
1019 buf_bytes += size;
1020 pkt_data_len += size;
1022 /* if EOP flag is set -> stop processing */
1023 if ((LAN8710A_DESC_FLAG_EOP & p_rx_desc->pkt_len_flags) &&
1024 (buf_bytes == buf_len)) {
1025 /* end of packet */
1026 break;
1029 do {
1030 /* reset owned descriptors up to EOP flag */
1031 flags = p_rx_desc->pkt_len_flags;
1032 p_rx_desc->buffer_length_off = LAN8710A_IOBUF_SIZE;
1033 /* set ownership of current descriptor to EMAC */
1034 p_rx_desc->pkt_len_flags = LAN8710A_DESC_FLAG_OWN;
1036 e->rx_desc_idx++;
1037 if (LAN8710A_NUM_RX_DESC == e->rx_desc_idx)
1038 e->rx_desc_idx = 0;
1040 p_rx_desc = &(e->rx_desc[e->rx_desc_idx]);
1042 while (0 == (flags & LAN8710A_DESC_FLAG_EOP));
1045 * Update state.
1047 e->status |= LAN8710A_RECEIVED;
1048 e->rx_size = pkt_data_len;
1051 reply(e);
1054 /*============================================================================*
1055 * lan8710a_phy_write *
1056 *============================================================================*/
1057 static void
1058 lan8710a_phy_write(reg, value)
1059 u32_t reg;
1060 u32_t value;
1062 if (!(lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO)) {
1063 /* Clearing MDIOUSERACCESS0 register */
1064 lan8710a_reg_write(MDIOUSERACCESS0, 0);
1065 /* Setting proper values in MDIOUSERACCESS0 */
1066 lan8710a_reg_set(MDIOUSERACCESS0, MDIO_WRITE);
1067 lan8710a_reg_set(MDIOUSERACCESS0, reg << MDIO_REGADR);
1068 lan8710a_reg_set(MDIOUSERACCESS0,
1069 lan8710a_state.phy_address << MDIO_PHYADR);
1070 /* Data written only 16 bits. */
1071 lan8710a_reg_set(MDIOUSERACCESS0, (value & 0xFFFF) << MDIO_DATA);
1072 lan8710a_reg_set(MDIOUSERACCESS0, MDIO_GO);
1074 /* Waiting for writing completion */
1075 while (lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO);
1079 /*============================================================================*
1080 * lan8710a_phy_read *
1081 *============================================================================*/
1082 static u32_t
1083 lan8710a_phy_read(reg)
1084 u32_t reg;
1086 u32_t value = 0xFFFFFFFF;
1088 if (!(lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO)) {
1089 /* Clearing MDIOUSERACCESS0 register */
1090 lan8710a_reg_write(MDIOUSERACCESS0, 0);
1091 /* Setting proper values in MDIOUSERACCESS0 */
1092 lan8710a_reg_unset(MDIOUSERACCESS0, MDIO_WRITE);
1093 /* Reg number must be 5 bit long */
1094 lan8710a_reg_set(MDIOUSERACCESS0, (reg & 0x1F) << MDIO_REGADR);
1095 /* Addr must be 5 bit long */
1096 lan8710a_reg_set(MDIOUSERACCESS0,
1097 (lan8710a_state.phy_address & 0x1F) << MDIO_PHYADR);
1098 lan8710a_reg_set(MDIOUSERACCESS0, MDIO_GO);
1100 /* Waiting for reading completion */
1101 while ((lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO)
1102 && !(lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_ACK));
1104 /* Reading data */
1105 value = lan8710a_reg_read(MDIOUSERACCESS0) & 0xFFFF;
1107 return value;
1110 /*============================================================================*
1111 * lan8710a_reset_hw *
1112 *============================================================================*/
1113 static void
1114 lan8710a_reset_hw()
1116 /* Assert a Device Reset signal. */
1117 lan8710a_phy_write(LAN8710A_CTRL_REG, LAN8710A_SOFT_RESET);
1119 /* Waiting for reset completion. */
1120 while (lan8710a_phy_read(LAN8710A_CTRL_REG) & LAN8710A_SOFT_RESET);
1123 /*============================================================================*
1124 * lan8710a_reg_read *
1125 *============================================================================*/
1126 static u32_t
1127 lan8710a_reg_read(reg)
1128 volatile u32_t *reg;
1130 u32_t value;
1132 /* Read from memory mapped register. */
1133 value = *reg;
1135 /* Return the result. */
1136 return value;
1139 /*============================================================================*
1140 * lan8710a_reg_write *
1141 *============================================================================*/
1142 static void
1143 lan8710a_reg_write(reg, value)
1144 volatile u32_t *reg;
1145 u32_t value;
1147 /* Write to memory mapped register. */
1148 *reg = value;
1151 /*============================================================================*
1152 * lan8710a_reg_set *
1153 *============================================================================*/
1154 static void
1155 lan8710a_reg_set(reg, value)
1156 volatile u32_t *reg;
1157 u32_t value;
1159 u32_t data;
1161 /* First read the current value. */
1162 data = lan8710a_reg_read(reg);
1164 /* Set value, and write back. */
1165 lan8710a_reg_write(reg, data | value);
1168 /*============================================================================*
1169 * lan8710a_reg_unset *
1170 *============================================================================*/
1171 static void
1172 lan8710a_reg_unset(reg, value)
1173 volatile u32_t *reg;
1174 u32_t value;
1176 u32_t data;
1178 /* First read the current value. */
1179 data = lan8710a_reg_read(reg);
1181 /* Unset value, and write back. */
1182 lan8710a_reg_write(reg, data & ~value);
1185 /*============================================================================*
1186 * mess_reply *
1187 *============================================================================*/
1188 static void
1189 mess_reply(req, reply)
1190 message *req;message *reply;
1192 if (ipc_send(req->m_source, reply) != OK) {
1193 panic("unable to send reply message");
1197 /*============================================================================*
1198 * reply *
1199 *============================================================================*/
1200 static void
1201 reply(e)
1202 lan8710a_t *e;
1204 message msg;
1205 int r;
1207 /* Only reply to client for read/write request. */
1208 if (!(e->status & LAN8710A_READING ||
1209 e->status & LAN8710A_WRITING)) {
1210 return;
1212 /* Construct reply message. */
1213 msg.m_type = DL_TASK_REPLY;
1214 msg.DL_FLAGS = DL_NOFLAGS;
1215 msg.DL_COUNT = 0;
1217 /* Did we successfully receive packet(s)? */
1218 if (e->status & LAN8710A_READING &&
1219 e->status & LAN8710A_RECEIVED) {
1220 msg.DL_FLAGS |= DL_PACK_RECV;
1221 msg.DL_COUNT = e->rx_size >= ETH_MIN_PACK_SIZE ?
1222 e->rx_size :
1223 ETH_MIN_PACK_SIZE;
1225 /* Clear flags. */
1226 e->status &= ~(LAN8710A_READING | LAN8710A_RECEIVED);
1228 /* Did we successfully transmit packet(s)? */
1229 if (e->status & LAN8710A_TRANSMIT &&
1230 e->status & LAN8710A_WRITING) {
1231 msg.DL_FLAGS |= DL_PACK_SEND;
1233 /* Clear flags. */
1234 e->status &= ~(LAN8710A_WRITING | LAN8710A_TRANSMIT);
1237 /* Acknowledge to INET. */
1238 if ((r = ipc_send(e->client, &msg) != OK)) {
1239 panic("ipc_send() failed: %d", r);