[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: Jaya Kumar <jayalk@intworks.biz> Signed-off-by: H. Peter Anvin <hpa@zytor.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Родитель
67701ae976
Коммит
a2f7c35415
|
@ -653,6 +653,24 @@ config I8K
|
|||
Say Y if you intend to run this kernel on a Dell Inspiron 8000.
|
||||
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
|
||||
tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
|
||||
---help---
|
||||
|
|
|
@ -23,6 +23,7 @@ obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
|
|||
obj-$(CONFIG_X86_MPPARSE) += mpparse.o
|
||||
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.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_SUMMIT_NUMA) += summit.o
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <asm/apic.h>
|
||||
#include "mach_reboot.h"
|
||||
#include <linux/reboot_fixups.h>
|
||||
|
||||
/*
|
||||
* Power off function, if any
|
||||
|
@ -348,6 +349,7 @@ void machine_restart(char * __unused)
|
|||
/* rebooting needs to touch the page at absolute addr 0 */
|
||||
*((unsigned short *)__va(0x472)) = reboot_mode;
|
||||
for (;;) {
|
||||
mach_reboot_fixups(); /* for board specific fixups */
|
||||
mach_reboot();
|
||||
/* That didn't work - force a triple fault.. */
|
||||
__asm__ __volatile__("lidt %0": :"m" (no_idt));
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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");
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#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 */
|
Загрузка…
Ссылка в новой задаче