warm reboot Geode

Andrew Ip aip at cwlinux.com
Thu Jan 16 09:38:00 CET 2003


John,

> When I use the reboot command on my Dorado demo board from National 
> (with their BIOS), It will successfully warm boot the machine.  When I 
> use my LinuxBIOS image on the Dorado or my Geode machine, the machine 
> just stalls at the point where the reset should occur.  It seems to me 
> that Linux is performing a BIOS Int function that is not implemented in 
> my build of LinuxBIOS.  Anyone had any luck with this?
Kenerl doesn't support it by default.  Basically you need to add a reset routine
for cs5530.  Here is my patch which works for me.  It is for 2.4.17, but
shouldn't be too hard to patch it on 2.4.20.

-Andrew

-- 
Andrew Ip
Email:  aip at cwlinux.com
Tel:    (852) 2542 2046
Fax:    (852) 2542 2036
Mobile: (852) 9201 9866

Cwlinux Limited
Unit 202B 2/F Lai Cheong Factory Building,
479-479A Castle Peak Road,
Lai Chi Kok, Kowloon,
Hong Kong.

Tel: (852)2542 2046
Fax: (852)2542 2036

For public pgp key, please obtain it from http://www.keyserver.net/en.
-------------- next part --------------
diff -Nur linux/arch/i386/kernel/process.c linux-geode.reset/arch/i386/kernel/process.c
--- linux/arch/i386/kernel/process.c	Fri Oct  5 09:42:54 2001
+++ linux-geode.reset/arch/i386/kernel/process.c	Fri Jul 19 15:17:49 2002
@@ -49,6 +49,153 @@
 
 #include <linux/irq.h>
 
+#define CONFIG_LINUXBIOS_PM
+#ifdef CONFIG_LINUXBIOS_PM
+#include <linux/pci.h>
+void
+cs5530_reset(struct pci_dev *dev)
+{
+	struct pci_dev *dev;
+
+	printk(KERN_ERR __FUNCTION__ ": starting reset operation. \n");
+
+	dev = pci_find_device(PCI_VENDOR_ID_CYRIX, \
+			PCI_DEVICE_ID_CYRIX_5530_LEGACY, 0);
+
+	if (dev == NULL) {
+		printk(KERN_ERR __FUNCTION__ ": can't find device!!!\n");
+	}
+
+	/* Execute system wide reset by doing X-Bus Warm Start*/
+	pci_write_config_byte(dev, 0x44, 0x1);
+
+	printk(KERN_ERR __FUNCTION__ ": We should reset soon. \n");
+}
+
+void
+sis503_reset(struct pci_dev *dev)
+{
+	unsigned char b;
+	unsigned short acpi_base;
+
+	printk(KERN_ERR __FUNCTION__ ": starting reset operation. \n");
+
+	/* Enable ACPI by set B7 on Reg 0x40, LPC */
+	pci_read_config_byte(dev, 0x40, &b);
+	pci_write_config_byte(dev, 0x40, b | 0x80);
+	printk(KERN_ERR __FUNCTION__ ": enabled ACPI. \n");
+
+	/* get the ACPI base address for register 0x74,0x75 of LPC */
+	pci_read_config_word(dev, 0x74, &acpi_base);	
+	printk(KERN_ERR __FUNCTION__ ":acpi base: %x\n", acpi_base);
+
+	/* Set software watchdog timer init value */
+	outb(0x03, 0x4a + acpi_base);
+	printk(KERN_ERR __FUNCTION__ ": set the dog. \n");
+
+	printk(KERN_ERR __FUNCTION__ ": enabling dog. \n");
+	/* Software watchdog enable, issue PCIRST# when time expire */
+	outb(0x8f, 0x4b + acpi_base);
+
+	printk(KERN_ERR __FUNCTION__ ": We should reset soon. \n");
+}
+
+void
+sis503_off(struct pci_dev *dev)
+{
+	unsigned char b;
+	unsigned short acpi_base;
+
+	printk(KERN_ERR __FUNCTION__ ": starting reset operation. \n");
+	/* Enable ACPI by set B7 on Reg 0x40, LPC */
+	pci_read_config_byte(dev, 0x40, &b);
+	pci_write_config_byte(dev, 0x40, b | 0x80);
+	printk(KERN_ERR __FUNCTION__ ": enabled ACPI. \n");
+
+        /* get the ACPI base address for register 0x74,0x75 of LPC */
+	pci_read_config_word(dev, 0x74, &acpi_base);
+	printk (KERN_ERR __FUNCTION__ ":acpi base: %x\n", acpi_base);
+
+	/* ACPI Register 5, Bit 10-12, Sleeping Type,
+	   set to 101 -> S5, soft_off */
+	outb(0x14, 0x05 + acpi_base);
+	printk(KERN_ERR __FUNCTION__ ": DONE setting sleep type. \n");
+
+	/* ACPI Register 5, Bit 13, Sleep Enable */
+	outb(0x20 | 0x14, 0x05 + acpi_base);
+	printk(KERN_ERR __FUNCTION__ ": DONE sleep enable. \n");
+}
+
+struct pci_dev * pci_find_device(unsigned int vendor, unsigned int device, 
+				 const struct pci_dev *from);
+
+struct linuxbios_control {
+	u_short vendor, device;
+	void (*poweroff)(struct pci_dev *);
+	void (*reset)(struct pci_dev *);
+};
+
+struct linuxbios_control controls[] = {
+	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, sis503_off, sis503_reset},
+	{PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, NULL, cs5530_reset}
+};
+
+struct linuxbios_control *findcontrol(struct pci_dev **d)
+{
+	struct linuxbios_control *lb = controls, *retval = 0;
+	int i;
+
+	printk(KERN_ERR __FUNCTION__ ": Find vendor 0x%x device 0x%x\n", 
+	       lb->vendor, lb->device);
+	for(lb = controls, i = 0; 
+	    (i < sizeof(controls)/sizeof(controls[0])) && (! retval); 
+	    i++, lb++)
+	{
+		*d = pci_find_device(lb->vendor, lb->device, 0);
+		if (*d)
+			retval = lb;
+	}
+
+	printk(KERN_ERR __FUNCTION__ ": result of find is %p\n", retval);
+	return retval;
+}
+
+void
+linuxbios_poweroff(void)
+{
+	struct linuxbios_control *lb = 0;
+	struct pci_dev *dev;
+
+	printk(KERN_ERR __FUNCTION__ ": find an lb\n");
+	lb = findcontrol(&dev);
+
+	printk(KERN_ERR __FUNCTION__ ": found lb %p, call %p\n", 
+	       lb, lb ? lb->poweroff : 0);
+	if (lb && (lb->poweroff))
+		lb->poweroff(dev);
+	printk(KERN_ERR __FUNCTION__ ": Returning? Can't happen, I thought?\n");
+}
+
+void
+linuxbios_reset(void)
+{
+	struct linuxbios_control *lb = 0;
+	struct pci_dev *dev;
+
+	printk(KERN_ERR __FUNCTION__ ": find an lb\n");
+	lb = findcontrol(&dev);
+
+	printk(KERN_ERR __FUNCTION__ ": found lb %p, call %p\n", 
+	       lb, lb ? lb->reset : 0);
+	if (lb && (lb->reset))
+		lb->reset(dev);
+
+	printk(KERN_ERR __FUNCTION__ ": Returning? Can't happen, I thought?\n");
+}
+
+#endif
+
+
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
 int hlt_counter;
@@ -399,6 +546,9 @@
 	 */
 	smp_send_stop();
 	disable_IO_APIC();
+#endif
+#ifdef CONFIG_LINUXBIOS_PM
+	linuxbios_reset();
 #endif
 
 	if(!reboot_thru_bios) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 232 bytes
Desc: not available
URL: <http://www.coreboot.org/pipermail/coreboot/attachments/20030116/4e26c69b/attachment.sig>


More information about the coreboot mailing list