Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31ac409a authored by Ingo Molnar's avatar Ingo Molnar
Browse files

x86, VisWS: turn into generic arch, add early init quirks



add early init quirks for VisWS. This gradually turns the VISWS subarch
into a generic PC architecture.

Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 22d5c67c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -186,7 +186,7 @@ config X86_HT

config X86_BIOS_REBOOT
	bool
	depends on !X86_VISWS && !X86_VOYAGER
	depends on !X86_VOYAGER
	default y

config X86_TRAMPOLINE
+1 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
# Makefile for the linux kernel.
#

obj-y				:= setup.o traps.o reboot.o
obj-y				:= setup.o setup_visws.o traps.o

obj-$(CONFIG_X86_VISWS_APIC)	+= visws_apic.o
obj-$(CONFIG_X86_LOCAL_APIC)	+= mpparse.o

arch/x86/mach-visws/reboot.c

deleted100644 → 0
+0 −55
Original line number Diff line number Diff line
#include <linux/module.h>
#include <linux/smp.h>
#include <linux/delay.h>

#include <asm/io.h>
#include "piix4.h"

void (*pm_power_off)(void);
EXPORT_SYMBOL(pm_power_off);

void machine_shutdown(void)
{
#ifdef CONFIG_SMP
	smp_send_stop();
#endif
}

void machine_emergency_restart(void)
{
	/*
	 * Visual Workstations restart after this
	 * register is poked on the PIIX4
	 */
	outb(PIIX4_RESET_VAL, PIIX4_RESET_PORT);
}

void machine_restart(char * __unused)
{
	machine_shutdown();
	machine_emergency_restart();
}

void machine_power_off(void)
{
	unsigned short pm_status;
/*	extern unsigned int pci_bus0; */

	while ((pm_status = inw(PMSTS_PORT)) & 0x100)
		outw(pm_status, PMSTS_PORT);

	outw(PM_SUSPEND_ENABLE, PMCNTRL_PORT);

	mdelay(10);

#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
	(0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))

/*	outl(PCI_CONF1_ADDRESS(pci_bus0, SPECIAL_DEV, SPECIAL_REG), 0xCF8); */
	outl(PIIX_SPECIAL_STOP, 0xCFC);
}

void machine_halt(void)
{
}
+30 −0
Original line number Diff line number Diff line
@@ -10,6 +10,14 @@
#include <asm/e820.h>
#include <asm/setup.h>

/*
 * Any quirks to be performed to initialize timers/irqs/etc?
 */
int (*arch_time_init_quirk)(void);
int (*arch_pre_intr_init_quirk)(void);
int (*arch_intr_init_quirk)(void);
int (*arch_trap_init_quirk)(void);

#ifdef CONFIG_HOTPLUG_CPU
#define DEFAULT_SEND_IPI	(1)
#else
@@ -29,6 +37,10 @@ int no_broadcast=DEFAULT_SEND_IPI;
 **/
void __init pre_intr_init_hook(void)
{
	if (arch_pre_intr_init_quirk) {
		if (arch_pre_intr_init_quirk())
			return;
	}
	init_ISA_irqs();
}

@@ -52,6 +64,10 @@ static struct irqaction irq2 = {
 **/
void __init intr_init_hook(void)
{
	if (arch_intr_init_quirk) {
		if (arch_intr_init_quirk())
			return;
	}
#ifdef CONFIG_X86_LOCAL_APIC
	apic_intr_init();
#endif
@@ -81,6 +97,10 @@ void __init pre_setup_arch_hook(void)
 **/
void __init trap_init_hook(void)
{
	if (arch_trap_init_quirk) {
		if (arch_trap_init_quirk())
			return;
	}
}

static struct irqaction irq0  = {
@@ -99,6 +119,16 @@ static struct irqaction irq0 = {
 **/
void __init time_init_hook(void)
{
	if (arch_time_init_quirk) {
		/*
		 * A nonzero return code does not mean failure, it means
		 * that the architecture quirk does not want any
		 * generic (timer) setup to be performed after this:
		 */
		if (arch_time_init_quirk())
			return;
	}

	irq0.mask = cpumask_of_cpu(0);
	setup_irq(0, &irq0);
}
+233 −0
Original line number Diff line number Diff line
/*
 *  Unmaintained SGI Visual Workstation support.
 *  Split out from setup.c by davej@suse.de
 */

#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/smp.h>

#include <asm/arch_hooks.h>
#include <asm/fixmap.h>
#include <asm/reboot.h>
#include <asm/setup.h>
#include <asm/e820.h>
#include <asm/io.h>

#include <mach_ipi.h>

#include "cobalt.h"
#include "piix4.h"

char visws_board_type	= -1;
char visws_board_rev	= -1;

static int __init visws_time_init_quirk(void)
{
	printk(KERN_INFO "Starting Cobalt Timer system clock\n");

	/* Set the countdown value */
	co_cpu_write(CO_CPU_TIMEVAL, CO_TIME_HZ/HZ);

	/* Start the timer */
	co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) | CO_CTRL_TIMERUN);

	/* Enable (unmask) the timer interrupt */
	co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK);

	/*
	 * Zero return means the generic timer setup code will set up
	 * the standard vector:
	 */
	return 0;
}

static int __init visws_pre_intr_init_quirk(void)
{
	init_VISWS_APIC_irqs();

	/*
	 * We dont want ISA irqs to be set up by the generic code:
	 */
	return 1;
}

/* Quirk for machine specific memory setup. */

#define MB (1024 * 1024)

unsigned long sgivwfb_mem_phys;
unsigned long sgivwfb_mem_size;
EXPORT_SYMBOL(sgivwfb_mem_phys);
EXPORT_SYMBOL(sgivwfb_mem_size);

long long mem_size __initdata = 0;

static char * __init visws_memory_setup_quirk(void)
{
	long long gfx_mem_size = 8 * MB;

	mem_size = boot_params.alt_mem_k;

	if (!mem_size) {
		printk(KERN_WARNING "Bootloader didn't set memory size, upgrade it !\n");
		mem_size = 128 * MB;
	}

	/*
	 * this hardcodes the graphics memory to 8 MB
	 * it really should be sized dynamically (or at least
	 * set as a boot param)
	 */
	if (!sgivwfb_mem_size) {
		printk(KERN_WARNING "Defaulting to 8 MB framebuffer size\n");
		sgivwfb_mem_size = 8 * MB;
	}

	/*
	 * Trim to nearest MB
	 */
	sgivwfb_mem_size &= ~((1 << 20) - 1);
	sgivwfb_mem_phys = mem_size - gfx_mem_size;

	e820_add_region(0, LOWMEMSIZE(), E820_RAM);
	e820_add_region(HIGH_MEMORY, mem_size - sgivwfb_mem_size - HIGH_MEMORY, E820_RAM);
	e820_add_region(sgivwfb_mem_phys, sgivwfb_mem_size, E820_RESERVED);

	return "PROM";
}

static void visws_machine_emergency_restart(void)
{
	/*
	 * Visual Workstations restart after this
	 * register is poked on the PIIX4
	 */
	outb(PIIX4_RESET_VAL, PIIX4_RESET_PORT);
}

static void visws_machine_power_off(void)
{
	unsigned short pm_status;
/*	extern unsigned int pci_bus0; */

	while ((pm_status = inw(PMSTS_PORT)) & 0x100)
		outw(pm_status, PMSTS_PORT);

	outw(PM_SUSPEND_ENABLE, PMCNTRL_PORT);

	mdelay(10);

#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
	(0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))

/*	outl(PCI_CONF1_ADDRESS(pci_bus0, SPECIAL_DEV, SPECIAL_REG), 0xCF8); */
	outl(PIIX_SPECIAL_STOP, 0xCFC);
}

extern int visws_trap_init_quirk(void);

void __init visws_early_detect(void)
{
	int raw;

	visws_board_type = (char)(inb_p(PIIX_GPI_BD_REG) & PIIX_GPI_BD_REG)
							 >> PIIX_GPI_BD_SHIFT;

	if (visws_board_type < 0)
		return;

	/*
	 * Install special quirks for timer, interrupt and memory setup:
	 */
	arch_time_init_quirk = visws_time_init_quirk;
	arch_pre_intr_init_quirk = visws_pre_intr_init_quirk;
	arch_memory_setup_quirk = visws_memory_setup_quirk;

	/*
	 * Fall back to generic behavior for traps:
	 */
	arch_intr_init_quirk = NULL;
	arch_trap_init_quirk = visws_trap_init_quirk;

	/*
	 * Install reboot quirks:
	 */
	pm_power_off = visws_machine_power_off;
	machine_ops.emergency_restart = visws_machine_emergency_restart;

	/*
	 * Do not use broadcast IPIs:
	 */
	no_broadcast = 0;

	/*
	 * Get Board rev.
	 * First, we have to initialize the 307 part to allow us access
	 * to the GPIO registers.  Let's map them at 0x0fc0 which is right
	 * after the PIIX4 PM section.
	 */
	outb_p(SIO_DEV_SEL, SIO_INDEX);
	outb_p(SIO_GP_DEV, SIO_DATA);	/* Talk to GPIO regs. */

	outb_p(SIO_DEV_MSB, SIO_INDEX);
	outb_p(SIO_GP_MSB, SIO_DATA);	/* MSB of GPIO base address */

	outb_p(SIO_DEV_LSB, SIO_INDEX);
	outb_p(SIO_GP_LSB, SIO_DATA);	/* LSB of GPIO base address */

	outb_p(SIO_DEV_ENB, SIO_INDEX);
	outb_p(1, SIO_DATA);		/* Enable GPIO registers. */

	/*
	 * Now, we have to map the power management section to write
	 * a bit which enables access to the GPIO registers.
	 * What lunatic came up with this shit?
	 */
	outb_p(SIO_DEV_SEL, SIO_INDEX);
	outb_p(SIO_PM_DEV, SIO_DATA);	/* Talk to GPIO regs. */

	outb_p(SIO_DEV_MSB, SIO_INDEX);
	outb_p(SIO_PM_MSB, SIO_DATA);	/* MSB of PM base address */

	outb_p(SIO_DEV_LSB, SIO_INDEX);
	outb_p(SIO_PM_LSB, SIO_DATA);	/* LSB of PM base address */

	outb_p(SIO_DEV_ENB, SIO_INDEX);
	outb_p(1, SIO_DATA);		/* Enable PM registers. */

	/*
	 * Now, write the PM register which enables the GPIO registers.
	 */
	outb_p(SIO_PM_FER2, SIO_PM_INDEX);
	outb_p(SIO_PM_GP_EN, SIO_PM_DATA);

	/*
	 * Now, initialize the GPIO registers.
	 * We want them all to be inputs which is the
	 * power on default, so let's leave them alone.
	 * So, let's just read the board rev!
	 */
	raw = inb_p(SIO_GP_DATA1);
	raw &= 0x7f;	/* 7 bits of valid board revision ID. */

	if (visws_board_type == VISWS_320) {
		if (raw < 0x6) {
			visws_board_rev = 4;
		} else if (raw < 0xc) {
			visws_board_rev = 5;
		} else {
			visws_board_rev = 6;
		}
	} else if (visws_board_type == VISWS_540) {
			visws_board_rev = 2;
		} else {
			visws_board_rev = raw;
		}

	printk(KERN_INFO "Silicon Graphics Visual Workstation %s (rev %d) detected\n",
	       (visws_board_type == VISWS_320 ? "320" :
	       (visws_board_type == VISWS_540 ? "540" :
		"unknown")), visws_board_rev);
}
Loading