MII-MDIO clocking and control

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MII-MDIO clocking and control

2,102 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by aras on Tue Feb 26 09:15:58 MST 2013
Hi,

The UM10503 43xx user manual indicates that the MDC clock is derived from the Ethernet block register interface clock CLK_M4_ETHERNET, and can be divided down by various ratios as indicated in the CR[4:0] field of MAC_MII_ADDR, address 0x4001 0010. I note that much of the example ENET driver code does not set this correctly which means that the clock runs completely out of spec (though it "works"). The description of "bit 5" (quoted below) is nonsensical and the division ratios a little random!

Q1) Is it the case that the only way to change the MDC frequency is thru these control bits and by adjusting the CPU clock?
Q2) Adjusting the CPU clk has some limitations (11.2.1.1 in the usr manual) when increasing frequency. Is there further info on exactly the limitations, please? I.e. is this a PLL issue or a clock-tree issue?  So, is it always OK to switch CPU clk back and forth, say between PLL1 and IRC? This is an important consideration for us more in low power than MDIO function, of course.

Thanks, Richard.


QUOTE
The CSR Clock Range selection determines the frequency of the MDC clock. The suggested range of CLK_M4_ETHERNET frequency applicable for each value below (when Bit[5] = 0) ensures that the MDC clock is approximately between the frequency range 1.0 MHz - 2.5 MHz.
When bit 5 is set, you can achieve MDC clock of frequency higher than the IEEE 802.3 specified frequency limit of 2.5 MHz and program a clock divider of lower value. For example, when CLK_M4_ETHERNET is of frequency 100 MHz and you program these bits as 1010, then the resultant MDC clock will be of 12.5 MHz which is outside the limit of IEEE 802.3 specified range. Program the values given below only if the interfacing chips supports faster MDC clocks.
See Table 547 for bit values.
Labels (1)
0 Kudos
2 Replies

1,548 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by aras on Tue Feb 26 11:11:14 MST 2013
Thanks Kevin, that makes perfect sense. (Even if the CR bits don't!)

Cheers, Richard.
0 Kudos

1,548 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by wellsk on Tue Feb 26 10:43:00 MST 2013
>Q1) Is it the case that the only way to change the MDC frequency is thru these control bits and by adjusting the CPU clock?
Yes, the MII clock is based on (only) the M3/M4 ethernet register clock, which is the same as the CPU clock rate (which uses the base clock for BASE_M3/M4_CLK setup in the CGU). Ideally, that MII clock rate should be under 2.5MHz, so a 204MHz CPU clock would require a divider of about 82, but 104 (the closest) would work to give a MII clock rate of about 1.96MHz.

Q2) Adjusting the CPU clk has some limitations (11.2.1.1 in the usr manual) when increasing frequency. Is there further info on exactly the limitations, please? I.e. is this a PLL issue or a clock-tree issue? So, is it always OK to switch CPU clk back and forth, say between PLL1 and IRC? This is an important consideration for us more in low power than MDIO function, of course.
When switching the CPU rate from the oscillator (or IRC) to the PLL, the PLL needs to be setup at 100MHz first and then the maximum rate (above 100MHz). This isn't really a PLL issue, but it allows the internal regulator to ramp up correctly. The code is below.
<code>
/* Switch main system clocking to crystal */
Chip_Clock_EnableCrystal();
Chip_Clock_SetBaseClock(CLK_BASE_MX, CLKIN_CRYSTAL, true, false);

/* Setup PLL for 100MHz and switch main system clocking */
Chip_Clock_SetupMainPLLHz(CLKIN_CRYSTAL, CRYSTAL_MAIN_FREQ_IN, 100 * 1000000, 100 * 1000000);
Chip_Clock_SetBaseClock(CLK_BASE_MX, CLKIN_MAINPLL, true, false);

/* Setup PLL for maximum clock */
Chip_Clock_SetupMainPLLHz(CLKIN_CRYSTAL, CRYSTAL_MAIN_FREQ_IN, MAX_CLOCK_FREQ, MAX_CLOCK_FREQ); // MAX_CLOCK_FREQ = 204000000
</code>

If you cycle the CPU between IRC rate (12MHz) and PLL rate (204MHz) and you want to keep the MII clock as close to 2.5Hhz as possible, you'll need to adjust the MII divider with the clock change (although running at a slower rate should probably be ok).

If you plan on keeping the ethernet interface active (transmit and/or receive) when adjusting CPU clocking, I would avoid adjusting the PLL at run-time when the CPU is using as it can halt the CPU (and buses) waiting for PLL lock. If ethernet is moving data during this lock wait period, the packets could be dropped/lost or you may get ethernet overrun/underrun errors. Instead, you might setup the PLL are 204MHz and keep it there and route the CPU base clock (and ethernet MII clock) via a divider something like this. This will allow clean clock transitiio ns
<code>
Chip_Clock_EnableCrystal();
Chip_Clock_SetBaseClock(CLK_BASE_MX, CLKIN_CRYSTAL, true, false);

/* Setup PLL for maximum clock */
Chip_Clock_SetupMainPLLHz(CLKIN_CRYSTAL, CRYSTAL_MAIN_FREQ_IN, MAX_CLOCK_FREQ, MAX_CLOCK_FREQ); // MAX_CLOCK_FREQ = 204000000

/* Setup a divider for about 100MHz operation (divide by 2 from main PLL) */
Chip_Clock_SetDivider(CLK_IDIV_B, CLKIN_MAINPLL, 2);

/* Route CPU clock from main osc (crystal) to divider B to get 102MHz rate on CPU */
Chip_Clock_SetBaseClock(CLK_BASE_MX, CLKIN_IDIVB, true, true);
for (i = 0; i < 250; i++); // Very small delay to allow power up

/* Setup divider for 1 for CPU rate of 204MHz */
Chip_Clock_SetDivider(CLK_IDIV_B, CLKIN_MAINPLL, 1);

...
...
...
...

/* To switch to a lower CPU rate, do this. Divider B can go up to divide by 16 */
Chip_Clock_SetDivider(CLK_IDIV_B, CLKIN_MAINPLL, 16); // CPU clock rate = 204/16 = 12.75MHz

...
...
...
...

/* When ramping back up to 204Mhz, do this ... */
Chip_Clock_SetDivider(CLK_IDIV_B, CLKIN_MAINPLL, 2);
for (i = 0; i < 250; i++); // Very small delay to allow power up

/* Setup divider for 1 for CPU rate of 204MHz */
Chip_Clock_SetDivider(CLK_IDIV_B, CLKIN_MAINPLL, 1);
</code>
0 Kudos