summaryrefslogtreecommitdiffstats
path: root/sys/arm/at91
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2013-03-29 18:17:51 +0000
committerian <ian@FreeBSD.org>2013-03-29 18:17:51 +0000
commit10e285049e547b7e8a65f5c56561c97420cdeea1 (patch)
treea9f4e7aef0b631b8605e6dd4458ecca6c72fe2b7 /sys/arm/at91
parent2d18442bf8ba56a133f85aac8c7170e5a1da8748 (diff)
downloadFreeBSD-src-10e285049e547b7e8a65f5c56561c97420cdeea1.zip
FreeBSD-src-10e285049e547b7e8a65f5c56561c97420cdeea1.tar.gz
Redo the workaround for at91rm9200 erratum #26 in a way that doesn't
cause a lockup on some rm92 hardware.
Diffstat (limited to 'sys/arm/at91')
-rw-r--r--sys/arm/at91/at91_pmc.c24
1 files changed, 9 insertions, 15 deletions
diff --git a/sys/arm/at91/at91_pmc.c b/sys/arm/at91/at91_pmc.c
index 0eeaa05..e001b5c 100644
--- a/sys/arm/at91/at91_pmc.c
+++ b/sys/arm/at91/at91_pmc.c
@@ -227,23 +227,18 @@ at91_pmc_set_pllb_mode(struct at91_pmc_clock *clk, int on)
struct at91_pmc_softc *sc = pmc_softc;
uint32_t value;
- if (on) {
- on = PMC_IER_LOCKB;
- value = pllb_init;
- } else
- value = 0;
+ value = on ? pllb_init : 0;
- /* Workaround RM9200 Errata #26 */
- if (at91_is_rm92() &&
- ((value ^ RD4(sc, CKGR_PLLBR)) & 0x03f0ff) != 0) {
- WR4(sc, CKGR_PLLBR, value ^ 1);
- while ((RD4(sc, PMC_SR) & PMC_IER_LOCKB) != on)
+ /*
+ * Only write to the register if the value is changing. Besides being
+ * good common sense, this works around RM9200 Errata #26 (CKGR_PLL[AB]R
+ * must not be written with the same value currently in the register).
+ */
+ if (RD4(sc, CKGR_PLLBR) != value) {
+ WR4(sc, CKGR_PLLBR, value);
+ while (on && (RD4(sc, PMC_SR) & PMC_IER_LOCKB) != PMC_IER_LOCKB)
continue;
}
-
- WR4(sc, CKGR_PLLBR, value);
- while ((RD4(sc, PMC_SR) & PMC_IER_LOCKB) != on)
- continue;
}
static void
@@ -577,7 +572,6 @@ at91_pmc_init_clock(void)
WR4(sc, PMC_SCER, PMC_SCER_MCKUDP);
} else
WR4(sc, PMC_SCDR, PMC_SCER_UHP_SAM9 | PMC_SCER_UDP_SAM9);
- WR4(sc, CKGR_PLLBR, 0);
/*
* MCK and PCU derive from one of the primary clocks. Initialize
OpenPOWER on IntegriCloud