Like other Intel chipsets, the Intel 3100 has a TCO timer that reboots the system automatically unless software resets the timer periodically. The extra reboot extends boot time by several seconds.
The attached patch adds a function to the Intel 3100 southbridge code that halts the TCO timer, thus preventing this extra reboot, and calls the function early in the boot process on the Mt. Arvon board.
It also fixes a bug in the LPC device initialization--the ACPI BAR enable flag is bit 7, not bit 4.
Signed-off-by: Ed Swierk eswierk@arastra.com
Quoting Ed Swierk eswierk@arastra.com:
Like other Intel chipsets, the Intel 3100 has a TCO timer that reboots the system automatically unless software resets the timer periodically. The extra reboot extends boot time by several seconds.
The attached patch adds a function to the Intel 3100 southbridge code that halts the TCO timer, thus preventing this extra reboot, and calls the function early in the boot process on the Mt. Arvon board.
It also fixes a bug in the LPC device initialization--the ACPI BAR enable flag is bit 7, not bit 4.
Signed-off-by: Ed Swierk eswierk@arastra.com
This also happens with the i830. Luckly it is just one simple register setting to disable it early in the process (auto.c).
/** * We have to disable the TCO Timer system reboot feature * or we get several reboots through out the boot processes. */ static void disable_tco_timer(void) { device_t dev; u8 reg8;
/* Set the LPC device statically. */ dev = PCI_DEV(0x0, 0x1f, 0x0);
/* Disable the TCO Timer system reboot feature. */ reg8 = pci_read_config8(dev, 0xd4); reg8 |= (1 << 1); pci_write_config8(dev, 0xd4, reg8); }
My only question is your code seems a little more complicated? Does it need to be that complicated? Otherwise it looks good. Acked-by: Joseph Smith joe@smittys.pointclark.net
Thanks - Joe
On Sat, Mar 29, 2008 at 6:38 AM, joe@smittys.pointclark.net wrote:
This also happens with the i830. Luckly it is just one simple register setting to disable it early in the process (auto.c).
/**
- We have to disable the TCO Timer system reboot feature
- or we get several reboots through out the boot processes.
*/ static void disable_tco_timer(void) { device_t dev; u8 reg8;
/* Set the LPC device statically. */ dev = PCI_DEV(0x0, 0x1f, 0x0); /* Disable the TCO Timer system reboot feature. */ reg8 = pci_read_config8(dev, 0xd4); reg8 |= (1 << 1); pci_write_config8(dev, 0xd4, reg8);
}
My only question is your code seems a little more complicated? Does it need to be that complicated? Otherwise it looks good. Acked-by: Joseph Smith joe@smittys.pointclark.net
The code you quoted above does not disable the TCO timer but rather prevents rebooting after the second timeout by setting the NO_REBOOT flag. My patch instead halts the TCO timer altogether, preventing both the SMI after the first timeout and rebooting after the second timeout, by setting the TCO_TMR_HALT flag in the TCO Control 1 register.
The NO_REBOOT flag also exists on the Intel 3100 but in a different place, at bit 5 of the GCS register at offset 0x3410 from memory BAR RCBA on the LPC bridge. Either approach would work, and either one requires mapping a memory or IO space to expose the register, so there's no difference in complexity.
Incidentally the TCO_TMR_HALT flag exists in the same place on a bunch of Intel chipsets, including ICH3, ICH7 and 3100. So while my code is a tad more complex, it's also more portable.
--Ed
Quoting Ed Swierk eswierk@arastra.com:
On Sat, Mar 29, 2008 at 6:38 AM, joe@smittys.pointclark.net wrote:
This also happens with the i830. Luckly it is just one simple register setting to disable it early in the process (auto.c).
/**
- We have to disable the TCO Timer system reboot feature
- or we get several reboots through out the boot processes.
*/ static void disable_tco_timer(void) { device_t dev; u8 reg8;
/* Set the LPC device statically. */ dev = PCI_DEV(0x0, 0x1f, 0x0); /* Disable the TCO Timer system reboot feature. */ reg8 = pci_read_config8(dev, 0xd4); reg8 |= (1 << 1); pci_write_config8(dev, 0xd4, reg8);
}
My only question is your code seems a little more complicated? Does it need to be that complicated? Otherwise it looks good. Acked-by: Joseph Smith joe@smittys.pointclark.net
The code you quoted above does not disable the TCO timer but rather prevents rebooting after the second timeout by setting the NO_REBOOT flag. My patch instead halts the TCO timer altogether, preventing both the SMI after the first timeout and rebooting after the second timeout, by setting the TCO_TMR_HALT flag in the TCO Control 1 register.
The NO_REBOOT flag also exists on the Intel 3100 but in a different place, at bit 5 of the GCS register at offset 0x3410 from memory BAR RCBA on the LPC bridge. Either approach would work, and either one requires mapping a memory or IO space to expose the register, so there's no difference in complexity.
Incidentally the TCO_TMR_HALT flag exists in the same place on a bunch of Intel chipsets, including ICH3, ICH7 and 3100. So while my code is a tad more complex, it's also more portable.
Hmm, I do like your approach alot better, it makes more sense. Thanks for the explination. Maybe there will be a patch coming for the i82801xx :-)
Thanks - Joe
Quoting joe@smittys.pointclark.net:
Quoting Ed Swierk eswierk@arastra.com:
On Sat, Mar 29, 2008 at 6:38 AM, joe@smittys.pointclark.net wrote:
This also happens with the i830. Luckly it is just one simple register setting to disable it early in the process (auto.c).
/**
- We have to disable the TCO Timer system reboot feature
- or we get several reboots through out the boot processes.
*/ static void disable_tco_timer(void) { device_t dev; u8 reg8;
/* Set the LPC device statically. */ dev = PCI_DEV(0x0, 0x1f, 0x0); /* Disable the TCO Timer system reboot feature. */ reg8 = pci_read_config8(dev, 0xd4); reg8 |= (1 << 1); pci_write_config8(dev, 0xd4, reg8);
}
My only question is your code seems a little more complicated? Does it need to be that complicated? Otherwise it looks good. Acked-by: Joseph Smith joe@smittys.pointclark.net
The code you quoted above does not disable the TCO timer but rather prevents rebooting after the second timeout by setting the NO_REBOOT flag. My patch instead halts the TCO timer altogether, preventing both the SMI after the first timeout and rebooting after the second timeout, by setting the TCO_TMR_HALT flag in the TCO Control 1 register.
The NO_REBOOT flag also exists on the Intel 3100 but in a different place, at bit 5 of the GCS register at offset 0x3410 from memory BAR RCBA on the LPC bridge. Either approach would work, and either one requires mapping a memory or IO space to expose the register, so there's no difference in complexity.
Incidentally the TCO_TMR_HALT flag exists in the same place on a bunch of Intel chipsets, including ICH3, ICH7 and 3100. So while my code is a tad more complex, it's also more portable.
Hmm, I do like your approach alot better, it makes more sense. Thanks for the explination. Maybe there will be a patch coming for the i82801xx :-)
After thinking about it..... What are the advantages of disabling the TCO timer (besides rebooting)? Doesn't the system need this to run properly? By setting the no reboot the timer is still running....does it need to be?
Thanks - Joe
On Sat, Mar 29, 2008 at 5:20 PM, joe@smittys.pointclark.net wrote:
After thinking about it..... What are the advantages of disabling the TCO timer (besides rebooting)? Doesn't the system need this to run properly? By setting the no reboot the timer is still running....does it need to be?
The point of the TCO timer is to let a system recover automatically by sending an interrupt and then rebooting if the OS crashes. While operating systems can crash for all sorts of reasons, coreboot code doesn't generally crash unless there's a hardware failure or misconfiguration that will not correct itself by rebooting. Thus it makes sense to disable the timer in coreboot and let a TCO-aware payload re-enable it.
The TCO timer has no other purpose that I'm aware of, so it doesn't matter whether coreboot neuters its effect by setting NO_REBOOT or halts it completely by setting TCO_TMR_HALT. Leaving the timer running still causes an interrupt to occur on timeout, but I think it's a no-op unless the OS is paying attention.
This document explains the TCO timer in more detail: ftp://download.intel.com/design/chipsets/applnots/29227301.pdf.
--Ed
Quoting Ed Swierk eswierk@arastra.com:
On Sat, Mar 29, 2008 at 5:20 PM, joe@smittys.pointclark.net wrote:
After thinking about it..... What are the advantages of disabling the TCO timer (besides rebooting)? Doesn't the system need this to run properly? By setting the no reboot the timer is still running....does it need to be?
The point of the TCO timer is to let a system recover automatically by sending an interrupt and then rebooting if the OS crashes. While operating systems can crash for all sorts of reasons, coreboot code doesn't generally crash unless there's a hardware failure or misconfiguration that will not correct itself by rebooting. Thus it makes sense to disable the timer in coreboot and let a TCO-aware payload re-enable it.
The TCO timer has no other purpose that I'm aware of, so it doesn't matter whether coreboot neuters its effect by setting NO_REBOOT or halts it completely by setting TCO_TMR_HALT. Leaving the timer running still causes an interrupt to occur on timeout, but I think it's a no-op unless the OS is paying attention.
This document explains the TCO timer in more detail: ftp://download.intel.com/design/chipsets/applnots/29227301.pdf.
--Ed
Thanks for the explanation Ed. That makes perfect sense.
Thanks - Joe
On 30.03.2008 16:18, joe@smittys.pointclark.net wrote:
Quoting Ed Swierk eswierk@arastra.com:
On Sat, Mar 29, 2008 at 5:20 PM, joe@smittys.pointclark.net wrote:
After thinking about it..... What are the advantages of disabling the TCO timer (besides rebooting)? Doesn't the system need this to run properly? By setting the no reboot the timer is still running....does it need to be?
The point of the TCO timer is to let a system recover automatically by sending an interrupt and then rebooting if the OS crashes. While operating systems can crash for all sorts of reasons, coreboot code doesn't generally crash unless there's a hardware failure or misconfiguration that will not correct itself by rebooting. Thus it makes sense to disable the timer in coreboot and let a TCO-aware payload re-enable it.
The TCO timer has no other purpose that I'm aware of, so it doesn't matter whether coreboot neuters its effect by setting NO_REBOOT or halts it completely by setting TCO_TMR_HALT. Leaving the timer running still causes an interrupt to occur on timeout, but I think it's a no-op unless the OS is paying attention.
This document explains the TCO timer in more detail: ftp://download.intel.com/design/chipsets/applnots/29227301.pdf.
Thanks for the explanation Ed. That makes perfect sense.
Please halt the timer completely if possible. We are not really prepared to handle interrupts in coreboot.
Regards, Carl-Daniel
Quoting Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net:
On 30.03.2008 16:18, joe@smittys.pointclark.net wrote:
Quoting Ed Swierk eswierk@arastra.com:
On Sat, Mar 29, 2008 at 5:20 PM, joe@smittys.pointclark.net wrote:
After thinking about it..... What are the advantages of disabling the TCO timer (besides rebooting)? Doesn't the system need this to run properly? By setting the no reboot the timer is still running....does it need to be?
The point of the TCO timer is to let a system recover automatically by sending an interrupt and then rebooting if the OS crashes. While operating systems can crash for all sorts of reasons, coreboot code doesn't generally crash unless there's a hardware failure or misconfiguration that will not correct itself by rebooting. Thus it makes sense to disable the timer in coreboot and let a TCO-aware payload re-enable it.
The TCO timer has no other purpose that I'm aware of, so it doesn't matter whether coreboot neuters its effect by setting NO_REBOOT or halts it completely by setting TCO_TMR_HALT. Leaving the timer running still causes an interrupt to occur on timeout, but I think it's a no-op unless the OS is paying attention.
This document explains the TCO timer in more detail: ftp://download.intel.com/design/chipsets/applnots/29227301.pdf.
Thanks for the explanation Ed. That makes perfect sense.
Please halt the timer completely if possible. We are not really prepared to handle interrupts in coreboot.
Hmm, this is going to be interesting on the ICH4, I still have to look at how the other ICH's are setup. The TCO Timer Halt is acually located in I/O space not PCI configuration space. It is ACPIBASE + TCOBASE(60h) + TCO1_CNT(08h) bit 11. We'll see.
Thanks - Joe
On Wed, Apr 2, 2008 at 10:48 AM, joe@smittys.pointclark.net wrote:
Hmm, this is going to be interesting on the ICH4, I still have to look at how the other ICH's are setup. The TCO Timer Halt is acually located in I/O space not PCI configuration space. It is ACPIBASE + TCOBASE(60h) + TCO1_CNT(08h) bit 11. We'll see.
This is exactly how it works on the Intel 3100; see i3100_halt_tco_timer() in my patch (http://qa.coreboot.org/log_commit.php?revision=3198).
--Ed
Quoting Ed Swierk eswierk@arastra.com:
On Wed, Apr 2, 2008 at 10:48 AM, joe@smittys.pointclark.net wrote:
Hmm, this is going to be interesting on the ICH4, I still have to look at how the other ICH's are setup. The TCO Timer Halt is acually located in I/O space not PCI configuration space. It is ACPIBASE + TCOBASE(60h) + TCO1_CNT(08h) bit 11. We'll see.
This is exactly how it works on the Intel 3100; see i3100_halt_tco_timer() in my patch (http://qa.coreboot.org/log_commit.php?revision=3198).
--Ed
Wow your right:-) Looks like the only difference is the I/O Base address is 0x00000500 on the ICH series, this should be simple than. Thanks for laying down the base code Ed :-)
Thanks - Joe
On Thu, Apr 3, 2008 at 9:34 AM, joe@smittys.pointclark.net wrote:
Wow your right:-) Looks like the only difference is the I/O Base address is 0x00000500 on the ICH series, this should be simple than. Thanks for laying down the base code Ed :-)
I'm not sure what you mean--you get to choose the base address for the ACPI I/O registers, and you program that into the ACPIBASE register (offset 0x40 in the LPC device's config space). The choice is fairly arbitrary, as this code runs very early during the boot process, well before most other I/O regions are allocated. Just don't overlap some important I/O address like 0x3f8 (owned by the serial port).
--Ed
Quoting Ed Swierk eswierk@arastra.com:
On Thu, Apr 3, 2008 at 9:34 AM, joe@smittys.pointclark.net wrote:
Wow your right:-) Looks like the only difference is the I/O Base address is 0x00000500 on the ICH series, this should be simple than. Thanks for laying down the base code Ed :-)
I'm not sure what you mean--you get to choose the base address for the ACPI I/O registers, and you program that into the ACPIBASE register (offset 0x40 in the LPC device's config space). The choice is fairly arbitrary, as this code runs very early during the boot process, well before most other I/O regions are allocated. Just don't overlap some important I/O address like 0x3f8 (owned by the serial port).
--Ed
I'm not sure what you mean?? I can't just pick any old base address for the ACPI I/O registers, it is already pre-determined in i82801xx_lpc.c at 0x00000500. So all I need to do is set ACPIBASE(00000500h) + TCOBASE(60h) + TCO1_CNT(08h) = 0x00000568 bit 11 to 1, it's that simple. I know this will run early before i82801xx_lpc.c but we don't want any conflicts do we?
Thanks - Joe
On Thu, Apr 3, 2008 at 10:06 AM, joe@smittys.pointclark.net wrote:
I'm not sure what you mean?? I can't just pick any old base address for the ACPI I/O registers, it is already pre-determined in i82801xx_lpc.c at 0x00000500. So all I need to do is set ACPIBASE(00000500h) + TCOBASE(60h) + TCO1_CNT(08h) = 0x00000568 bit 11 to 1, it's that simple. I know this will run early before i82801xx_lpc.c but we don't want any conflicts do we?
As long as the early code disables the I/O region when it's finished using it (as i3100_halt_tco_timer() does), there's no possibility of a conflict. But I think we're in violent agreement that 0x0500 will work just fine.
--Ed
Quoting Ed Swierk eswierk@arastra.com:
On Thu, Apr 3, 2008 at 10:06 AM, joe@smittys.pointclark.net wrote:
I'm not sure what you mean?? I can't just pick any old base address for the ACPI I/O registers, it is already pre-determined in i82801xx_lpc.c at 0x00000500. So all I need to do is set ACPIBASE(00000500h) + TCOBASE(60h) + TCO1_CNT(08h) = 0x00000568 bit 11 to 1, it's that simple. I know this will run early before i82801xx_lpc.c but we don't want any conflicts do we?
As long as the early code disables the I/O region when it's finished using it (as i3100_halt_tco_timer() does), there's no possibility of a conflict. But I think we're in violent agreement that 0x0500 will work just fine.
No need for a violent agreement Ed. As you may already know, sometimes I like to debate things to make sure I understand them properly. This is how I learn :-)
Thanks - Joe
On Sat, Mar 29, 2008 at 12:07:36AM -0700, Ed Swierk wrote:
Like other Intel chipsets, the Intel 3100 has a TCO timer that reboots the system automatically unless software resets the timer periodically. The extra reboot extends boot time by several seconds.
The attached patch adds a function to the Intel 3100 southbridge code that halts the TCO timer, thus preventing this extra reboot, and calls the function early in the boot process on the Mt. Arvon board.
It also fixes a bug in the LPC device initialization--the ACPI BAR enable flag is bit 7, not bit 4.
Signed-off-by: Ed Swierk eswierk@arastra.com
Looks good, thanks. Committed in r3198.
Index: coreboot-v2-3189/src/southbridge/intel/i3100/i3100_early_lpc.c
--- coreboot-v2-3189.orig/src/southbridge/intel/i3100/i3100_early_lpc.c +++ coreboot-v2-3189/src/southbridge/intel/i3100/i3100_early_lpc.c @@ -30,3 +30,23 @@ static void i3100_enable_superio(void) /* Enable decoding of I/O locations for SuperIO devices */ pci_write_config16(dev, 0x82, 0x340f); }
+static void i3100_halt_tco_timer(void) +{
- device_t dev;
- dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_3100_LPC), 0);
- if (dev == PCI_DEV_INVALID) {
die("LPC bridge not found\r\n");
- }
If you feel bored one of these days, please post a patch to remove the unneeded pci_locate_device() stuff from all of i3100 (and also other chipsets if you're inclined), as discussed in another thread. Those checks are not needed, as no non-i3100 boards should call those functions anyway...
Uwe.
Pardon my ignorance, but doesn't this at least partly defeat the purpose of the TCO timer? Shouldn't Linuxbios instead be taught to poke the keepalive register periodically?
How about the case of primary/fallback images, can't the TCO timer be leveraged to auto-fallback when flashing a new primary image?
On Sat, 2008-03-29 at 00:07 -0700, Ed Swierk wrote:
Like other Intel chipsets, the Intel 3100 has a TCO timer that reboots the system automatically unless software resets the timer periodically. The extra reboot extends boot time by several seconds.
The attached patch adds a function to the Intel 3100 southbridge code that halts the TCO timer, thus preventing this extra reboot, and calls the function early in the boot process on the Mt. Arvon board.
It also fixes a bug in the LPC device initialization--the ACPI BAR enable flag is bit 7, not bit 4.
Signed-off-by: Ed Swierk eswierk@arastra.com
coreboot mailing list coreboot@coreboot.org http://www.coreboot.org/mailman/listinfo/coreboot
On Mon, Apr 07, 2008 at 03:50:42PM -0400, Jeremy Jackson wrote:
Pardon my ignorance, but doesn't this at least partly defeat the purpose of the TCO timer? Shouldn't Linuxbios instead be taught to poke the keepalive register periodically?
There are some technical issues..
How about the case of primary/fallback images, can't the TCO timer be leveraged to auto-fallback when flashing a new primary image?
..specifically coreboot doesn't handle interrupts.
I think adding interrupt handling would need a bit of work, to make sure that it is reliable.
Also, there may not be much point in enabling interrupts within coreboot since interrupts are assigned somewhat late in the process.
Finally there's the payload issue. Even if coreboot keeps the timer alive the payload may not => fail.
//Peter
On Mon, Apr 7, 2008 at 2:03 PM, Peter Stuge peter@stuge.se wrote:
There are some technical issues..
..specifically coreboot doesn't handle interrupts.
Well, the TCO watchdog can reboot the system without software handling any interrupts.
It would indeed be nice if boards with normal+fallback images allowed watchdog to reboot with the fallback image automatically if the normal image fails. If the normal image doesn't boot far enough to call i3100_halt_tco_timer(), this is exactly what will happen.
--Ed
On Mon, Apr 07, 2008 at 03:55:41PM -0700, Ed Swierk wrote:
On Mon, Apr 7, 2008 at 2:03 PM, Peter Stuge peter@stuge.se wrote:
There are some technical issues..
..specifically coreboot doesn't handle interrupts.
Well, the TCO watchdog can reboot the system without software handling any interrupts.
True, but it's not very easy to regularly poke the timer without an interrupt - or the code will be full of try_poke() every other line.
It would indeed be nice if boards with normal+fallback images allowed watchdog to reboot with the fallback image automatically if the normal image fails. If the normal image doesn't boot far enough to call i3100_halt_tco_timer(), this is exactly what will happen.
Yes, I like the idea too. But it may not be so easy to implement. That shouldn't scare anyone off of course. :)
//Peter
On Tue, 2008-04-08 at 01:13 +0200, Peter Stuge wrote:
True, but it's not very easy to regularly poke the timer without an interrupt - or the code will be full of try_poke() every other line.
What about the mostly existing code that pokes port 0x80? make it a macro that also pokes the WDT?
If there are "long" sections for a single POST code, (like clearing 4GB ECC ram), having a bit toggling would be less boring to watch anyhow.
I was reading datasheet for Intel 845 chipset, there seems to be a lot of registers outside the reset domain of the processor. Adding in a 3rd poke of the POST code to a scratch register like that, would mean that the last POST code before the WDT resets the CPU would be available to the next incarnation (perhaps fallback).