27 #include <eth/fec_buffer.h>
28 #include <eth/phy/mii.h>
36 #define DPRINT(...) rprintp ("FEC: "__VA_ARGS__)
42 #define DUMP_PACKET(p, l) fec_ecat_dump_packet (p, l)
44 #define DUMP_PACKET(p, l)
47 #define ETHERNET_FCS_SIZE_IN_BYTES 4
49 #define DELAY(ms) task_delay (tick_from_ms (ms) + 1)
51 #define ETH_PHY_ADDRESS 0x1
54 #define FEC_ALLIGNED __attribute__((section(".dma"),aligned(16)))
63 #define FEC_MIN_MODULE_CLOCK_Hz (25 * 1000 * 1000)
66 #define FEC_MODULE_CLOCK_Hz CFG_IPG_CLOCK
203 #define FEC_EIR_CLEAR_ALL (0xFFF80000)
204 #define FEC_EIR_HBERR (0x80000000)
205 #define FEC_EIR_BABR (0x40000000)
206 #define FEC_EIR_BABT (0x20000000)
207 #define FEC_EIR_GRA (0x10000000)
208 #define FEC_EIR_TXF (0x08000000)
209 #define FEC_EIR_TXB (0x04000000)
210 #define FEC_EIR_RXF (0x02000000)
211 #define FEC_EIR_RXB (0x01000000)
212 #define FEC_EIR_MII (0x00800000)
213 #define FEC_EIR_EBERR (0x00400000)
214 #define FEC_EIR_LC (0x00200000)
215 #define FEC_EIR_RL (0x00100000)
216 #define FEC_EIR_UN (0x00080000)
219 #define FEC_RDAR_R_DES_ACTIVE (0x01000000)
222 #define FEC_TDAR_X_DES_ACTIVE (0x01000000)
225 #define FEC_ECR_DBSWP (0x00000100)
226 #define FEC_ECR_ETHER_EN (0x00000002)
227 #define FEC_ECR_RESET (0x00000001)
230 #define FEC_MMFR_DATA(x) (((x)&0xFFFF))
231 #define FEC_MMFR_ST(x) (((x)&0x03)<<30)
232 #define FEC_MMFR_ST_01 (0x40000000)
233 #define FEC_MMFR_OP_RD (0x20000000)
234 #define FEC_MMFR_OP_WR (0x10000000)
235 #define FEC_MMFR_PA(x) (((x)&0x1F)<<23)
236 #define FEC_MMFR_RA(x) (((x)&0x1F)<<18)
237 #define FEC_MMFR_TA(x) (((x)&0x03)<<16)
238 #define FEC_MMFR_TA_10 (0x00020000)
241 #define FEC_MSCR_DIS_PREAMBLE (0x00000080)
242 #define FEC_MSCR_MII_SPEED(x) (((x)&0x3F)<<1)
245 #define FEC_MIBC_MIB_DISABLE (0x80000000)
246 #define FEC_MIBC_MIB_IDLE (0x40000000)
249 #define FEC_RCR_GRS (0x80000000)
250 #define FEC_RCR_NO_LGTH_CHECK (0x40000000)
251 #define FEC_RCR_MAX_FL(x) (((x)&0x7FF)<<16)
252 #define FEC_RCR_CNTL_FRM_ENA (0x00008000)
253 #define FEC_RCR_CRC_FWD (0x00004000)
254 #define FEC_RCR_PAUSE_FWD (0x00002000)
255 #define FEC_RCR_PAD_EN (0x00001000)
256 #define FEC_RCR_RMII_ECHO (0x00000800)
257 #define FEC_RCR_RMII_LOOP (0x00000400)
258 #define FEC_RCR_RMII_10T (0x00000200)
259 #define FEC_RCR_RMII_MODE (0x00000100)
260 #define FEC_RCR_SGMII_ENA (0x00000080)
261 #define FEC_RCR_RGMII_ENA (0x00000040)
262 #define FEC_RCR_FCE (0x00000020)
263 #define FEC_RCR_BC_REJ (0x00000010)
264 #define FEC_RCR_PROM (0x00000008)
265 #define FEC_RCR_MII_MODE (0x00000004)
266 #define FEC_RCR_DRT (0x00000002)
267 #define FEC_RCR_LOOP (0x00000001)
270 #define FEC_TCR_RFC_PAUSE (0x00000010)
271 #define FEC_TCR_TFC_PAUSE (0x00000008)
272 #define FEC_TCR_FDEN (0x00000004)
273 #define FEC_TCR_HBC (0x00000002)
274 #define FEC_TCR_GTS (0x00000001)
277 #define FEC_PAUR_PADDR2(x) (((x)&0xFFFF)<<16)
278 #define FEC_PAUR_TYPE(x) ((x)&0xFFFF)
281 #define FEC_OPD_PAUSE_DUR(x) (((x)&0x0000FFFF)<<0)
282 #define FEC_OPD_OPCODE(x) (((x)&0x0000FFFF)<<16)
285 #define FEC_TFWR_STR_FWD BIT (8)
286 #define FEC_TFWR_X_WMRK(x) ((x)&0x03)
287 #define FEC_TFWR_X_WMRK_64 (0x01)
288 #define FEC_TFWR_X_WMRK_128 (0x02)
289 #define FEC_TFWR_X_WMRK_192 (0x03)
292 #define FEC_FRBR_R_BOUND(x) (((x)&0xFF)<<2)
295 #define FEC_FRSR_R_FSTART(x) (((x)&0xFF)<<2)
298 #define FEC_ERDSR_R_DES_START(x) (((x)&0x3FFFFFFF)<<2)
301 #define FEC_ETDSR_X_DES_START(x) (((x)&0x3FFFFFFF)<<2)
304 #define FEC_EMRBR_R_BUF_SIZE(x) (((x)&0x7F)<<4)
309 #define FEC_MII_ST 0x40000000
310 #define FEC_MII_OP_OFF 28
311 #define FEC_MII_OP_MASK 0x03
312 #define FEC_MII_OP_RD 0x02
313 #define FEC_MII_OP_WR 0x01
314 #define FEC_MII_PA_OFF 23
315 #define FEC_MII_PA_MASK 0xFF
316 #define FEC_MII_RA_OFF 18
317 #define FEC_MII_RA_MASK 0xFF
318 #define FEC_MII_TA 0x00020000
319 #define FEC_MII_DATA_OFF 0
320 #define FEC_MII_DATA_MASK 0x0000FFFF
322 #define FEC_MII_FRAME (FEC_MII_ST | FEC_MII_TA)
323 #define FEC_MII_OP(x) (((x) & FEC_MII_OP_MASK) << FEC_MII_OP_OFF)
324 #define FEC_MII_PA(pa) (((pa) & FEC_MII_PA_MASK) << FEC_MII_PA_OFF)
325 #define FEC_MII_RA(ra) (((ra) & FEC_MII_RA_MASK) << FEC_MII_RA_OFF)
326 #define FEC_MII_SET_DATA(v) (((v) & FEC_MII_DATA_MASK) << FEC_MII_DATA_OFF)
327 #define FEC_MII_GET_DATA(v) (((v) >> FEC_MII_DATA_OFF) & FEC_MII_DATA_MASK)
328 #define FEC_MII_READ(pa, ra) ((FEC_MII_FRAME | FEC_MII_OP(FEC_MII_OP_RD)) |\
329 FEC_MII_PA(pa) | FEC_MII_RA(ra))
330 #define FEC_MII_WRITE(pa, ra, v) (FEC_MII_FRAME | FEC_MII_OP(FEC_MII_OP_WR)|\
331 FEC_MII_PA(pa) | FEC_MII_RA(ra) | FEC_MII_SET_DATA(v))
333 #define FEC_MII_TIMEOUT 10 // 1 * 10 ms
334 #define FEC_MII_TICK 1 // 1 ms
339 #define PKT_MAXBUF_SIZE 1518
390 const char * fec_ecat_link_duplex_name (
uint8_t link_state)
392 if (link_state & PHY_LINK_OK)
394 if (link_state & PHY_LINK_FULL_DUPLEX)
396 return "full duplex";
400 return "half duplex";
405 return "no duplex (link down)";
409 const char * fec_ecat_link_speed_name (
uint8_t link_state)
411 if (link_state & PHY_LINK_OK)
413 if (link_state & PHY_LINK_10MBIT)
417 else if (link_state & PHY_LINK_100MBIT)
421 else if (link_state & PHY_LINK_1000MBIT)
427 return "unknown speed";
432 return "0 Mbps (link down)";
437 #ifdef RTK_DEBUG_DATA
439 static void fec_ecat_dump_packet (
const uint8_t * payload,
size_t len)
444 ASSERT (payload != NULL);
446 for (i = 0; i < len; i += 16)
449 for (
j = 0;
j < 16 && (i +
j) < len;
j++)
451 ASSERT (n <=
sizeof(s));
452 n += rsnprintf (s + n,
sizeof(s) - n,
"%02x ", payload[i +
j]);
456 ASSERT (n <=
sizeof(s));
457 n += rsnprintf (s + n,
sizeof(s) - n,
" ");
459 ASSERT (n <=
sizeof(s));
460 n += rsnprintf (s + n,
sizeof(s) - n,
"|");
461 for (
j = 0;
j < 16 && (i +
j) < len;
j++)
464 c = (isprint (c)) ? c :
'.';
465 ASSERT (n <=
sizeof(s));
466 n += rsnprintf (s + n,
sizeof(s) - n,
"%c", c);
468 ASSERT (n <=
sizeof(s));
469 n += rsnprintf (s + n,
sizeof(s) - n,
"|\n");
470 ASSERT (n <=
sizeof(s));
513 mii_speed = (
fec->
clock + 499999) / 5000000;
548 (mac_address->
octet[1] << 16) +
549 (mac_address->
octet[2] << 8) +
550 (mac_address->
octet[3] << 0);
552 (mac_address->
octet[5] << 16) +
561 fec_buffer_bd_t * bd;
565 ASSERT (tot_len <= TX_BUFFER_SIZE);
578 bd = fec_buffer_get_tx ();
581 DPRINT (
"out (%u):\n", tot_len);
585 memcpy (bd->data, payload, tot_len);
586 bd->length = tot_len;
588 fec_buffer_produce_tx (bd);
608 fec_buffer_bd_t * bd;
610 size_t frame_length_without_fcs;
617 bd = fec_buffer_get_rx ();
629 if ((bd->status & BD_RX_L)== 0){
635 DPRINT (
"recv(): End of frame not found. Status: 0x%x\n", bd->status);
638 else if (bd->status & (BD_RX_LG | BD_RX_NO | BD_RX_CR | BD_RX_OV))
640 DPRINT (
"recv(): Frame is damaged. Status: 0x%x\n", bd->status);
643 else if (buffer_length >= frame_length_without_fcs)
646 ASSERT (frame_length_without_fcs > 0);
648 memcpy (buffer, bd->data, frame_length_without_fcs);
649 DPRINT (
"in (%u):\n", frame_length_without_fcs);
651 return_value = frame_length_without_fcs;
655 DPRINT (
"received_frame: User buffer is too small.\n");
660 fec_buffer_produce_rx (bd);
678 if (link_state & PHY_LINK_FULL_DUPLEX)
690 if (link_state & PHY_LINK_10MBIT)
738 DPRINT (
"Link up. Speed: %s. Mode: %s.\n", fec_ecat_link_speed_name (link_state),
739 fec_ecat_link_duplex_name (link_state));
748 return (link_state & PHY_LINK_OK) ? StateAttached : StateDetached;
754 bool phy_loopback_mode)
761 .tx_bd_base = fec_tx_bd,
762 .rx_bd_base = fec_rx_bd,
765 static phy_cfg_t phy_cfg =
772 phy_cfg.loopback_mode = phy_loopback_mode;
775 fec_buffer_init_tx (fec_tx_bd, fec_tx_data,
NUM_BUFFERS);
776 fec_buffer_init_rx (fec_rx_bd, fec_rx_data,
NUM_BUFFERS);
779 UASSERT (
fec != NULL, EMEM);
787 fec->
phy = mii_init (&phy_cfg);
794 state = StateDetached;
795 while (state == StateDetached)