FreeBSD Bugzilla – Attachment 195033 Details for
Bug 229644
PINE64+ 12.0-CURRENT #0 r336112 - time management problem
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Reworked patch for unstable-a64 eventttimer.
a64unstable_generic_timer_take2.diff (text/plain), 3.14 KB, created by
Ian Lepore
on 2018-07-10 16:50:00 UTC
(
hide
)
Description:
Reworked patch for unstable-a64 eventttimer.
Filename:
MIME Type:
Creator:
Ian Lepore
Created:
2018-07-10 16:50:00 UTC
Size:
3.14 KB
patch
obsolete
>Index: sys/arm/arm/generic_timer.c >=================================================================== >--- sys/arm/arm/generic_timer.c (revision 336112) >+++ sys/arm/arm/generic_timer.c (working copy) >@@ -136,6 +136,9 @@ static struct timecounter arm_tmr_timecount = { > #define set_el1(x, val) WRITE_SPECIALREG(x ##_el1, val) > #endif > >+#define A64_UNSTABLE_LOBITS 0x7ff >+#define A64_UNSTABLE_HIBITS (~A64_UNSTABLE_LOBITS) >+ > static int > get_freq(void) > { >@@ -145,20 +148,20 @@ get_freq(void) > static uint64_t > get_cntxct_a64_unstable(bool physical) > { >- uint64_t val >-; >+ uint64_t val; >+ > isb(); > if (physical) { > do { > val = get_el0(cntpct); > } >- while (((val + 1) & 0x7FF) <= 1); >+ while (((val + 1) & A64_UNSTABLE_LOBITS) <= 1); > } > else { > do { > val = get_el0(cntvct); > } >- while (((val + 1) & 0x7FF) <= 1); >+ while (((val + 1) & A64_UNSTABLE_LOBITS) <= 1); > } > > return (val); >@@ -275,6 +278,42 @@ arm_tmr_start(struct eventtimer *et, sbintime_t fi > > } > >+static int >+arm_tmr_start_a64_unstable(struct eventtimer *et, sbintime_t first, >+ sbintime_t period __unused) >+{ >+ struct arm_tmr_softc *sc; >+ int counts, ctrl; >+ uint64_t cntreg1, cntreg2; >+ >+ sc = (struct arm_tmr_softc *)et->et_priv; >+ >+ if (first == 0) >+ return (EINVAL); >+ >+ /* >+ * The hardware apparently suffers internally from the same bug software >+ * sees when reading the count register: during a rollover the read >+ * returns an indeterminate value for the low 11 bits (all-zeroes or >+ * all-ones). A write to the tval register is handled internally by >+ * reading the count register, adding the tval, and storing the result >+ * to the compare register. A rollover glitch on the read resutls in a >+ * compare value roughly 2^32 ticks late (so we hang for 3 minutes). We >+ * retry if the upper bits of the counter are different before and >+ * after setting tval -- we ensure no rollover during the set. >+ */ >+ counts = ((uint32_t)et->et_frequency * first) >> 32; >+ ctrl = (get_ctrl(sc->physical) & ~GT_CTRL_INT_MASK) | GT_CTRL_ENABLE; >+ do { >+ cntreg1 = get_cntxct(sc->physical) & A64_UNSTABLE_HIBITS; >+ set_tval(counts, sc->physical); >+ cntreg2 = get_cntxct(sc->physical) & A64_UNSTABLE_HIBITS; >+ } while (cntreg1 != cntreg2); >+ set_ctrl(ctrl, sc->physical); >+ >+ return (0); >+} >+ > static void > arm_tmr_disable(bool physical) > { >@@ -397,7 +436,9 @@ arm_tmr_attach(device_t dev) > #endif > int error; > int i; >+ bool a64_unstable; > >+ a64_unstable = false; > sc = device_get_softc(dev); > if (arm_tmr_sc) > return (ENXIO); >@@ -413,6 +454,7 @@ arm_tmr_attach(device_t dev) > sc->clkfreq = clock; > > if (OF_hasprop(node, "allwinner,sun50i-a64-unstable-timer")) { >+ a64_unstable = true; > sc->get_cntxct = &get_cntxct_a64_unstable; > if (bootverbose) > device_printf(dev, >@@ -475,7 +517,7 @@ arm_tmr_attach(device_t dev) > sc->et.et_frequency = sc->clkfreq; > sc->et.et_min_period = (0x00000010LLU << 32) / sc->et.et_frequency; > sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency; >- sc->et.et_start = arm_tmr_start; >+ sc->et.et_start = (a64_unstable) ? arm_tmr_start_a64_unstable : arm_tmr_start; > sc->et.et_stop = arm_tmr_stop; > sc->et.et_priv = sc; > et_register(&sc->et);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 229644
:
195014
|
195033
|
195062
|
196420