1 /* Blackfin Ethernet Media Access Controller (EMAC) model. 2 3 Copyright (C) 2010-2024 Free Software Foundation, Inc. 4 Contributed by Analog Devices, Inc. 5 6 This file is part of simulators. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21 /* This must come before any other includes. */ 22 #include "defs.h" 23 24 #include <errno.h> 25 #include <fcntl.h> 26 #include <unistd.h> 27 28 #ifdef HAVE_SYS_IOCTL_H 29 #include <sys/ioctl.h> 30 #endif 31 #ifdef HAVE_NET_IF_H 32 #include <net/if.h> 33 #endif 34 #ifdef HAVE_LINUX_IF_TUN_H 35 #include <linux/if_tun.h> 36 #endif 37 38 #ifdef HAVE_LINUX_IF_TUN_H 39 # define WITH_TUN 1 40 #else 41 # define WITH_TUN 0 42 #endif 43 44 #include "sim-main.h" 45 #include "sim-hw.h" 46 #include "devices.h" 47 #include "dv-bfin_emac.h" 48 49 /* XXX: This doesn't support partial DMA transfers. */ 50 /* XXX: The TUN pieces should be pushed to the PHY so that we work with 51 multiple "networks" and the PHY takes care of it. */ 52 53 struct bfin_emac 54 { 55 /* This top portion matches common dv_bfin struct. */ 56 bu32 base; 57 struct hw *dma_master; 58 bool acked; 59 60 int tap; 61 #if WITH_TUN 62 struct ifreq ifr; 63 #endif 64 bu32 rx_crc; 65 66 /* Order after here is important -- matches hardware MMR layout. */ 67 bu32 opmode, addrlo, addrhi, hashlo, hashhi, staadd, stadat, flc, vlan1, vlan2; 68 bu32 _pad0; 69 bu32 wkup_ctl, wkup_ffmsk0, wkup_ffmsk1, wkup_ffmsk2, wkup_ffmsk3; 70 bu32 wkup_ffcmd, wkup_ffoff, wkup_ffcrc0, wkup_ffcrc1; 71 bu32 _pad1[4]; 72 bu32 sysctl, systat, rx_stat, rx_stky, rx_irqe, tx_stat, tx_stky, tx_irqe; 73 bu32 mmc_ctl, mmc_rirqs, mmc_rirqe, mmc_tirqs, mmc_tirqe; 74 bu32 _pad2[3]; 75 bu16 BFIN_MMR_16(ptp_ctl); 76 bu16 BFIN_MMR_16(ptp_ie); 77 bu16 BFIN_MMR_16(ptp_istat); 78 bu32 ptp_foff, ptp_fv1, ptp_fv2, ptp_fv3, ptp_addend, ptp_accr, ptp_offset; 79 bu32 ptp_timelo, ptp_timehi, ptp_rxsnaplo, ptp_rxsnaphi, ptp_txsnaplo; 80 bu32 ptp_txsnaphi, ptp_alarmlo, ptp_alarmhi, ptp_id_off, ptp_id_snap; 81 bu32 ptp_pps_startlo, ptp_pps_starthi, ptp_pps_period; 82 bu32 _pad3[1]; 83 bu32 rxc_ok, rxc_fcs, rxc_lign, rxc_octet, rxc_dmaovf, rxc_unicst, rxc_multi; 84 bu32 rxc_broad, rxc_lnerri, rxc_lnerro, rxc_long, rxc_macctl, rxc_opcode; 85 bu32 rxc_pause, rxc_allfrm, rxc_alloct, rxc_typed, rxc_short, rxc_eq64; 86 bu32 rxc_lt128, rxc_lt256, rxc_lt512, rxc_lt1024, rxc_ge1024; 87 bu32 _pad4[8]; 88 bu32 txc_ok, txc_1col, txc_gt1col, txc_octet, txc_defer, txc_latecl; 89 bu32 txc_xs_col, txc_dmaund, txc_crserr, txc_unicst, txc_multi, txc_broad; 90 bu32 txc_xs_dfr, txc_macctl, txc_allfrm, txc_alloct, txc_eq64, txc_lt128; 91 bu32 txc_lt256, txc_lt512, txc_lt1024, txc_ge1024, txc_abort; 92 }; 93 #define mmr_base() offsetof(struct bfin_emac, opmode) 94 #define mmr_offset(mmr) (offsetof(struct bfin_emac, mmr) - mmr_base()) 95 #define mmr_idx(mmr) (mmr_offset (mmr) / 4) 96 97 static const char * const mmr_names[BFIN_MMR_EMAC_SIZE / 4] = 98 { 99 "EMAC_OPMODE", "EMAC_ADDRLO", "EMAC_ADDRHI", "EMAC_HASHLO", "EMAC_HASHHI", 100 "EMAC_STAADD", "EMAC_STADAT", "EMAC_FLC", "EMAC_VLAN1", "EMAC_VLAN2", NULL, 101 "EMAC_WKUP_CTL", "EMAC_WKUP_FFMSK0", "EMAC_WKUP_FFMSK1", "EMAC_WKUP_FFMSK2", 102 "EMAC_WKUP_FFMSK3", "EMAC_WKUP_FFCMD", "EMAC_WKUP_FFOFF", "EMAC_WKUP_FFCRC0", 103 "EMAC_WKUP_FFCRC1", [mmr_idx (sysctl)] = "EMAC_SYSCTL", "EMAC_SYSTAT", 104 "EMAC_RX_STAT", "EMAC_RX_STKY", "EMAC_RX_IRQE", "EMAC_TX_STAT", 105 "EMAC_TX_STKY", "EMAC_TX_IRQE", "EMAC_MMC_CTL", "EMAC_MMC_RIRQS", 106 "EMAC_MMC_RIRQE", "EMAC_MMC_TIRQS", "EMAC_MMC_TIRQE", 107 [mmr_idx (ptp_ctl)] = "EMAC_PTP_CTL", "EMAC_PTP_IE", "EMAC_PTP_ISTAT", 108 "EMAC_PTP_FOFF", "EMAC_PTP_FV1", "EMAC_PTP_FV2", "EMAC_PTP_FV3", 109 "EMAC_PTP_ADDEND", "EMAC_PTP_ACCR", "EMAC_PTP_OFFSET", "EMAC_PTP_TIMELO", 110 "EMAC_PTP_TIMEHI", "EMAC_PTP_RXSNAPLO", "EMAC_PTP_RXSNAPHI", 111 "EMAC_PTP_TXSNAPLO", "EMAC_PTP_TXSNAPHI", "EMAC_PTP_ALARMLO", 112 "EMAC_PTP_ALARMHI", "EMAC_PTP_ID_OFF", "EMAC_PTP_ID_SNAP", 113 "EMAC_PTP_PPS_STARTLO", "EMAC_PTP_PPS_STARTHI", "EMAC_PTP_PPS_PERIOD", 114 [mmr_idx (rxc_ok)] = "EMAC_RXC_OK", "EMAC_RXC_FCS", "EMAC_RXC_LIGN", 115 "EMAC_RXC_OCTET", "EMAC_RXC_DMAOVF", "EMAC_RXC_UNICST", "EMAC_RXC_MULTI", 116 "EMAC_RXC_BROAD", "EMAC_RXC_LNERRI", "EMAC_RXC_LNERRO", "EMAC_RXC_LONG", 117 "EMAC_RXC_MACCTL", "EMAC_RXC_OPCODE", "EMAC_RXC_PAUSE", "EMAC_RXC_ALLFRM", 118 "EMAC_RXC_ALLOCT", "EMAC_RXC_TYPED", "EMAC_RXC_SHORT", "EMAC_RXC_EQ64", 119 "EMAC_RXC_LT128", "EMAC_RXC_LT256", "EMAC_RXC_LT512", "EMAC_RXC_LT1024", 120 "EMAC_RXC_GE1024", 121 [mmr_idx (txc_ok)] = "EMAC_TXC_OK", "EMAC_TXC_1COL", "EMAC_TXC_GT1COL", 122 "EMAC_TXC_OCTET", "EMAC_TXC_DEFER", "EMAC_TXC_LATECL", "EMAC_TXC_XS_COL", 123 "EMAC_TXC_DMAUND", "EMAC_TXC_CRSERR", "EMAC_TXC_UNICST", "EMAC_TXC_MULTI", 124 "EMAC_TXC_BROAD", "EMAC_TXC_XS_DFR", "EMAC_TXC_MACCTL", "EMAC_TXC_ALLFRM", 125 "EMAC_TXC_ALLOCT", "EMAC_TXC_EQ64", "EMAC_TXC_LT128", "EMAC_TXC_LT256", 126 "EMAC_TXC_LT512", "EMAC_TXC_LT1024", "EMAC_TXC_GE1024", "EMAC_TXC_ABORT", 127 }; 128 #define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>") 129 130 static struct hw * 131 mii_find_phy (struct hw *me, bu8 addr) 132 { 133 struct hw *phy = hw_child (me); 134 while (phy && --addr) 135 phy = hw_sibling (phy); 136 return phy; 137 } 138 139 static void 140 mii_write (struct hw *me) 141 { 142 SIM_DESC sd = hw_system (me); 143 struct bfin_emac *emac = hw_data (me); 144 struct hw *phy; 145 bu8 addr = PHYAD (emac->staadd); 146 bu8 reg = REGAD (emac->staadd); 147 bu16 data = emac->stadat; 148 149 phy = mii_find_phy (me, addr); 150 if (!phy) 151 return; 152 sim_hw_io_write_buffer (sd, phy, &data, 1, reg, 2); 153 } 154 155 static void 156 mii_read (struct hw *me) 157 { 158 SIM_DESC sd = hw_system (me); 159 struct bfin_emac *emac = hw_data (me); 160 struct hw *phy; 161 bu8 addr = PHYAD (emac->staadd); 162 bu8 reg = REGAD (emac->staadd); 163 bu16 data; 164 165 phy = mii_find_phy (me, addr); 166 if (!phy || sim_hw_io_read_buffer (sd, phy, &data, 1, reg, 2) != 2) 167 data = 0xffff; 168 169 emac->stadat = data; 170 } 171 172 static unsigned 173 bfin_emac_io_write_buffer (struct hw *me, const void *source, 174 int space, address_word addr, unsigned nr_bytes) 175 { 176 struct bfin_emac *emac = hw_data (me); 177 bu32 mmr_off; 178 bu32 value; 179 bu32 *valuep; 180 181 /* Invalid access mode is higher priority than missing register. */ 182 /* XXX: 16bit accesses are allowed ... */ 183 if (!dv_bfin_mmr_require_32 (me, addr, nr_bytes, true)) 184 return 0; 185 value = dv_load_4 (source); 186 187 mmr_off = addr - emac->base; 188 valuep = (void *)((uintptr_t)emac + mmr_base() + mmr_off); 189 190 HW_TRACE_WRITE (); 191 192 switch (mmr_off) 193 { 194 case mmr_offset(hashlo): 195 case mmr_offset(hashhi): 196 case mmr_offset(stadat): 197 case mmr_offset(flc): 198 case mmr_offset(vlan1): 199 case mmr_offset(vlan2): 200 case mmr_offset(wkup_ffmsk0): 201 case mmr_offset(wkup_ffmsk1): 202 case mmr_offset(wkup_ffmsk2): 203 case mmr_offset(wkup_ffmsk3): 204 case mmr_offset(wkup_ffcmd): 205 case mmr_offset(wkup_ffoff): 206 case mmr_offset(wkup_ffcrc0): 207 case mmr_offset(wkup_ffcrc1): 208 case mmr_offset(sysctl): 209 case mmr_offset(rx_irqe): 210 case mmr_offset(tx_irqe): 211 case mmr_offset(mmc_rirqe): 212 case mmr_offset(mmc_tirqe): 213 *valuep = value; 214 break; 215 case mmr_offset(opmode): 216 if (!(*valuep & RE) && (value & RE)) 217 emac->rx_stat &= ~RX_COMP; 218 if (!(*valuep & TE) && (value & TE)) 219 emac->tx_stat &= ~TX_COMP; 220 *valuep = value; 221 break; 222 case mmr_offset(addrlo): 223 case mmr_offset(addrhi): 224 *valuep = value; 225 break; 226 case mmr_offset(wkup_ctl): 227 dv_w1c_4_partial (valuep, value, 0xf20); 228 break; 229 case mmr_offset(systat): 230 dv_w1c_4 (valuep, value, 0xe1); 231 break; 232 case mmr_offset(staadd): 233 *valuep = value | STABUSY; 234 if (value & STAOP) 235 mii_write (me); 236 else 237 mii_read (me); 238 *valuep &= ~STABUSY; 239 break; 240 case mmr_offset(rx_stat): 241 case mmr_offset(tx_stat): 242 /* Discard writes to these. */ 243 break; 244 case mmr_offset(rx_stky): 245 case mmr_offset(tx_stky): 246 case mmr_offset(mmc_rirqs): 247 case mmr_offset(mmc_tirqs): 248 dv_w1c_4 (valuep, value, -1); 249 break; 250 case mmr_offset(mmc_ctl): 251 /* Writing to bit 0 clears all counters. */ 252 *valuep = value & ~1; 253 if (value & 1) 254 { 255 memset (&emac->rxc_ok, 0, mmr_offset (rxc_ge1024) - mmr_offset (rxc_ok) + 4); 256 memset (&emac->txc_ok, 0, mmr_offset (txc_abort) - mmr_offset (txc_ok) + 4); 257 } 258 break; 259 case mmr_offset(rxc_ok) ... mmr_offset(rxc_ge1024): 260 case mmr_offset(txc_ok) ... mmr_offset(txc_abort): 261 /* XXX: Are these supposed to be read-only ? */ 262 *valuep = value; 263 break; 264 case mmr_offset(ptp_ctl) ... mmr_offset(ptp_pps_period): 265 /* XXX: Only on some models; ignore for now. */ 266 break; 267 default: 268 dv_bfin_mmr_invalid (me, addr, nr_bytes, true); 269 return 0; 270 } 271 272 return nr_bytes; 273 } 274 275 static unsigned 276 bfin_emac_io_read_buffer (struct hw *me, void *dest, 277 int space, address_word addr, unsigned nr_bytes) 278 { 279 struct bfin_emac *emac = hw_data (me); 280 bu32 mmr_off; 281 bu32 *valuep; 282 283 /* Invalid access mode is higher priority than missing register. */ 284 /* XXX: 16bit accesses are allowed ... */ 285 if (!dv_bfin_mmr_require_32 (me, addr, nr_bytes, false)) 286 return 0; 287 288 mmr_off = addr - emac->base; 289 valuep = (void *)((uintptr_t)emac + mmr_base() + mmr_off); 290 291 HW_TRACE_READ (); 292 293 switch (mmr_off) 294 { 295 case mmr_offset(opmode): 296 case mmr_offset(addrlo): 297 case mmr_offset(addrhi): 298 case mmr_offset(hashlo): 299 case mmr_offset(hashhi): 300 case mmr_offset(staadd): 301 case mmr_offset(stadat): 302 case mmr_offset(flc): 303 case mmr_offset(vlan1): 304 case mmr_offset(vlan2): 305 case mmr_offset(wkup_ctl): 306 case mmr_offset(wkup_ffmsk0): 307 case mmr_offset(wkup_ffmsk1): 308 case mmr_offset(wkup_ffmsk2): 309 case mmr_offset(wkup_ffmsk3): 310 case mmr_offset(wkup_ffcmd): 311 case mmr_offset(wkup_ffoff): 312 case mmr_offset(wkup_ffcrc0): 313 case mmr_offset(wkup_ffcrc1): 314 case mmr_offset(sysctl): 315 case mmr_offset(systat): 316 case mmr_offset(rx_stat): 317 case mmr_offset(rx_stky): 318 case mmr_offset(rx_irqe): 319 case mmr_offset(tx_stat): 320 case mmr_offset(tx_stky): 321 case mmr_offset(tx_irqe): 322 case mmr_offset(mmc_rirqs): 323 case mmr_offset(mmc_rirqe): 324 case mmr_offset(mmc_tirqs): 325 case mmr_offset(mmc_tirqe): 326 case mmr_offset(mmc_ctl): 327 case mmr_offset(rxc_ok) ... mmr_offset(rxc_ge1024): 328 case mmr_offset(txc_ok) ... mmr_offset(txc_abort): 329 dv_store_4 (dest, *valuep); 330 break; 331 case mmr_offset(ptp_ctl) ... mmr_offset(ptp_pps_period): 332 /* XXX: Only on some models; ignore for now. */ 333 break; 334 default: 335 dv_bfin_mmr_invalid (me, addr, nr_bytes, false); 336 return 0; 337 } 338 339 return nr_bytes; 340 } 341 342 static void 343 attach_bfin_emac_regs (struct hw *me, struct bfin_emac *emac) 344 { 345 address_word attach_address; 346 int attach_space; 347 unsigned attach_size; 348 reg_property_spec reg; 349 350 if (hw_find_property (me, "reg") == NULL) 351 hw_abort (me, "Missing \"reg\" property"); 352 353 if (!hw_find_reg_array_property (me, "reg", 0, ®)) 354 hw_abort (me, "\"reg\" property must contain three addr/size entries"); 355 356 hw_unit_address_to_attach_address (hw_parent (me), 357 ®.address, 358 &attach_space, &attach_address, me); 359 hw_unit_size_to_attach_size (hw_parent (me), ®.size, &attach_size, me); 360 361 if (attach_size != BFIN_MMR_EMAC_SIZE) 362 hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_EMAC_SIZE); 363 364 hw_attach_address (hw_parent (me), 365 0, attach_space, attach_address, attach_size, me); 366 367 emac->base = attach_address; 368 } 369 370 static struct dv_bfin *dma_tx; 371 372 static unsigned 373 bfin_emac_dma_read_buffer (struct hw *me, void *dest, int space, 374 unsigned_word addr, unsigned nr_bytes) 375 { 376 struct bfin_emac *emac = hw_data (me); 377 struct dv_bfin *dma = hw_data (emac->dma_master); 378 unsigned char *data = dest; 379 static bool flop; /* XXX: This sucks. */ 380 bu16 len; 381 ssize_t ret; 382 383 HW_TRACE_DMA_READ (); 384 385 if (dma_tx == dma) 386 { 387 /* Handle the TX turn around and write the status. */ 388 emac->tx_stat |= TX_OK; 389 emac->tx_stky |= TX_OK; 390 391 memcpy (data, &emac->tx_stat, 4); 392 393 dma->acked = true; 394 return 4; 395 } 396 397 if (!(emac->opmode & RE)) 398 return 0; 399 400 if (!flop) 401 { 402 ssize_t pad_ret; 403 /* Outgoing DMA buffer has 16bit len prepended to it. */ 404 data += 2; 405 406 /* This doesn't seem to work. 407 if (emac->sysctl & RXDWA) 408 { 409 memset (data, 0, 2); 410 data += 2; 411 } */ 412 413 ret = read (emac->tap, data, nr_bytes); 414 if (ret < 0) 415 return 0; 416 ret += 4; /* include crc */ 417 pad_ret = max (ret + 4, 64); 418 len = pad_ret; 419 memcpy (dest, &len, 2); 420 421 pad_ret = (pad_ret + 3) & ~3; 422 if (ret < pad_ret) 423 memset (data + ret, 0, pad_ret - ret); 424 pad_ret += 4; 425 426 /* XXX: Need to check -- u-boot doesn't look at this. */ 427 if (emac->sysctl & RXCKS) 428 { 429 pad_ret += 4; 430 emac->rx_crc = 0; 431 } 432 ret = pad_ret; 433 434 /* XXX: Don't support promiscuous yet. */ 435 emac->rx_stat |= RX_ACCEPT; 436 emac->rx_stat = (emac->rx_stat & ~RX_FRLEN) | len; 437 438 emac->rx_stat |= RX_COMP; 439 emac->rx_stky |= RX_COMP; 440 } 441 else 442 { 443 /* Write the RX status and crc info. */ 444 emac->rx_stat |= RX_OK; 445 emac->rx_stky |= RX_OK; 446 447 ret = 4; 448 if (emac->sysctl & RXCKS) 449 { 450 memcpy (data, &emac->rx_crc, 4); 451 data += 4; 452 ret += 4; 453 } 454 memcpy (data, &emac->rx_stat, 4); 455 } 456 457 flop = !flop; 458 dma->acked = true; 459 return ret; 460 } 461 462 static unsigned 463 bfin_emac_dma_write_buffer (struct hw *me, const void *source, 464 int space, unsigned_word addr, 465 unsigned nr_bytes, 466 int violate_read_only_section) 467 { 468 struct bfin_emac *emac = hw_data (me); 469 struct dv_bfin *dma = hw_data (emac->dma_master); 470 const unsigned char *data = source; 471 bu16 len; 472 ssize_t ret; 473 474 HW_TRACE_DMA_WRITE (); 475 476 if (!(emac->opmode & TE)) 477 return 0; 478 479 /* Incoming DMA buffer has 16bit len prepended to it. */ 480 memcpy (&len, data, 2); 481 if (!len) 482 return 0; 483 484 ret = write (emac->tap, data + 2, len); 485 if (ret < 0) 486 return 0; 487 ret += 2; 488 489 emac->tx_stat |= TX_COMP; 490 emac->tx_stky |= TX_COMP; 491 492 dma_tx = dma; 493 dma->acked = true; 494 return ret; 495 } 496 497 static const struct hw_port_descriptor bfin_emac_ports[] = 498 { 499 { "tx", DV_PORT_TX, 0, output_port, }, 500 { "rx", DV_PORT_RX, 0, output_port, }, 501 { "stat", DV_PORT_STAT, 0, output_port, }, 502 { NULL, 0, 0, 0, }, 503 }; 504 505 static void 506 bfin_emac_attach_address_callback (struct hw *me, 507 int level, 508 int space, 509 address_word addr, 510 address_word nr_bytes, 511 struct hw *client) 512 { 513 const hw_unit *unit = hw_unit_address (client); 514 HW_TRACE ((me, "attach - level=%d, space=%d, addr=0x%lx, nr_bytes=%lu, client=%s", 515 level, space, (unsigned long) addr, (unsigned long) nr_bytes, hw_path (client))); 516 /* NOTE: At preset the space is assumed to be zero. Perhaphs the 517 space should be mapped onto something for instance: space0 - 518 unified memory; space1 - IO memory; ... */ 519 sim_core_attach (hw_system (me), 520 NULL, /*cpu*/ 521 level + 10 + unit->cells[unit->nr_cells - 1], 522 access_read_write_exec, 523 space, addr, 524 nr_bytes, 525 0, /* modulo */ 526 client, 527 NULL); 528 } 529 530 static void 531 bfin_emac_delete (struct hw *me) 532 { 533 struct bfin_emac *emac = hw_data (me); 534 close (emac->tap); 535 } 536 537 static void 538 bfin_emac_tap_init (struct hw *me) 539 { 540 #if WITH_TUN 541 struct bfin_emac *emac = hw_data (me); 542 int flags; 543 544 emac->tap = open ("/dev/net/tun", O_RDWR); 545 if (emac->tap == -1) 546 { 547 HW_TRACE ((me, "unable to open /dev/net/tun: %s", strerror (errno))); 548 return; 549 } 550 551 memset (&emac->ifr, 0, sizeof (emac->ifr)); 552 emac->ifr.ifr_flags = IFF_TAP | IFF_NO_PI; 553 strcpy (emac->ifr.ifr_name, "tap-gdb"); 554 555 flags = 1 * 1024 * 1024; 556 if (ioctl (emac->tap, TUNSETIFF, &emac->ifr) < 0 557 #ifdef TUNSETNOCSUM 558 || ioctl (emac->tap, TUNSETNOCSUM) < 0 559 #endif 560 #ifdef TUNSETSNDBUF 561 || ioctl (emac->tap, TUNSETSNDBUF, &flags) < 0 562 #endif 563 ) 564 { 565 HW_TRACE ((me, "tap ioctl setup failed: %s", strerror (errno))); 566 close (emac->tap); 567 return; 568 } 569 570 flags = fcntl (emac->tap, F_GETFL); 571 fcntl (emac->tap, F_SETFL, flags | O_NONBLOCK); 572 #endif 573 } 574 575 static void 576 bfin_emac_finish (struct hw *me) 577 { 578 struct bfin_emac *emac; 579 580 emac = HW_ZALLOC (me, struct bfin_emac); 581 582 set_hw_data (me, emac); 583 set_hw_io_read_buffer (me, bfin_emac_io_read_buffer); 584 set_hw_io_write_buffer (me, bfin_emac_io_write_buffer); 585 set_hw_dma_read_buffer (me, bfin_emac_dma_read_buffer); 586 set_hw_dma_write_buffer (me, bfin_emac_dma_write_buffer); 587 set_hw_ports (me, bfin_emac_ports); 588 set_hw_attach_address (me, bfin_emac_attach_address_callback); 589 set_hw_delete (me, bfin_emac_delete); 590 591 attach_bfin_emac_regs (me, emac); 592 593 /* Initialize the EMAC. */ 594 emac->addrlo = 0xffffffff; 595 emac->addrhi = 0x0000ffff; 596 emac->vlan1 = 0x0000ffff; 597 emac->vlan2 = 0x0000ffff; 598 emac->sysctl = 0x00003f00; 599 emac->mmc_ctl = 0x0000000a; 600 601 bfin_emac_tap_init (me); 602 } 603 604 const struct hw_descriptor dv_bfin_emac_descriptor[] = 605 { 606 {"bfin_emac", bfin_emac_finish,}, 607 {NULL, NULL}, 608 }; 609