Commit d50e8fc7 authored by H. Peter Anvin's avatar H. Peter Anvin

Merge branch 'x86/apic-cleanups' into x86/numa

parents a387e95a 0aa002fe
...@@ -600,6 +600,7 @@ Protocol: 2.07+ ...@@ -600,6 +600,7 @@ Protocol: 2.07+
0x00000001 lguest 0x00000001 lguest
0x00000002 Xen 0x00000002 Xen
0x00000003 Moorestown MID 0x00000003 Moorestown MID
0x00000004 CE4100 TV Platform
Field name: hardware_subarch_data Field name: hardware_subarch_data
Type: write (subarch-dependent) Type: write (subarch-dependent)
......
...@@ -377,6 +377,18 @@ config X86_ELAN ...@@ -377,6 +377,18 @@ config X86_ELAN
If unsure, choose "PC-compatible" instead. If unsure, choose "PC-compatible" instead.
config X86_INTEL_CE
bool "CE4100 TV platform"
depends on PCI
depends on PCI_GODIRECT
depends on X86_32
depends on X86_EXTENDED_PLATFORM
select X86_REBOOTFIXUPS
---help---
Select for the Intel CE media processor (CE4100) SOC.
This option compiles in support for the CE4100 SOC for settop
boxes and media devices.
config X86_MRST config X86_MRST
bool "Moorestown MID platform" bool "Moorestown MID platform"
depends on PCI depends on PCI
...@@ -385,6 +397,10 @@ config X86_MRST ...@@ -385,6 +397,10 @@ config X86_MRST
depends on X86_EXTENDED_PLATFORM depends on X86_EXTENDED_PLATFORM
depends on X86_IO_APIC depends on X86_IO_APIC
select APB_TIMER select APB_TIMER
select I2C
select SPI
select INTEL_SCU_IPC
select X86_PLATFORM_DEVICES
---help--- ---help---
Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin
Internet Device(MID) platform. Moorestown consists of two chips: Internet Device(MID) platform. Moorestown consists of two chips:
...@@ -466,6 +482,19 @@ config X86_ES7000 ...@@ -466,6 +482,19 @@ config X86_ES7000
Support for Unisys ES7000 systems. Say 'Y' here if this kernel is Support for Unisys ES7000 systems. Say 'Y' here if this kernel is
supposed to run on an IA32-based Unisys ES7000 system. supposed to run on an IA32-based Unisys ES7000 system.
config X86_32_IRIS
tristate "Eurobraille/Iris poweroff module"
depends on X86_32
---help---
The Iris machines from EuroBraille do not have APM or ACPI support
to shut themselves down properly. A special I/O sequence is
needed to do so, which is what this module does at
kernel shutdown.
This is only for Iris machines from EuroBraille.
If unused, say N.
config SCHED_OMIT_FRAME_POINTER config SCHED_OMIT_FRAME_POINTER
def_bool y def_bool y
prompt "Single-depth WCHAN output" prompt "Single-depth WCHAN output"
......
...@@ -234,16 +234,17 @@ extern void init_bsp_APIC(void); ...@@ -234,16 +234,17 @@ extern void init_bsp_APIC(void);
extern void setup_local_APIC(void); extern void setup_local_APIC(void);
extern void end_local_APIC_setup(void); extern void end_local_APIC_setup(void);
extern void init_apic_mappings(void); extern void init_apic_mappings(void);
void register_lapic_address(unsigned long address);
extern void setup_boot_APIC_clock(void); extern void setup_boot_APIC_clock(void);
extern void setup_secondary_APIC_clock(void); extern void setup_secondary_APIC_clock(void);
extern int APIC_init_uniprocessor(void); extern int APIC_init_uniprocessor(void);
extern void enable_NMI_through_LVT0(void); extern void enable_NMI_through_LVT0(void);
extern int apic_force_enable(void);
/* /*
* On 32bit this is mach-xxx local * On 32bit this is mach-xxx local
*/ */
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
extern void early_init_lapic_mapping(void);
extern int apic_is_clustered_box(void); extern int apic_is_clustered_box(void);
#else #else
static inline int apic_is_clustered_box(void) static inline int apic_is_clustered_box(void)
......
...@@ -124,6 +124,7 @@ enum { ...@@ -124,6 +124,7 @@ enum {
X86_SUBARCH_LGUEST, X86_SUBARCH_LGUEST,
X86_SUBARCH_XEN, X86_SUBARCH_XEN,
X86_SUBARCH_MRST, X86_SUBARCH_MRST,
X86_SUBARCH_CE4100,
X86_NR_SUBARCHS, X86_NR_SUBARCHS,
}; };
......
...@@ -117,6 +117,10 @@ enum fixed_addresses { ...@@ -117,6 +117,10 @@ enum fixed_addresses {
FIX_TEXT_POKE1, /* reserve 2 pages for text_poke() */ FIX_TEXT_POKE1, /* reserve 2 pages for text_poke() */
FIX_TEXT_POKE0, /* first page is last, because allocation is backward */ FIX_TEXT_POKE0, /* first page is last, because allocation is backward */
__end_of_permanent_fixed_addresses, __end_of_permanent_fixed_addresses,
#ifdef CONFIG_X86_MRST
FIX_LNW_VRTC,
#endif
/* /*
* 256 temporary boot-time mappings, used by early_ioremap(), * 256 temporary boot-time mappings, used by early_ioremap(),
* before ioremap() is functional. * before ioremap() is functional.
......
...@@ -159,7 +159,7 @@ struct io_apic_irq_attr; ...@@ -159,7 +159,7 @@ struct io_apic_irq_attr;
extern int io_apic_set_pci_routing(struct device *dev, int irq, extern int io_apic_set_pci_routing(struct device *dev, int irq,
struct io_apic_irq_attr *irq_attr); struct io_apic_irq_attr *irq_attr);
void setup_IO_APIC_irq_extra(u32 gsi); void setup_IO_APIC_irq_extra(u32 gsi);
extern void ioapic_init_mappings(void); extern void ioapic_and_gsi_init(void);
extern void ioapic_insert_resources(void); extern void ioapic_insert_resources(void);
extern struct IO_APIC_route_entry **alloc_ioapic_entries(void); extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
...@@ -168,10 +168,10 @@ extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); ...@@ -168,10 +168,10 @@ extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
extern void probe_nr_irqs_gsi(void);
extern int get_nr_irqs_gsi(void); extern int get_nr_irqs_gsi(void);
extern void setup_ioapic_ids_from_mpc(void); extern void setup_ioapic_ids_from_mpc(void);
extern void setup_ioapic_ids_from_mpc_nocheck(void);
struct mp_ioapic_gsi{ struct mp_ioapic_gsi{
u32 gsi_base; u32 gsi_base;
...@@ -184,14 +184,15 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi); ...@@ -184,14 +184,15 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi);
void __init mp_register_ioapic(int id, u32 address, u32 gsi_base); void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void __init pre_init_apic_IRQ0(void); extern void __init pre_init_apic_IRQ0(void);
extern void mp_save_irq(struct mpc_intsrc *m);
#else /* !CONFIG_X86_IO_APIC */ #else /* !CONFIG_X86_IO_APIC */
#define io_apic_assign_pci_irqs 0 #define io_apic_assign_pci_irqs 0
#define setup_ioapic_ids_from_mpc x86_init_noop #define setup_ioapic_ids_from_mpc x86_init_noop
static const int timer_through_8259 = 0; static const int timer_through_8259 = 0;
static inline void ioapic_init_mappings(void) { } static inline void ioapic_and_gsi_init(void) { }
static inline void ioapic_insert_resources(void) { } static inline void ioapic_insert_resources(void) { }
static inline void probe_nr_irqs_gsi(void) { }
#define gsi_top (NR_IRQS_LEGACY) #define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; } static inline int mp_find_ioapic(u32 gsi) { return 0; }
......
#ifndef _MRST_VRTC_H
#define _MRST_VRTC_H
extern unsigned char vrtc_cmos_read(unsigned char reg);
extern void vrtc_cmos_write(unsigned char val, unsigned char reg);
extern unsigned long vrtc_get_time(void);
extern int vrtc_set_mmss(unsigned long nowtime);
#endif
...@@ -14,7 +14,9 @@ ...@@ -14,7 +14,9 @@
#include <linux/sfi.h> #include <linux/sfi.h>
extern int pci_mrst_init(void); extern int pci_mrst_init(void);
int __init sfi_parse_mrtc(struct sfi_table_header *table); extern int __init sfi_parse_mrtc(struct sfi_table_header *table);
extern int sfi_mrtc_num;
extern struct sfi_rtc_table_entry sfi_mrtc_array[];
/* /*
* Medfield is the follow-up of Moorestown, it combines two chip solution into * Medfield is the follow-up of Moorestown, it combines two chip solution into
...@@ -50,4 +52,14 @@ extern void mrst_early_console_init(void); ...@@ -50,4 +52,14 @@ extern void mrst_early_console_init(void);
extern struct console early_hsu_console; extern struct console early_hsu_console;
extern void hsu_early_console_init(void); extern void hsu_early_console_init(void);
extern void intel_scu_devices_create(void);
extern void intel_scu_devices_destroy(void);
/* VRTC timer */
#define MRST_VRTC_MAP_SZ (1024)
/*#define MRST_VRTC_PGOFFSET (0xc00) */
extern void mrst_rtc_init(void);
#endif /* _ASM_X86_MRST_H */ #endif /* _ASM_X86_MRST_H */
...@@ -53,6 +53,12 @@ extern void x86_mrst_early_setup(void); ...@@ -53,6 +53,12 @@ extern void x86_mrst_early_setup(void);
static inline void x86_mrst_early_setup(void) { } static inline void x86_mrst_early_setup(void) { }
#endif #endif
#ifdef CONFIG_X86_INTEL_CE
extern void x86_ce4100_early_setup(void);
#else
static inline void x86_ce4100_early_setup(void) { }
#endif
#ifndef _SETUP #ifndef _SETUP
/* /*
......
...@@ -84,7 +84,6 @@ obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o ...@@ -84,7 +84,6 @@ obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o
obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_VM86) += vm86_32.o obj-$(CONFIG_VM86) += vm86_32.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_EARLY_PRINTK_MRST) += early_printk_mrst.o
obj-$(CONFIG_HPET_TIMER) += hpet.o obj-$(CONFIG_HPET_TIMER) += hpet.o
obj-$(CONFIG_APB_TIMER) += apb_timer.o obj-$(CONFIG_APB_TIMER) += apb_timer.o
......
...@@ -847,18 +847,6 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table) ...@@ -847,18 +847,6 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
* returns 0 on success, < 0 on error * returns 0 on success, < 0 on error
*/ */
static void __init acpi_register_lapic_address(unsigned long address)
{
mp_lapic_addr = address;
set_fixmap_nocache(FIX_APIC_BASE, address);
if (boot_cpu_physical_apicid == -1U) {
boot_cpu_physical_apicid = read_apic_id();
apic_version[boot_cpu_physical_apicid] =
GET_APIC_VERSION(apic_read(APIC_LVR));
}
}
static int __init early_acpi_parse_madt_lapic_addr_ovr(void) static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
{ {
int count; int count;
...@@ -880,7 +868,7 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void) ...@@ -880,7 +868,7 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
return count; return count;
} }
acpi_register_lapic_address(acpi_lapic_addr); register_lapic_address(acpi_lapic_addr);
return count; return count;
} }
...@@ -907,7 +895,7 @@ static int __init acpi_parse_madt_lapic_entries(void) ...@@ -907,7 +895,7 @@ static int __init acpi_parse_madt_lapic_entries(void)
return count; return count;
} }
acpi_register_lapic_address(acpi_lapic_addr); register_lapic_address(acpi_lapic_addr);
count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC, count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC,
acpi_parse_sapic, MAX_APICS); acpi_parse_sapic, MAX_APICS);
...@@ -949,32 +937,6 @@ static int __init acpi_parse_madt_lapic_entries(void) ...@@ -949,32 +937,6 @@ static int __init acpi_parse_madt_lapic_entries(void)
extern int es7000_plat; extern int es7000_plat;
#endif #endif
static void assign_to_mp_irq(struct mpc_intsrc *m,
struct mpc_intsrc *mp_irq)
{
memcpy(mp_irq, m, sizeof(struct mpc_intsrc));
}
static int mp_irq_cmp(struct mpc_intsrc *mp_irq,
struct mpc_intsrc *m)
{
return memcmp(mp_irq, m, sizeof(struct mpc_intsrc));
}
static void save_mp_irq(struct mpc_intsrc *m)
{
int i;
for (i = 0; i < mp_irq_entries; i++) {
if (!mp_irq_cmp(&mp_irqs[i], m))
return;
}
assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
if (++mp_irq_entries == MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!!\n");
}
void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
{ {
int ioapic; int ioapic;
...@@ -1005,7 +967,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) ...@@ -1005,7 +967,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
mp_irq.dstapic = mp_ioapics[ioapic].apicid; /* APIC ID */ mp_irq.dstapic = mp_ioapics[ioapic].apicid; /* APIC ID */
mp_irq.dstirq = pin; /* INTIN# */ mp_irq.dstirq = pin; /* INTIN# */
save_mp_irq(&mp_irq); mp_save_irq(&mp_irq);
isa_irq_to_gsi[bus_irq] = gsi; isa_irq_to_gsi[bus_irq] = gsi;
} }
...@@ -1080,7 +1042,7 @@ void __init mp_config_acpi_legacy_irqs(void) ...@@ -1080,7 +1042,7 @@ void __init mp_config_acpi_legacy_irqs(void)
mp_irq.srcbusirq = i; /* Identity mapped */ mp_irq.srcbusirq = i; /* Identity mapped */
mp_irq.dstirq = pin; mp_irq.dstirq = pin;
save_mp_irq(&mp_irq); mp_save_irq(&mp_irq);
} }
} }
...@@ -1117,7 +1079,7 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger, ...@@ -1117,7 +1079,7 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
mp_irq.dstapic = mp_ioapics[ioapic].apicid; mp_irq.dstapic = mp_ioapics[ioapic].apicid;
mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi); mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
save_mp_irq(&mp_irq); mp_save_irq(&mp_irq);
#endif #endif
return 0; return 0;
} }
......
...@@ -315,6 +315,7 @@ static void apbt_setup_irq(struct apbt_dev *adev) ...@@ -315,6 +315,7 @@ static void apbt_setup_irq(struct apbt_dev *adev)
if (system_state == SYSTEM_BOOTING) { if (system_state == SYSTEM_BOOTING) {
irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT); irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT);
irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
/* APB timer irqs are set up as mp_irqs, timer is edge type */ /* APB timer irqs are set up as mp_irqs, timer is edge type */
__set_irq_handler(adev->irq, handle_edge_irq, 0, "edge"); __set_irq_handler(adev->irq, handle_edge_irq, 0, "edge");
if (request_irq(adev->irq, apbt_interrupt_handler, if (request_irq(adev->irq, apbt_interrupt_handler,
......
...@@ -1195,12 +1195,15 @@ static void __cpuinit lapic_setup_esr(void) ...@@ -1195,12 +1195,15 @@ static void __cpuinit lapic_setup_esr(void)
oldvalue, value); oldvalue, value);
} }
/** /**
* setup_local_APIC - setup the local APIC * setup_local_APIC - setup the local APIC
*
* Used to setup local APIC while initializing BSP or bringin up APs.
* Always called with preemption disabled.
*/ */
void __cpuinit setup_local_APIC(void) void __cpuinit setup_local_APIC(void)
{ {
int cpu = smp_processor_id();
unsigned int value, queued; unsigned int value, queued;
int i, j, acked = 0; int i, j, acked = 0;
unsigned long long tsc = 0, ntsc; unsigned long long tsc = 0, ntsc;
...@@ -1225,8 +1228,6 @@ void __cpuinit setup_local_APIC(void) ...@@ -1225,8 +1228,6 @@ void __cpuinit setup_local_APIC(void)
#endif #endif
perf_events_lapic_init(); perf_events_lapic_init();
preempt_disable();
/* /*
* Double-check whether this APIC is really registered. * Double-check whether this APIC is really registered.
* This is meaningless in clustered apic mode, so we skip it. * This is meaningless in clustered apic mode, so we skip it.
...@@ -1342,21 +1343,19 @@ void __cpuinit setup_local_APIC(void) ...@@ -1342,21 +1343,19 @@ void __cpuinit setup_local_APIC(void)
* TODO: set up through-local-APIC from through-I/O-APIC? --macro * TODO: set up through-local-APIC from through-I/O-APIC? --macro
*/ */
value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
if (!smp_processor_id() && (pic_mode || !value)) { if (!cpu && (pic_mode || !value)) {
value = APIC_DM_EXTINT; value = APIC_DM_EXTINT;
apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", cpu);
smp_processor_id());
} else { } else {
value = APIC_DM_EXTINT | APIC_LVT_MASKED; value = APIC_DM_EXTINT | APIC_LVT_MASKED;
apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", cpu);
smp_processor_id());
} }
apic_write(APIC_LVT0, value); apic_write(APIC_LVT0, value);
/* /*
* only the BP should see the LINT1 NMI signal, obviously. * only the BP should see the LINT1 NMI signal, obviously.
*/ */
if (!smp_processor_id()) if (!cpu)
value = APIC_DM_NMI; value = APIC_DM_NMI;
else else
value = APIC_DM_NMI | APIC_LVT_MASKED; value = APIC_DM_NMI | APIC_LVT_MASKED;
...@@ -1364,11 +1363,9 @@ void __cpuinit setup_local_APIC(void) ...@@ -1364,11 +1363,9 @@ void __cpuinit setup_local_APIC(void)
value |= APIC_LVT_LEVEL_TRIGGER; value |= APIC_LVT_LEVEL_TRIGGER;
apic_write(APIC_LVT1, value); apic_write(APIC_LVT1, value);
preempt_enable();
#ifdef CONFIG_X86_MCE_INTEL #ifdef CONFIG_X86_MCE_INTEL
/* Recheck CMCI information after local APIC is up on CPU #0 */ /* Recheck CMCI information after local APIC is up on CPU #0 */
if (smp_processor_id() == 0) if (!cpu)
cmci_recheck(); cmci_recheck();
#endif #endif
} }
...@@ -1530,13 +1527,60 @@ static int __init detect_init_APIC(void) ...@@ -1530,13 +1527,60 @@ static int __init detect_init_APIC(void)
return 0; return 0;
} }
#else #else
static int apic_verify(void)
{
u32 features, h, l;
/*
* The APIC feature bit should now be enabled
* in `cpuid'
*/
features = cpuid_edx(1);
if (!(features & (1 << X86_FEATURE_APIC))) {
pr_warning("Could not enable APIC!\n");
return -1;
}
set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
/* The BIOS may have set up the APIC at some other address */
rdmsr(MSR_IA32_APICBASE, l, h);
if (l & MSR_IA32_APICBASE_ENABLE)
mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
pr_info("Found and enabled local APIC!\n");
return 0;
}
int apic_force_enable(void)
{
u32 h, l;
if (disable_apic)
return -1;
/*
* Some BIOSes disable the local APIC in the APIC_BASE
* MSR. This can only be done in software for Intel P6 or later
* and AMD K7 (Model > 1) or later.
*/
rdmsr(MSR_IA32_APICBASE, l, h);
if (!(l & MSR_IA32_APICBASE_ENABLE)) {
pr_info("Local APIC disabled by BIOS -- reenabling.\n");
l &= ~MSR_IA32_APICBASE_BASE;
l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
wrmsr(MSR_IA32_APICBASE, l, h);
enabled_via_apicbase = 1;
}
return apic_verify();
}
/* /*
* Detect and initialize APIC * Detect and initialize APIC
*/ */
static int __init detect_init_APIC(void) static int __init detect_init_APIC(void)
{ {
u32 h, l, features;
/* Disabled by kernel option? */ /* Disabled by kernel option? */
if (disable_apic) if (disable_apic)
return -1; return -1;
...@@ -1566,38 +1610,12 @@ static int __init detect_init_APIC(void) ...@@ -1566,38 +1610,12 @@ static int __init detect_init_APIC(void)
"you can enable it with \"lapic\"\n"); "you can enable it with \"lapic\"\n");
return -1; return -1;
} }
/* if (apic_force_enable())
* Some BIOSes disable the local APIC in the APIC_BASE return -1;
* MSR. This can only be done in software for Intel P6 or later } else {
* and AMD K7 (Model > 1) or later. if (apic_verify())
*/ return -1;
rdmsr(MSR_IA32_APICBASE, l, h);
if (!(l & MSR_IA32_APICBASE_ENABLE)) {
pr_info("Local APIC disabled by BIOS -- reenabling.\n");
l &= ~MSR_IA32_APICBASE_BASE;
l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
wrmsr(MSR_IA32_APICBASE, l, h);
enabled_via_apicbase = 1;
}
}
/*
* The APIC feature bit should now be enabled
* in `cpuid'
*/
features = cpuid_edx(1);
if (!(features & (1 << X86_FEATURE_APIC))) {
pr_warning("Could not enable APIC!\n");
return -1;
} }
set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
/* The BIOS may have set up the APIC at some other address */
rdmsr(MSR_IA32_APICBASE, l, h);
if (l & MSR_IA32_APICBASE_ENABLE)
mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
pr_info("Found and enabled local APIC!\n");
apic_pm_activate(); apic_pm_activate();
...@@ -1609,28 +1627,6 @@ static int __init detect_init_APIC(void) ...@@ -1609,28 +1627,6 @@ static int __init detect_init_APIC(void)
} }
#endif #endif
#ifdef CONFIG_X86_64
void __init early_init_lapic_mapping(void)
{
/*
* If no local APIC can be found then go out
* : it means there is no mpatable and MADT
*/
if (!smp_found_config)
return;
set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
APIC_BASE, mp_lapic_addr);
/*
* Fetch the APIC ID of the BSP in case we have a
* default configuration (or the MP table is broken).
*/
boot_cpu_physical_apicid = read_apic_id();
}
#endif
/** /**
* init_apic_mappings - initialize APIC mappings * init_apic_mappings - initialize APIC mappings
*/ */
...@@ -1656,10 +1652,7 @@ void __init init_apic_mappings(void) ...@@ -1656,10 +1652,7 @@ void __init init_apic_mappings(void)
* acpi_register_lapic_address() * acpi_register_lapic_address()
*/ */
if (!acpi_lapic && !smp_found_config) if (!acpi_lapic && !smp_found_config)
set_fixmap_nocache(FIX_APIC_BASE, apic_phys); register_lapic_address(apic_phys);
apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n",
APIC_BASE, apic_phys);
} }
/* /*
...@@ -1681,6 +1674,22 @@ void __init init_apic_mappings(void) ...@@ -1681,6 +1674,22 @@ void __init init_apic_mappings(void)
} }
} }
void __init register_lapic_address(unsigned long address)
{
mp_lapic_addr = address;
if (!x2apic_mode) {
set_fixmap_nocache(FIX_APIC_BASE, address);
apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
APIC_BASE, mp_lapic_addr);
}
if (boot_cpu_physical_apicid == -1U) {
boot_cpu_physical_apicid = read_apic_id();
apic_version[boot_cpu_physical_apicid] =
GET_APIC_VERSION(apic_read(APIC_LVR));
}
}
/* /*
* This initializes the IO-APIC and APIC hardware if this is * This initializes the IO-APIC and APIC hardware if this is
* a UP kernel. * a UP kernel.
......
...@@ -126,6 +126,26 @@ static int __init parse_noapic(char *str) ...@@ -126,6 +126,26 @@ static int __init parse_noapic(char *str)
} }
early_param("noapic", parse_noapic); early_param("noapic", parse_noapic);
/* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
void mp_save_irq(struct mpc_intsrc *m)
{
int i;
apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
" IRQ %02x, APIC ID %x, APIC INT %02x\n",
m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbus,
m->srcbusirq, m->dstapic, m->dstirq);
for (i = 0; i < mp_irq_entries; i++) {
if (!memcmp(&mp_irqs[i], m, sizeof(*m)))
return;
}
memcpy(&mp_irqs[mp_irq_entries], m, sizeof(*m));
if (++mp_irq_entries == MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!!\n");
}
struct irq_pin_list { struct irq_pin_list {
int apic, pin; int apic, pin;
struct irq_pin_list *next; struct irq_pin_list *next;
...@@ -136,6 +156,7 @@ static struct irq_pin_list *alloc_irq_pin_list(int node) ...@@ -136,6 +156,7 @@ static struct irq_pin_list *alloc_irq_pin_list(int node)
return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node); return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node);
} }
/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
#ifdef CONFIG_SPARSE_IRQ #ifdef CONFIG_SPARSE_IRQ
static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY]; static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY];
...@@ -1934,8 +1955,7 @@ void disable_IO_APIC(void) ...@@ -1934,8 +1955,7 @@ void disable_IO_APIC(void)
* *
* by Matt Domsch <Matt_Domsch@dell.com> Tue Dec 21 12:25:05 CST 1999 * by Matt Domsch <Matt_Domsch@dell.com> Tue Dec 21 12:25:05 CST 1999
*/ */
void __init setup_ioapic_ids_from_mpc_nocheck(void)
void __init setup_ioapic_ids_from_mpc(void)
{ {
union IO_APIC_reg_00 reg_00; union IO_APIC_reg_00 reg_00;
physid_mask_t phys_id_present_map; physid_mask_t phys_id_present_map;
...@@ -1944,15 +1964,6 @@ void __init setup_ioapic_ids_from_mpc(void) ...@@ -1944,15 +1964,6 @@ void __init setup_ioapic_ids_from_mpc(void)
unsigned char old_id; unsigned char old_id;
unsigned long flags; unsigned long flags;
if (acpi_ioapic)
return;
/*
* Don't check I/O APIC IDs for xAPIC systems. They have
* no meaning without the serial APIC bus.
*/
if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
|| APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
return;
/* /*
* This is broken; anything with a real cpu count has to * This is broken; anything with a real cpu count has to
* circumvent this idiocy regardless. * circumvent this idiocy regardless.
...@@ -2006,7 +2017,6 @@ void __init setup_ioapic_ids_from_mpc(void) ...@@ -2006,7 +2017,6 @@ void __init setup_ioapic_ids_from_mpc(void)
physids_or(phys_id_present_map, phys_id_present_map, tmp); physids_or(phys_id_present_map, phys_id_present_map, tmp);
} }
/* /*
* We need to adjust the IRQ routing table * We need to adjust the IRQ routing table
* if the ID changed. * if the ID changed.
...@@ -2018,9 +2028,12 @@ void __init setup_ioapic_ids_from_mpc(void) ...@@ -2018,9 +2028,12 @@ void __init setup_ioapic_ids_from_mpc(void)
= mp_ioapics[apic_id].apicid; = mp_ioapics[apic_id].apicid;
/* /*
* Read the right value from the MPC table and * Update the ID register according to the right value
* write it into the ID register. * from the MPC table if they are different.
*/ */
if (mp_ioapics[apic_id].apicid == reg_00.bits.ID)
continue;
apic_printk(APIC_VERBOSE, KERN_INFO apic_printk(APIC_VERBOSE, KERN_INFO
"...changing IO-APIC physical APIC ID to %d ...", "...changing IO-APIC physical APIC ID to %d ...",
mp_ioapics[apic_id].apicid); mp_ioapics[apic_id].apicid);
...@@ -2042,6 +2055,21 @@ void __init setup_ioapic_ids_from_mpc(void) ...@@ -2042,6 +2055,21 @@ void __init setup_ioapic_ids_from_mpc(void)
apic_printk(APIC_VERBOSE, " ok.\n"); apic_printk(APIC_VERBOSE, " ok.\n");
} }
} }
void __init setup_ioapic_ids_from_mpc(void)
{
if (acpi_ioapic)
return;
/*
* Don't check I/O APIC IDs for xAPIC systems. They have
* no meaning without the serial APIC bus.
*/
if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
|| APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
return;
setup_ioapic_ids_from_mpc_nocheck();
}
#endif #endif
int no_timer_check __initdata; int no_timer_check __initdata;
...@@ -3639,7 +3667,7 @@ int __init io_apic_get_redir_entries (int ioapic) ...@@ -3639,7 +3667,7 @@ int __init io_apic_get_redir_entries (int ioapic)
return reg_01.bits.entries + 1; return reg_01.bits.entries + 1;
} }
void __init probe_nr_irqs_gsi(void) static void __init probe_nr_irqs_gsi(void)
{ {
int nr; int nr;
...@@ -3956,7 +3984,7 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics) ...@@ -3956,7 +3984,7 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics)
return res; return res;
} }
void __init ioapic_init_mappings(void) void __init ioapic_and_gsi_init(void)
{ {
unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
struct resource *ioapic_res; struct resource *ioapic_res;
...@@ -3994,6 +4022,8 @@ void __init ioapic_init_mappings(void) ...@@ -3994,6 +4022,8 @@ void __init ioapic_init_mappings(void)
ioapic_res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1; ioapic_res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1;
ioapic_res++; ioapic_res++;
} }
probe_nr_irqs_gsi();
} }
void __init ioapic_insert_resources(void) void __init ioapic_insert_resources(void)
......
...@@ -240,7 +240,7 @@ static int __init setup_early_printk(char *buf) ...@@ -240,7 +240,7 @@ static int __init setup_early_printk(char *buf)
if (!strncmp(buf, "xen", 3)) if (!strncmp(buf, "xen", 3))
early_console_register(&xenboot_console, keep); early_console_register(&xenboot_console, keep);
#endif #endif
#ifdef CONFIG_X86_MRST_EARLY_PRINTK #ifdef CONFIG_EARLY_PRINTK_MRST
if (!strncmp(buf, "mrst", 4)) { if (!strncmp(buf, "mrst", 4)) {
mrst_early_console_init(); mrst_early_console_init();
early_console_register(&early_mrst_console, keep); early_console_register(&early_mrst_console, keep);
...@@ -250,7 +250,6 @@ static int __init setup_early_printk(char *buf) ...@@ -250,7 +250,6 @@ static int __init setup_early_printk(char *buf)
hsu_early_console_init(); hsu_early_console_init();
early_console_register(&early_hsu_console, keep); early_console_register(&early_hsu_console, keep);
} }
#endif #endif
buf++; buf++;
} }
......
...@@ -61,6 +61,9 @@ void __init i386_start_kernel(void) ...@@ -61,6 +61,9 @@ void __init i386_start_kernel(void)
case X86_SUBARCH_MRST: case X86_SUBARCH_MRST:
x86_mrst_early_setup(); x86_mrst_early_setup();
break; break;
case X86_SUBARCH_CE4100:
x86_ce4100_early_setup();
break;
default: default:
i386_default_early_setup(); i386_default_early_setup();
break; break;
......
...@@ -118,21 +118,8 @@ static void __init MP_bus_info(struct mpc_bus *m) ...@@ -118,21 +118,8 @@ static void __init MP_bus_info(struct mpc_bus *m)
static void __init MP_ioapic_info(struct mpc_ioapic *m) static void __init MP_ioapic_info(struct mpc_ioapic *m)
{ {
if (!(m->flags & MPC_APIC_USABLE)) if (m->flags & MPC_APIC_USABLE)
return; mp_register_ioapic(m->apicid, m->apicaddr, gsi_top);
printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
m->apicid, m->apicver, m->apicaddr);
mp_register_ioapic(m->apicid, m->apicaddr, gsi_top);
}
static void print_MP_intsrc_info(struct mpc_intsrc *m)
{
apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
" IRQ %02x, APIC ID %x, APIC INT %02x\n",
m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbus,
m->srcbusirq, m->dstapic, m->dstirq);
} }
static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq) static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
...@@ -144,73 +131,11 @@ static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq) ...@@ -144,73 +131,11 @@ static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq); mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq);
} }
static void __init assign_to_mp_irq(struct mpc_intsrc *m,
struct mpc_intsrc *mp_irq)
{
mp_irq->dstapic = m->dstapic;
mp_irq->type = m->type;
mp_irq->irqtype = m->irqtype;
mp_irq->irqflag = m->irqflag;
mp_irq->srcbus = m->srcbus;
mp_irq->srcbusirq = m->srcbusirq;
mp_irq->dstirq = m->dstirq;
}
static void __init assign_to_mpc_intsrc(struct mpc_intsrc *mp_irq,
struct mpc_intsrc *m)
{
m->dstapic = mp_irq->dstapic;
m->type = mp_irq->type;
m->irqtype = mp_irq->irqtype;
m->irqflag = mp_irq->irqflag;
m->srcbus = mp_irq->srcbus;
m->srcbusirq = mp_irq->srcbusirq;
m->dstirq = mp_irq->dstirq;
}
static int __init mp_irq_mpc_intsrc_cmp(struct mpc_intsrc *mp_irq,
struct mpc_intsrc *m)
{
if (mp_irq->dstapic != m->dstapic)
return 1;
if (mp_irq->type != m->type)
return 2;
if (mp_irq->irqtype != m->irqtype)
return 3;
if (mp_irq->irqflag != m->irqflag)
return 4;
if (mp_irq->srcbus != m->srcbus)
return 5;
if (mp_irq->srcbusirq != m->srcbusirq)
return 6;
if (mp_irq->dstirq != m->dstirq)
return 7;
return 0;
}
static void __init MP_intsrc_info(struct mpc_intsrc *m)
{
int i;
print_MP_intsrc_info(m);
for (i = 0; i < mp_irq_entries; i++) {
if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
return;
}
assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
if (++mp_irq_entries == MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!!\n");
}
#else /* CONFIG_X86_IO_APIC */ #else /* CONFIG_X86_IO_APIC */
static inline void __init MP_bus_info(struct mpc_bus *m) {} static inline void __init MP_bus_info(struct mpc_bus *m) {}
static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {} static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {}
static inline void __init MP_intsrc_info(struct mpc_intsrc *m) {}
#endif /* CONFIG_X86_IO_APIC */ #endif /* CONFIG_X86_IO_APIC */
static void __init MP_lintsrc_info(struct mpc_lintsrc *m) static void __init MP_lintsrc_info(struct mpc_lintsrc *m)
{ {
apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x," apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x,"
...@@ -222,7 +147,6 @@ static void __init MP_lintsrc_info(struct mpc_lintsrc *m) ...@@ -222,7 +147,6 @@ static void __init MP_lintsrc_info(struct mpc_lintsrc *m)
/* /*
* Read/parse the MPC * Read/parse the MPC
*/ */
static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str) static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str)
{ {
...@@ -275,18 +199,6 @@ static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt) ...@@ -275,18 +199,6 @@ static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt)
void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { } void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { }
static void __init smp_register_lapic_address(unsigned long address)
{
mp_lapic_addr = address;
set_fixmap_nocache(FIX_APIC_BASE, address);
if (boot_cpu_physical_apicid == -1U) {
boot_cpu_physical_apicid = read_apic_id();
apic_version[boot_cpu_physical_apicid] =
GET_APIC_VERSION(apic_read(APIC_LVR));
}
}
static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
{ {
char str[16]; char str[16];
...@@ -301,17 +213,13 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) ...@@ -301,17 +213,13 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
generic_mps_oem_check(mpc, oem, str); generic_mps_oem_check(mpc, oem, str);
#endif #endif
/* save the local APIC address, it might be non-default */ /* Initialize the lapic mapping */
if (!acpi_lapic) if (!acpi_lapic)
mp_lapic_addr = mpc->lapic; register_lapic_address(mpc->lapic);
if (early) if (early)
return 1; return 1;
/* Initialize the lapic mapping */
if (!acpi_lapic)
smp_register_lapic_address(mpc->lapic);
if (mpc->oemptr) if (mpc->oemptr)
x86_init.mpparse.smp_read_mpc_oem(mpc); x86_init.mpparse.smp_read_mpc_oem(mpc);
...@@ -337,7 +245,7 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) ...@@ -337,7 +245,7 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
skip_entry(&mpt, &count, sizeof(struct mpc_ioapic)); skip_entry(&mpt, &count, sizeof(struct mpc_ioapic));
break; break;
case MP_INTSRC: case MP_INTSRC:
MP_intsrc_info((struct mpc_intsrc *)mpt); mp_save_irq((struct mpc_intsrc *)mpt);
skip_entry(&mpt, &count, sizeof(struct mpc_intsrc)); skip_entry(&mpt, &count, sizeof(struct mpc_intsrc));
break; break;
case MP_LINTSRC: case MP_LINTSRC:
...@@ -429,13 +337,13 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type) ...@@ -429,13 +337,13 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type)
intsrc.srcbusirq = i; intsrc.srcbusirq = i;
intsrc.dstirq = i ? i : 2; /* IRQ0 to INTIN2 */ intsrc.dstirq = i ? i : 2; /* IRQ0 to INTIN2 */
MP_intsrc_info(&intsrc); mp_save_irq(&intsrc);
} }
intsrc.irqtype = mp_ExtINT; intsrc.irqtype = mp_ExtINT;
intsrc.srcbusirq = 0; intsrc.srcbusirq = 0;
intsrc.dstirq = 0; /* 8259A to INTIN0 */ intsrc.dstirq = 0; /* 8259A to INTIN0 */
MP_intsrc_info(&intsrc); mp_save_irq(&intsrc);
} }
...@@ -784,11 +692,11 @@ static void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) ...@@ -784,11 +692,11 @@ static void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare)
int i; int i;
apic_printk(APIC_VERBOSE, "OLD "); apic_printk(APIC_VERBOSE, "OLD ");
print_MP_intsrc_info(m); print_mp_irq_info(m);
i = get_MP_intsrc_index(m); i = get_MP_intsrc_index(m);
if (i > 0) { if (i > 0) {
assign_to_mpc_intsrc(&mp_irqs[i], m); memcpy(m, &mp_irqs[i], sizeof(*m));
apic_printk(APIC_VERBOSE, "NEW "); apic_printk(APIC_VERBOSE, "NEW ");
print_mp_irq_info(&mp_irqs[i]); print_mp_irq_info(&mp_irqs[i]);
return; return;
...@@ -875,14 +783,14 @@ static int __init replace_intsrc_all(struct mpc_table *mpc, ...@@ -875,14 +783,14 @@ static int __init replace_intsrc_all(struct mpc_table *mpc,
if (nr_m_spare > 0) { if (nr_m_spare > 0) {
apic_printk(APIC_VERBOSE, "*NEW* found\n"); apic_printk(APIC_VERBOSE, "*NEW* found\n");
nr_m_spare--; nr_m_spare--;
assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]); memcpy(m_spare[nr_m_spare], &mp_irqs[i], sizeof(mp_irqs[i]));
m_spare[nr_m_spare] = NULL; m_spare[nr_m_spare] = NULL;
} else { } else {
struct mpc_intsrc *m = (struct mpc_intsrc *)mpt; struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
count += sizeof(struct mpc_intsrc); count += sizeof(struct mpc_intsrc);
if (check_slot(mpc_new_phys, mpc_new_length, count) < 0) if (check_slot(mpc_new_phys, mpc_new_length, count) < 0)
goto out; goto out;
assign_to_mpc_intsrc(&mp_irqs[i], m); memcpy(m, &mp_irqs[i], sizeof(*m));
mpc->length = count; mpc->length = count;
mpt += sizeof(struct mpc_intsrc); mpt += sizeof(struct mpc_intsrc);
} }
......
...@@ -43,17 +43,33 @@ static void rdc321x_reset(struct pci_dev *dev) ...@@ -43,17 +43,33 @@ static void rdc321x_reset(struct pci_dev *dev)
outb(1, 0x92); outb(1, 0x92);
} }
static void ce4100_reset(struct pci_dev *dev)
{
int i;
for (i = 0; i < 10; i++) {
outb(0x2, 0xcf9);
udelay(50);
}
}
struct device_fixup { struct device_fixup {
unsigned int vendor; unsigned int vendor;
unsigned int device; unsigned int device;
void (*reboot_fixup)(struct pci_dev *); void (*reboot_fixup)(struct pci_dev *);
}; };
/*
* PCI ids solely used for fixups_table go here
*/
#define PCI_DEVICE_ID_INTEL_CE4100 0x0708
static const struct device_fixup fixups_table[] = { static const struct device_fixup fixups_table[] = {
{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset }, { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset },
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, cs5536_warm_reset }, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, cs5536_warm_reset },
{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE, cs5530a_warm_reset }, { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE, cs5530a_warm_reset },
{ PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030, rdc321x_reset }, { PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030, rdc321x_reset },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100, ce4100_reset },
}; };
/* /*
......
...@@ -1035,10 +1035,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -1035,10 +1035,7 @@ void __init setup_arch(char **cmdline_p)
#endif #endif
init_apic_mappings(); init_apic_mappings();
ioapic_init_mappings(); ioapic_and_gsi_init();
/* need to wait for io_apic is mapped */
probe_nr_irqs_gsi();
kvm_guest_init(); kvm_guest_init();
......
...@@ -67,7 +67,6 @@ static __init void early_get_boot_cpu_id(void) ...@@ -67,7 +67,6 @@ static __init void early_get_boot_cpu_id(void)
if (smp_found_config) if (smp_found_config)
early_get_smp_config(); early_get_smp_config();
#endif #endif
early_init_lapic_mapping();
} }
int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
......
...@@ -7,6 +7,7 @@ obj-$(CONFIG_PCI_OLPC) += olpc.o ...@@ -7,6 +7,7 @@ obj-$(CONFIG_PCI_OLPC) += olpc.o
obj-$(CONFIG_PCI_XEN) += xen.o obj-$(CONFIG_PCI_XEN) += xen.o
obj-y += fixup.o obj-y += fixup.o
obj-$(CONFIG_X86_INTEL_CE) += ce4100.o
obj-$(CONFIG_ACPI) += acpi.o obj-$(CONFIG_ACPI) += acpi.o
obj-y += legacy.o irq.o obj-y += legacy.o irq.o
......
/*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2010 Intel 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 will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* Contact Information:
* Intel Corporation
* 2200 Mission College Blvd.
* Santa Clara, CA 97052
*
* This provides access methods for PCI registers that mis-behave on
* the CE4100. Each register can be assigned a private init, read and
* write routine. The exception to this is the bridge device. The
* bridge device is the only device on bus zero (0) that requires any
* fixup so it is a special case ATM
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/pci_x86.h>
struct sim_reg {
u32 value;
u32 mask;
};
struct sim_dev_reg {
int dev_func;
int reg;
void (*init)(struct sim_dev_reg *reg);
void (*read)(struct sim_dev_reg *reg, u32 *value);
void (*write)(struct sim_dev_reg *reg, u32 value);
struct sim_reg sim_reg;
};
struct sim_reg_op {
void (*init)(struct sim_dev_reg *reg);
void (*read)(struct sim_dev_reg *reg, u32 value);
void (*write)(struct sim_dev_reg *reg, u32 value);
};
#define MB (1024 * 1024)
#define KB (1024)
#define SIZE_TO_MASK(size) (~(size - 1))
#define DEFINE_REG(device, func, offset, size, init_op, read_op, write_op)\
{ PCI_DEVFN(device, func), offset, init_op, read_op, write_op,\
{0, SIZE_TO_MASK(size)} },
static void reg_init(struct sim_dev_reg *reg)
{
pci_direct_conf1.read(0, 1, reg->dev_func, reg->reg, 4,
&reg->sim_reg.value);
}
static void reg_read(struct sim_dev_reg *reg, u32 *value)
{
unsigned long flags;
raw_spin_lock_irqsave(&pci_config_lock, flags);
*value = reg->sim_reg.value;
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
}
static void reg_write(struct sim_dev_reg *reg, u32 value)
{
unsigned long flags;
raw_spin_lock_irqsave(&pci_config_lock, flags);
reg->sim_reg.value = (value & reg->sim_reg.mask) |
(reg->sim_reg.value & ~reg->sim_reg.mask);
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
}
static void sata_reg_init(struct sim_dev_reg *reg)
{
pci_direct_conf1.read(0, 1, PCI_DEVFN(14, 0), 0x10, 4,
&reg->sim_reg.value);
reg->sim_reg.value += 0x400;
}
static void ehci_reg_read(struct sim_dev_reg *reg, u32 *value)
{
reg_read(reg, value);
if (*value != reg->sim_reg.mask)
*value |= 0x100;
}
void sata_revid_init(struct sim_dev_reg *reg)
{
reg->sim_reg.value = 0x01060100;
reg->sim_reg.mask = 0;
}
static void sata_revid_read(struct sim_dev_reg *reg, u32 *value)
{
reg_read(reg, value);
}
static struct sim_dev_reg bus1_fixups[] = {
DEFINE_REG(2, 0, 0x10, (16*MB), reg_init, reg_read, reg_write)
DEFINE_REG(2, 0, 0x14, (256), reg_init, reg_read, reg_write)
DEFINE_REG(2, 1, 0x10, (64*KB), reg_init, reg_read, reg_write)
DEFINE_REG(3, 0, 0x10, (64*KB), reg_init, reg_read, reg_write)
DEFINE_REG(4, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
DEFINE_REG(4, 1, 0x10, (128*KB), reg_init, reg_read, reg_write)
DEFINE_REG(6, 0, 0x10, (512*KB), reg_init, reg_read, reg_write)
DEFINE_REG(6, 1, 0x10, (512*KB), reg_init, reg_read, reg_write)
DEFINE_REG(6, 2, 0x10, (64*KB), reg_init, reg_read, reg_write)
DEFINE_REG(8, 0, 0x10, (1*MB), reg_init, reg_read, reg_write)
DEFINE_REG(8, 1, 0x10, (64*KB), reg_init, reg_read, reg_write)
DEFINE_REG(8, 2, 0x10, (64*KB), reg_init, reg_read, reg_write)
DEFINE_REG(9, 0, 0x10 , (1*MB), reg_init, reg_read, reg_write)
DEFINE_REG(9, 0, 0x14, (64*KB), reg_init, reg_read, reg_write)
DEFINE_REG(10, 0, 0x10, (256), reg_init, reg_read, reg_write)
DEFINE_REG(10, 0, 0x14, (256*MB), reg_init, reg_read, reg_write)
DEFINE_REG(11, 0, 0x10, (256), reg_init, reg_read, reg_write)
DEFINE_REG(11, 0, 0x14, (256), reg_init, reg_read, reg_write)
DEFINE_REG(11, 1, 0x10, (256), reg_init, reg_read, reg_write)
DEFINE_REG(11, 2, 0x10, (256), reg_init, reg_read, reg_write)
DEFINE_REG(11, 2, 0x14, (256), reg_init, reg_read, reg_write)
DEFINE_REG(11, 2, 0x18, (256), reg_init, reg_read, reg_write)
DEFINE_REG(11, 3, 0x10, (256), reg_init, reg_read, reg_write)
DEFINE_REG(11, 3, 0x14, (256), reg_init, reg_read, reg_write)
DEFINE_REG(11, 4, 0x10, (256), reg_init, reg_read, reg_write)
DEFINE_REG(11, 5, 0x10, (64*KB), reg_init, reg_read, reg_write)
DEFINE_REG(11, 6, 0x10, (256), reg_init, reg_read, reg_write)
DEFINE_REG(11, 7, 0x10, (64*KB), reg_init, reg_read, reg_write)
DEFINE_REG(12, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
DEFINE_REG(12, 0, 0x14, (256), reg_init, reg_read, reg_write)
DEFINE_REG(12, 1, 0x10, (1024), reg_init, reg_read, reg_write)
DEFINE_REG(13, 0, 0x10, (32*KB), reg_init, ehci_reg_read, reg_write)
DEFINE_REG(13, 1, 0x10, (32*KB), reg_init, ehci_reg_read, reg_write)
DEFINE_REG(14, 0, 0x8, 0, sata_revid_init, sata_revid_read, 0)
DEFINE_REG(14, 0, 0x10, 0, reg_init, reg_read, reg_write)
DEFINE_REG(14, 0, 0x14, 0, reg_init, reg_read, reg_write)
DEFINE_REG(14, 0, 0x18, 0, reg_init, reg_read, reg_write)
DEFINE_REG(14, 0, 0x1C, 0, reg_init, reg_read, reg_write)
DEFINE_REG(14, 0, 0x20, 0, reg_init, reg_read, reg_write)
DEFINE_REG(14, 0, 0x24, (0x200), sata_reg_init, reg_read, reg_write)
DEFINE_REG(15, 0, 0x10, (64*KB), reg_init, reg_read, reg_write)
DEFINE_REG(15, 0, 0x14, (64*KB), reg_init, reg_read, reg_write)
DEFINE_REG(16, 0, 0x10, (64*KB), reg_init, reg_read, reg_write)
DEFINE_REG(16, 0, 0x14, (64*MB), reg_init, reg_read, reg_write)
DEFINE_REG(16, 0, 0x18, (64*MB), reg_init, reg_read, reg_write)
DEFINE_REG(17, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
DEFINE_REG(18, 0, 0x10, (1*KB), reg_init, reg_read, reg_write)
};
static void __init init_sim_regs(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
if (bus1_fixups[i].init)
bus1_fixups[i].init(&bus1_fixups[i]);
}
}
static inline void extract_bytes(u32 *value, int reg, int len)
{
uint32_t mask;
*value >>= ((reg & 3) * 8);
mask = 0xFFFFFFFF >> ((4 - len) * 8);
*value &= mask;
}
int bridge_read(unsigned int devfn, int reg, int len, u32 *value)
{
u32 av_bridge_base, av_bridge_limit;
int retval = 0;
switch (reg) {
/* Make BARs appear to not request any memory. */
case PCI_BASE_ADDRESS_0:
case PCI_BASE_ADDRESS_0 + 1:
case PCI_BASE_ADDRESS_0 + 2:
case PCI_BASE_ADDRESS_0 + 3:
*value = 0;
break;
/* Since subordinate bus number register is hardwired
* to zero and read only, so do the simulation.
*/
case PCI_PRIMARY_BUS:
if (len == 4)
*value = 0x00010100;
break;
case PCI_SUBORDINATE_BUS:
*value = 1;
break;
case PCI_MEMORY_BASE:
case PCI_MEMORY_LIMIT:
/* Get the A/V bridge base address. */
pci_direct_conf1.read(0, 0, devfn,
PCI_BASE_ADDRESS_0, 4, &av_bridge_base);
av_bridge_limit = av_bridge_base + (512*MB - 1);
av_bridge_limit >>= 16;
av_bridge_limit &= 0xFFF0;
av_bridge_base >>= 16;
av_bridge_base &= 0xFFF0;
if (reg == PCI_MEMORY_LIMIT)
*value = av_bridge_limit;
else if (len == 2)
*value = av_bridge_base;
else
*value = (av_bridge_limit << 16) | av_bridge_base;
break;
/* Make prefetchable memory limit smaller than prefetchable
* memory base, so not claim prefetchable memory space.
*/
case PCI_PREF_MEMORY_BASE:
*value = 0xFFF0;
break;
case PCI_PREF_MEMORY_LIMIT:
*value = 0x0;
break;
/* Make IO limit smaller than IO base, so not claim IO space. */
case PCI_IO_BASE:
*value = 0xF0;
break;
case PCI_IO_LIMIT:
*value = 0;
break;
default:
retval = 1;
}
return retval;
}
static int ce4100_conf_read(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 *value)
{
int i, retval = 1;
if (bus == 1) {
for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
if (bus1_fixups[i].dev_func == devfn &&
bus1_fixups[i].reg == (reg & ~3) &&
bus1_fixups[i].read) {
bus1_fixups[i].read(&(bus1_fixups[i]),
value);
extract_bytes(value, reg, len);
return 0;
}
}
}
if (bus == 0 && (PCI_DEVFN(1, 0) == devfn) &&
!bridge_read(devfn, reg, len, value))
return 0;
return pci_direct_conf1.read(seg, bus, devfn, reg, len, value);
}
static int ce4100_conf_write(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 value)
{
int i;
if (bus == 1) {
for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
if (bus1_fixups[i].dev_func == devfn &&
bus1_fixups[i].reg == (reg & ~3) &&
bus1_fixups[i].write) {
bus1_fixups[i].write(&(bus1_fixups[i]),
value);
return 0;
}
}
}
/* Discard writes to A/V bridge BAR. */
if (bus == 0 && PCI_DEVFN(1, 0) == devfn &&
((reg & ~3) == PCI_BASE_ADDRESS_0))
return 0;
return pci_direct_conf1.write(seg, bus, devfn, reg, len, value);
}
struct pci_raw_ops ce4100_pci_conf = {
.read = ce4100_conf_read,
.write = ce4100_conf_write,
};
static int __init ce4100_pci_init(void)
{
init_sim_regs();
raw_pci_ops = &ce4100_pci_conf;
return 0;
}
subsys_initcall(ce4100_pci_init);
# Platform specific code goes here # Platform specific code goes here
obj-y += ce4100/
obj-y += efi/ obj-y += efi/
obj-y += iris/
obj-y += mrst/ obj-y += mrst/
obj-y += olpc/ obj-y += olpc/
obj-y += scx200/ obj-y += scx200/
......
obj-$(CONFIG_X86_INTEL_CE) += ce4100.o
/*
* Intel CE4100 platform specific setup code
*
* (C) Copyright 2010 Intel Corporation
*
* 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; version 2
* of the License.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/serial_reg.h>
#include <linux/serial_8250.h>
#include <asm/setup.h>
#include <asm/io.h>
static int ce4100_i8042_detect(void)
{
return 0;
}
static void __init sdv_find_smp_config(void)
{
}
#ifdef CONFIG_SERIAL_8250
static unsigned int mem_serial_in(struct uart_port *p, int offset)
{
offset = offset << p->regshift;
return readl(p->membase + offset);
}
/*
* The UART Tx interrupts are not set under some conditions and therefore serial
* transmission hangs. This is a silicon issue and has not been root caused. The
* workaround for this silicon issue checks UART_LSR_THRE bit and UART_LSR_TEMT
* bit of LSR register in interrupt handler to see whether at least one of these
* two bits is set, if so then process the transmit request. If this workaround
* is not applied, then the serial transmission may hang. This workaround is for
* errata number 9 in Errata - B step.
*/
static unsigned int ce4100_mem_serial_in(struct uart_port *p, int offset)
{
unsigned int ret, ier, lsr;
if (offset == UART_IIR) {
offset = offset << p->regshift;
ret = readl(p->membase + offset);
if (ret & UART_IIR_NO_INT) {
/* see if the TX interrupt should have really set */
ier = mem_serial_in(p, UART_IER);
/* see if the UART's XMIT interrupt is enabled */
if (ier & UART_IER_THRI) {
lsr = mem_serial_in(p, UART_LSR);
/* now check to see if the UART should be
generating an interrupt (but isn't) */
if (lsr & (UART_LSR_THRE | UART_LSR_TEMT))
ret &= ~UART_IIR_NO_INT;
}
}
} else
ret = mem_serial_in(p, offset);
return ret;
}
static void ce4100_mem_serial_out(struct uart_port *p, int offset, int value)
{
offset = offset << p->regshift;
writel(value, p->membase + offset);
}
static void ce4100_serial_fixup(int port, struct uart_port *up,
unsigned short *capabilites)
{
#ifdef CONFIG_EARLY_PRINTK
/*
* Over ride the legacy port configuration that comes from
* asm/serial.h. Using the ioport driver then switching to the
* PCI memmaped driver hangs the IOAPIC
*/
if (up->iotype != UPIO_MEM32) {
up->uartclk = 14745600;
up->mapbase = 0xdffe0200;
set_fixmap_nocache(FIX_EARLYCON_MEM_BASE,
up->mapbase & PAGE_MASK);
up->membase =
(void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
up->membase += up->mapbase & ~PAGE_MASK;
up->iotype = UPIO_MEM32;
up->regshift = 2;
}
#endif
up->iobase = 0;
up->serial_in = ce4100_mem_serial_in;
up->serial_out = ce4100_mem_serial_out;
*capabilites |= (1 << 12);
}
static __init void sdv_serial_fixup(void)
{
serial8250_set_isa_configurator(ce4100_serial_fixup);
}
#else
static inline void sdv_serial_fixup(void);
#endif
static void __init sdv_arch_setup(void)
{
sdv_serial_fixup();
}
/*
* CE4100 specific x86_init function overrides and early setup
* calls.
*/
void __init x86_ce4100_early_setup(void)
{
x86_init.oem.arch_setup = sdv_arch_setup;
x86_platform.i8042_detect = ce4100_i8042_detect;
x86_init.resources.probe_roms = x86_init_noop;
x86_init.mpparse.get_smp_config = x86_init_uint_noop;
x86_init.mpparse.find_smp_config = sdv_find_smp_config;
}
obj-$(CONFIG_X86_32_IRIS) += iris.o
/*
* Eurobraille/Iris power off support.
*
* Eurobraille's Iris machine is a PC with no APM or ACPI support.
* It is shutdown by a special I/O sequence which this module provides.
*
* Copyright (C) Shérab <Sebastien.Hinderer@ens-lyon.org>
*
* 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program ; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/moduleparam.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/pm.h>
#include <asm/io.h>
#define IRIS_GIO_BASE 0x340
#define IRIS_GIO_INPUT IRIS_GIO_BASE
#define IRIS_GIO_OUTPUT (IRIS_GIO_BASE + 1)
#define IRIS_GIO_PULSE 0x80 /* First byte to send */
#define IRIS_GIO_REST 0x00 /* Second byte to send */
#define IRIS_GIO_NODEV 0xff /* Likely not an Iris */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sébastien Hinderer <Sebastien.Hinderer@ens-lyon.org>");
MODULE_DESCRIPTION("A power_off handler for Iris devices from EuroBraille");
MODULE_SUPPORTED_DEVICE("Eurobraille/Iris");
static int force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Set to one to force poweroff handler installation.");
static void (*old_pm_power_off)(void);
static void iris_power_off(void)
{
outb(IRIS_GIO_PULSE, IRIS_GIO_OUTPUT);
msleep(850);
outb(IRIS_GIO_REST, IRIS_GIO_OUTPUT);
}
/*
* Before installing the power_off handler, try to make sure the OS is
* running on an Iris. Since Iris does not support DMI, this is done
* by reading its input port and seeing whether the read value is
* meaningful.
*/
static int iris_init(void)
{
unsigned char status;
if (force != 1) {
printk(KERN_ERR "The force parameter has not been set to 1 so the Iris poweroff handler will not be installed.\n");
return -ENODEV;
}
status = inb(IRIS_GIO_INPUT);
if (status == IRIS_GIO_NODEV) {
printk(KERN_ERR "This machine does not seem to be an Iris. Power_off handler not installed.\n");
return -ENODEV;
}
old_pm_power_off = pm_power_off;
pm_power_off = &iris_power_off;
printk(KERN_INFO "Iris power_off handler installed.\n");
return 0;
}
static void iris_exit(void)
{
pm_power_off = old_pm_power_off;
printk(KERN_INFO "Iris power_off handler uninstalled.\n");
}
module_init(iris_init);
module_exit(iris_exit);
obj-$(CONFIG_X86_MRST) += mrst.o obj-$(CONFIG_X86_MRST) += mrst.o
obj-$(CONFIG_X86_MRST) += vrtc.o
obj-$(CONFIG_EARLY_PRINTK_MRST) += early_printk_mrst.o
This diff is collapsed.
/*
* vrtc.c: Driver for virtual RTC device on Intel MID platform
*
* (C) Copyright 2009 Intel Corporation
*
* 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; version 2
* of the License.
*
* Note:
* VRTC is emulated by system controller firmware, the real HW
* RTC is located in the PMIC device. SCU FW shadows PMIC RTC
* in a memory mapped IO space that is visible to the host IA
* processor.
*
* This driver is based on RTC CMOS driver.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sfi.h>
#include <linux/platform_device.h>
#include <asm/mrst.h>
#include <asm/mrst-vrtc.h>
#include <asm/time.h>
#include <asm/fixmap.h>
static unsigned char __iomem *vrtc_virt_base;
unsigned char vrtc_cmos_read(unsigned char reg)
{
unsigned char retval;
/* vRTC's registers range from 0x0 to 0xD */
if (reg > 0xd || !vrtc_virt_base)
return 0xff;
lock_cmos_prefix(reg);
retval = __raw_readb(vrtc_virt_base + (reg << 2));
lock_cmos_suffix(reg);
return retval;
}
EXPORT_SYMBOL_GPL(vrtc_cmos_read);
void vrtc_cmos_write(unsigned char val, unsigned char reg)
{
if (reg > 0xd || !vrtc_virt_base)
return;
lock_cmos_prefix(reg);
__raw_writeb(val, vrtc_virt_base + (reg << 2));
lock_cmos_suffix(reg);
}
EXPORT_SYMBOL_GPL(vrtc_cmos_write);
unsigned long vrtc_get_time(void)
{
u8 sec, min, hour, mday, mon;
u32 year;
while ((vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP))
cpu_relax();
sec = vrtc_cmos_read(RTC_SECONDS);
min = vrtc_cmos_read(RTC_MINUTES);
hour = vrtc_cmos_read(RTC_HOURS);
mday = vrtc_cmos_read(RTC_DAY_OF_MONTH);
mon = vrtc_cmos_read(RTC_MONTH);
year = vrtc_cmos_read(RTC_YEAR);
/* vRTC YEAR reg contains the offset to 1960 */
year += 1960;
printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
"mon: %d year: %d\n", sec, min, hour, mday, mon, year);
return mktime(year, mon, mday, hour, min, sec);
}
/* Only care about the minutes and seconds */
int vrtc_set_mmss(unsigned long nowtime)
{
int real_sec, real_min;
int vrtc_min;
vrtc_min = vrtc_cmos_read(RTC_MINUTES);
real_sec = nowtime % 60;
real_min = nowtime / 60;
if (((abs(real_min - vrtc_min) + 15)/30) & 1)
real_min += 30;
real_min %= 60;
vrtc_cmos_write(real_sec, RTC_SECONDS);
vrtc_cmos_write(real_min, RTC_MINUTES);
return 0;
}
void __init mrst_rtc_init(void)
{
unsigned long rtc_paddr;
void __iomem *virt_base;
sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
if (!sfi_mrtc_num)
return;
rtc_paddr = sfi_mrtc_array[0].phys_addr;
/* vRTC's register address may not be page aligned */
set_fixmap_nocache(FIX_LNW_VRTC, rtc_paddr);
virt_base = (void __iomem *)__fix_to_virt(FIX_LNW_VRTC);
virt_base += rtc_paddr & ~PAGE_MASK;
vrtc_virt_base = virt_base;
x86_platform.get_wallclock = vrtc_get_time;
x86_platform.set_wallclock = vrtc_set_mmss;
}
/*
* The Moorestown platform has a memory mapped virtual RTC device that emulates
* the programming interface of the RTC.
*/
static struct resource vrtc_resources[] = {
[0] = {
.flags = IORESOURCE_MEM,
},
[1] = {
.flags = IORESOURCE_IRQ,
}
};
static struct platform_device vrtc_device = {
.name = "rtc_mrst",
.id = -1,
.resource = vrtc_resources,
.num_resources = ARRAY_SIZE(vrtc_resources),
};
/* Register the RTC device if appropriate */
static int __init mrst_device_create(void)
{
/* No Moorestown, no device */
if (!mrst_identify_cpu())
return -ENODEV;
/* No timer, no device */
if (!sfi_mrtc_num)
return -ENODEV;
/* iomem resource */
vrtc_resources[0].start = sfi_mrtc_array[0].phys_addr;
vrtc_resources[0].end = sfi_mrtc_array[0].phys_addr +
MRST_VRTC_MAP_SZ;
/* irq resource */
vrtc_resources[1].start = sfi_mrtc_array[0].irq;
vrtc_resources[1].end = sfi_mrtc_array[0].irq;
return platform_device_register(&vrtc_device);
}
module_init(mrst_device_create);
...@@ -34,17 +34,6 @@ ...@@ -34,17 +34,6 @@
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
static void __init mp_sfi_register_lapic_address(unsigned long address)
{
mp_lapic_addr = address;
set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
if (boot_cpu_physical_apicid == -1U)
boot_cpu_physical_apicid = read_apic_id();
pr_info("Boot CPU = %d\n", boot_cpu_physical_apicid);
}
/* All CPUs enumerated by SFI must be present and enabled */ /* All CPUs enumerated by SFI must be present and enabled */
static void __cpuinit mp_sfi_register_lapic(u8 id) static void __cpuinit mp_sfi_register_lapic(u8 id)
{ {
...@@ -110,7 +99,7 @@ static int __init sfi_parse_ioapic(struct sfi_table_header *table) ...@@ -110,7 +99,7 @@ static int __init sfi_parse_ioapic(struct sfi_table_header *table)
int __init sfi_platform_init(void) int __init sfi_platform_init(void)
{ {
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
mp_sfi_register_lapic_address(sfi_lapic_addr); register_lapic_address(sfi_lapic_addr);
sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, sfi_parse_cpus); sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, sfi_parse_cpus);
#endif #endif
#ifdef CONFIG_X86_IO_APIC #ifdef CONFIG_X86_IO_APIC
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/sfi.h> #include <linux/sfi.h>
#include <asm/mrst.h> #include <asm/mrst.h>
#include <asm/intel_scu_ipc.h> #include <asm/intel_scu_ipc.h>
#include <asm/mrst.h>
/* IPC defines the following message types */ /* IPC defines the following message types */
#define IPCMSG_WATCHDOG_TIMER 0xF8 /* Set Kernel Watchdog Threshold */ #define IPCMSG_WATCHDOG_TIMER 0xF8 /* Set Kernel Watchdog Threshold */
...@@ -699,6 +700,9 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -699,6 +700,9 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
iounmap(ipcdev.ipc_base); iounmap(ipcdev.ipc_base);
return -ENOMEM; return -ENOMEM;
} }
intel_scu_devices_create();
return 0; return 0;
} }
...@@ -720,6 +724,7 @@ static void ipc_remove(struct pci_dev *pdev) ...@@ -720,6 +724,7 @@ static void ipc_remove(struct pci_dev *pdev)
iounmap(ipcdev.ipc_base); iounmap(ipcdev.ipc_base);
iounmap(ipcdev.i2c_base); iounmap(ipcdev.i2c_base);
ipcdev.pdev = NULL; ipcdev.pdev = NULL;
intel_scu_devices_destroy();
} }
static const struct pci_device_id pci_ids[] = { static const struct pci_device_id pci_ids[] = {
......
...@@ -463,6 +463,18 @@ config RTC_DRV_CMOS ...@@ -463,6 +463,18 @@ config RTC_DRV_CMOS
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-cmos. will be called rtc-cmos.
config RTC_DRV_VRTC
tristate "Virtual RTC for Moorestown platforms"
depends on X86_MRST
default y if X86_MRST
help
Say "yes" here to get direct support for the real time clock
found on Moorestown platforms. The VRTC is a emulated RTC that
derives its clock source from a real RTC in the PMIC. The MC146818
style programming interface is mostly conserved, but any
updates are done via IPC calls to the system controller FW.
config RTC_DRV_DS1216 config RTC_DRV_DS1216
tristate "Dallas DS1216" tristate "Dallas DS1216"
depends on SNI_RM depends on SNI_RM
......
...@@ -30,6 +30,7 @@ obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o ...@@ -30,6 +30,7 @@ obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o
obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o
obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o
obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o
obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o
obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o
obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
......
This diff is collapsed.
...@@ -77,6 +77,8 @@ ...@@ -77,6 +77,8 @@
#define SFI_OEM_ID_SIZE 6 #define SFI_OEM_ID_SIZE 6
#define SFI_OEM_TABLE_ID_SIZE 8 #define SFI_OEM_TABLE_ID_SIZE 8
#define SFI_NAME_LEN 16
#define SFI_SYST_SEARCH_BEGIN 0x000E0000 #define SFI_SYST_SEARCH_BEGIN 0x000E0000
#define SFI_SYST_SEARCH_END 0x000FFFFF #define SFI_SYST_SEARCH_END 0x000FFFFF
...@@ -156,13 +158,13 @@ struct sfi_device_table_entry { ...@@ -156,13 +158,13 @@ struct sfi_device_table_entry {
u16 addr; u16 addr;
u8 irq; u8 irq;
u32 max_freq; u32 max_freq;
char name[16]; char name[SFI_NAME_LEN];
} __packed; } __packed;
struct sfi_gpio_table_entry { struct sfi_gpio_table_entry {
char controller_name[16]; char controller_name[SFI_NAME_LEN];
u16 pin_no; u16 pin_no;
char pin_name[16]; char pin_name[SFI_NAME_LEN];
} __packed; } __packed;
typedef int (*sfi_table_handler) (struct sfi_table_header *table); typedef int (*sfi_table_handler) (struct sfi_table_header *table);
......
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