[coreboot] New patch to review for coreboot: 11d98bb Fix udelay() implementation for i945 romstage

Patrick Georgi (patrick@georgi-clan.de) gerrit at coreboot.org
Fri Jul 20 14:15:53 CEST 2012


Patrick Georgi (patrick at georgi-clan.de) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1254

-gerrit

commit 11d98bbd78ba811d961b11033240521a6f9ffb68
Author: Nico Huber <nico.huber at secunet.com>
Date:   Thu Jul 19 16:16:59 2012 +0200

    Fix udelay() implementation for i945 romstage
    
    Work around 32-bit overflow with 64-bit multiplication. Calculate
    correct CPU frequency.
    
    Change-Id: I86d78f2d70b9f9c62fd4e1e0d765e92e4de83f67
    Signed-off-by: Nico Huber <nico.huber at secunet.com>
---
 src/northbridge/intel/i945/udelay.c |   18 ++++++++++++++----
 1 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/src/northbridge/intel/i945/udelay.c b/src/northbridge/intel/i945/udelay.c
index 9170335..ce5e9d8 100644
--- a/src/northbridge/intel/i945/udelay.c
+++ b/src/northbridge/intel/i945/udelay.c
@@ -2,6 +2,7 @@
  * This file is part of the coreboot project.
  *
  * Copyright (C) 2007-2008 coresystems GmbH
+ *               2012 secunet Security Networks AG
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,6 +23,17 @@
 #include <cpu/x86/tsc.h>
 #include <cpu/x86/msr.h>
 
+/* Simple 32- to 64-bit multiplication. Uses 16-bit words to avoid overflow. */
+static inline void multiply_to_tsc(tsc_t *const tsc, const u32 a, const u32 b)
+{
+	tsc->lo = (a & 0xffff) * (b & 0xffff);
+	tsc->hi = ((tsc->lo >> 16)
+		   + ((a & 0xffff) * (b >> 16))
+		   + ((b & 0xffff) * (a >> 16)));
+	tsc->lo = ((tsc->hi & 0xffff) << 16) | (tsc->lo & 0xffff);
+	tsc->hi = ((a >> 16) * (b >> 16)) + (tsc->hi >> 16);
+}
+
 /**
  * Intel Core(tm) cpus always run the TSC at the maximum possible CPU clock
  */
@@ -33,7 +45,6 @@ void udelay(u32 us)
 	msr_t msr;
 	u32 fsb = 0, divisor;
 	u32 d;			/* ticks per us */
-	u32 dn = 0x1000000 / 2;	/* how many us before we need to use hi */
 
 	msr = rdmsr(0xcd);
 	switch (msr.lo & 0x07) {
@@ -63,10 +74,9 @@ void udelay(u32 us)
 	msr = rdmsr(0x198);
 	divisor = (msr.hi >> 8) & 0x1f;
 
-	d = fsb * divisor;
+	d = (fsb * divisor) / 4; /* CPU clock is always a quarter. */
 
-	tscd.hi = us / dn;
-	tscd.lo = (us - tscd.hi * dn) * d;
+	multiply_to_tsc(&tscd, us, d);
 
 	tsc1 = rdtsc();
 	dword = tsc1.lo + tscd.lo;




More information about the coreboot mailing list