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" 10 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); 16 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(); 29 30 static void lan8710a_phy_write(u32_t reg, u32_t value); 31 static u32_t lan8710a_phy_read(u32_t reg); 32 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); 37 38 static void mess_reply(message *req, message *reply); 39 static void reply(lan8710a_t *e); 40 41 /* Local variables */ 42 static lan8710a_t lan8710a_state; 43 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); 48 49 /*============================================================================* 50 * main * 51 *============================================================================*/ 52 int 53 main(int argc, char *argv[]) 54 { 55 56 /* Local variables */ 57 message m; 58 int r; 59 int ipc_status; 60 struct machine machine ; 61 62 sys_getmachine(&machine); 63 if ( BOARD_IS_BB(machine.board_id)) { 64 65 /* SEF local startup */ 66 env_setargs(argc, argv); 67 sef_local_startup(); 68 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); 74 } 75 76 if (is_ipc_notify(ipc_status)) { 77 switch (_ENDPOINT_P(m.m_source)) { 78 case HARDWARE: 79 lan8710a_interrupt(&m); 80 break; 81 } 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); 98 } 99 } 100 } 101 } 102 return EXIT_SUCCESS; 103 } 104 105 /*============================================================================* 106 * sef_local_startup * 107 *============================================================================*/ 108 static void 109 sef_local_startup() 110 { 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); 115 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); 119 120 /* Register signal callbacks. */ 121 sef_setcb_signal_handler(sef_cb_signal_handler); 122 123 /* Let SEF perform startup. */ 124 sef_startup(); 125 } 126 127 /*============================================================================* 128 * sef_cb_init_fresh * 129 *============================================================================*/ 130 static int 131 sef_cb_init_fresh(int UNUSED( type), sef_init_info_t *UNUSED( info)) 132 { 133 /* Initialize the ethernet driver. */ 134 long v = 0; 135 136 /* Clear state. */ 137 memset(&lan8710a_state, 0, sizeof(lan8710a_state)); 138 139 /* Initialize driver. */ 140 lan8710a_init(); 141 142 /* Get instance of ethernet device */ 143 env_parse("instance", "d", 0, &v, 0, 255); 144 lan8710a_state.instance = (int) v; 145 146 /* Announce we are up! */ 147 netdriver_announce(); 148 149 return OK; 150 } 151 152 /*============================================================================* 153 * sef_cb_signal_handler * 154 *============================================================================*/ 155 static void 156 sef_cb_signal_handler(int signal) 157 { 158 /* Only check for termination signal, ignore anything else. */ 159 if (signal != SIGTERM) 160 return; 161 162 lan8710a_stop(); 163 } 164 165 /*============================================================================* 166 * lan8710a_enable_interrupt * 167 *============================================================================*/ 168 static void 169 lan8710a_enable_interrupt(interrupt) 170 u8_t interrupt; 171 { 172 int r; 173 174 if (interrupt & RX_INT) { 175 if ((r = sys_irqenable(&lan8710a_state.irq_rx_hook)) != OK) { 176 panic("sys_irqenable failed: %d", r); 177 } 178 } 179 if (interrupt & TX_INT) { 180 if ((r = sys_irqenable(&lan8710a_state.irq_tx_hook)) != OK) { 181 panic("sys_irqenable failed: %d", r); 182 } 183 } 184 } 185 /*============================================================================* 186 * lan8710a_interrupt * 187 *============================================================================*/ 188 static void 189 lan8710a_interrupt(m) 190 message *m; 191 { 192 lan8710a_t *e = &lan8710a_state; 193 u32_t dma_status; 194 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; 199 200 /* Handle interrupts. */ 201 if (rx_stat) { 202 cp = lan8710a_reg_read(CPDMA_STRAM_RX_CP(0)); 203 204 lan8710a_readv_s(&(e->rx_message), TRUE); 205 206 lan8710a_reg_write(CPDMA_STRAM_RX_CP(0), cp); 207 lan8710a_reg_write(CPDMA_EOI_VECTOR, RX_INT); 208 } 209 if (tx_stat) { 210 cp = lan8710a_reg_read(CPDMA_STRAM_TX_CP(0)); 211 212 /* Disabling channels, where Tx interrupt occurred */ 213 lan8710a_reg_set(CPDMA_TX_INTMASK_CLEAR, tx_stat); 214 215 lan8710a_writev_s(&(e->tx_message), TRUE); 216 217 lan8710a_reg_write(CPDMA_STRAM_TX_CP(0), cp); 218 lan8710a_reg_write(CPDMA_EOI_VECTOR, TX_INT); 219 } 220 221 dma_status = lan8710a_reg_read(CPDMA_STATUS); 222 223 if (dma_status & CPDMA_ERROR) { 224 LAN8710A_DEBUG_PRINT(("CPDMA error: 0x%X, reset", dma_status)); 225 lan8710a_dma_reset_init(); 226 } 227 228 /* Re-enable Rx interrupt. */ 229 if(m->m_notify.interrupts & (1 << RX_INT)) 230 lan8710a_enable_interrupt(RX_INT); 231 232 /* Re-enable Tx interrupt. */ 233 if(m->m_notify.interrupts & (1 << TX_INT)) 234 lan8710a_enable_interrupt(TX_INT); 235 } 236 237 /*============================================================================* 238 * lan8710a_conf * 239 *============================================================================*/ 240 static void 241 lan8710a_conf(m) 242 message *m; 243 { 244 message reply; 245 246 if (!(lan8710a_state.status & LAN8710A_ENABLED) && 247 !(lan8710a_init_hw())) { 248 reply.m_type = DL_CONF_REPLY; 249 reply.m_netdrv_net_dl_conf.stat = ENXIO; 250 mess_reply(m, &reply); 251 return; 252 } 253 /* Reply back to INET. */ 254 reply.m_type = DL_CONF_REPLY; 255 reply.m_netdrv_net_dl_conf.stat = OK; 256 memcpy(reply.m_netdrv_net_dl_conf.hw_addr, 257 lan8710a_state.address.ea_addr, 258 sizeof(reply.m_netdrv_net_dl_conf.hw_addr)); 259 mess_reply(m, &reply); 260 } 261 262 /*============================================================================* 263 * lan8710a_init * 264 *============================================================================*/ 265 static void 266 lan8710a_init(void) 267 { 268 lan8710a_map_regs(); 269 strlcpy(lan8710a_state.name, "lan8710a#0", LAN8710A_NAME_LEN); 270 lan8710a_state.name[9] += lan8710a_state.instance; 271 lan8710a_state.status |= LAN8710A_DETECTED; 272 273 if (!(lan8710a_state.status & LAN8710A_ENABLED) && 274 !(lan8710a_init_hw())) { 275 return; 276 } 277 } 278 279 /*============================================================================* 280 * lan8710a_init_addr * 281 *============================================================================*/ 282 static void 283 lan8710a_init_addr(void) 284 { 285 static char eakey[]= LAN8710A_ENVVAR "#_EA"; 286 static char eafmt[]= "x:x:x:x:x:x"; 287 int i; 288 long v; 289 290 /* 291 * Do we have a user defined ethernet address? 292 */ 293 eakey[sizeof(LAN8710A_ENVVAR)-1] = '0' + lan8710a_state.instance; 294 295 for (i= 0; i < 6; i++) { 296 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET) 297 break; 298 else 299 lan8710a_state.address.ea_addr[i] = v; 300 } 301 if (i != 6) { 302 lan8710a_state.address.ea_addr[0] = 303 (lan8710a_reg_read(CTRL_MAC_ID0_HI) & 0xFF); 304 lan8710a_state.address.ea_addr[1] = 305 ((lan8710a_reg_read(CTRL_MAC_ID0_HI) & 0xFF00) >> 8); 306 lan8710a_state.address.ea_addr[2] = 307 ((lan8710a_reg_read(CTRL_MAC_ID0_HI) & 0xFF0000) >> 16); 308 lan8710a_state.address.ea_addr[3] = 309 ((lan8710a_reg_read(CTRL_MAC_ID0_HI) & 0xFF000000) >> 24); 310 lan8710a_state.address.ea_addr[4] = 311 (lan8710a_reg_read(CTRL_MAC_ID0_LO) & 0xFF); 312 lan8710a_state.address.ea_addr[5] = 313 ((lan8710a_reg_read(CTRL_MAC_ID0_LO) & 0xFF00) >> 8); 314 } 315 } 316 317 /*============================================================================* 318 * lan8710a_map_regs * 319 *============================================================================*/ 320 static void 321 lan8710a_map_regs(void) 322 { 323 struct minix_mem_range mr; 324 mr.mr_base = CM_PER_BASE_ADR; 325 mr.mr_limit = CM_PER_BASE_ADR + MEMORY_LIMIT; 326 327 if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) { 328 panic("Unable to request permission to map memory"); 329 } 330 lan8710a_state.regs_cp_per = 331 (vir_bytes)vm_map_phys(SELF, (void *)CM_PER_BASE_ADR, 512); 332 if ((void *)lan8710a_state.regs_cp_per == MAP_FAILED) { 333 panic("lan8710a_state.regs_cp_per: vm_map_phys failed"); 334 } 335 lan8710a_state.regs_cpdma_stram = 336 (vir_bytes)vm_map_phys(SELF, (void *)CPDMA_STRAM_BASE_ADR, 512); 337 if ((void *)lan8710a_state.regs_cpdma_stram == MAP_FAILED) { 338 panic("lan8710a_state.regs_cpdma_stram: vm_map_phys failed"); 339 } 340 lan8710a_state.regs_cpsw_cpdma = 341 (vir_bytes)vm_map_phys(SELF, (void *)CPSW_CPDMA_BASE_ADR, 512); 342 if ((void *)lan8710a_state.regs_cpsw_cpdma == MAP_FAILED) { 343 panic("lan8710a_state.regs_cpsw_cpdma: vm_map_phys failed"); 344 } 345 lan8710a_state.regs_cpsw_ale = 346 (vir_bytes)vm_map_phys(SELF, (void *)CPSW_ALE_BASE_ADR, 256); 347 if ((void *)lan8710a_state.regs_cpsw_ale == MAP_FAILED) { 348 panic("lan8710a_state.regs_cpsw_ale: vm_map_phys failed"); 349 } 350 lan8710a_state.regs_cpsw_sl = 351 (vir_bytes)vm_map_phys(SELF, (void *)CPSW_SL_BASE_ADR, 512); 352 if ((void *)lan8710a_state.regs_cpsw_sl == MAP_FAILED) { 353 panic("lan8710a_state.regs_cpsw_sl: vm_map_phys failed"); 354 } 355 lan8710a_state.regs_cpsw_ss = 356 (vir_bytes)vm_map_phys(SELF, (void *)CPSW_SS_BASE_ADR, 512); 357 if ((void *)lan8710a_state.regs_cpsw_ss == MAP_FAILED) { 358 panic("lan8710a_state.regs_cpsw_ss: vm_map_phys failed"); 359 } 360 lan8710a_state.regs_cpsw_wr = 361 (vir_bytes)vm_map_phys(SELF, (void *)CPSW_WR_BASE_ADR, 512); 362 if ((void *)lan8710a_state.regs_cpsw_wr == MAP_FAILED) { 363 panic("lan8710a_state.regs_cpsw_wr: vm_map_phys failed"); 364 } 365 lan8710a_state.regs_ctrl_mod = 366 (vir_bytes)vm_map_phys(SELF, (void *)CTRL_MOD_BASE_ADR, 2560); 367 if ((void *)lan8710a_state.regs_ctrl_mod == MAP_FAILED) { 368 panic("lan8710a_state.regs_ctrl_mod: vm_map_phys failed"); 369 } 370 lan8710a_state.regs_intc = 371 (vir_bytes)vm_map_phys(SELF, (void *)INTC_BASE_ADR, 512); 372 if ((void *)lan8710a_state.regs_intc == MAP_FAILED) { 373 panic("lan8710a_state.regs_intc: vm_map_phys failed"); 374 } 375 lan8710a_state.regs_mdio = 376 (vir_bytes)vm_map_phys(SELF, (void *)MDIO_BASE_ADDR, 512); 377 if ((void *)lan8710a_state.regs_mdio == MAP_FAILED) { 378 panic("lan8710a_state.regs_mdio: vm_map_phys failed"); 379 } 380 381 mr.mr_base = BEGINNING_DESC_MEM; 382 mr.mr_limit = BEGINNING_DESC_MEM + DESC_MEMORY_LIMIT; 383 384 if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) { 385 panic("Unable to request permission to map memory"); 386 } 387 lan8710a_state.rx_desc_phy = BEGINNING_RX_DESC_MEM; 388 lan8710a_state.tx_desc_phy = BEGINNING_TX_DESC_MEM; 389 lan8710a_state.rx_desc = (lan8710a_desc_t *)vm_map_phys(SELF, 390 (void *)lan8710a_state.rx_desc_phy, 1024); 391 if ((void *)lan8710a_state.rx_desc == MAP_FAILED) { 392 panic("lan8710a_state.rx_desc: vm_map_phys failed"); 393 } 394 lan8710a_state.tx_desc = (lan8710a_desc_t *)vm_map_phys(SELF, 395 (void *)lan8710a_state.tx_desc_phy, 1024); 396 if ((void *)lan8710a_state.tx_desc == MAP_FAILED) { 397 panic("lan8710a_state.tx_desc: vm_map_phys failed"); 398 } 399 400 mr.mr_base = CPSW_STATS_BASE_ADR; 401 mr.mr_limit = CPSW_STATS_BASE_ADR + CPSW_STATS_MEM_LIMIT; 402 403 if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) { 404 panic("Unable to request permission to map memory"); 405 } 406 lan8710a_state.regs_cpsw_stats = 407 (vir_bytes)vm_map_phys(SELF, (void *)CPSW_STATS_BASE_ADR, 256); 408 if ((void *)lan8710a_state.regs_cpsw_stats == MAP_FAILED) { 409 panic("lan8710a_state.regs_cpsw_stats: vm_map_phys failed"); 410 } 411 } 412 413 /*============================================================================* 414 * lan8710a_getstat * 415 *============================================================================*/ 416 static void 417 lan8710a_getstat(mp) 418 message *mp; 419 { 420 int r; 421 eth_stat_t stats; 422 423 stats.ets_recvErr = lan8710a_reg_read(CPSW_STAT_RX_CRC_ERR) 424 + lan8710a_reg_read(CPSW_STAT_RX_AGNCD_ERR) 425 + lan8710a_reg_read(CPSW_STAT_RX_OVERSIZE); 426 stats.ets_sendErr = 0; 427 stats.ets_OVW = 0; 428 stats.ets_CRCerr = lan8710a_reg_read(CPSW_STAT_RX_CRC_ERR); 429 stats.ets_frameAll = lan8710a_reg_read(CPSW_STAT_RX_AGNCD_ERR); 430 stats.ets_missedP = 0; 431 stats.ets_packetR = lan8710a_reg_read(CPSW_STAT_RX_GOOD); 432 stats.ets_packetT = lan8710a_reg_read(CPSW_STAT_TX_GOOD); 433 stats.ets_collision = lan8710a_reg_read(CPSW_STAT_COLLISIONS); 434 stats.ets_transAb = 0; 435 stats.ets_carrSense = lan8710a_reg_read(CPSW_STAT_CARR_SENS_ERR); 436 stats.ets_fifoUnder = lan8710a_reg_read(CPSW_STAT_TX_UNDERRUN); 437 stats.ets_fifoOver = lan8710a_reg_read(CPSW_STAT_RX_OVERRUN); 438 stats.ets_CDheartbeat = 0; 439 stats.ets_OWC = 0; 440 441 sys_safecopyto(mp->m_source, mp->m_net_netdrv_dl_getstat_s.grant, 0, 442 (vir_bytes)&stats, sizeof(stats)); 443 mp->m_type = DL_STAT_REPLY; 444 445 if ((r=ipc_send(mp->m_source, mp)) != OK) { 446 panic("lan8710a_getstat: ipc_send() failed: %d", r); 447 } 448 } 449 450 /*============================================================================* 451 * lan8710a_stop * 452 *============================================================================*/ 453 static void 454 lan8710a_stop(void) 455 { 456 /* Reset hardware. */ 457 lan8710a_reset_hw(); 458 459 /* Exit driver. */ 460 exit(EXIT_SUCCESS); 461 } 462 463 /*============================================================================* 464 * lan8710a_dma_config_tx * 465 *============================================================================*/ 466 static void 467 lan8710a_dma_config_tx(desc_idx) 468 u8_t desc_idx; 469 { 470 phys_bytes phys_addr; 471 int i; 472 for (i = 0; i < TX_DMA_CHANNELS; ++i) { 473 if (!lan8710a_reg_read(CPDMA_STRAM_TX_HDP(i))) break; 474 } 475 if (i == TX_DMA_CHANNELS) { 476 panic("There are no free TX DMA channels."); 477 } 478 479 /* Enabling only one channel Tx interrupt */ 480 lan8710a_reg_write(CPDMA_TX_INTMASK_SET, 1 << i); 481 /* Routing only one channel Tx int to TX_PULSE signal */ 482 lan8710a_reg_write(CPSW_WR_C0_TX_EN, 1 << i); 483 484 /* Setting HDP */ 485 phys_addr = lan8710a_state.tx_desc_phy + 486 (desc_idx * sizeof(lan8710a_desc_t)); 487 lan8710a_reg_write(CPDMA_STRAM_TX_HDP(i), (u32_t)phys_addr); 488 } 489 490 /*============================================================================* 491 * lan8710a_dma_reset_init * 492 *============================================================================*/ 493 static void 494 lan8710a_dma_reset_init(void) 495 { 496 int i; 497 lan8710a_reg_write(CPDMA_SOFT_RESET, SOFT_RESET); 498 while ((lan8710a_reg_read(CPDMA_SOFT_RESET) & SOFT_RESET)); 499 500 /* 501 * Initialize the HDPs (Header Description Pointers) and 502 * CPs (Completion Pointers) to NULL. 503 */ 504 for (i = 0; i < DMA_MAX_CHANNELS; ++i) { 505 lan8710a_reg_write(CPDMA_STRAM_TX_HDP(i), 0); 506 lan8710a_reg_write(CPDMA_STRAM_RX_HDP(i), 0); 507 lan8710a_reg_write(CPDMA_STRAM_TX_CP(i), 0); 508 lan8710a_reg_write(CPDMA_STRAM_RX_CP(i), 0); 509 } 510 511 lan8710a_reg_write(CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF); 512 lan8710a_reg_write(CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF); 513 514 /* Configure the CPDMA controller. */ 515 lan8710a_reg_set(CPDMA_RX_CONTROL, CPDMA_RX_EN); /* RX Enabled */ 516 lan8710a_reg_set(CPDMA_TX_CONTROL, CPDMA_TX_EN); /* TX Enabled */ 517 518 /* Enabling first channel Rx interrupt */ 519 lan8710a_reg_set(CPDMA_RX_INTMASK_SET, CPDMA_FIRST_CHAN_INT); 520 521 /* 522 * Writing the address of the first buffer descriptor in the queue 523 * (nonzero value)to the channel�s head descriptor pointer in the 524 * channel�s Rx DMA state. 525 */ 526 lan8710a_reg_write(CPDMA_STRAM_RX_HDP(0), 527 (u32_t)lan8710a_state.rx_desc_phy); 528 529 lan8710a_state.rx_desc_idx = 0; 530 lan8710a_state.tx_desc_idx = 0; 531 } 532 533 /*============================================================================* 534 * lan8710a_init_desc * 535 *============================================================================*/ 536 static void 537 lan8710a_init_desc(void) 538 { 539 lan8710a_desc_t *p_rx_desc; 540 lan8710a_desc_t *p_tx_desc; 541 phys_bytes buf_phys_addr; 542 u8_t *p_buf; 543 u8_t i; 544 545 /* Attempt to allocate. */ 546 if ((lan8710a_state.p_rx_buf = alloc_contig((LAN8710A_NUM_RX_DESC 547 * LAN8710A_IOBUF_SIZE), AC_ALIGN4K, 548 &buf_phys_addr)) == NULL) { 549 panic("failed to allocate RX buffers."); 550 } 551 p_buf = lan8710a_state.p_rx_buf; 552 for (i = 0; i < LAN8710A_NUM_RX_DESC; i++) { 553 p_rx_desc = &(lan8710a_state.rx_desc[i]); 554 memset(p_rx_desc, 0x0, sizeof(lan8710a_desc_t)); 555 p_rx_desc->pkt_len_flags = LAN8710A_DESC_FLAG_OWN; 556 p_rx_desc->buffer_length_off = LAN8710A_IOBUF_SIZE; 557 p_rx_desc->buffer_pointer = (u32_t)(buf_phys_addr + 558 (i * LAN8710A_IOBUF_SIZE)); 559 560 p_rx_desc->next_pointer = 561 (u32_t)((i == (LAN8710A_NUM_RX_DESC - 1)) ? 562 (lan8710a_state.rx_desc_phy) : 563 (lan8710a_state.rx_desc_phy + 564 ((i + 1) * sizeof(lan8710a_desc_t)))); 565 } 566 567 /* Attempt to allocate. */ 568 if ((lan8710a_state.p_tx_buf = alloc_contig((LAN8710A_NUM_TX_DESC 569 * LAN8710A_IOBUF_SIZE), AC_ALIGN4K, 570 &buf_phys_addr)) == NULL) { 571 panic("failed to allocate TX buffers"); 572 } 573 p_buf = lan8710a_state.p_tx_buf; 574 for (i = 0; i < LAN8710A_NUM_TX_DESC; i++) { 575 p_tx_desc = &(lan8710a_state.tx_desc[i]); 576 memset(p_tx_desc, 0x0, sizeof(lan8710a_desc_t)); 577 p_tx_desc->buffer_pointer = (u32_t)(buf_phys_addr + 578 (i * LAN8710A_IOBUF_SIZE)); 579 } 580 lan8710a_state.rx_desc_idx = 0; 581 lan8710a_state.tx_desc_idx = 0; 582 } 583 584 /*============================================================================* 585 * lan8710a_init_hw * 586 *============================================================================*/ 587 static int 588 lan8710a_init_hw(void) 589 { 590 int r, i; 591 592 lan8710a_state.status |= LAN8710A_ENABLED; 593 594 /* 595 * Set the interrupt handler and policy. Do not automatically 596 * re-enable interrupts. Return the IRQ line number on interrupts. 597 */ 598 lan8710a_state.irq_rx_hook = RX_INT; 599 if ((r = sys_irqsetpolicy(LAN8710A_RX_INTR, 0, 600 &lan8710a_state.irq_rx_hook)) != OK) { 601 panic("sys_irqsetpolicy failed: %d", r); 602 } 603 lan8710a_state.irq_tx_hook = TX_INT; 604 if ((r = sys_irqsetpolicy(LAN8710A_TX_INTR, 0, 605 &lan8710a_state.irq_tx_hook)) != OK) { 606 panic("sys_irqsetpolicy failed: %d", r); 607 } 608 609 /* Reset hardware. */ 610 lan8710a_reset_hw(); 611 612 /* 613 * Select the Interface (GMII/RGMII/MII) Mode in the Control Module. 614 * Port1 GMII/MII Mode, Port2 not used. 615 */ 616 lan8710a_reg_write(GMII_SEL, (GMII2_SEL_BIT1 | GMII2_SEL_BIT0)); 617 618 /* 619 * Configure pads (PIN muxing) as per the Interface Selected using the 620 * appropriate pin muxing conf_xxx registers in the Control Module. 621 * 622 * CONF_MOD_SLEW_CTRL when 0 - Fast Mode, when 1 - Slow Mode 623 * CONF_MOD_RX_ACTIVE when 0 - Only output, when 1 - Also input 624 * CONF_MOD_PU_TYPESEL when 0 - Pull-down, when 1 - Pull-up 625 * CONF_MOD_PUDEN when 0 Pull* enabled, when 1 Pull* disabled 626 * CONF_MOD_MMODE_MII selects pin to work for MII interface 627 */ 628 lan8710a_reg_unset(CONF_MII1_COL, CONF_MOD_SLEW_CTRL); 629 lan8710a_reg_set(CONF_MII1_COL, CONF_MOD_RX_ACTIVE); 630 lan8710a_reg_set(CONF_MII1_COL, CONF_MOD_PU_TYPESEL); 631 lan8710a_reg_unset(CONF_MII1_COL, CONF_MOD_PUDEN); 632 lan8710a_reg_unset(CONF_MII1_COL, CONF_MOD_MMODE_MII); 633 634 lan8710a_reg_unset(CONF_MII1_CRS, CONF_MOD_SLEW_CTRL); 635 lan8710a_reg_set(CONF_MII1_CRS, CONF_MOD_RX_ACTIVE); 636 lan8710a_reg_set(CONF_MII1_CRS, CONF_MOD_PU_TYPESEL); 637 lan8710a_reg_unset(CONF_MII1_CRS, CONF_MOD_PUDEN); 638 lan8710a_reg_unset(CONF_MII1_CRS, CONF_MOD_MMODE_MII); 639 640 lan8710a_reg_unset(CONF_MII1_RX_ER, CONF_MOD_SLEW_CTRL); 641 lan8710a_reg_set(CONF_MII1_RX_ER, CONF_MOD_RX_ACTIVE); 642 lan8710a_reg_set(CONF_MII1_RX_ER, CONF_MOD_PU_TYPESEL); 643 lan8710a_reg_unset(CONF_MII1_RX_ER, CONF_MOD_PUDEN); 644 lan8710a_reg_unset(CONF_MII1_RX_ER, CONF_MOD_MMODE_MII); 645 646 lan8710a_reg_unset(CONF_MII1_TX_EN, CONF_MOD_SLEW_CTRL); 647 lan8710a_reg_unset(CONF_MII1_TX_EN, CONF_MOD_RX_ACTIVE); 648 lan8710a_reg_set(CONF_MII1_TX_EN, CONF_MOD_PUDEN); 649 lan8710a_reg_unset(CONF_MII1_TX_EN, CONF_MOD_MMODE_MII); 650 651 lan8710a_reg_unset(CONF_MII1_RX_DV, CONF_MOD_SLEW_CTRL); 652 lan8710a_reg_set(CONF_MII1_RX_DV, CONF_MOD_RX_ACTIVE); 653 lan8710a_reg_set(CONF_MII1_RX_DV, CONF_MOD_PU_TYPESEL); 654 lan8710a_reg_unset(CONF_MII1_RX_DV, CONF_MOD_PUDEN); 655 lan8710a_reg_unset(CONF_MII1_RX_DV, CONF_MOD_MMODE_MII); 656 657 lan8710a_reg_unset(CONF_MII1_TXD3, CONF_MOD_SLEW_CTRL); 658 lan8710a_reg_unset(CONF_MII1_TXD3, CONF_MOD_RX_ACTIVE); 659 lan8710a_reg_set(CONF_MII1_TXD3, CONF_MOD_PUDEN); 660 lan8710a_reg_unset(CONF_MII1_TXD3, CONF_MOD_MMODE_MII); 661 662 lan8710a_reg_unset(CONF_MII1_TXD2, CONF_MOD_SLEW_CTRL); 663 lan8710a_reg_unset(CONF_MII1_TXD2, CONF_MOD_RX_ACTIVE); 664 lan8710a_reg_set(CONF_MII1_TXD2, CONF_MOD_PUDEN); 665 lan8710a_reg_unset(CONF_MII1_TXD2, CONF_MOD_MMODE_MII); 666 667 lan8710a_reg_unset(CONF_MII1_TXD1, CONF_MOD_SLEW_CTRL); 668 lan8710a_reg_unset(CONF_MII1_TXD1, CONF_MOD_RX_ACTIVE); 669 lan8710a_reg_set(CONF_MII1_TXD1, CONF_MOD_PUDEN); 670 lan8710a_reg_unset(CONF_MII1_TXD1, CONF_MOD_MMODE_MII); 671 672 lan8710a_reg_unset(CONF_MII1_TXD0, CONF_MOD_SLEW_CTRL); 673 lan8710a_reg_unset(CONF_MII1_TXD0, CONF_MOD_RX_ACTIVE); 674 lan8710a_reg_set(CONF_MII1_TXD0, CONF_MOD_PUDEN); 675 lan8710a_reg_unset(CONF_MII1_TXD0, CONF_MOD_MMODE_MII); 676 677 lan8710a_reg_unset(CONF_MII1_TX_CLK, CONF_MOD_SLEW_CTRL); 678 lan8710a_reg_set(CONF_MII1_TX_CLK, CONF_MOD_RX_ACTIVE); 679 lan8710a_reg_set(CONF_MII1_TX_CLK, CONF_MOD_PUDEN); 680 lan8710a_reg_unset(CONF_MII1_TX_CLK, CONF_MOD_MMODE_MII); 681 682 lan8710a_reg_unset(CONF_MII1_RX_CLK, CONF_MOD_SLEW_CTRL); 683 lan8710a_reg_set(CONF_MII1_RX_CLK, CONF_MOD_RX_ACTIVE); 684 lan8710a_reg_set(CONF_MII1_RX_CLK, CONF_MOD_PUDEN); 685 lan8710a_reg_unset(CONF_MII1_RX_CLK, CONF_MOD_MMODE_MII); 686 687 lan8710a_reg_unset(CONF_MII1_RXD3, CONF_MOD_SLEW_CTRL); 688 lan8710a_reg_set(CONF_MII1_RXD3, CONF_MOD_RX_ACTIVE); 689 lan8710a_reg_set(CONF_MII1_RXD3, CONF_MOD_PU_TYPESEL); 690 lan8710a_reg_unset(CONF_MII1_RXD3, CONF_MOD_PUDEN); 691 lan8710a_reg_unset(CONF_MII1_RXD3, CONF_MOD_MMODE_MII); 692 693 lan8710a_reg_unset(CONF_MII1_RXD2, CONF_MOD_SLEW_CTRL); 694 lan8710a_reg_set(CONF_MII1_RXD2, CONF_MOD_RX_ACTIVE); 695 lan8710a_reg_set(CONF_MII1_RXD2, CONF_MOD_PU_TYPESEL); 696 lan8710a_reg_unset(CONF_MII1_RXD2, CONF_MOD_PUDEN); 697 lan8710a_reg_unset(CONF_MII1_RXD2, CONF_MOD_MMODE_MII); 698 699 lan8710a_reg_unset(CONF_MII1_RXD1, CONF_MOD_SLEW_CTRL); 700 lan8710a_reg_set(CONF_MII1_RXD1, CONF_MOD_RX_ACTIVE); 701 lan8710a_reg_set(CONF_MII1_RXD1, CONF_MOD_PU_TYPESEL); 702 lan8710a_reg_unset(CONF_MII1_RXD1, CONF_MOD_PUDEN); 703 lan8710a_reg_unset(CONF_MII1_RXD1, CONF_MOD_MMODE_MII); 704 705 lan8710a_reg_unset(CONF_MII1_RXD0, CONF_MOD_SLEW_CTRL); 706 lan8710a_reg_set(CONF_MII1_RXD0, CONF_MOD_RX_ACTIVE); 707 lan8710a_reg_set(CONF_MII1_RXD0, CONF_MOD_PU_TYPESEL); 708 lan8710a_reg_unset(CONF_MII1_RXD0, CONF_MOD_PUDEN); 709 lan8710a_reg_unset(CONF_MII1_RXD0, CONF_MOD_MMODE_MII); 710 711 lan8710a_reg_unset(CONF_MDIO, CONF_MOD_SLEW_CTRL); 712 lan8710a_reg_set(CONF_MDIO, CONF_MOD_RX_ACTIVE); 713 lan8710a_reg_set(CONF_MDIO, CONF_MOD_PU_TYPESEL); 714 lan8710a_reg_unset(CONF_MDIO, CONF_MOD_PUDEN); 715 lan8710a_reg_unset(CONF_MDIO, CONF_MOD_MMODE_MII); 716 717 lan8710a_reg_unset(CONF_MDC, CONF_MOD_SLEW_CTRL); 718 lan8710a_reg_unset(CONF_MDC, CONF_MOD_RX_ACTIVE); 719 lan8710a_reg_set(CONF_MDC, CONF_MOD_PUDEN); 720 lan8710a_reg_unset(CONF_MDC, CONF_MOD_MMODE_MII); 721 722 /* Apply soft reset to 3PSW Subsytem, CPSW_3G, CPGMAC_SL, and CPDMA. */ 723 lan8710a_reg_write(CPSW_SS_SOFT_RESET, SOFT_RESET); 724 lan8710a_reg_write(CPSW_SL_SOFT_RESET(1), SOFT_RESET); 725 lan8710a_reg_write(CPSW_SL_SOFT_RESET(2), SOFT_RESET); 726 727 /* Wait for software resets completion */ 728 while ((lan8710a_reg_read(CPSW_SS_SOFT_RESET) & SOFT_RESET) || 729 (lan8710a_reg_read(CPSW_SL_SOFT_RESET(1)) & SOFT_RESET) || 730 (lan8710a_reg_read(CPSW_SL_SOFT_RESET(2)) & SOFT_RESET)); 731 732 /* Configure the Statistics Port Enable register. */ 733 /* Enable port 0 and 1 statistics. */ 734 lan8710a_reg_write(CPSW_SS_STAT_PORT_EN, (CPSW_P1_STAT_EN | 735 CPSW_P0_STAT_EN)); 736 737 /* 738 * Configure the ALE. 739 * Enabling Ale. 740 * All packets received on ports 1 are 741 * sent to the host (only to the host). 742 */ 743 lan8710a_reg_write(CPSW_ALE_CONTROL, (CPSW_ALE_ENABLE | 744 CPSW_ALE_BYPASS)); 745 /* Port 0 (host) in forwarding mode. */ 746 lan8710a_reg_write(CPSW_ALE_PORTCTL0, CPSW_ALE_PORT_FWD); 747 /* Port 1 in forwarding mode. */ 748 lan8710a_reg_write(CPSW_ALE_PORTCTL1, CPSW_ALE_PORT_FWD); 749 750 /* 751 * Configure CPSW_SL Register 752 * Full duplex mode. 753 */ 754 lan8710a_reg_write(CPSW_SL_MACCONTROL(1), CPSW_SL_FULLDUPLEX); 755 756 /* Initialize MDIO Protocol */ 757 lan8710a_init_mdio(); 758 759 /* Getting MAC Address */ 760 lan8710a_init_addr(); 761 762 /* Initialize descriptors */ 763 lan8710a_init_desc(); 764 765 /* Reset and initialize CPDMA */ 766 lan8710a_dma_reset_init(); 767 768 /* 769 * Configure the Interrupts. 770 * Routing all channel Rx int to RX_PULSE signal. 771 */ 772 lan8710a_reg_set(CPSW_WR_C0_RX_EN, CPSW_FIRST_CHAN_INT); 773 774 /* 775 * Enabling LAN8710A Auto-negotiation 776 */ 777 lan8710a_phy_write(LAN8710A_CTRL_REG, LAN8710A_AUTO_NEG); 778 779 /* Waiting for auto-negotiaion completion. */ 780 for (i = 0; !(lan8710a_phy_read(LAN8710A_STATUS_REG) & 781 LAN8710A_AUTO_NEG_COMPL); ++i) { 782 if (i == 100) { 783 LAN8710A_DEBUG_PRINT(("Autonegotiation failed")); 784 break; 785 } 786 tickdelay(100); 787 } 788 789 /* GMII RX and TX release from reset. */ 790 lan8710a_reg_set(CPSW_SL_MACCONTROL(1), CPSW_SL_GMII_EN); 791 792 /* Enable interrupts. */ 793 lan8710a_enable_interrupt(RX_INT | TX_INT); 794 795 return TRUE; 796 } 797 798 /*============================================================================* 799 * lan8710a_init_mdio * 800 *============================================================================*/ 801 static void 802 lan8710a_init_mdio(void) 803 { 804 u16_t address = 0; 805 u32_t r; 806 807 /* Clearing MDIOCONTROL register */ 808 lan8710a_reg_write(MDIOCONTROL, 0); 809 /* Configure the PREAMBLE and CLKDIV in the MDIO control register */ 810 lan8710a_reg_unset(MDIOCONTROL, MDIO_PREAMBLE); /* CLKDIV default */ 811 /* Enable sending MDIO frame preambles */ 812 lan8710a_reg_set(MDIOCONTROL, (MDCLK_DIVIDER | MDIO_ENABLE)); 813 /* Enable the MDIO module by setting the ENABLE bit in MDIOCONTROL */ 814 815 while (!(r = lan8710a_reg_read(MDIOALIVE))); 816 817 /* Get PHY address */ 818 while (r >>= 1) { 819 ++address; 820 } 821 lan8710a_state.phy_address = address; 822 823 /* Setup appropiate address in MDIOUSERPHYSEL0 */ 824 lan8710a_reg_set(MDIOUSERPHYSEL0, address); 825 } 826 827 /*============================================================================* 828 * lan8710a_writev_s * 829 *============================================================================*/ 830 static void 831 lan8710a_writev_s(mp, from_int) 832 message *mp; 833 int from_int; 834 { 835 iovec_s_t iovec[LAN8710A_IOVEC_NR]; 836 lan8710a_t *e = &lan8710a_state; 837 lan8710a_desc_t *p_tx_desc; 838 u8_t *p_buf; 839 int r, size, buf_data_len, i; 840 841 /* Are we called from the interrupt handler? */ 842 if (!from_int) { 843 /* We cannot write twice simultaneously. */ 844 assert(!(e->status & LAN8710A_WRITING)); 845 846 /* Copy write message. */ 847 e->tx_message = *mp; 848 e->client = mp->m_source; 849 e->status |= LAN8710A_WRITING; 850 851 /* verify vector count */ 852 assert(mp->m_net_netdrv_dl_writev_s.count > 0); 853 assert(mp->m_net_netdrv_dl_writev_s.count < LAN8710A_IOVEC_NR); 854 855 /* 856 * Copy the I/O vector table. 857 */ 858 if ((r = sys_safecopyfrom(mp->m_source, 859 mp->m_net_netdrv_dl_writev_s.grant, 0, 860 (vir_bytes) iovec, 861 mp->m_net_netdrv_dl_writev_s.count * 862 sizeof(iovec_s_t))) != OK) { 863 panic("sys_safecopyfrom() failed: %d", r); 864 } 865 /* setup descriptors */ 866 p_tx_desc = &(e->tx_desc[e->tx_desc_idx]); 867 868 /* 869 * Check if descriptor is available for host 870 * and drop the packet if not. 871 */ 872 if (LAN8710A_DESC_FLAG_OWN & p_tx_desc->pkt_len_flags) { 873 panic("No available transmit descriptor."); 874 } 875 876 /* virtual address of buffer */ 877 p_buf = e->p_tx_buf + e->tx_desc_idx * LAN8710A_IOBUF_SIZE; 878 buf_data_len = 0; 879 for (i = 0; i < mp->m_net_netdrv_dl_writev_s.count; i++) { 880 if ((buf_data_len + iovec[i].iov_size) 881 > LAN8710A_IOBUF_SIZE) { 882 panic("packet too long"); 883 } 884 885 /* copy data to buffer */ 886 size = iovec[i].iov_size 887 < (LAN8710A_IOBUF_SIZE - buf_data_len) ? 888 iovec[i].iov_size 889 : (LAN8710A_IOBUF_SIZE - buf_data_len); 890 891 /* Copy bytes to TX queue buffers. */ 892 if ((r = sys_safecopyfrom(mp->m_source, 893 iovec[i].iov_grant, 0, 894 (vir_bytes) p_buf, size)) != OK) { 895 panic("sys_safecopyfrom() failed: %d", r); 896 } 897 p_buf += size; 898 buf_data_len += size; 899 } 900 901 /* set descriptor length */ 902 p_tx_desc->buffer_length_off = buf_data_len; 903 /* set flags */ 904 p_tx_desc->pkt_len_flags = (LAN8710A_DESC_FLAG_OWN | 905 LAN8710A_DESC_FLAG_SOP | 906 LAN8710A_DESC_FLAG_EOP | 907 TX_DESC_TO_PORT1 | 908 TX_DESC_TO_PORT_EN); 909 p_tx_desc->pkt_len_flags |= buf_data_len; 910 911 /* setup DMA transfer */ 912 lan8710a_dma_config_tx(e->tx_desc_idx); 913 914 e->tx_desc_idx++; 915 if (LAN8710A_NUM_TX_DESC == e->tx_desc_idx) { 916 e->tx_desc_idx = 0; 917 } 918 } else { 919 e->status |= LAN8710A_TRANSMIT; 920 } 921 reply(e); 922 } 923 924 /*============================================================================* 925 * lan8710a_readv_s * 926 *============================================================================*/ 927 static void 928 lan8710a_readv_s(mp, from_int) 929 message *mp; 930 int from_int; 931 { 932 iovec_s_t iovec[LAN8710A_IOVEC_NR]; 933 lan8710a_t *e = &lan8710a_state; 934 lan8710a_desc_t *p_rx_desc; 935 u32_t flags; 936 u8_t *p_buf; 937 u16_t pkt_data_len; 938 u16_t buf_bytes, buf_len; 939 int i, r, size; 940 941 /* Are we called from the interrupt handler? */ 942 if (!from_int) { 943 e->rx_message = *mp; 944 e->client = mp->m_source; 945 e->status |= LAN8710A_READING; 946 e->rx_size = 0; 947 948 assert(e->rx_message.m_net_netdrv_dl_readv_s.count > 0); 949 assert(e->rx_message.m_net_netdrv_dl_readv_s.count < LAN8710A_IOVEC_NR); 950 } 951 if (e->status & LAN8710A_READING) { 952 /* 953 * Copy the I/O vector table first. 954 */ 955 if ((r = sys_safecopyfrom(e->rx_message.m_source, 956 e->rx_message.m_net_netdrv_dl_readv_s.grant, 0, 957 (vir_bytes) iovec, 958 e->rx_message.m_net_netdrv_dl_readv_s.count * 959 sizeof(iovec_s_t))) != OK) { 960 panic("sys_safecopyfrom() failed: %d", r); 961 } 962 963 /* 964 * Only handle one packet at a time. 965 */ 966 p_rx_desc = &(e->rx_desc[e->rx_desc_idx]); 967 /* find next OWN descriptor with SOP flag */ 968 while ((0 == (LAN8710A_DESC_FLAG_SOP & 969 p_rx_desc->pkt_len_flags)) && 970 (0 == (LAN8710A_DESC_FLAG_OWN & 971 p_rx_desc->pkt_len_flags))) { 972 p_rx_desc->buffer_length_off = LAN8710A_IOBUF_SIZE; 973 /* set ownership of current descriptor to EMAC */ 974 p_rx_desc->pkt_len_flags = LAN8710A_DESC_FLAG_OWN; 975 976 e->rx_desc_idx++; 977 if (LAN8710A_NUM_RX_DESC == e->rx_desc_idx) 978 e->rx_desc_idx = 0; 979 p_rx_desc = &(e->rx_desc[e->rx_desc_idx]); 980 } 981 if (0 == (LAN8710A_DESC_FLAG_SOP & p_rx_desc->pkt_len_flags)) { 982 /* SOP was not found */ 983 reply(e); 984 return; 985 } 986 987 /* 988 * Copy to vector elements. 989 */ 990 pkt_data_len = 0; 991 buf_bytes = 0; 992 p_buf = e->p_rx_buf + e->rx_desc_idx * LAN8710A_IOBUF_SIZE; 993 for (i = 0; i < e->rx_message.m_net_netdrv_dl_readv_s.count; i++) { 994 buf_len = p_rx_desc->buffer_length_off & 0xFFFF; 995 if (buf_bytes == buf_len) { 996 /* Whole buffer move to the next descriptor */ 997 p_rx_desc->buffer_length_off = 998 LAN8710A_IOBUF_SIZE; 999 /* set ownership of current desc to EMAC */ 1000 p_rx_desc->pkt_len_flags = 1001 LAN8710A_DESC_FLAG_OWN; 1002 buf_bytes = 0; 1003 1004 e->rx_desc_idx++; 1005 if (LAN8710A_NUM_RX_DESC == e->rx_desc_idx) 1006 e->rx_desc_idx = 0; 1007 p_rx_desc = &(e->rx_desc[e->rx_desc_idx]); 1008 p_buf = e->p_rx_buf + (e->rx_desc_idx * 1009 LAN8710A_IOBUF_SIZE) + 1010 (p_rx_desc->buffer_length_off >> 16); 1011 buf_len = p_rx_desc->buffer_length_off & 0xFFFF; 1012 } 1013 size = iovec[i].iov_size < (buf_len - buf_bytes) ? 1014 iovec[i].iov_size : 1015 (buf_len - buf_bytes); 1016 1017 if ((r = sys_safecopyto(e->rx_message.m_source, 1018 iovec[i].iov_grant, 0, 1019 (vir_bytes) p_buf, 1020 size)) != OK) { 1021 panic("sys_safecopyto() failed: %d", r); 1022 } 1023 p_buf += size; 1024 buf_bytes += size; 1025 pkt_data_len += size; 1026 1027 /* if EOP flag is set -> stop processing */ 1028 if ((LAN8710A_DESC_FLAG_EOP & p_rx_desc->pkt_len_flags) && 1029 (buf_bytes == buf_len)) { 1030 /* end of packet */ 1031 break; 1032 } 1033 } 1034 do { 1035 /* reset owned descriptors up to EOP flag */ 1036 flags = p_rx_desc->pkt_len_flags; 1037 p_rx_desc->buffer_length_off = LAN8710A_IOBUF_SIZE; 1038 /* set ownership of current descriptor to EMAC */ 1039 p_rx_desc->pkt_len_flags = LAN8710A_DESC_FLAG_OWN; 1040 1041 e->rx_desc_idx++; 1042 if (LAN8710A_NUM_RX_DESC == e->rx_desc_idx) 1043 e->rx_desc_idx = 0; 1044 1045 p_rx_desc = &(e->rx_desc[e->rx_desc_idx]); 1046 } 1047 while (0 == (flags & LAN8710A_DESC_FLAG_EOP)); 1048 1049 /* 1050 * Update state. 1051 */ 1052 e->status |= LAN8710A_RECEIVED; 1053 e->rx_size = pkt_data_len; 1054 1055 } 1056 reply(e); 1057 } 1058 1059 /*============================================================================* 1060 * lan8710a_phy_write * 1061 *============================================================================*/ 1062 static void 1063 lan8710a_phy_write(reg, value) 1064 u32_t reg; 1065 u32_t value; 1066 { 1067 if (!(lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO)) { 1068 /* Clearing MDIOUSERACCESS0 register */ 1069 lan8710a_reg_write(MDIOUSERACCESS0, 0); 1070 /* Setting proper values in MDIOUSERACCESS0 */ 1071 lan8710a_reg_set(MDIOUSERACCESS0, MDIO_WRITE); 1072 lan8710a_reg_set(MDIOUSERACCESS0, reg << MDIO_REGADR); 1073 lan8710a_reg_set(MDIOUSERACCESS0, 1074 lan8710a_state.phy_address << MDIO_PHYADR); 1075 /* Data written only 16 bits. */ 1076 lan8710a_reg_set(MDIOUSERACCESS0, (value & 0xFFFF) << MDIO_DATA); 1077 lan8710a_reg_set(MDIOUSERACCESS0, MDIO_GO); 1078 1079 /* Waiting for writing completion */ 1080 while (lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO); 1081 } 1082 } 1083 1084 /*============================================================================* 1085 * lan8710a_phy_read * 1086 *============================================================================*/ 1087 static u32_t 1088 lan8710a_phy_read(reg) 1089 u32_t reg; 1090 { 1091 u32_t value = 0xFFFFFFFF; 1092 1093 if (!(lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO)) { 1094 /* Clearing MDIOUSERACCESS0 register */ 1095 lan8710a_reg_write(MDIOUSERACCESS0, 0); 1096 /* Setting proper values in MDIOUSERACCESS0 */ 1097 lan8710a_reg_unset(MDIOUSERACCESS0, MDIO_WRITE); 1098 /* Reg number must be 5 bit long */ 1099 lan8710a_reg_set(MDIOUSERACCESS0, (reg & 0x1F) << MDIO_REGADR); 1100 /* Addr must be 5 bit long */ 1101 lan8710a_reg_set(MDIOUSERACCESS0, 1102 (lan8710a_state.phy_address & 0x1F) << MDIO_PHYADR); 1103 lan8710a_reg_set(MDIOUSERACCESS0, MDIO_GO); 1104 1105 /* Waiting for reading completion */ 1106 while ((lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO) 1107 && !(lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_ACK)); 1108 1109 /* Reading data */ 1110 value = lan8710a_reg_read(MDIOUSERACCESS0) & 0xFFFF; 1111 } 1112 return value; 1113 } 1114 1115 /*============================================================================* 1116 * lan8710a_reset_hw * 1117 *============================================================================*/ 1118 static void 1119 lan8710a_reset_hw() 1120 { 1121 /* Assert a Device Reset signal. */ 1122 lan8710a_phy_write(LAN8710A_CTRL_REG, LAN8710A_SOFT_RESET); 1123 1124 /* Waiting for reset completion. */ 1125 while (lan8710a_phy_read(LAN8710A_CTRL_REG) & LAN8710A_SOFT_RESET); 1126 } 1127 1128 /*============================================================================* 1129 * lan8710a_reg_read * 1130 *============================================================================*/ 1131 static u32_t 1132 lan8710a_reg_read(reg) 1133 volatile u32_t *reg; 1134 { 1135 u32_t value; 1136 1137 /* Read from memory mapped register. */ 1138 value = *reg; 1139 1140 /* Return the result. */ 1141 return value; 1142 } 1143 1144 /*============================================================================* 1145 * lan8710a_reg_write * 1146 *============================================================================*/ 1147 static void 1148 lan8710a_reg_write(reg, value) 1149 volatile u32_t *reg; 1150 u32_t value; 1151 { 1152 /* Write to memory mapped register. */ 1153 *reg = value; 1154 } 1155 1156 /*============================================================================* 1157 * lan8710a_reg_set * 1158 *============================================================================*/ 1159 static void 1160 lan8710a_reg_set(reg, value) 1161 volatile u32_t *reg; 1162 u32_t value; 1163 { 1164 u32_t data; 1165 1166 /* First read the current value. */ 1167 data = lan8710a_reg_read(reg); 1168 1169 /* Set value, and write back. */ 1170 lan8710a_reg_write(reg, data | value); 1171 } 1172 1173 /*============================================================================* 1174 * lan8710a_reg_unset * 1175 *============================================================================*/ 1176 static void 1177 lan8710a_reg_unset(reg, value) 1178 volatile u32_t *reg; 1179 u32_t value; 1180 { 1181 u32_t data; 1182 1183 /* First read the current value. */ 1184 data = lan8710a_reg_read(reg); 1185 1186 /* Unset value, and write back. */ 1187 lan8710a_reg_write(reg, data & ~value); 1188 } 1189 1190 /*============================================================================* 1191 * mess_reply * 1192 *============================================================================*/ 1193 static void 1194 mess_reply(req, reply) 1195 message *req;message *reply; 1196 { 1197 if (ipc_send(req->m_source, reply) != OK) { 1198 panic("unable to send reply message"); 1199 } 1200 } 1201 1202 /*============================================================================* 1203 * reply * 1204 *============================================================================*/ 1205 static void 1206 reply(e) 1207 lan8710a_t *e; 1208 { 1209 message msg; 1210 int r; 1211 1212 /* Only reply to client for read/write request. */ 1213 if (!(e->status & LAN8710A_READING || 1214 e->status & LAN8710A_WRITING)) { 1215 return; 1216 } 1217 /* Construct reply message. */ 1218 msg.m_type = DL_TASK_REPLY; 1219 msg.m_netdrv_net_dl_task.flags = DL_NOFLAGS; 1220 msg.m_netdrv_net_dl_task.count = 0; 1221 1222 /* Did we successfully receive packet(s)? */ 1223 if (e->status & LAN8710A_READING && 1224 e->status & LAN8710A_RECEIVED) { 1225 msg.m_netdrv_net_dl_task.flags |= DL_PACK_RECV; 1226 msg.m_netdrv_net_dl_task.count = 1227 e->rx_size >= ETH_MIN_PACK_SIZE ? 1228 e->rx_size : ETH_MIN_PACK_SIZE; 1229 1230 /* Clear flags. */ 1231 e->status &= ~(LAN8710A_READING | LAN8710A_RECEIVED); 1232 } 1233 /* Did we successfully transmit packet(s)? */ 1234 if (e->status & LAN8710A_TRANSMIT && 1235 e->status & LAN8710A_WRITING) { 1236 msg.m_netdrv_net_dl_task.flags |= DL_PACK_SEND; 1237 1238 /* Clear flags. */ 1239 e->status &= ~(LAN8710A_WRITING | LAN8710A_TRANSMIT); 1240 } 1241 1242 /* Acknowledge to INET. */ 1243 if ((r = ipc_send(e->client, &msg) != OK)) { 1244 panic("ipc_send() failed: %d", r); 1245 } 1246 } 1247