@@ -66,6 +66,8 @@ uint32_t *rx_ptr[ENET_RX_RING_LEN];
66
66
#define ENET_ALIGN (x,align ) ((unsigned int )((x) + ((align)-1 )) & (unsigned int )(~(unsigned int )((align)- 1 )))
67
67
68
68
extern " C" void kinetis_init_eth_hardware (void );
69
+ extern " C" uint32_t ENET_GetInstance (ENET_Type *base);
70
+ extern " C" clock_ip_name_t s_enetClock[];
69
71
70
72
/* \brief Flags for worker thread */
71
73
#define FLAG_TX 1
@@ -186,7 +188,6 @@ bool Kinetis_EMAC::low_level_init_successful()
186
188
phy_speed_t phy_speed;
187
189
phy_duplex_t phy_duplex;
188
190
uint32_t phyAddr = 0 ;
189
- bool link = false ;
190
191
enet_config_t config;
191
192
192
193
// Allocate RX descriptors
@@ -231,16 +232,16 @@ bool Kinetis_EMAC::low_level_init_successful()
231
232
232
233
ENET_GetDefaultConfig (&config);
233
234
234
- PHY_Init (ENET, 0 , sysClock);
235
- PHY_GetLinkStatus (ENET, phyAddr, &link);
236
- if (link) {
237
- /* Get link information from PHY */
238
- PHY_GetLinkSpeedDuplex (ENET, phyAddr, &phy_speed, &phy_duplex);
239
- /* Change the MII speed and duplex for actual link status. */
240
- config.miiSpeed = (enet_mii_speed_t )phy_speed;
241
- config.miiDuplex = (enet_mii_duplex_t )phy_duplex;
242
- config.interrupt = kENET_RxFrameInterrupt | kENET_TxFrameInterrupt ;
235
+ if (init_enet_phy (ENET, phyAddr, sysClock) != kStatus_Success ) {
236
+ return false ;
243
237
}
238
+
239
+ /* Get link information from PHY */
240
+ PHY_GetLinkSpeedDuplex (ENET, phyAddr, &phy_speed, &phy_duplex);
241
+ /* Change the MII speed and duplex for actual link status. */
242
+ config.miiSpeed = (enet_mii_speed_t )phy_speed;
243
+ config.miiDuplex = (enet_mii_duplex_t )phy_duplex;
244
+ config.interrupt = kENET_RxFrameInterrupt | kENET_TxFrameInterrupt ;
244
245
config.rxMaxFrameLen = ENET_ETH_MAX_FLEN;
245
246
config.macSpecialConfig = kENET_ControlFlowControlEnable ;
246
247
config.txAccelerConfig = 0 ;
@@ -262,6 +263,77 @@ bool Kinetis_EMAC::low_level_init_successful()
262
263
return true ;
263
264
}
264
265
266
+ status_t Kinetis_EMAC::init_enet_phy (ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz)
267
+ {
268
+ status_t result = kStatus_Success ;
269
+ uint32_t instance = ENET_GetInstance (base);
270
+
271
+ #if TARGET_K66F
272
+ uint32_t counter = 0xFFFFFU ;
273
+ uint32_t idReg = 0 ;
274
+
275
+ #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
276
+ /* Set SMI first. */
277
+ CLOCK_EnableClock (s_enetClock[instance]);
278
+ #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
279
+ ENET_SetSMI (base, srcClock_Hz, false );
280
+
281
+ /* Initialization after PHY stars to work. */
282
+ while ((idReg != PHY_CONTROL_ID1) && (counter != 0 )) {
283
+ PHY_Read (base, phyAddr, PHY_ID1_REG, &idReg);
284
+ counter --;
285
+ }
286
+
287
+ if (!counter) {
288
+ return kStatus_Fail ;
289
+ }
290
+
291
+ counter = 0xFFFFFU ;
292
+ #elif TARGET_K64F
293
+ /* Set SMI first. */
294
+ CLOCK_EnableClock (s_enetClock[instance]);
295
+ ENET_SetSMI (base, srcClock_Hz, false );
296
+ #else
297
+ #error invalid target!
298
+ #endif
299
+
300
+ /* Reset PHY. */
301
+ result = PHY_Write (base, phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK);
302
+ return result;
303
+ }
304
+
305
+ status_t Kinetis_EMAC::auto_negotiation (ENET_Type *base, uint32_t phyAddr)
306
+ {
307
+ uint32_t bssReg;
308
+ status_t result;
309
+ uint32_t counter = 0xFFFFFFU ;
310
+
311
+ /* Set the negotiation. */
312
+ result = PHY_Write (base, phyAddr, PHY_AUTONEG_ADVERTISE_REG,
313
+ (PHY_100BASETX_FULLDUPLEX_MASK | PHY_100BASETX_HALFDUPLEX_MASK |
314
+ PHY_10BASETX_FULLDUPLEX_MASK | PHY_10BASETX_HALFDUPLEX_MASK | 0x1U ));
315
+ if (result == kStatus_Success ) {
316
+ result = PHY_Write (base, phyAddr, PHY_BASICCONTROL_REG,
317
+ (PHY_BCTL_AUTONEG_MASK | PHY_BCTL_RESTART_AUTONEG_MASK));
318
+ if (result == kStatus_Success ) {
319
+ /* Check auto negotiation complete. */
320
+ while (counter --) {
321
+ result = PHY_Read (base, phyAddr, PHY_BASICSTATUS_REG, &bssReg);
322
+ if (result == kStatus_Success ) {
323
+ if ((bssReg & PHY_BSTATUS_AUTONEGCOMP_MASK) != 0 ) {
324
+ break ;
325
+ }
326
+ }
327
+
328
+ if (!counter) {
329
+ return kStatus_PHY_AutoNegotiateFail ;
330
+ }
331
+ }
332
+ }
333
+ }
334
+
335
+ return result;
336
+ }
265
337
266
338
/* * \brief Allocates a emac_mem_buf_t and returns the data from the incoming packet.
267
339
*
@@ -452,41 +524,42 @@ bool Kinetis_EMAC::link_out(emac_mem_buf_t *buf)
452
524
*******************************************************************************/
453
525
454
526
#define STATE_UNKNOWN (-1 )
455
-
456
- int phy_link_status (void ) {
457
- bool connection_status;
458
- uint32_t phyAddr = 0 ;
459
-
460
- PHY_GetLinkStatus (ENET, phyAddr, &connection_status);
461
- return (int )connection_status;
462
- }
527
+ #define STATE_LINK_DOWN (0 )
528
+ #define STATE_LINK_UP (1 )
463
529
464
530
void Kinetis_EMAC::phy_task ()
465
531
{
466
- static PHY_STATE prev_state = {STATE_UNKNOWN, (phy_speed_t )STATE_UNKNOWN, (phy_duplex_t )STATE_UNKNOWN};
467
-
468
532
uint32_t phyAddr = 0 ;
469
533
470
534
// Get current status
471
535
PHY_STATE crt_state;
472
536
bool connection_status;
473
537
PHY_GetLinkStatus (ENET, phyAddr, &connection_status);
474
- crt_state.connected = connection_status;
475
- // Get the actual PHY link speed
476
- PHY_GetLinkSpeedDuplex (ENET, phyAddr, &crt_state.speed , &crt_state.duplex );
538
+
539
+ if (connection_status) {
540
+ crt_state.connected = STATE_LINK_UP;
541
+ } else {
542
+ crt_state.connected = STATE_LINK_DOWN;
543
+ }
544
+
545
+ if (crt_state.connected == STATE_LINK_UP) {
546
+ if (prev_state.connected != STATE_LINK_UP) {
547
+ auto_negotiation (ENET, phyAddr);
548
+ }
549
+
550
+ PHY_GetLinkSpeedDuplex (ENET, phyAddr, &crt_state.speed , &crt_state.duplex );
551
+
552
+ if (prev_state.connected != STATE_LINK_UP || crt_state.speed != prev_state.speed ) {
553
+ /* Poke the registers*/
554
+ ENET_SetMII (ENET, (enet_mii_speed_t )crt_state.speed , (enet_mii_duplex_t )crt_state.duplex );
555
+ }
556
+ }
477
557
478
558
// Compare with previous state
479
559
if (crt_state.connected != prev_state.connected && emac_link_state_cb) {
480
560
emac_link_state_cb (crt_state.connected );
481
561
}
482
562
483
- if (crt_state.speed != prev_state.speed ) {
484
- uint32_t rcr = ENET->RCR ;
485
- rcr &= ~ENET_RCR_RMII_10T_MASK;
486
- rcr |= ENET_RCR_RMII_10T (!crt_state.speed );
487
- ENET->RCR = rcr;
488
- }
489
-
490
563
prev_state = crt_state;
491
564
}
492
565
@@ -504,19 +577,20 @@ bool Kinetis_EMAC::power_up()
504
577
rx_isr ();
505
578
506
579
/* PHY monitoring task */
507
- prev_state.connected = STATE_UNKNOWN ;
580
+ prev_state.connected = STATE_LINK_DOWN ;
508
581
prev_state.speed = (phy_speed_t )STATE_UNKNOWN;
509
582
prev_state.duplex = (phy_duplex_t )STATE_UNKNOWN;
510
583
511
- phy_task_handle = mbed::mbed_event_queue ()->call_every (PHY_TASK_PERIOD_MS, mbed::callback (this , &Kinetis_EMAC::phy_task));
584
+ mbed::mbed_event_queue ()->call ( mbed::callback (this , &Kinetis_EMAC::phy_task));
512
585
513
586
/* Allow the PHY task to detect the initial link state and set up the proper flags */
514
587
osDelay (10 );
515
588
589
+ phy_task_handle = mbed::mbed_event_queue ()->call_every (PHY_TASK_PERIOD_MS, mbed::callback (this , &Kinetis_EMAC::phy_task));
590
+
516
591
return true ;
517
592
}
518
593
519
-
520
594
uint32_t Kinetis_EMAC::get_mtu_size () const
521
595
{
522
596
return KINETIS_ETH_MTU_SIZE;
0 commit comments