[U-Boot-Users] MPC85xx: Question about Local Bus initialization

Hi,
I took a look into the files board/mpc8560ads.c and board/tqm85xx.c and found something strange:
1. In the function local_bus_init() the current CLKDIV is read from the register LCRR as was set by Hardreset. After that, the decision is made, wether the DLL has to be enabled/disabled/overridden. Inside the if-else blocks the new CLKDIV is changed. But IMO the CLKDIV has to be set before the query.
This is the current code: clkdiv = lbc->lcrr & 0x0f; lbc_hz = sysinfo.freqSystemBus / 1000000 / clkdiv;
if (lbc_hz < 66) { lbc->lcrr = CFG_LBC_LCRR | 0x80000000; /* DLL Bypass */
} else if (lbc_hz >= 133) { lbc->lcrr = CFG_LBC_LCRR & (~0x80000000); /* DLL Enabled ... This may be the situation on other 85xx boards, too. I didn't check them all. What was the intention, DLL modification dependent on the clock set by the MPC at hardreset or dependent on the targeted frequency?
2. The variable is named lbc_hz, but it contains a value in units of MHz. I suggest to use the name lbc_mhz or to use Hertz values by removing the division by 1,000,000 and replacing 66 and 133 by 66666667 and 133333333. What's your opinion?
3. I assume, the function above is called while the MPC executes this code from flash memory (array init_sequence[] in lib_ppc/board.c). Is there a potential that the U-Boot would hang when it changed the CLKDIV?
Regards, Jens

Hi Jens,
I took a look into the files board/mpc8560ads.c and board/tqm85xx.c and found something strange:
- In the function local_bus_init() the current CLKDIV is read from the
register LCRR as was set by Hardreset. After that, the decision is made, wether the DLL has to be enabled/disabled/overridden. Inside the if-else blocks the new CLKDIV is changed. But IMO the CLKDIV has to be set before the query.
This is the current code: clkdiv = lbc->lcrr & 0x0f; lbc_hz = sysinfo.freqSystemBus / 1000000 / clkdiv;
if (lbc_hz < 66) { lbc->lcrr = CFG_LBC_LCRR | 0x80000000; /* DLL Bypass */
} else if (lbc_hz >= 133) { lbc->lcrr = CFG_LBC_LCRR & (~0x80000000); /* DLL Enabled ... This may be the situation on other 85xx boards, too. I didn't check them all. What was the intention, DLL modification dependent on the clock set by the MPC at hardreset or dependent on the targeted frequency?
I am definitely not the specialist on these chips, but checking the 8555 and 8560 manuals, it seems that LCRR comes out of reset with 0x8000,0008. I cannot find any reference to LCRR from the POR description.
Keeping this in mind, "clkdiv" in the above code will always be 8 and so it looks to me indeed like the tests really were intended to check (CFG_LBC_LCRR & 0x0f). Can anyone more knowledgable in this area confirm this suspicion?
- The variable is named lbc_hz, but it contains a value in units of
MHz. I suggest to use the name lbc_mhz or to use Hertz values by removing the division by 1,000,000 and replacing 66 and 133 by 66666667 and 133333333. What's your opinion?
Personally I would second your reasoning. But for others to comment, it is really best to implement your proposed change and send a diff to comment on. Such a suggestion is more likely by several magnitudes to be considered ;)
- I assume, the function above is called while the MPC executes this
code from flash memory (array init_sequence[] in lib_ppc/board.c). Is there a potential that the U-Boot would hang when it changed the CLKDIV?
If you get the timings wrong, of course things could get hairy, or am I missing something?
Cheers Detlev

Hi Detlev,
thanks for the reply.
Detlev Zundel schrieb:
Hi Jens,
I took a look into the files board/mpc8560ads.c and board/tqm85xx.c and found something strange:
- In the function local_bus_init() the current CLKDIV is read from the
register LCRR as was set by Hardreset. After that, the decision is made, wether the DLL has to be enabled/disabled/overridden. Inside the if-else blocks the new CLKDIV is changed. But IMO the CLKDIV has to be set before the query.
This is the current code: clkdiv = lbc->lcrr & 0x0f; lbc_hz = sysinfo.freqSystemBus / 1000000 / clkdiv;
if (lbc_hz < 66) { lbc->lcrr = CFG_LBC_LCRR | 0x80000000; /* DLL Bypass */
} else if (lbc_hz >= 133) { lbc->lcrr = CFG_LBC_LCRR & (~0x80000000); /* DLL Enabled ... This may be the situation on other 85xx boards, too. I didn't check them all. What was the intention, DLL modification dependent on the clock set by the MPC at hardreset or dependent on the targeted frequency?
I am definitely not the specialist on these chips, but checking the 8555 and 8560 manuals, it seems that LCRR comes out of reset with 0x8000,0008. I cannot find any reference to LCRR from the POR description.
Agreed. 0x80000008 is the hard reset value.
Keeping this in mind, "clkdiv" in the above code will always be 8 and so it looks to me indeed like the tests really were intended to check (CFG_LBC_LCRR & 0x0f). Can anyone more knowledgable in this area confirm this suspicion?
In the current implementation CLKDIV is not modified earlier. Therefore, lbc->lcrr & 0x0f == CFG_LBC_LCRR & 0x0f is in this code only true, if CFG_LBC_LCRR is defined equally to the MPC's hard reset value. But what if I desire another clock frequency and other timings? In the current code the decision to bypass or not to bypass the DLL is made, _before_ it is changed. Shouldn't it be "clkdiv = (CFG_LBC_LCRR & 0x0f);" in the first line?
I'm not sure. And that's is the reason for my question. I hoped that the Freescale developers had something to say about it.
- The variable is named lbc_hz, but it contains a value in units of
MHz. I suggest to use the name lbc_mhz or to use Hertz values by removing the division by 1,000,000 and replacing 66 and 133 by 66666667 and 133333333. What's your opinion?
Personally I would second your reasoning. But for others to comment, it is really best to implement your proposed change and send a diff to comment on. Such a suggestion is more likely by several magnitudes to be considered ;)
No problem. It was just a question.
Regards, Jens

Hi,
I took a look into the files board/mpc8560ads.c and board/tqm85xx.c and found something strange:
- In the function local_bus_init() the current CLKDIV is read from the
register LCRR as was set by Hardreset. After that, the decision is made, wether the DLL has to be enabled/disabled/overridden. Inside the if-else blocks the new CLKDIV is changed. But IMO the CLKDIV has to be set before the query.
This is the current code: clkdiv = lbc->lcrr & 0x0f; lbc_hz = sysinfo.freqSystemBus / 1000000 / clkdiv;
if (lbc_hz < 66) { lbc->lcrr = CFG_LBC_LCRR | 0x80000000; /* DLL Bypass */
} else if (lbc_hz >= 133) { lbc->lcrr = CFG_LBC_LCRR & (~0x80000000); /* DLL Enabled ... This may be the situation on other 85xx boards, too. I didn't check them all. What was the intention, DLL modification dependent on the clock set by the MPC at hardreset or dependent on the targeted frequency?
MPC8540 Reference Manual, Page 13-23, LCRR Field Descriptions: "DLL bypass. This bit should be set when using low bus clock frequencies if the DLL is unable to lock. When in DLL bypass mode, incoming data is captured in the middle of the bus clock cycle."
Usually 85xx boot from Flash connected to the Local Bus, so the bootstrap configuration out of a hard reset need to be correct at first place. Then, if the bootloader (or later, the kernel) wants to (re-)set it during runtime, it also has to set the DLL enable bit depending on the desired target frequency.
Regards,

Hi Clemens,
thanks for the reply.
Clemens Koller schrieb:
Hi,
I took a look into the files board/mpc8560ads.c and board/tqm85xx.c and found something strange:
- In the function local_bus_init() the current CLKDIV is read from the
register LCRR as was set by Hardreset. After that, the decision is made, wether the DLL has to be enabled/disabled/overridden. Inside the if-else blocks the new CLKDIV is changed. But IMO the CLKDIV has to be set before the query.
This is the current code: clkdiv = lbc->lcrr & 0x0f; lbc_hz = sysinfo.freqSystemBus / 1000000 / clkdiv;
if (lbc_hz < 66) { lbc->lcrr = CFG_LBC_LCRR | 0x80000000; /* DLL Bypass */ } else if (lbc_hz >= 133) { lbc->lcrr = CFG_LBC_LCRR & (~0x80000000); /* DLL Enabled ...
This may be the situation on other 85xx boards, too. I didn't check them all. What was the intention, DLL modification dependent on the clock set by the MPC at hardreset or dependent on the targeted frequency?
MPC8540 Reference Manual, Page 13-23, LCRR Field Descriptions: "DLL bypass. This bit should be set when using low bus clock frequencies if the DLL is unable to lock. When in DLL bypass mode, incoming data is captured in the middle of the bus clock cycle."
Usually 85xx boot from Flash connected to the Local Bus, so the bootstrap configuration out of a hard reset need to be correct at first place. Then, if the bootloader (or later, the kernel) wants to (re-)set it during runtime, it also has to set the DLL enable bit depending on the desired target frequency.
But the bootloader should not itself pull the rug out from under its feet. As I see, the U-Boot works if I change the frequency during runtime (changed define CFG_LBC_LCRR). Does anybody know why? In our Monitor MON85XX we don't change the frequency in flash code, but later in RAM code according to the target frequency. Additionally LCRR[EADC] and OR[EAD] are modified if the target frequency is greater than 83 MHz according to the HW developer's timing calculations.
Regards, Jens
participants (3)
-
Clemens Koller
-
Detlev Zundel
-
Jens Gehrlein