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