Commit 4761c449 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Unisys ES7000 2/2: platform subarch

From: "Protasevich, Natalie" <Natalie.Protasevich@UNISYS.com>

Include ES7000 specific code for es7000 subarch.
parent 40546029
......@@ -99,6 +99,15 @@ config X86_GENERICARCH
This option compiles in the Summit, bigsmp, default subarchitectures.
It is intended for a generic binary kernel.
config X86_ES7000
bool "Support for Unisys ES7000 IA32 series"
depends on SMP
help
Support for Unisys ES7000 systems. Say 'Y' here if this kernel is
supposed to run on an IA32-based Unisys ES7000 system.
Only choose this option if you have such a system, otherwise you
should say N here.
endchoice
config ACPI_SRAT
......@@ -111,6 +120,11 @@ config X86_CYCLONE_TIMER
default y
depends on X86_SUMMIT || X86_GENERICARCH
config ES7000_CLUSTERED_APIC
bool
default y
depends on SMP && X86_ES7000 && MPENTIUMIII
choice
prompt "Processor family"
default M686
......
......@@ -78,6 +78,10 @@ mflags-$(CONFIG_X86_GENERICARCH) := -Iinclude/asm-i386/mach-generic
mcore-$(CONFIG_X86_GENERICARCH) := mach-default
core-$(CONFIG_X86_GENERICARCH) += arch/i386/mach-generic/
# ES7000 subarch support
mflags-$(CONFIG_X86_ES7000) := -Iinclude/asm-i386/mach-es7000
mcore-$(CONFIG_X86_ES7000) := mach-es7000
# default subarch .h files
mflags-y += -Iinclude/asm-i386/mach-default
......
......@@ -159,6 +159,7 @@ void __init connect_bsp_APIC(void)
outb(0x70, 0x22);
outb(0x01, 0x23);
}
enable_apic_mode();
}
void disconnect_bsp_APIC(void)
......
#
# Makefile for the linux kernel.
#
EXTRA_CFLAGS += -I../kernel
obj-y := setup.o topology.o es7000.o
/*
* Written by: Garry Forsgren, Unisys Corporation
* Natalie Protasevich, Unisys Corporation
* This file contains the code to configure and interface
* with Unisys ES7000 series hardware system manager.
*
* Copyright (c) 2003 Unisys Corporation. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Unisys Corporation, Township Line & Union Meeting
* Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or:
*
* http://www.unisys.com
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/acpi.h>
#include <asm/io.h>
#include <asm/nmi.h>
#include <asm/smp.h>
#include <asm/apicdef.h>
#include "es7000.h"
/*
* ES7000 Globals
*/
volatile unsigned long *psai = NULL;
struct mip_reg *mip_reg;
struct mip_reg *host_reg;
int mip_port;
unsigned long mip_addr, host_addr;
static int es7000_plat;
/*
* Parse the OEM Table
*/
void __init
parse_unisys_oem (char *oemptr, int oem_entries)
{
int i;
int success = 0;
unsigned char type, size;
unsigned long val;
char *tp = NULL;
struct psai *psaip = NULL;
struct mip_reg_info *mi;
struct mip_reg *host, *mip;
tp = oemptr;
tp += 8;
for (i=0; i <= oem_entries; i++) {
type = *tp++;
size = *tp++;
tp -= 2;
switch (type) {
case MIP_REG:
mi = (struct mip_reg_info *)tp;
val = MIP_RD_LO(mi->host_reg);
host_addr = val;
host = (struct mip_reg *)val;
host_reg = __va(host);
val = MIP_RD_LO(mi->mip_reg);
mip_addr = val;
mip = (struct mip_reg *)val;
mip_reg = __va(mip);
Dprintk("es7000_mipcfg: host_reg = 0x%lx \n",
(unsigned long)host_reg);
Dprintk("es7000_mipcfg: mip_reg = 0x%lx \n",
(unsigned long)mip_reg);
success++;
break;
case MIP_PSAI_REG:
psaip = (struct psai *)tp;
if (tp != NULL) {
if (psaip->addr)
psai = __va(psaip->addr);
else
psai = NULL;
success++;
}
break;
default:
break;
}
if (i == 6) break;
tp += size;
}
if (success < 2) {
printk("\nNo ES7000 found.\n");
es7000_plat = 0;
} else {
printk("\nEnabling ES7000 specific features...\n");
es7000_plat = 1;
}
return;
}
int __init
find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length)
{
struct acpi_table_rsdp *rsdp = NULL;
unsigned long rsdp_phys = 0;
struct acpi_table_header *header = NULL;
int i;
struct acpi_table_sdt sdt;
rsdp_phys = acpi_find_rsdp();
rsdp = __va(rsdp_phys);
if (rsdp->rsdt_address) {
struct acpi_table_rsdt *mapped_rsdt = NULL;
sdt.pa = rsdp->rsdt_address;
header = (struct acpi_table_header *)
__acpi_map_table(sdt.pa, sizeof(struct acpi_table_header));
if (!header)
return -ENODEV;
sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 3;
mapped_rsdt = (struct acpi_table_rsdt *)
__acpi_map_table(sdt.pa, header->length);
if (!mapped_rsdt)
return -ENODEV;
header = &mapped_rsdt->header;
for (i = 0; i < sdt.count; i++)
sdt.entry[i].pa = (unsigned long) mapped_rsdt->entry[i];
};
for (i = 0; i < sdt.count; i++) {
header = (struct acpi_table_header *)
__acpi_map_table(sdt.entry[i].pa,
sizeof(struct acpi_table_header));
if (!header)
continue;
if (!strncmp((char *) &header->signature, "OEM1", 4)) {
if (!strncmp((char *) &header->oem_id, "UNISYS", 6)) {
void *addr;
struct oem_table *t;
acpi_table_print(header, sdt.entry[i].pa);
t = (struct oem_table *) __acpi_map_table(sdt.entry[i].pa, header->length);
addr = (void *) __acpi_map_table(t->OEMTableAddr, t->OEMTableSize);
*length = header->length;
*oem_addr = (unsigned long) addr;
return 0;
}
}
}
printk("ES7000: did not find Unisys ACPI OEM table!\n");
return -1;
}
static void
es7000_spin(int n)
{
int i = 0;
while (i++ < n)
rep_nop();
}
static int __init
es7000_mip_write(struct mip_reg *mip_reg)
{
int status = 0;
int spin;
spin = MIP_SPIN;
while (((unsigned long long)host_reg->off_38 &
(unsigned long long)MIP_VALID) != 0) {
if (--spin <= 0) {
printk("es7000_mip_write: Timeout waiting for Host Valid Flag");
return -1;
}
es7000_spin(MIP_SPIN);
}
memcpy(host_reg, mip_reg, sizeof(struct mip_reg));
outb(1, mip_port);
spin = MIP_SPIN;
while (((unsigned long long)mip_reg->off_38 &
(unsigned long long)MIP_VALID) == 0) {
if (--spin <= 0) {
printk("es7000_mip_write: Timeout waiting for MIP Valid Flag");
return -1;
}
es7000_spin(MIP_SPIN);
}
status = ((unsigned long long)mip_reg->off_0 &
(unsigned long long)0xffff0000000000) >> 48;
mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 &
(unsigned long long)~MIP_VALID);
return status;
}
int
es7000_start_cpu(int cpu, unsigned long eip)
{
unsigned long vect = 0, psaival = 0;
if (psai == NULL)
return -1;
vect = ((unsigned long)__pa(eip)/0x1000) << 16;
psaival = (0x1000000 | vect | cpu);
while (*psai & 0x1000000)
;
*psai = psaival;
return 0;
}
int
es7000_stop_cpu(int cpu)
{
int startup;
if (psai == NULL)
return -1;
startup= (0x1000000 | cpu);
while ((*psai & 0xff00ffff) != startup)
;
startup = (*psai & 0xff0000) >> 16;
*psai &= 0xffffff;
return 0;
}
void __init
es7000_sw_apic()
{
if (es7000_plat) {
int mip_status;
struct mip_reg es7000_mip_reg;
printk("ES7000: Enabling APIC mode.\n");
memset(&es7000_mip_reg, 0, sizeof(struct mip_reg));
es7000_mip_reg.off_0 = MIP_SW_APIC;
es7000_mip_reg.off_38 = (MIP_VALID);
while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0)
printk("es7000_sw_apic: command failed, status = %x\n",
mip_status);
return;
}
}
/*
* Written by: Garry Forsgren, Unisys Corporation
* Natalie Protasevich, Unisys Corporation
* This file contains the code to configure and interface
* with Unisys ES7000 series hardware system manager.
*
* Copyright (c) 2003 Unisys Corporation. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Unisys Corporation, Township Line & Union Meeting
* Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or:
*
* http://www.unisys.com
*/
#define MIP_REG 1
#define MIP_PSAI_REG 4
#define MIP_BUSY 1
#define MIP_SPIN 0xf0000
#define MIP_VALID 0x0100000000000000
#define MIP_RD_LO(VALUE) (VALUE & 0xffffffff)
struct mip_reg_info {
unsigned long long mip_info;
unsigned long long delivery_info;
unsigned long long host_reg;
unsigned long long mip_reg;
};
struct part_info {
unsigned char type;
unsigned char length;
unsigned char part_id;
unsigned char apic_mode;
unsigned long snum;
char ptype[16];
char sname[64];
char pname[64];
};
struct psai {
unsigned long long entry_type;
unsigned long long addr;
unsigned long long bep_addr;
};
struct es7000_mem_info {
unsigned char type;
unsigned char length;
unsigned char resv[6];
unsigned long long start;
unsigned long long size;
};
struct es7000_oem_table {
unsigned long long hdr;
struct mip_reg_info mip;
struct part_info pif;
struct es7000_mem_info shm;
struct psai psai;
};
struct acpi_table_sdt {
unsigned long pa;
unsigned long count;
struct {
unsigned long pa;
enum acpi_table_id id;
unsigned long size;
} entry[50];
};
struct oem_table {
struct acpi_table_header Header;
u32 OEMTableAddr;
u32 OEMTableSize;
};
struct mip_reg {
unsigned long long off_0;
unsigned long long off_8;
unsigned long long off_10;
unsigned long long off_18;
unsigned long long off_20;
unsigned long long off_28;
unsigned long long off_30;
unsigned long long off_38;
};
#define MIP_SW_APIC 0x1020b
#define MIP_FUNC(VALUE) (VALUE & 0xff)
extern void parse_unisys_oem (char *oemptr, int oem_entries);
extern int find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length);
extern int es7000_start_cpu(int cpu, unsigned long eip);
extern void es7000_sw_apic(void);
/*
* Machine specific setup for es7000
*/
#include <linux/config.h>
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/arch_hooks.h>
/**
* pre_intr_init_hook - initialisation prior to setting up interrupt vectors
*
* Description:
* Perform any necessary interrupt initialisation prior to setting up
* the "ordinary" interrupt call gates. For legacy reasons, the ISA
* interrupts should be initialised here if the machine emulates a PC
* in any way.
**/
void __init pre_intr_init_hook(void)
{
init_ISA_irqs();
}
/*
* IRQ2 is cascade interrupt to second interrupt controller
*/
static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL};
/**
* intr_init_hook - post gate setup interrupt initialisation
*
* Description:
* Fill in any interrupts that may have been left out by the general
* init_IRQ() routine. interrupts having to do with the machine rather
* than the devices on the I/O bus (like APIC interrupts in intel MP
* systems) are started here.
**/
void __init intr_init_hook(void)
{
#ifdef CONFIG_X86_LOCAL_APIC
apic_intr_init();
#endif
setup_irq(2, &irq2);
}
/**
* pre_setup_arch_hook - hook called prior to any setup_arch() execution
*
* Description:
* generally used to activate any machine specific identification
* routines that may be needed before setup_arch() runs. On VISWS
* this is used to get the board revision and type.
**/
void __init pre_setup_arch_hook(void)
{
}
/**
* trap_init_hook - initialise system specific traps
*
* Description:
* Called as the final act of trap_init(). Used in VISWS to initialise
* the various board specific APIC traps.
**/
void __init trap_init_hook(void)
{
}
static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
/**
* time_init_hook - do any specific initialisations for the system timer.
*
* Description:
* Must plug the system timer interrupt source at HZ into the IRQ listed
* in irq_vectors.h:TIMER_IRQ
**/
void __init time_init_hook(void)
{
setup_irq(0, &irq0);
}
#ifdef CONFIG_MCA
/**
* mca_nmi_hook - hook into MCA specific NMI chain
*
* Description:
* The MCA (Microchannel Arcitecture) has an NMI chain for NMI sources
* along the MCA bus. Use this to hook into that chain if you will need
* it.
**/
void __init mca_nmi_hook(void)
{
/* If I recall correctly, there's a whole bunch of other things that
* we can do to check for NMI problems, but that's all I know about
* at the moment.
*/
printk("NMI generated from unknown source!\n");
}
#endif
/*
* arch/i386/mach-generic/topology.c - Populate driverfs with topology information
*
* Written by: Matthew Dobson, IBM Corporation
* Original Code: Paul Dorwin, IBM Corporation, Patrick Mochel, OSDL
*
* Copyright (C) 2002, IBM Corp.
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <colpatch@us.ibm.com>
*/
#include <linux/init.h>
#include <linux/smp.h>
#include <asm/cpu.h>
struct i386_cpu cpu_devices[NR_CPUS];
#ifdef CONFIG_NUMA
#include <linux/mmzone.h>
#include <asm/node.h>
#include <asm/memblk.h>
struct i386_node node_devices[MAX_NUMNODES];
struct i386_memblk memblk_devices[MAX_NR_MEMBLKS];
static int __init topology_init(void)
{
int i;
for (i = 0; i < num_online_nodes(); i++)
arch_register_node(i);
for (i = 0; i < NR_CPUS; i++)
if (cpu_possible(i)) arch_register_cpu(i);
for (i = 0; i < num_online_memblks(); i++)
arch_register_memblk(i);
return 0;
}
#else /* !CONFIG_NUMA */
static int __init topology_init(void)
{
int i;
for (i = 0; i < NR_CPUS; i++)
if (cpu_possible(i)) arch_register_cpu(i);
return 0;
}
#endif /* CONFIG_NUMA */
subsys_initcall(topology_init);
......@@ -123,6 +123,10 @@ static inline void setup_portio_remap(void)
{
}
static inline void enable_apic_mode(void)
{
}
static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
{
return (1);
......
......@@ -118,4 +118,8 @@ static inline unsigned int cpu_mask_to_apicid (unsigned long cpumask)
return cpumask;
}
static inline void enable_apic_mode(void)
{
}
#endif /* __ASM_MACH_APIC_H */
#ifndef __ASM_MACH_APIC_H
#define __ASM_MACH_APIC_H
extern u8 bios_cpu_apicid[];
#define xapic_phys_to_log_apicid(cpu) (bios_cpu_apicid[cpu])
#define esr_disable (1)
static inline int apic_id_registered(void)
{
return (1);
}
static inline unsigned long target_cpus(void)
{
#if defined CONFIG_ES7000_CLUSTERED_APIC
return (0xff);
#else
return (bios_cpu_apicid[smp_processor_id()]);
#endif
}
#define TARGET_CPUS (target_cpus())
#if defined CONFIG_ES7000_CLUSTERED_APIC
#define APIC_DFR_VALUE (APIC_DFR_CLUSTER)
#define INT_DELIVERY_MODE (dest_LowestPrio)
#define INT_DEST_MODE (1) /* logical delivery broadcast to all procs */
#define NO_BALANCE_IRQ (1)
#undef WAKE_SECONDARY_VIA_INIT
#define WAKE_SECONDARY_VIA_MIP
#else
#define APIC_DFR_VALUE (APIC_DFR_FLAT)
#define INT_DELIVERY_MODE (dest_Fixed)
#define INT_DEST_MODE (0) /* phys delivery to target procs */
#define NO_BALANCE_IRQ (0)
#undef APIC_DEST_LOGICAL
#define APIC_DEST_LOGICAL 0x0
#define WAKE_SECONDARY_VIA_INIT
#endif
#define APIC_BROADCAST_ID (0xff)
static inline unsigned long check_apicid_used(unsigned long bitmap, int apicid)
{
return 0;
}
static inline unsigned long check_apicid_present(int bit)
{
return (phys_cpu_present_map & (1 << bit));
}
#define apicid_cluster(apicid) (apicid & 0xF0)
static inline unsigned long calculate_ldr(int cpu)
{
unsigned long id;
id = xapic_phys_to_log_apicid(cpu);
return (SET_APIC_LOGICAL_ID(id));
}
/*
* Set up the logical destination ID.
*
* Intel recommends to set DFR, LdR and TPR before enabling
* an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
* document number 292116). So here it goes...
*/
static inline void init_apic_ldr(void)
{
unsigned long val;
int cpu = smp_processor_id();
apic_write_around(APIC_DFR, APIC_DFR_VALUE);
val = calculate_ldr(cpu);
apic_write_around(APIC_LDR, val);
}
extern void es7000_sw_apic(void);
static inline void enable_apic_mode(void)
{
es7000_sw_apic();
return;
}
extern int apic_version [MAX_APICS];
static inline void clustered_apic_check(void)
{
int apic = bios_cpu_apicid[smp_processor_id()];
printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n",
(apic_version[apic] == 0x14) ?
"Physical Cluster" : "Logical Cluster", nr_ioapics, TARGET_CPUS);
}
static inline int multi_timer_check(int apic, int irq)
{
return 0;
}
static inline int apicid_to_node(int logical_apicid)
{
return 0;
}
static inline int cpu_present_to_apicid(int mps_cpu)
{
if (!mps_cpu)
return boot_cpu_physical_apicid;
else
return (int) bios_cpu_apicid[mps_cpu];
}
static inline unsigned long apicid_to_cpu_present(int phys_apicid)
{
static int cpu = 0;
return (1ul << cpu++);
}
extern volatile u8 cpu_2_logical_apicid[];
/* Mapping from cpu number to logical apicid */
static inline int cpu_to_logical_apicid(int cpu)
{
return (int)cpu_2_logical_apicid[cpu];
}
static inline int mpc_apic_id(struct mpc_config_processor *m, int quad)
{
printk("Processor #%d %ld:%ld APIC version %d\n",
m->mpc_apicid,
(m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
(m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
m->mpc_apicver);
return (m->mpc_apicid);
}
static inline ulong ioapic_phys_id_map(ulong phys_map)
{
/* For clustered we don't have a good way to do this yet - hack */
return (0xff);
}
static inline void setup_portio_remap(void)
{
}
extern unsigned int boot_cpu_physical_apicid;
static inline int check_phys_apicid_present(int cpu_physical_apicid)
{
boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
return (1);
}
static inline unsigned int cpu_mask_to_apicid (unsigned long cpumask)
{
int num_bits_set;
int cpus_found = 0;
int cpu;
int apicid;
if (cpumask == TARGET_CPUS)
return cpumask;
num_bits_set = hweight32(cpumask);
/* Return id to all */
if (num_bits_set == 32)
return TARGET_CPUS;
/*
* The cpus in the mask must all be on the apic cluster. If are not
* on the same apicid cluster return default value of TARGET_CPUS.
*/
cpu = ffs(cpumask)-1;
apicid = cpu_to_logical_apicid(cpu);
while (cpus_found < num_bits_set) {
if (cpumask & (1 << cpu)) {
int new_apicid = cpu_to_logical_apicid(cpu);
if (apicid_cluster(apicid) !=
apicid_cluster(new_apicid)){
printk ("%s: Not a valid mask!\n",__FUNCTION__);
return TARGET_CPUS;
}
apicid = new_apicid;
cpus_found++;
}
cpu++;
}
return apicid;
}
#endif /* __ASM_MACH_APIC_H */
#ifndef __ASM_MACH_APICDEF_H
#define __ASM_MACH_APICDEF_H
#define APIC_ID_MASK (0xFF<<24)
static inline unsigned get_apic_id(unsigned long x)
{
return (((x)>>24)&0xFF);
}
#define GET_APIC_ID(x) get_apic_id(x)
#endif
#ifndef __ASM_MACH_IPI_H
#define __ASM_MACH_IPI_H
static inline void send_IPI_mask_sequence(int mask, int vector);
static inline void send_IPI_mask(int mask, int vector)
{
send_IPI_mask_sequence(mask, vector);
}
static inline void send_IPI_allbutself(int vector)
{
unsigned long mask = cpu_online_map & ~(1 << smp_processor_id());
if (mask)
send_IPI_mask(mask, vector);
}
static inline void send_IPI_all(int vector)
{
send_IPI_mask(cpu_online_map, vector);
}
#endif /* __ASM_MACH_IPI_H */
#ifndef __ASM_MACH_MPPARSE_H
#define __ASM_MACH_MPPARSE_H
static inline void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
struct mpc_config_translation *translation)
{
Dprintk("Bus #%d is %s\n", m->mpc_busid, name);
}
static inline void mpc_oem_pci_bus(struct mpc_config_bus *m,
struct mpc_config_translation *translation)
{
}
extern void parse_unisys_oem (char *oemptr, int oem_entries);
extern int find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length);
static inline void mps_oem_check(struct mp_config_table *mpc, char *oem,
char *productid)
{
if (mpc->mpc_oemptr) {
struct mp_config_oemtable *oem_table =
(struct mp_config_oemtable *)mpc->mpc_oemptr;
parse_unisys_oem((char *)oem_table, oem_table->oem_length);
}
}
/* Hook from generic ACPI tables.c */
static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
unsigned long oem_addr;
int oem_entries;
if (!find_unisys_acpi_oem_table(&oem_addr, &oem_entries))
parse_unisys_oem((char *)oem_addr, oem_entries);
}
#endif /* __ASM_MACH_MPPARSE_H */
#ifndef __ASM_MACH_MPSPEC_H
#define __ASM_MACH_MPSPEC_H
/*
* a maximum of 256 APICs with the current APIC ID architecture.
*/
#define MAX_APICS 256
#define MAX_IRQ_SOURCES 256
#define MAX_MP_BUSSES 32
#endif /* __ASM_MACH_MPSPEC_H */
#ifndef __ASM_MACH_WAKECPU_H
#define __ASM_MACH_WAKECPU_H
/*
* This file copes with machines that wakeup secondary CPUs by the
* INIT, INIT, STARTUP sequence.
*/
#ifdef CONFIG_ES7000_CLUSTERED_APIC
#define WAKE_SECONDARY_VIA_MIP
#else
#define WAKE_SECONDARY_VIA_INIT
#endif
#ifdef WAKE_SECONDARY_VIA_MIP
extern int es7000_start_cpu(int cpu, unsigned long eip);
static inline int
wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
{
int boot_error = 0;
boot_error = es7000_start_cpu(phys_apicid, start_eip);
return boot_error;
}
#endif
#define TRAMPOLINE_LOW phys_to_virt(0x467)
#define TRAMPOLINE_HIGH phys_to_virt(0x469)
#define boot_cpu_apicid boot_cpu_physical_apicid
static inline void wait_for_init_deassert(atomic_t *deassert)
{
#ifdef WAKE_SECONDARY_VIA_INIT
while (!atomic_read(deassert));
#endif
return;
}
/* Nothing to do for most platforms, since cleared by the INIT cycle */
static inline void smp_callin_clear_local_apic(void)
{
}
static inline void store_NMI_vector(unsigned short *high, unsigned short *low)
{
}
static inline void restore_NMI_vector(unsigned short *high, unsigned short *low)
{
}
#if APIC_DEBUG
#define inquire_remote_apic(apicid) __inquire_remote_apic(apicid)
#else
#define inquire_remote_apic(apicid) {}
#endif
#endif /* __ASM_MACH_WAKECPU_H */
......@@ -107,6 +107,10 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
return (1);
}
static inline void enable_apic_mode(void)
{
}
/*
* We use physical apicids here, not logical, so just return the default
* physical broadcast to stop people from breaking us
......
......@@ -118,6 +118,10 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
return 1;
}
static inline void enable_apic_mode(void)
{
}
static inline unsigned int cpu_mask_to_apicid (unsigned long cpumask)
{
int num_bits_set;
......
......@@ -72,6 +72,10 @@ static inline void setup_portio_remap(void)
{
}
static inline void enable_apic_mode(void)
{
}
static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
{
return test_bit(boot_cpu_physical_apicid, &phys_cpu_present_map);
......
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