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;
531 if (fec->
phy->ops->reset)
533 fec->
phy->ops->reset (fec->
phy);
548 (mac_address->
octet[1] << 16) +
549 (mac_address->
octet[2] << 8) +
550 (mac_address->
octet[3] << 0);
552 (mac_address->
octet[5] << 16) +
556 fec->
phy->ops->start (fec->
phy);
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);
675 link_state = fec->
phy->ops->get_link_state (fec->
phy);
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));
746 link_state = fec->
phy->ops->get_link_state (fec->
phy);
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);
778 fec = malloc (
sizeof (
fec_t));
779 UASSERT (fec != NULL, EMEM);
787 fec->
phy = mii_init (&phy_cfg);
794 state = StateDetached;
795 while (state == StateDetached)
uint32_t rmon_r_undersize
uint32_t rmon_t_crc_align
#define FEC_RCR_MAX_FL(x)
#define FEC_MII_WRITE(pa, ra, v)
fec_buffer_bd_t * tx_bd_base
#define FEC_RCR_RGMII_ENA
#define FEC_MODULE_CLOCK_Hz
fec_buffer_bd_t * rx_bd_base
int fec_ecat_init(const fec_mac_address_t *mac_address, bool phy_loopback_mode)
uint32_t tx_section_empty
int fec_ecat_recv(void *buffer, size_t buffer_length)
volatile reg_fec_t * base
static void fec_ecat_write_phy(void *arg, uint8_t address, uint8_t reg, uint16_t value)
fec_buffer_bd_t * tx_bd_base
static void fec_ecat_init_hw(const fec_mac_address_t *mac_address)
#define ETHERNET_FCS_SIZE_IN_BYTES
uint32_t rx_section_empty
uint32_t rmon_r_p_gte2048
fec_phy_inteface_t phy_interface
#define DUMP_PACKET(p, l)
uint32_t ieee_t_octets_ok
COMPILETIME_ASSERT(sizeof(fec_mib_t)==0x100)
uint32_t rmon_r_crc_align
uint32_t ieee_r_octets_ok
uint32_t rmon_t_p1024to2047
fec_buffer_bd_t * rx_bd_base
static void fec_ecat_hotplug(void)
int fec_ecat_send(const void *payload, size_t tot_len)
struct fec_mac_t fec_mac_t
uint32_t rmon_t_p512to1023
uint32_t rmon_r_p256to511
uint32_t rmon_r_p1024to2047
enum fec_phy_inteface fec_phy_inteface_t
uint32_t rmon_t_p128to255
#define FEC_MII_READ(pa, ra)
static dev_state_t fec_ecat_probe(void)
#define FEC_RCR_RMII_MODE
uint32_t rmon_t_undersize
uint32_t rmon_r_p512to1023
fec_phy_inteface_t phy_interface
#define FEC_MII_GET_DATA(v)
uint32_t rmon_r_p128to255
#define FEC_MIN_MODULE_CLOCK_Hz
static uint16_t fec_ecat_read_phy(void *arg, uint8_t address, uint8_t reg)
uint32_t rmon_t_p_gte2048
uint32_t rmon_t_p256to511