mirror of
https://github.com/AsahiLinux/u-boot
synced 2025-02-17 22:49:02 +00:00
powerpc/85xx: Implement work-around for P4080 erratum SERDES-A001
Bank powerdown through RCW[SRDS_LPD_Bn] for XAUI on FM2 and SGMII on FM1 are swapped. Erratum SERDES-A001 says that if bank two is kept disabled and after bank three is enabled, then the PLL for bank three won't lock properly. The work-around is to enable and then disable bank two after bank three is enabled. Signed-off-by: Timur Tabi <timur@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
This commit is contained in:
parent
f68d306349
commit
d90fdba6ca
2 changed files with 65 additions and 16 deletions
|
@ -432,6 +432,28 @@ static void p4080_erratum_serdes_a005(serdes_corenet_t *regs, unsigned int cfg)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for the RSTDONE bit to get set, or a one-second timeout.
|
||||||
|
*/
|
||||||
|
static void wait_for_rstdone(unsigned int bank)
|
||||||
|
{
|
||||||
|
serdes_corenet_t *srds_regs =
|
||||||
|
(void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
|
||||||
|
unsigned long long end_tick;
|
||||||
|
u32 rstctl;
|
||||||
|
|
||||||
|
/* wait for reset complete or 1-second timeout */
|
||||||
|
end_tick = usec2ticks(1000000) + get_ticks();
|
||||||
|
do {
|
||||||
|
rstctl = in_be32(&srds_regs->bank[bank].rstctl);
|
||||||
|
if (rstctl & SRDS_RSTCTL_RSTDONE)
|
||||||
|
break;
|
||||||
|
} while (end_tick > get_ticks());
|
||||||
|
|
||||||
|
if (!(rstctl & SRDS_RSTCTL_RSTDONE))
|
||||||
|
printf("SERDES: timeout resetting bank %u\n", bank);
|
||||||
|
}
|
||||||
|
|
||||||
void fsl_serdes_init(void)
|
void fsl_serdes_init(void)
|
||||||
{
|
{
|
||||||
ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
|
ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
|
||||||
|
@ -439,7 +461,6 @@ void fsl_serdes_init(void)
|
||||||
serdes_corenet_t *srds_regs;
|
serdes_corenet_t *srds_regs;
|
||||||
int lane, bank, idx;
|
int lane, bank, idx;
|
||||||
enum srds_prtcl lane_prtcl;
|
enum srds_prtcl lane_prtcl;
|
||||||
long long end_tick;
|
|
||||||
int have_bank[SRDS_MAX_BANK] = {};
|
int have_bank[SRDS_MAX_BANK] = {};
|
||||||
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
|
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
|
||||||
u32 serdes8_devdisr = 0;
|
u32 serdes8_devdisr = 0;
|
||||||
|
@ -450,6 +471,9 @@ void fsl_serdes_init(void)
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9
|
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9
|
||||||
enum srds_prtcl device;
|
enum srds_prtcl device;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001
|
||||||
|
int need_serdes_a001; /* TRUE == need work-around for SERDES A001 */
|
||||||
#endif
|
#endif
|
||||||
char buffer[HWCONFIG_BUFFER_SIZE];
|
char buffer[HWCONFIG_BUFFER_SIZE];
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
|
@ -519,11 +543,32 @@ void fsl_serdes_init(void)
|
||||||
have_bank[FSL_SRDS_BANK_3] = 1;
|
have_bank[FSL_SRDS_BANK_3] = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001
|
||||||
|
/*
|
||||||
|
* The work-aroud for erratum SERDES-A001 is needed only if bank two
|
||||||
|
* is disabled and bank three is enabled.
|
||||||
|
*/
|
||||||
|
need_serdes_a001 =
|
||||||
|
!have_bank[FSL_SRDS_BANK_2] && have_bank[FSL_SRDS_BANK_3];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Power down the banks we're not interested in */
|
||||||
for (bank = 0; bank < SRDS_MAX_BANK; bank++) {
|
for (bank = 0; bank < SRDS_MAX_BANK; bank++) {
|
||||||
if (!have_bank[bank]) {
|
if (!have_bank[bank]) {
|
||||||
printf("SERDES: bank %d disabled\n", bank + 1);
|
printf("SERDES: bank %d disabled\n", bank + 1);
|
||||||
|
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001
|
||||||
|
/*
|
||||||
|
* Erratum SERDES-A001 says bank two needs to be powered
|
||||||
|
* down after bank three is powered up, so don't power
|
||||||
|
* down bank two here.
|
||||||
|
*/
|
||||||
|
if (!need_serdes_a001 || (bank != FSL_SRDS_BANK_2))
|
||||||
|
setbits_be32(&srds_regs->bank[bank].rstctl,
|
||||||
|
SRDS_RSTCTL_SDPD);
|
||||||
|
#else
|
||||||
setbits_be32(&srds_regs->bank[bank].rstctl,
|
setbits_be32(&srds_regs->bank[bank].rstctl,
|
||||||
SRDS_RSTCTL_SDPD);
|
SRDS_RSTCTL_SDPD);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,8 +694,6 @@ void fsl_serdes_init(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (idx = 0; idx < SRDS_MAX_BANK; idx++) {
|
for (idx = 0; idx < SRDS_MAX_BANK; idx++) {
|
||||||
u32 rstctl;
|
|
||||||
|
|
||||||
bank = idx;
|
bank = idx;
|
||||||
|
|
||||||
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
|
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
|
||||||
|
@ -689,21 +732,26 @@ void fsl_serdes_init(void)
|
||||||
/* reset banks for errata */
|
/* reset banks for errata */
|
||||||
setbits_be32(&srds_regs->bank[bank].rstctl, SRDS_RSTCTL_RST);
|
setbits_be32(&srds_regs->bank[bank].rstctl, SRDS_RSTCTL_RST);
|
||||||
|
|
||||||
/* wait for reset complete or 1-second timeout */
|
wait_for_rstdone(bank);
|
||||||
end_tick = usec2ticks(1000000) + get_ticks();
|
|
||||||
do {
|
|
||||||
rstctl = in_be32(&srds_regs->bank[bank].rstctl);
|
|
||||||
if (rstctl & SRDS_RSTCTL_RSTDONE)
|
|
||||||
break;
|
|
||||||
} while (end_tick > get_ticks());
|
|
||||||
|
|
||||||
if (!(rstctl & SRDS_RSTCTL_RSTDONE)) {
|
|
||||||
printf("SERDES: timeout resetting bank %d\n",
|
|
||||||
bank + 1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001
|
||||||
|
if (need_serdes_a001) {
|
||||||
|
/*
|
||||||
|
* Bank three has been enabled, so enable bank two and then
|
||||||
|
* disable it.
|
||||||
|
*/
|
||||||
|
srds_lpd_b[FSL_SRDS_BANK_2] = 0;
|
||||||
|
enable_bank(gur, FSL_SRDS_BANK_2);
|
||||||
|
|
||||||
|
wait_for_rstdone(FSL_SRDS_BANK_2);
|
||||||
|
|
||||||
|
/* Disable bank 2 */
|
||||||
|
setbits_be32(&srds_regs->bank[FSL_SRDS_BANK_2].rstctl,
|
||||||
|
SRDS_RSTCTL_SDPD);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9
|
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9
|
||||||
for (device = XAUI_FM1; device <= XAUI_FM2; device++) {
|
for (device = XAUI_FM1; device <= XAUI_FM2; device++) {
|
||||||
if (is_serdes_configured(device))
|
if (is_serdes_configured(device))
|
||||||
|
|
|
@ -311,6 +311,7 @@
|
||||||
#define CONFIG_SYS_P4080_ERRATUM_CPU22
|
#define CONFIG_SYS_P4080_ERRATUM_CPU22
|
||||||
#define CONFIG_SYS_P4080_ERRATUM_SERDES8
|
#define CONFIG_SYS_P4080_ERRATUM_SERDES8
|
||||||
#define CONFIG_SYS_P4080_ERRATUM_SERDES9
|
#define CONFIG_SYS_P4080_ERRATUM_SERDES9
|
||||||
|
#define CONFIG_SYS_P4080_ERRATUM_SERDES_A001
|
||||||
#define CONFIG_SYS_P4080_ERRATUM_SERDES_A005
|
#define CONFIG_SYS_P4080_ERRATUM_SERDES_A005
|
||||||
|
|
||||||
/* P5010 is single core version of P5020 */
|
/* P5010 is single core version of P5020 */
|
||||||
|
|
Loading…
Add table
Reference in a new issue