summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2012-11-03 11:41:37 +0000
committerSimon Glass <sjg@chromium.org>2012-12-06 14:30:43 -0800
commit1350f1cce1859e277ed6766608554bd3914a2413 (patch)
tree23a40e6e18ac835e7127bc69ea0e0f4f6eb94575
parent7c71034d3ca2f4bd01812e94e813d35a78a27e34 (diff)
downloadu-boot-imx-1350f1cce1859e277ed6766608554bd3914a2413.zip
u-boot-imx-1350f1cce1859e277ed6766608554bd3914a2413.tar.gz
u-boot-imx-1350f1cce1859e277ed6766608554bd3914a2413.tar.bz2
x86: Provide a way to throttle port80 accesses
Some systems (like Google Link device) provide the ability to keep a history of the target CPU port80 accesses, which is extremely handy for debugging. The problem is that the EC handling port 80 access is orders of magnitude slower than the AP. This causes random loss of trace data. This change allows to throttle port 80 accesses such that in case the AP is trying to post faster than the EC can handle, a delay is introduced to make sure that the post rate is throttled. Experiments have shown that on Link the delay should be at least 350,000 of tsc clocks. Throttling is not being enabled by default: to enable it one would have to set MIN_PORT80_KCLOCKS_DELAY to something like 400 and rebuild the u-boot image. With upcoming EC code optimizations this number could be decreased (new new value should be established experimentally). Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Signed-off-by: Simon Glass <sjg@chromium.org>
-rw-r--r--arch/x86/cpu/coreboot/coreboot.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c
index 1c8a007..6e196d7 100644
--- a/arch/x86/cpu/coreboot/coreboot.c
+++ b/arch/x86/cpu/coreboot/coreboot.c
@@ -69,6 +69,27 @@ int board_early_init_r(void)
void show_boot_progress(int val)
{
+#if MIN_PORT80_KCLOCKS_DELAY
+ static uint32_t prev_stamp;
+ static uint32_t base;
+
+ /*
+ * Scale the time counter reading to avoid using 64 bit arithmetics.
+ * Can't use get_timer() here becuase it could be not yet
+ * initialized or even implemented.
+ */
+ if (!prev_stamp) {
+ base = rdtsc() / 1000;
+ prev_stamp = 0;
+ } else {
+ uint32_t now;
+
+ do {
+ now = rdtsc() / 1000 - base;
+ } while (now < (prev_stamp + MIN_PORT80_KCLOCKS_DELAY));
+ prev_stamp = now;
+ }
+#endif
outb(val, 0x80);
}