1 /* Blackfin Ethernet Media Access Controller (EMAC) model.
3 Copyright (C) 2010-2014 Free Software Foundation, Inc.
4 Contributed by Analog Devices, Inc.
6 This file is part of simulators.
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.
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.
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/>. */
27 #ifdef HAVE_SYS_IOCTL_H
28 #include <sys/ioctl.h>
33 #ifdef HAVE_LINUX_IF_TUN_H
34 #include <linux/if_tun.h>
37 #ifdef HAVE_LINUX_IF_TUN_H
46 #include "dv-bfin_emac.h"
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. */
54 /* This top portion matches common dv_bfin struct. */
56 struct hw
*dma_master
;
65 /* Order after here is important -- matches hardware MMR layout. */
66 bu32 opmode
, addrlo
, addrhi
, hashlo
, hashhi
, staadd
, stadat
, flc
, vlan1
, vlan2
;
68 bu32 wkup_ctl
, wkup_ffmsk0
, wkup_ffmsk1
, wkup_ffmsk2
, wkup_ffmsk3
;
69 bu32 wkup_ffcmd
, wkup_ffoff
, wkup_ffcrc0
, wkup_ffcrc1
;
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
;
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
;
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
;
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
;
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)
96 static const char * const mmr_names
[BFIN_MMR_EMAC_SIZE
/ 4] =
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",
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",
127 #define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
130 mii_find_phy (struct hw
*me
, bu8 addr
)
132 struct hw
*phy
= hw_child (me
);
133 while (phy
&& --addr
)
134 phy
= hw_sibling (phy
);
139 mii_write (struct hw
*me
)
141 SIM_DESC sd
= hw_system (me
);
142 struct bfin_emac
*emac
= hw_data (me
);
144 bu8 addr
= PHYAD (emac
->staadd
);
145 bu8 reg
= REGAD (emac
->staadd
);
146 bu16 data
= emac
->stadat
;
148 phy
= mii_find_phy (me
, addr
);
151 sim_hw_io_write_buffer (sd
, phy
, &data
, 1, reg
, 2);
155 mii_read (struct hw
*me
)
157 SIM_DESC sd
= hw_system (me
);
158 struct bfin_emac
*emac
= hw_data (me
);
160 bu8 addr
= PHYAD (emac
->staadd
);
161 bu8 reg
= REGAD (emac
->staadd
);
164 phy
= mii_find_phy (me
, addr
);
165 if (!phy
|| sim_hw_io_read_buffer (sd
, phy
, &data
, 1, reg
, 2) != 2)
172 bfin_emac_io_write_buffer (struct hw
*me
, const void *source
,
173 int space
, address_word addr
, unsigned nr_bytes
)
175 struct bfin_emac
*emac
= hw_data (me
);
180 /* XXX: 16bit accesses are allowed ... */
181 dv_bfin_mmr_require_32 (me
, addr
, nr_bytes
, true);
182 value
= dv_load_4 (source
);
184 mmr_off
= addr
- emac
->base
;
185 valuep
= (void *)((unsigned long)emac
+ mmr_base() + mmr_off
);
191 case mmr_offset(hashlo
):
192 case mmr_offset(hashhi
):
193 case mmr_offset(stadat
):
194 case mmr_offset(flc
):
195 case mmr_offset(vlan1
):
196 case mmr_offset(vlan2
):
197 case mmr_offset(wkup_ffmsk0
):
198 case mmr_offset(wkup_ffmsk1
):
199 case mmr_offset(wkup_ffmsk2
):
200 case mmr_offset(wkup_ffmsk3
):
201 case mmr_offset(wkup_ffcmd
):
202 case mmr_offset(wkup_ffoff
):
203 case mmr_offset(wkup_ffcrc0
):
204 case mmr_offset(wkup_ffcrc1
):
205 case mmr_offset(sysctl
):
206 case mmr_offset(rx_irqe
):
207 case mmr_offset(tx_irqe
):
208 case mmr_offset(mmc_rirqe
):
209 case mmr_offset(mmc_tirqe
):
212 case mmr_offset(opmode
):
213 if (!(*valuep
& RE
) && (value
& RE
))
214 emac
->rx_stat
&= ~RX_COMP
;
215 if (!(*valuep
& TE
) && (value
& TE
))
216 emac
->tx_stat
&= ~TX_COMP
;
219 case mmr_offset(addrlo
):
220 case mmr_offset(addrhi
):
223 case mmr_offset(wkup_ctl
):
224 dv_w1c_4_partial (valuep
, value
, 0xf20);
226 case mmr_offset(systat
):
227 dv_w1c_4 (valuep
, value
, 0xe1);
229 case mmr_offset(staadd
):
230 *valuep
= value
| STABUSY
;
237 case mmr_offset(rx_stat
):
238 case mmr_offset(tx_stat
):
239 /* Discard writes to these. */
241 case mmr_offset(rx_stky
):
242 case mmr_offset(tx_stky
):
243 case mmr_offset(mmc_rirqs
):
244 case mmr_offset(mmc_tirqs
):
245 dv_w1c_4 (valuep
, value
, -1);
247 case mmr_offset(mmc_ctl
):
248 /* Writing to bit 0 clears all counters. */
249 *valuep
= value
& ~1;
252 memset (&emac
->rxc_ok
, 0, mmr_offset (rxc_ge1024
) - mmr_offset (rxc_ok
) + 4);
253 memset (&emac
->txc_ok
, 0, mmr_offset (txc_abort
) - mmr_offset (txc_ok
) + 4);
256 case mmr_offset(rxc_ok
) ... mmr_offset(rxc_ge1024
):
257 case mmr_offset(txc_ok
) ... mmr_offset(txc_abort
):
258 /* XXX: Are these supposed to be read-only ? */
261 case mmr_offset(ptp_ctl
) ... mmr_offset(ptp_pps_period
):
262 /* XXX: Only on some models; ignore for now. */
265 dv_bfin_mmr_invalid (me
, addr
, nr_bytes
, true);
273 bfin_emac_io_read_buffer (struct hw
*me
, void *dest
,
274 int space
, address_word addr
, unsigned nr_bytes
)
276 struct bfin_emac
*emac
= hw_data (me
);
280 /* XXX: 16bit accesses are allowed ... */
281 dv_bfin_mmr_require_32 (me
, addr
, nr_bytes
, false);
283 mmr_off
= addr
- emac
->base
;
284 valuep
= (void *)((unsigned long)emac
+ mmr_base() + mmr_off
);
290 case mmr_offset(opmode
):
291 case mmr_offset(addrlo
):
292 case mmr_offset(addrhi
):
293 case mmr_offset(hashlo
):
294 case mmr_offset(hashhi
):
295 case mmr_offset(staadd
):
296 case mmr_offset(stadat
):
297 case mmr_offset(flc
):
298 case mmr_offset(vlan1
):
299 case mmr_offset(vlan2
):
300 case mmr_offset(wkup_ctl
):
301 case mmr_offset(wkup_ffmsk0
):
302 case mmr_offset(wkup_ffmsk1
):
303 case mmr_offset(wkup_ffmsk2
):
304 case mmr_offset(wkup_ffmsk3
):
305 case mmr_offset(wkup_ffcmd
):
306 case mmr_offset(wkup_ffoff
):
307 case mmr_offset(wkup_ffcrc0
):
308 case mmr_offset(wkup_ffcrc1
):
309 case mmr_offset(sysctl
):
310 case mmr_offset(systat
):
311 case mmr_offset(rx_stat
):
312 case mmr_offset(rx_stky
):
313 case mmr_offset(rx_irqe
):
314 case mmr_offset(tx_stat
):
315 case mmr_offset(tx_stky
):
316 case mmr_offset(tx_irqe
):
317 case mmr_offset(mmc_rirqs
):
318 case mmr_offset(mmc_rirqe
):
319 case mmr_offset(mmc_tirqs
):
320 case mmr_offset(mmc_tirqe
):
321 case mmr_offset(mmc_ctl
):
322 case mmr_offset(rxc_ok
) ... mmr_offset(rxc_ge1024
):
323 case mmr_offset(txc_ok
) ... mmr_offset(txc_abort
):
324 dv_store_4 (dest
, *valuep
);
326 case mmr_offset(ptp_ctl
) ... mmr_offset(ptp_pps_period
):
327 /* XXX: Only on some models; ignore for now. */
330 dv_bfin_mmr_invalid (me
, addr
, nr_bytes
, false);
338 attach_bfin_emac_regs (struct hw
*me
, struct bfin_emac
*emac
)
340 address_word attach_address
;
342 unsigned attach_size
;
343 reg_property_spec reg
;
345 if (hw_find_property (me
, "reg") == NULL
)
346 hw_abort (me
, "Missing \"reg\" property");
348 if (!hw_find_reg_array_property (me
, "reg", 0, ®
))
349 hw_abort (me
, "\"reg\" property must contain three addr/size entries");
351 hw_unit_address_to_attach_address (hw_parent (me
),
353 &attach_space
, &attach_address
, me
);
354 hw_unit_size_to_attach_size (hw_parent (me
), ®
.size
, &attach_size
, me
);
356 if (attach_size
!= BFIN_MMR_EMAC_SIZE
)
357 hw_abort (me
, "\"reg\" size must be %#x", BFIN_MMR_EMAC_SIZE
);
359 hw_attach_address (hw_parent (me
),
360 0, attach_space
, attach_address
, attach_size
, me
);
362 emac
->base
= attach_address
;
365 static struct dv_bfin
*dma_tx
;
368 bfin_emac_dma_read_buffer (struct hw
*me
, void *dest
, int space
,
369 unsigned_word addr
, unsigned nr_bytes
)
371 struct bfin_emac
*emac
= hw_data (me
);
372 struct dv_bfin
*dma
= hw_data (emac
->dma_master
);
373 unsigned char *data
= dest
;
374 static bool flop
; /* XXX: This sucks. */
378 HW_TRACE_DMA_READ ();
382 /* Handle the TX turn around and write the status. */
383 emac
->tx_stat
|= TX_OK
;
384 emac
->tx_stky
|= TX_OK
;
386 memcpy (data
, &emac
->tx_stat
, 4);
392 if (!(emac
->opmode
& RE
))
398 /* Outgoing DMA buffer has 16bit len prepended to it. */
401 /* This doesn't seem to work.
402 if (emac->sysctl & RXDWA)
408 ret
= read (emac
->tap
, data
, nr_bytes
);
411 ret
+= 4; /* include crc */
412 pad_ret
= MAX (ret
+ 4, 64);
414 memcpy (dest
, &len
, 2);
416 pad_ret
= (pad_ret
+ 3) & ~3;
418 memset (data
+ ret
, 0, pad_ret
- ret
);
421 /* XXX: Need to check -- u-boot doesn't look at this. */
422 if (emac
->sysctl
& RXCKS
)
429 /* XXX: Don't support promiscuous yet. */
430 emac
->rx_stat
|= RX_ACCEPT
;
431 emac
->rx_stat
= (emac
->rx_stat
& ~RX_FRLEN
) | len
;
433 emac
->rx_stat
|= RX_COMP
;
434 emac
->rx_stky
|= RX_COMP
;
438 /* Write the RX status and crc info. */
439 emac
->rx_stat
|= RX_OK
;
440 emac
->rx_stky
|= RX_OK
;
443 if (emac
->sysctl
& RXCKS
)
445 memcpy (data
, &emac
->rx_crc
, 4);
449 memcpy (data
, &emac
->rx_stat
, 4);
458 bfin_emac_dma_write_buffer (struct hw
*me
, const void *source
,
459 int space
, unsigned_word addr
,
461 int violate_read_only_section
)
463 struct bfin_emac
*emac
= hw_data (me
);
464 struct dv_bfin
*dma
= hw_data (emac
->dma_master
);
465 const unsigned char *data
= source
;
469 HW_TRACE_DMA_WRITE ();
471 if (!(emac
->opmode
& TE
))
474 /* Incoming DMA buffer has 16bit len prepended to it. */
475 memcpy (&len
, data
, 2);
479 ret
= write (emac
->tap
, data
+ 2, len
);
484 emac
->tx_stat
|= TX_COMP
;
485 emac
->tx_stky
|= TX_COMP
;
492 static const struct hw_port_descriptor bfin_emac_ports
[] =
494 { "tx", DV_PORT_TX
, 0, output_port
, },
495 { "rx", DV_PORT_RX
, 0, output_port
, },
496 { "stat", DV_PORT_STAT
, 0, output_port
, },
501 bfin_emac_attach_address_callback (struct hw
*me
,
505 address_word nr_bytes
,
508 const hw_unit
*unit
= hw_unit_address (client
);
509 HW_TRACE ((me
, "attach - level=%d, space=%d, addr=0x%lx, nr_bytes=%lu, client=%s",
510 level
, space
, (unsigned long) addr
, (unsigned long) nr_bytes
, hw_path (client
)));
511 /* NOTE: At preset the space is assumed to be zero. Perhaphs the
512 space should be mapped onto something for instance: space0 -
513 unified memory; space1 - IO memory; ... */
514 sim_core_attach (hw_system (me
),
516 level
+ 10 + unit
->cells
[unit
->nr_cells
- 1],
517 access_read_write_exec
,
526 bfin_emac_delete (struct hw
*me
)
528 struct bfin_emac
*emac
= hw_data (me
);
533 bfin_emac_tap_init (struct hw
*me
)
536 struct bfin_emac
*emac
= hw_data (me
);
540 unit
= hw_unit_address (me
);
542 emac
->tap
= open ("/dev/net/tun", O_RDWR
);
545 HW_TRACE ((me
, "unable to open /dev/net/tun: %s", strerror (errno
)));
549 memset (&emac
->ifr
, 0, sizeof (emac
->ifr
));
550 emac
->ifr
.ifr_flags
= IFF_TAP
| IFF_NO_PI
;
551 strcpy (emac
->ifr
.ifr_name
, "tap-gdb");
553 flags
= 1 * 1024 * 1024;
554 if (ioctl (emac
->tap
, TUNSETIFF
, &emac
->ifr
) < 0
556 || ioctl (emac
->tap
, TUNSETNOCSUM
) < 0
559 || ioctl (emac
->tap
, TUNSETSNDBUF
, &flags
) < 0
563 HW_TRACE ((me
, "tap ioctl setup failed: %s", strerror (errno
)));
568 flags
= fcntl (emac
->tap
, F_GETFL
);
569 fcntl (emac
->tap
, F_SETFL
, flags
| O_NONBLOCK
);
574 bfin_emac_finish (struct hw
*me
)
576 struct bfin_emac
*emac
;
578 emac
= HW_ZALLOC (me
, struct bfin_emac
);
580 set_hw_data (me
, emac
);
581 set_hw_io_read_buffer (me
, bfin_emac_io_read_buffer
);
582 set_hw_io_write_buffer (me
, bfin_emac_io_write_buffer
);
583 set_hw_dma_read_buffer (me
, bfin_emac_dma_read_buffer
);
584 set_hw_dma_write_buffer (me
, bfin_emac_dma_write_buffer
);
585 set_hw_ports (me
, bfin_emac_ports
);
586 set_hw_attach_address (me
, bfin_emac_attach_address_callback
);
587 set_hw_delete (me
, bfin_emac_delete
);
589 attach_bfin_emac_regs (me
, emac
);
591 /* Initialize the EMAC. */
592 emac
->addrlo
= 0xffffffff;
593 emac
->addrhi
= 0x0000ffff;
594 emac
->vlan1
= 0x0000ffff;
595 emac
->vlan2
= 0x0000ffff;
596 emac
->sysctl
= 0x00003f00;
597 emac
->mmc_ctl
= 0x0000000a;
599 bfin_emac_tap_init (me
);
602 const struct hw_descriptor dv_bfin_emac_descriptor
[] =
604 {"bfin_emac", bfin_emac_finish
,},