Commit a2f7c354 authored by Jaya Kumar's avatar Jaya Kumar Committed by Linus Torvalds

[PATCH] x86 reboot: Add reboot fixup for gx1/cs5530a

This patch by Jaya Kumar introduces a generic infrastructure to deal with
x86 chipsets with nonstandard reset sequences, and adds support for the
Geode gx1/cs5530a chipset.
Signed-off-by: default avatarJaya Kumar <jayalk@intworks.biz>
Signed-off-by: default avatarH. Peter Anvin <hpa@zytor.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 67701ae9
...@@ -653,6 +653,24 @@ config I8K ...@@ -653,6 +653,24 @@ config I8K
Say Y if you intend to run this kernel on a Dell Inspiron 8000. Say Y if you intend to run this kernel on a Dell Inspiron 8000.
Say N otherwise. Say N otherwise.
config X86_REBOOTFIXUPS
bool "Enable X86 board specific fixups for reboot"
depends on X86
default n
---help---
This enables chipset and/or board specific fixups to be done
in order to get reboot to work correctly. This is only needed on
some combinations of hardware and BIOS. The symptom, for which
this config is intended, is when reboot ends with a stalled/hung
system.
Currently, the only fixup is for the Geode GX1/CS5530A/TROM2.1.
combination.
Say Y if you want to enable the fixup. Currently, it's safe to
enable this option even if you don't need it.
Say N otherwise.
config MICROCODE config MICROCODE
tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support" tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
---help--- ---help---
......
...@@ -23,6 +23,7 @@ obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o ...@@ -23,6 +23,7 @@ obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
obj-$(CONFIG_X86_MPPARSE) += mpparse.o obj-$(CONFIG_X86_MPPARSE) += mpparse.o
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o
obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o
obj-$(CONFIG_X86_NUMAQ) += numaq.o obj-$(CONFIG_X86_NUMAQ) += numaq.o
obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o
obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_KPROBES) += kprobes.o
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/apic.h> #include <asm/apic.h>
#include "mach_reboot.h" #include "mach_reboot.h"
#include <linux/reboot_fixups.h>
/* /*
* Power off function, if any * Power off function, if any
...@@ -348,6 +349,7 @@ void machine_restart(char * __unused) ...@@ -348,6 +349,7 @@ void machine_restart(char * __unused)
/* rebooting needs to touch the page at absolute addr 0 */ /* rebooting needs to touch the page at absolute addr 0 */
*((unsigned short *)__va(0x472)) = reboot_mode; *((unsigned short *)__va(0x472)) = reboot_mode;
for (;;) { for (;;) {
mach_reboot_fixups(); /* for board specific fixups */
mach_reboot(); mach_reboot();
/* That didn't work - force a triple fault.. */ /* That didn't work - force a triple fault.. */
__asm__ __volatile__("lidt %0": :"m" (no_idt)); __asm__ __volatile__("lidt %0": :"m" (no_idt));
......
/*
* linux/arch/i386/kernel/reboot_fixups.c
*
* This is a good place to put board specific reboot fixups.
*
* List of supported fixups:
* geode-gx1/cs5530a - Jaya Kumar <jayalk@intworks.biz>
*
*/
#include <asm/delay.h>
#include <linux/pci.h>
static void cs5530a_warm_reset(struct pci_dev *dev)
{
/* writing 1 to the reset control register, 0x44 causes the
cs5530a to perform a system warm reset */
pci_write_config_byte(dev, 0x44, 0x1);
udelay(50); /* shouldn't get here but be safe and spin-a-while */
return;
}
struct device_fixup {
unsigned int vendor;
unsigned int device;
void (*reboot_fixup)(struct pci_dev *);
};
static struct device_fixup fixups_table[] = {
{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset },
};
/*
* we see if any fixup is available for our current hardware. if there
* is a fixup, we call it and we expect to never return from it. if we
* do return, we keep looking and then eventually fall back to the
* standard mach_reboot on return.
*/
void mach_reboot_fixups(void)
{
struct device_fixup *cur;
struct pci_dev *dev;
int i;
for (i=0; i < (sizeof(fixups_table)/sizeof(fixups_table[0])); i++) {
cur = &(fixups_table[i]);
dev = pci_get_device(cur->vendor, cur->device, 0);
if (!dev)
continue;
cur->reboot_fixup(dev);
}
printk(KERN_WARNING "No reboot fixup found for your hardware\n");
}
#ifndef _LINUX_REBOOT_FIXUPS_H
#define _LINUX_REBOOT_FIXUPS_H
#ifdef CONFIG_X86_REBOOTFIXUPS
extern void mach_reboot_fixups(void);
#else
#define mach_reboot_fixups() ((void)(0))
#endif
#endif /* _LINUX_REBOOT_FIXUPS_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment