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