diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2010-12-29 14:36:26 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2010-12-29 14:36:26 -0500 |
commit | d50e8fc7e38d88909448a723cb1f825bb3af30e2 (patch) | |
tree | 099e969b273c3d180c89aa64b1e359ef66a9fc5d /arch/x86 | |
parent | a387e95a49743cf9835c5299ca549232618d8249 (diff) | |
parent | 0aa002fe602939370e9476e5ec32b562000a0425 (diff) |
Merge branch 'x86/apic-cleanups' into x86/numa
Diffstat (limited to 'arch/x86')
31 files changed, 1481 insertions, 298 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 08993a38b119..58ecad57aad1 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -377,6 +377,18 @@ config X86_ELAN | |||
377 | 377 | ||
378 | If unsure, choose "PC-compatible" instead. | 378 | If unsure, choose "PC-compatible" instead. |
379 | 379 | ||
380 | config X86_INTEL_CE | ||
381 | bool "CE4100 TV platform" | ||
382 | depends on PCI | ||
383 | depends on PCI_GODIRECT | ||
384 | depends on X86_32 | ||
385 | depends on X86_EXTENDED_PLATFORM | ||
386 | select X86_REBOOTFIXUPS | ||
387 | ---help--- | ||
388 | Select for the Intel CE media processor (CE4100) SOC. | ||
389 | This option compiles in support for the CE4100 SOC for settop | ||
390 | boxes and media devices. | ||
391 | |||
380 | config X86_MRST | 392 | config X86_MRST |
381 | bool "Moorestown MID platform" | 393 | bool "Moorestown MID platform" |
382 | depends on PCI | 394 | depends on PCI |
@@ -385,6 +397,10 @@ config X86_MRST | |||
385 | depends on X86_EXTENDED_PLATFORM | 397 | depends on X86_EXTENDED_PLATFORM |
386 | depends on X86_IO_APIC | 398 | depends on X86_IO_APIC |
387 | select APB_TIMER | 399 | select APB_TIMER |
400 | select I2C | ||
401 | select SPI | ||
402 | select INTEL_SCU_IPC | ||
403 | select X86_PLATFORM_DEVICES | ||
388 | ---help--- | 404 | ---help--- |
389 | Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin | 405 | Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin |
390 | Internet Device(MID) platform. Moorestown consists of two chips: | 406 | Internet Device(MID) platform. Moorestown consists of two chips: |
@@ -466,6 +482,19 @@ config X86_ES7000 | |||
466 | Support for Unisys ES7000 systems. Say 'Y' here if this kernel is | 482 | Support for Unisys ES7000 systems. Say 'Y' here if this kernel is |
467 | supposed to run on an IA32-based Unisys ES7000 system. | 483 | supposed to run on an IA32-based Unisys ES7000 system. |
468 | 484 | ||
485 | config X86_32_IRIS | ||
486 | tristate "Eurobraille/Iris poweroff module" | ||
487 | depends on X86_32 | ||
488 | ---help--- | ||
489 | The Iris machines from EuroBraille do not have APM or ACPI support | ||
490 | to shut themselves down properly. A special I/O sequence is | ||
491 | needed to do so, which is what this module does at | ||
492 | kernel shutdown. | ||
493 | |||
494 | This is only for Iris machines from EuroBraille. | ||
495 | |||
496 | If unused, say N. | ||
497 | |||
469 | config SCHED_OMIT_FRAME_POINTER | 498 | config SCHED_OMIT_FRAME_POINTER |
470 | def_bool y | 499 | def_bool y |
471 | prompt "Single-depth WCHAN output" | 500 | prompt "Single-depth WCHAN output" |
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index f6ce0bda3b98..5e3969c36d7f 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h | |||
@@ -234,16 +234,17 @@ extern void init_bsp_APIC(void); | |||
234 | extern void setup_local_APIC(void); | 234 | extern void setup_local_APIC(void); |
235 | extern void end_local_APIC_setup(void); | 235 | extern void end_local_APIC_setup(void); |
236 | extern void init_apic_mappings(void); | 236 | extern void init_apic_mappings(void); |
237 | void register_lapic_address(unsigned long address); | ||
237 | extern void setup_boot_APIC_clock(void); | 238 | extern void setup_boot_APIC_clock(void); |
238 | extern void setup_secondary_APIC_clock(void); | 239 | extern void setup_secondary_APIC_clock(void); |
239 | extern int APIC_init_uniprocessor(void); | 240 | extern int APIC_init_uniprocessor(void); |
240 | extern void enable_NMI_through_LVT0(void); | 241 | extern void enable_NMI_through_LVT0(void); |
242 | extern int apic_force_enable(void); | ||
241 | 243 | ||
242 | /* | 244 | /* |
243 | * On 32bit this is mach-xxx local | 245 | * On 32bit this is mach-xxx local |
244 | */ | 246 | */ |
245 | #ifdef CONFIG_X86_64 | 247 | #ifdef CONFIG_X86_64 |
246 | extern void early_init_lapic_mapping(void); | ||
247 | extern int apic_is_clustered_box(void); | 248 | extern int apic_is_clustered_box(void); |
248 | #else | 249 | #else |
249 | static inline int apic_is_clustered_box(void) | 250 | static inline int apic_is_clustered_box(void) |
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h index 8e6218550e77..c8bfe63a06de 100644 --- a/arch/x86/include/asm/bootparam.h +++ b/arch/x86/include/asm/bootparam.h | |||
@@ -124,6 +124,7 @@ enum { | |||
124 | X86_SUBARCH_LGUEST, | 124 | X86_SUBARCH_LGUEST, |
125 | X86_SUBARCH_XEN, | 125 | X86_SUBARCH_XEN, |
126 | X86_SUBARCH_MRST, | 126 | X86_SUBARCH_MRST, |
127 | X86_SUBARCH_CE4100, | ||
127 | X86_NR_SUBARCHS, | 128 | X86_NR_SUBARCHS, |
128 | }; | 129 | }; |
129 | 130 | ||
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index 4d293dced62f..139591a933f6 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h | |||
@@ -117,6 +117,10 @@ enum fixed_addresses { | |||
117 | FIX_TEXT_POKE1, /* reserve 2 pages for text_poke() */ | 117 | FIX_TEXT_POKE1, /* reserve 2 pages for text_poke() */ |
118 | FIX_TEXT_POKE0, /* first page is last, because allocation is backward */ | 118 | FIX_TEXT_POKE0, /* first page is last, because allocation is backward */ |
119 | __end_of_permanent_fixed_addresses, | 119 | __end_of_permanent_fixed_addresses, |
120 | |||
121 | #ifdef CONFIG_X86_MRST | ||
122 | FIX_LNW_VRTC, | ||
123 | #endif | ||
120 | /* | 124 | /* |
121 | * 256 temporary boot-time mappings, used by early_ioremap(), | 125 | * 256 temporary boot-time mappings, used by early_ioremap(), |
122 | * before ioremap() is functional. | 126 | * before ioremap() is functional. |
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index a6b28d017c2f..f327d386d6cc 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h | |||
@@ -159,7 +159,7 @@ struct io_apic_irq_attr; | |||
159 | extern int io_apic_set_pci_routing(struct device *dev, int irq, | 159 | extern int io_apic_set_pci_routing(struct device *dev, int irq, |
160 | struct io_apic_irq_attr *irq_attr); | 160 | struct io_apic_irq_attr *irq_attr); |
161 | void setup_IO_APIC_irq_extra(u32 gsi); | 161 | void setup_IO_APIC_irq_extra(u32 gsi); |
162 | extern void ioapic_init_mappings(void); | 162 | extern void ioapic_and_gsi_init(void); |
163 | extern void ioapic_insert_resources(void); | 163 | extern void ioapic_insert_resources(void); |
164 | 164 | ||
165 | extern struct IO_APIC_route_entry **alloc_ioapic_entries(void); | 165 | 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 | extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); | 168 | extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); |
169 | extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); | 169 | extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); |
170 | 170 | ||
171 | extern void probe_nr_irqs_gsi(void); | ||
172 | extern int get_nr_irqs_gsi(void); | 171 | extern int get_nr_irqs_gsi(void); |
173 | 172 | ||
174 | extern void setup_ioapic_ids_from_mpc(void); | 173 | extern void setup_ioapic_ids_from_mpc(void); |
174 | extern void setup_ioapic_ids_from_mpc_nocheck(void); | ||
175 | 175 | ||
176 | struct mp_ioapic_gsi{ | 176 | struct mp_ioapic_gsi{ |
177 | u32 gsi_base; | 177 | u32 gsi_base; |
@@ -184,14 +184,15 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi); | |||
184 | void __init mp_register_ioapic(int id, u32 address, u32 gsi_base); | 184 | void __init mp_register_ioapic(int id, u32 address, u32 gsi_base); |
185 | extern void __init pre_init_apic_IRQ0(void); | 185 | extern void __init pre_init_apic_IRQ0(void); |
186 | 186 | ||
187 | extern void mp_save_irq(struct mpc_intsrc *m); | ||
188 | |||
187 | #else /* !CONFIG_X86_IO_APIC */ | 189 | #else /* !CONFIG_X86_IO_APIC */ |
188 | 190 | ||
189 | #define io_apic_assign_pci_irqs 0 | 191 | #define io_apic_assign_pci_irqs 0 |
190 | #define setup_ioapic_ids_from_mpc x86_init_noop | 192 | #define setup_ioapic_ids_from_mpc x86_init_noop |
191 | static const int timer_through_8259 = 0; | 193 | static const int timer_through_8259 = 0; |
192 | static inline void ioapic_init_mappings(void) { } | 194 | static inline void ioapic_and_gsi_init(void) { } |
193 | static inline void ioapic_insert_resources(void) { } | 195 | static inline void ioapic_insert_resources(void) { } |
194 | static inline void probe_nr_irqs_gsi(void) { } | ||
195 | #define gsi_top (NR_IRQS_LEGACY) | 196 | #define gsi_top (NR_IRQS_LEGACY) |
196 | static inline int mp_find_ioapic(u32 gsi) { return 0; } | 197 | static inline int mp_find_ioapic(u32 gsi) { return 0; } |
197 | 198 | ||
diff --git a/arch/x86/include/asm/mrst-vrtc.h b/arch/x86/include/asm/mrst-vrtc.h new file mode 100644 index 000000000000..73668abdbedf --- /dev/null +++ b/arch/x86/include/asm/mrst-vrtc.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef _MRST_VRTC_H | ||
2 | #define _MRST_VRTC_H | ||
3 | |||
4 | extern unsigned char vrtc_cmos_read(unsigned char reg); | ||
5 | extern void vrtc_cmos_write(unsigned char val, unsigned char reg); | ||
6 | extern unsigned long vrtc_get_time(void); | ||
7 | extern int vrtc_set_mmss(unsigned long nowtime); | ||
8 | |||
9 | #endif | ||
diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h index 4a711a684b17..719f00b28ff5 100644 --- a/arch/x86/include/asm/mrst.h +++ b/arch/x86/include/asm/mrst.h | |||
@@ -14,7 +14,9 @@ | |||
14 | #include <linux/sfi.h> | 14 | #include <linux/sfi.h> |
15 | 15 | ||
16 | extern int pci_mrst_init(void); | 16 | extern int pci_mrst_init(void); |
17 | int __init sfi_parse_mrtc(struct sfi_table_header *table); | 17 | extern int __init sfi_parse_mrtc(struct sfi_table_header *table); |
18 | extern int sfi_mrtc_num; | ||
19 | extern struct sfi_rtc_table_entry sfi_mrtc_array[]; | ||
18 | 20 | ||
19 | /* | 21 | /* |
20 | * Medfield is the follow-up of Moorestown, it combines two chip solution into | 22 | * 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 | 52 | ||
51 | extern struct console early_hsu_console; | 53 | extern struct console early_hsu_console; |
52 | extern void hsu_early_console_init(void); | 54 | extern void hsu_early_console_init(void); |
55 | |||
56 | extern void intel_scu_devices_create(void); | ||
57 | extern void intel_scu_devices_destroy(void); | ||
58 | |||
59 | /* VRTC timer */ | ||
60 | #define MRST_VRTC_MAP_SZ (1024) | ||
61 | /*#define MRST_VRTC_PGOFFSET (0xc00) */ | ||
62 | |||
63 | extern void mrst_rtc_init(void); | ||
64 | |||
53 | #endif /* _ASM_X86_MRST_H */ | 65 | #endif /* _ASM_X86_MRST_H */ |
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index d6763b139a84..db8aa19a08a2 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h | |||
@@ -53,6 +53,12 @@ extern void x86_mrst_early_setup(void); | |||
53 | static inline void x86_mrst_early_setup(void) { } | 53 | static inline void x86_mrst_early_setup(void) { } |
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | #ifdef CONFIG_X86_INTEL_CE | ||
57 | extern void x86_ce4100_early_setup(void); | ||
58 | #else | ||
59 | static inline void x86_ce4100_early_setup(void) { } | ||
60 | #endif | ||
61 | |||
56 | #ifndef _SETUP | 62 | #ifndef _SETUP |
57 | 63 | ||
58 | /* | 64 | /* |
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 9e13763b6092..f60153d5de57 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -84,7 +84,6 @@ obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o | |||
84 | obj-$(CONFIG_KGDB) += kgdb.o | 84 | obj-$(CONFIG_KGDB) += kgdb.o |
85 | obj-$(CONFIG_VM86) += vm86_32.o | 85 | obj-$(CONFIG_VM86) += vm86_32.o |
86 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 86 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
87 | obj-$(CONFIG_EARLY_PRINTK_MRST) += early_printk_mrst.o | ||
88 | 87 | ||
89 | obj-$(CONFIG_HPET_TIMER) += hpet.o | 88 | obj-$(CONFIG_HPET_TIMER) += hpet.o |
90 | obj-$(CONFIG_APB_TIMER) += apb_timer.o | 89 | obj-$(CONFIG_APB_TIMER) += apb_timer.o |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 71232b941b6c..1a5b9a8e6c4f 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -847,18 +847,6 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table) | |||
847 | * returns 0 on success, < 0 on error | 847 | * returns 0 on success, < 0 on error |
848 | */ | 848 | */ |
849 | 849 | ||
850 | static void __init acpi_register_lapic_address(unsigned long address) | ||
851 | { | ||
852 | mp_lapic_addr = address; | ||
853 | |||
854 | set_fixmap_nocache(FIX_APIC_BASE, address); | ||
855 | if (boot_cpu_physical_apicid == -1U) { | ||
856 | boot_cpu_physical_apicid = read_apic_id(); | ||
857 | apic_version[boot_cpu_physical_apicid] = | ||
858 | GET_APIC_VERSION(apic_read(APIC_LVR)); | ||
859 | } | ||
860 | } | ||
861 | |||
862 | static int __init early_acpi_parse_madt_lapic_addr_ovr(void) | 850 | static int __init early_acpi_parse_madt_lapic_addr_ovr(void) |
863 | { | 851 | { |
864 | int count; | 852 | int count; |
@@ -880,7 +868,7 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void) | |||
880 | return count; | 868 | return count; |
881 | } | 869 | } |
882 | 870 | ||
883 | acpi_register_lapic_address(acpi_lapic_addr); | 871 | register_lapic_address(acpi_lapic_addr); |
884 | 872 | ||
885 | return count; | 873 | return count; |
886 | } | 874 | } |
@@ -907,7 +895,7 @@ static int __init acpi_parse_madt_lapic_entries(void) | |||
907 | return count; | 895 | return count; |
908 | } | 896 | } |
909 | 897 | ||
910 | acpi_register_lapic_address(acpi_lapic_addr); | 898 | register_lapic_address(acpi_lapic_addr); |
911 | 899 | ||
912 | count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC, | 900 | count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC, |
913 | acpi_parse_sapic, MAX_APICS); | 901 | acpi_parse_sapic, MAX_APICS); |
@@ -949,32 +937,6 @@ static int __init acpi_parse_madt_lapic_entries(void) | |||
949 | extern int es7000_plat; | 937 | extern int es7000_plat; |
950 | #endif | 938 | #endif |
951 | 939 | ||
952 | static void assign_to_mp_irq(struct mpc_intsrc *m, | ||
953 | struct mpc_intsrc *mp_irq) | ||
954 | { | ||
955 | memcpy(mp_irq, m, sizeof(struct mpc_intsrc)); | ||
956 | } | ||
957 | |||
958 | static int mp_irq_cmp(struct mpc_intsrc *mp_irq, | ||
959 | struct mpc_intsrc *m) | ||
960 | { | ||
961 | return memcmp(mp_irq, m, sizeof(struct mpc_intsrc)); | ||
962 | } | ||
963 | |||
964 | static void save_mp_irq(struct mpc_intsrc *m) | ||
965 | { | ||
966 | int i; | ||
967 | |||
968 | for (i = 0; i < mp_irq_entries; i++) { | ||
969 | if (!mp_irq_cmp(&mp_irqs[i], m)) | ||
970 | return; | ||
971 | } | ||
972 | |||
973 | assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]); | ||
974 | if (++mp_irq_entries == MAX_IRQ_SOURCES) | ||
975 | panic("Max # of irq sources exceeded!!\n"); | ||
976 | } | ||
977 | |||
978 | void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) | 940 | void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) |
979 | { | 941 | { |
980 | int ioapic; | 942 | int ioapic; |
@@ -1005,7 +967,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) | |||
1005 | mp_irq.dstapic = mp_ioapics[ioapic].apicid; /* APIC ID */ | 967 | mp_irq.dstapic = mp_ioapics[ioapic].apicid; /* APIC ID */ |
1006 | mp_irq.dstirq = pin; /* INTIN# */ | 968 | mp_irq.dstirq = pin; /* INTIN# */ |
1007 | 969 | ||
1008 | save_mp_irq(&mp_irq); | 970 | mp_save_irq(&mp_irq); |
1009 | 971 | ||
1010 | isa_irq_to_gsi[bus_irq] = gsi; | 972 | isa_irq_to_gsi[bus_irq] = gsi; |
1011 | } | 973 | } |
@@ -1080,7 +1042,7 @@ void __init mp_config_acpi_legacy_irqs(void) | |||
1080 | mp_irq.srcbusirq = i; /* Identity mapped */ | 1042 | mp_irq.srcbusirq = i; /* Identity mapped */ |
1081 | mp_irq.dstirq = pin; | 1043 | mp_irq.dstirq = pin; |
1082 | 1044 | ||
1083 | save_mp_irq(&mp_irq); | 1045 | mp_save_irq(&mp_irq); |
1084 | } | 1046 | } |
1085 | } | 1047 | } |
1086 | 1048 | ||
@@ -1117,7 +1079,7 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger, | |||
1117 | mp_irq.dstapic = mp_ioapics[ioapic].apicid; | 1079 | mp_irq.dstapic = mp_ioapics[ioapic].apicid; |
1118 | mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi); | 1080 | mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi); |
1119 | 1081 | ||
1120 | save_mp_irq(&mp_irq); | 1082 | mp_save_irq(&mp_irq); |
1121 | #endif | 1083 | #endif |
1122 | return 0; | 1084 | return 0; |
1123 | } | 1085 | } |
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c index 92543c73cf8e..7c9ab59653e8 100644 --- a/arch/x86/kernel/apb_timer.c +++ b/arch/x86/kernel/apb_timer.c | |||
@@ -315,6 +315,7 @@ static void apbt_setup_irq(struct apbt_dev *adev) | |||
315 | 315 | ||
316 | if (system_state == SYSTEM_BOOTING) { | 316 | if (system_state == SYSTEM_BOOTING) { |
317 | irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT); | 317 | irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT); |
318 | irq_set_affinity(adev->irq, cpumask_of(adev->cpu)); | ||
318 | /* APB timer irqs are set up as mp_irqs, timer is edge type */ | 319 | /* APB timer irqs are set up as mp_irqs, timer is edge type */ |
319 | __set_irq_handler(adev->irq, handle_edge_irq, 0, "edge"); | 320 | __set_irq_handler(adev->irq, handle_edge_irq, 0, "edge"); |
320 | if (request_irq(adev->irq, apbt_interrupt_handler, | 321 | if (request_irq(adev->irq, apbt_interrupt_handler, |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 3f838d537392..c0f6426cd337 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -1195,12 +1195,15 @@ static void __cpuinit lapic_setup_esr(void) | |||
1195 | oldvalue, value); | 1195 | oldvalue, value); |
1196 | } | 1196 | } |
1197 | 1197 | ||
1198 | |||
1199 | /** | 1198 | /** |
1200 | * setup_local_APIC - setup the local APIC | 1199 | * setup_local_APIC - setup the local APIC |
1200 | * | ||
1201 | * Used to setup local APIC while initializing BSP or bringin up APs. | ||
1202 | * Always called with preemption disabled. | ||
1201 | */ | 1203 | */ |
1202 | void __cpuinit setup_local_APIC(void) | 1204 | void __cpuinit setup_local_APIC(void) |
1203 | { | 1205 | { |
1206 | int cpu = smp_processor_id(); | ||
1204 | unsigned int value, queued; | 1207 | unsigned int value, queued; |
1205 | int i, j, acked = 0; | 1208 | int i, j, acked = 0; |
1206 | unsigned long long tsc = 0, ntsc; | 1209 | unsigned long long tsc = 0, ntsc; |
@@ -1225,8 +1228,6 @@ void __cpuinit setup_local_APIC(void) | |||
1225 | #endif | 1228 | #endif |
1226 | perf_events_lapic_init(); | 1229 | perf_events_lapic_init(); |
1227 | 1230 | ||
1228 | preempt_disable(); | ||
1229 | |||
1230 | /* | 1231 | /* |
1231 | * Double-check whether this APIC is really registered. | 1232 | * Double-check whether this APIC is really registered. |
1232 | * This is meaningless in clustered apic mode, so we skip it. | 1233 | * This is meaningless in clustered apic mode, so we skip it. |
@@ -1342,21 +1343,19 @@ void __cpuinit setup_local_APIC(void) | |||
1342 | * TODO: set up through-local-APIC from through-I/O-APIC? --macro | 1343 | * TODO: set up through-local-APIC from through-I/O-APIC? --macro |
1343 | */ | 1344 | */ |
1344 | value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; | 1345 | value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; |
1345 | if (!smp_processor_id() && (pic_mode || !value)) { | 1346 | if (!cpu && (pic_mode || !value)) { |
1346 | value = APIC_DM_EXTINT; | 1347 | value = APIC_DM_EXTINT; |
1347 | apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", | 1348 | apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", cpu); |
1348 | smp_processor_id()); | ||
1349 | } else { | 1349 | } else { |
1350 | value = APIC_DM_EXTINT | APIC_LVT_MASKED; | 1350 | value = APIC_DM_EXTINT | APIC_LVT_MASKED; |
1351 | apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", | 1351 | apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", cpu); |
1352 | smp_processor_id()); | ||
1353 | } | 1352 | } |
1354 | apic_write(APIC_LVT0, value); | 1353 | apic_write(APIC_LVT0, value); |
1355 | 1354 | ||
1356 | /* | 1355 | /* |
1357 | * only the BP should see the LINT1 NMI signal, obviously. | 1356 | * only the BP should see the LINT1 NMI signal, obviously. |
1358 | */ | 1357 | */ |
1359 | if (!smp_processor_id()) | 1358 | if (!cpu) |
1360 | value = APIC_DM_NMI; | 1359 | value = APIC_DM_NMI; |
1361 | else | 1360 | else |
1362 | value = APIC_DM_NMI | APIC_LVT_MASKED; | 1361 | value = APIC_DM_NMI | APIC_LVT_MASKED; |
@@ -1364,11 +1363,9 @@ void __cpuinit setup_local_APIC(void) | |||
1364 | value |= APIC_LVT_LEVEL_TRIGGER; | 1363 | value |= APIC_LVT_LEVEL_TRIGGER; |
1365 | apic_write(APIC_LVT1, value); | 1364 | apic_write(APIC_LVT1, value); |
1366 | 1365 | ||
1367 | preempt_enable(); | ||
1368 | |||
1369 | #ifdef CONFIG_X86_MCE_INTEL | 1366 | #ifdef CONFIG_X86_MCE_INTEL |
1370 | /* Recheck CMCI information after local APIC is up on CPU #0 */ | 1367 | /* Recheck CMCI information after local APIC is up on CPU #0 */ |
1371 | if (smp_processor_id() == 0) | 1368 | if (!cpu) |
1372 | cmci_recheck(); | 1369 | cmci_recheck(); |
1373 | #endif | 1370 | #endif |
1374 | } | 1371 | } |
@@ -1530,13 +1527,60 @@ static int __init detect_init_APIC(void) | |||
1530 | return 0; | 1527 | return 0; |
1531 | } | 1528 | } |
1532 | #else | 1529 | #else |
1530 | |||
1531 | static int apic_verify(void) | ||
1532 | { | ||
1533 | u32 features, h, l; | ||
1534 | |||
1535 | /* | ||
1536 | * The APIC feature bit should now be enabled | ||
1537 | * in `cpuid' | ||
1538 | */ | ||
1539 | features = cpuid_edx(1); | ||
1540 | if (!(features & (1 << X86_FEATURE_APIC))) { | ||
1541 | pr_warning("Could not enable APIC!\n"); | ||
1542 | return -1; | ||
1543 | } | ||
1544 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); | ||
1545 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | ||
1546 | |||
1547 | /* The BIOS may have set up the APIC at some other address */ | ||
1548 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
1549 | if (l & MSR_IA32_APICBASE_ENABLE) | ||
1550 | mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; | ||
1551 | |||
1552 | pr_info("Found and enabled local APIC!\n"); | ||
1553 | return 0; | ||
1554 | } | ||
1555 | |||
1556 | int apic_force_enable(void) | ||
1557 | { | ||
1558 | u32 h, l; | ||
1559 | |||
1560 | if (disable_apic) | ||
1561 | return -1; | ||
1562 | |||
1563 | /* | ||
1564 | * Some BIOSes disable the local APIC in the APIC_BASE | ||
1565 | * MSR. This can only be done in software for Intel P6 or later | ||
1566 | * and AMD K7 (Model > 1) or later. | ||
1567 | */ | ||
1568 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
1569 | if (!(l & MSR_IA32_APICBASE_ENABLE)) { | ||
1570 | pr_info("Local APIC disabled by BIOS -- reenabling.\n"); | ||
1571 | l &= ~MSR_IA32_APICBASE_BASE; | ||
1572 | l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; | ||
1573 | wrmsr(MSR_IA32_APICBASE, l, h); | ||
1574 | enabled_via_apicbase = 1; | ||
1575 | } | ||
1576 | return apic_verify(); | ||
1577 | } | ||
1578 | |||
1533 | /* | 1579 | /* |
1534 | * Detect and initialize APIC | 1580 | * Detect and initialize APIC |
1535 | */ | 1581 | */ |
1536 | static int __init detect_init_APIC(void) | 1582 | static int __init detect_init_APIC(void) |
1537 | { | 1583 | { |
1538 | u32 h, l, features; | ||
1539 | |||
1540 | /* Disabled by kernel option? */ | 1584 | /* Disabled by kernel option? */ |
1541 | if (disable_apic) | 1585 | if (disable_apic) |
1542 | return -1; | 1586 | return -1; |
@@ -1566,38 +1610,12 @@ static int __init detect_init_APIC(void) | |||
1566 | "you can enable it with \"lapic\"\n"); | 1610 | "you can enable it with \"lapic\"\n"); |
1567 | return -1; | 1611 | return -1; |
1568 | } | 1612 | } |
1569 | /* | 1613 | if (apic_force_enable()) |
1570 | * Some BIOSes disable the local APIC in the APIC_BASE | 1614 | return -1; |
1571 | * MSR. This can only be done in software for Intel P6 or later | 1615 | } else { |
1572 | * and AMD K7 (Model > 1) or later. | 1616 | if (apic_verify()) |
1573 | */ | 1617 | return -1; |
1574 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
1575 | if (!(l & MSR_IA32_APICBASE_ENABLE)) { | ||
1576 | pr_info("Local APIC disabled by BIOS -- reenabling.\n"); | ||
1577 | l &= ~MSR_IA32_APICBASE_BASE; | ||
1578 | l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; | ||
1579 | wrmsr(MSR_IA32_APICBASE, l, h); | ||
1580 | enabled_via_apicbase = 1; | ||
1581 | } | ||
1582 | } | ||
1583 | /* | ||
1584 | * The APIC feature bit should now be enabled | ||
1585 | * in `cpuid' | ||
1586 | */ | ||
1587 | features = cpuid_edx(1); | ||
1588 | if (!(features & (1 << X86_FEATURE_APIC))) { | ||
1589 | pr_warning("Could not enable APIC!\n"); | ||
1590 | return -1; | ||
1591 | } | 1618 | } |
1592 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); | ||
1593 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | ||
1594 | |||
1595 | /* The BIOS may have set up the APIC at some other address */ | ||
1596 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
1597 | if (l & MSR_IA32_APICBASE_ENABLE) | ||
1598 | mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; | ||
1599 | |||
1600 | pr_info("Found and enabled local APIC!\n"); | ||
1601 | 1619 | ||
1602 | apic_pm_activate(); | 1620 | apic_pm_activate(); |
1603 | 1621 | ||
@@ -1609,28 +1627,6 @@ no_apic: | |||
1609 | } | 1627 | } |
1610 | #endif | 1628 | #endif |
1611 | 1629 | ||
1612 | #ifdef CONFIG_X86_64 | ||
1613 | void __init early_init_lapic_mapping(void) | ||
1614 | { | ||
1615 | /* | ||
1616 | * If no local APIC can be found then go out | ||
1617 | * : it means there is no mpatable and MADT | ||
1618 | */ | ||
1619 | if (!smp_found_config) | ||
1620 | return; | ||
1621 | |||
1622 | set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); | ||
1623 | apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", | ||
1624 | APIC_BASE, mp_lapic_addr); | ||
1625 | |||
1626 | /* | ||
1627 | * Fetch the APIC ID of the BSP in case we have a | ||
1628 | * default configuration (or the MP table is broken). | ||
1629 | */ | ||
1630 | boot_cpu_physical_apicid = read_apic_id(); | ||
1631 | } | ||
1632 | #endif | ||
1633 | |||
1634 | /** | 1630 | /** |
1635 | * init_apic_mappings - initialize APIC mappings | 1631 | * init_apic_mappings - initialize APIC mappings |
1636 | */ | 1632 | */ |
@@ -1656,10 +1652,7 @@ void __init init_apic_mappings(void) | |||
1656 | * acpi_register_lapic_address() | 1652 | * acpi_register_lapic_address() |
1657 | */ | 1653 | */ |
1658 | if (!acpi_lapic && !smp_found_config) | 1654 | if (!acpi_lapic && !smp_found_config) |
1659 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); | 1655 | register_lapic_address(apic_phys); |
1660 | |||
1661 | apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n", | ||
1662 | APIC_BASE, apic_phys); | ||
1663 | } | 1656 | } |
1664 | 1657 | ||
1665 | /* | 1658 | /* |
@@ -1681,6 +1674,22 @@ void __init init_apic_mappings(void) | |||
1681 | } | 1674 | } |
1682 | } | 1675 | } |
1683 | 1676 | ||
1677 | void __init register_lapic_address(unsigned long address) | ||
1678 | { | ||
1679 | mp_lapic_addr = address; | ||
1680 | |||
1681 | if (!x2apic_mode) { | ||
1682 | set_fixmap_nocache(FIX_APIC_BASE, address); | ||
1683 | apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", | ||
1684 | APIC_BASE, mp_lapic_addr); | ||
1685 | } | ||
1686 | if (boot_cpu_physical_apicid == -1U) { | ||
1687 | boot_cpu_physical_apicid = read_apic_id(); | ||
1688 | apic_version[boot_cpu_physical_apicid] = | ||
1689 | GET_APIC_VERSION(apic_read(APIC_LVR)); | ||
1690 | } | ||
1691 | } | ||
1692 | |||
1684 | /* | 1693 | /* |
1685 | * This initializes the IO-APIC and APIC hardware if this is | 1694 | * This initializes the IO-APIC and APIC hardware if this is |
1686 | * a UP kernel. | 1695 | * a UP kernel. |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 7cc0a721f628..bb61a552d8c6 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -126,6 +126,26 @@ static int __init parse_noapic(char *str) | |||
126 | } | 126 | } |
127 | early_param("noapic", parse_noapic); | 127 | early_param("noapic", parse_noapic); |
128 | 128 | ||
129 | /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */ | ||
130 | void mp_save_irq(struct mpc_intsrc *m) | ||
131 | { | ||
132 | int i; | ||
133 | |||
134 | apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x," | ||
135 | " IRQ %02x, APIC ID %x, APIC INT %02x\n", | ||
136 | m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbus, | ||
137 | m->srcbusirq, m->dstapic, m->dstirq); | ||
138 | |||
139 | for (i = 0; i < mp_irq_entries; i++) { | ||
140 | if (!memcmp(&mp_irqs[i], m, sizeof(*m))) | ||
141 | return; | ||
142 | } | ||
143 | |||
144 | memcpy(&mp_irqs[mp_irq_entries], m, sizeof(*m)); | ||
145 | if (++mp_irq_entries == MAX_IRQ_SOURCES) | ||
146 | panic("Max # of irq sources exceeded!!\n"); | ||
147 | } | ||
148 | |||
129 | struct irq_pin_list { | 149 | struct irq_pin_list { |
130 | int apic, pin; | 150 | int apic, pin; |
131 | struct irq_pin_list *next; | 151 | struct irq_pin_list *next; |
@@ -136,6 +156,7 @@ static struct irq_pin_list *alloc_irq_pin_list(int node) | |||
136 | return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node); | 156 | return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node); |
137 | } | 157 | } |
138 | 158 | ||
159 | |||
139 | /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ | 160 | /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ |
140 | #ifdef CONFIG_SPARSE_IRQ | 161 | #ifdef CONFIG_SPARSE_IRQ |
141 | static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY]; | 162 | static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY]; |
@@ -1934,8 +1955,7 @@ void disable_IO_APIC(void) | |||
1934 | * | 1955 | * |
1935 | * by Matt Domsch <Matt_Domsch@dell.com> Tue Dec 21 12:25:05 CST 1999 | 1956 | * by Matt Domsch <Matt_Domsch@dell.com> Tue Dec 21 12:25:05 CST 1999 |
1936 | */ | 1957 | */ |
1937 | 1958 | void __init setup_ioapic_ids_from_mpc_nocheck(void) | |
1938 | void __init setup_ioapic_ids_from_mpc(void) | ||
1939 | { | 1959 | { |
1940 | union IO_APIC_reg_00 reg_00; | 1960 | union IO_APIC_reg_00 reg_00; |
1941 | physid_mask_t phys_id_present_map; | 1961 | physid_mask_t phys_id_present_map; |
@@ -1944,15 +1964,6 @@ void __init setup_ioapic_ids_from_mpc(void) | |||
1944 | unsigned char old_id; | 1964 | unsigned char old_id; |
1945 | unsigned long flags; | 1965 | unsigned long flags; |
1946 | 1966 | ||
1947 | if (acpi_ioapic) | ||
1948 | return; | ||
1949 | /* | ||
1950 | * Don't check I/O APIC IDs for xAPIC systems. They have | ||
1951 | * no meaning without the serial APIC bus. | ||
1952 | */ | ||
1953 | if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) | ||
1954 | || APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) | ||
1955 | return; | ||
1956 | /* | 1967 | /* |
1957 | * This is broken; anything with a real cpu count has to | 1968 | * This is broken; anything with a real cpu count has to |
1958 | * circumvent this idiocy regardless. | 1969 | * circumvent this idiocy regardless. |
@@ -2006,7 +2017,6 @@ void __init setup_ioapic_ids_from_mpc(void) | |||
2006 | physids_or(phys_id_present_map, phys_id_present_map, tmp); | 2017 | physids_or(phys_id_present_map, phys_id_present_map, tmp); |
2007 | } | 2018 | } |
2008 | 2019 | ||
2009 | |||
2010 | /* | 2020 | /* |
2011 | * We need to adjust the IRQ routing table | 2021 | * We need to adjust the IRQ routing table |
2012 | * if the ID changed. | 2022 | * if the ID changed. |
@@ -2018,9 +2028,12 @@ void __init setup_ioapic_ids_from_mpc(void) | |||
2018 | = mp_ioapics[apic_id].apicid; | 2028 | = mp_ioapics[apic_id].apicid; |
2019 | 2029 | ||
2020 | /* | 2030 | /* |
2021 | * Read the right value from the MPC table and | 2031 | * Update the ID register according to the right value |
2022 | * write it into the ID register. | 2032 | * from the MPC table if they are different. |
2023 | */ | 2033 | */ |
2034 | if (mp_ioapics[apic_id].apicid == reg_00.bits.ID) | ||
2035 | continue; | ||
2036 | |||
2024 | apic_printk(APIC_VERBOSE, KERN_INFO | 2037 | apic_printk(APIC_VERBOSE, KERN_INFO |
2025 | "...changing IO-APIC physical APIC ID to %d ...", | 2038 | "...changing IO-APIC physical APIC ID to %d ...", |
2026 | mp_ioapics[apic_id].apicid); | 2039 | mp_ioapics[apic_id].apicid); |
@@ -2042,6 +2055,21 @@ void __init setup_ioapic_ids_from_mpc(void) | |||
2042 | apic_printk(APIC_VERBOSE, " ok.\n"); | 2055 | apic_printk(APIC_VERBOSE, " ok.\n"); |
2043 | } | 2056 | } |
2044 | } | 2057 | } |
2058 | |||
2059 | void __init setup_ioapic_ids_from_mpc(void) | ||
2060 | { | ||
2061 | |||
2062 | if (acpi_ioapic) | ||
2063 | return; | ||
2064 | /* | ||
2065 | * Don't check I/O APIC IDs for xAPIC systems. They have | ||
2066 | * no meaning without the serial APIC bus. | ||
2067 | */ | ||
2068 | if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) | ||
2069 | || APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) | ||
2070 | return; | ||
2071 | setup_ioapic_ids_from_mpc_nocheck(); | ||
2072 | } | ||
2045 | #endif | 2073 | #endif |
2046 | 2074 | ||
2047 | int no_timer_check __initdata; | 2075 | int no_timer_check __initdata; |
@@ -3639,7 +3667,7 @@ int __init io_apic_get_redir_entries (int ioapic) | |||
3639 | return reg_01.bits.entries + 1; | 3667 | return reg_01.bits.entries + 1; |
3640 | } | 3668 | } |
3641 | 3669 | ||
3642 | void __init probe_nr_irqs_gsi(void) | 3670 | static void __init probe_nr_irqs_gsi(void) |
3643 | { | 3671 | { |
3644 | int nr; | 3672 | int nr; |
3645 | 3673 | ||
@@ -3956,7 +3984,7 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics) | |||
3956 | return res; | 3984 | return res; |
3957 | } | 3985 | } |
3958 | 3986 | ||
3959 | void __init ioapic_init_mappings(void) | 3987 | void __init ioapic_and_gsi_init(void) |
3960 | { | 3988 | { |
3961 | unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; | 3989 | unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; |
3962 | struct resource *ioapic_res; | 3990 | struct resource *ioapic_res; |
@@ -3994,6 +4022,8 @@ fake_ioapic_page: | |||
3994 | ioapic_res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1; | 4022 | ioapic_res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1; |
3995 | ioapic_res++; | 4023 | ioapic_res++; |
3996 | } | 4024 | } |
4025 | |||
4026 | probe_nr_irqs_gsi(); | ||
3997 | } | 4027 | } |
3998 | 4028 | ||
3999 | void __init ioapic_insert_resources(void) | 4029 | void __init ioapic_insert_resources(void) |
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 4572f25f9325..cd28a350f7f9 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c | |||
@@ -240,7 +240,7 @@ static int __init setup_early_printk(char *buf) | |||
240 | if (!strncmp(buf, "xen", 3)) | 240 | if (!strncmp(buf, "xen", 3)) |
241 | early_console_register(&xenboot_console, keep); | 241 | early_console_register(&xenboot_console, keep); |
242 | #endif | 242 | #endif |
243 | #ifdef CONFIG_X86_MRST_EARLY_PRINTK | 243 | #ifdef CONFIG_EARLY_PRINTK_MRST |
244 | if (!strncmp(buf, "mrst", 4)) { | 244 | if (!strncmp(buf, "mrst", 4)) { |
245 | mrst_early_console_init(); | 245 | mrst_early_console_init(); |
246 | early_console_register(&early_mrst_console, keep); | 246 | early_console_register(&early_mrst_console, keep); |
@@ -250,7 +250,6 @@ static int __init setup_early_printk(char *buf) | |||
250 | hsu_early_console_init(); | 250 | hsu_early_console_init(); |
251 | early_console_register(&early_hsu_console, keep); | 251 | early_console_register(&early_hsu_console, keep); |
252 | } | 252 | } |
253 | |||
254 | #endif | 253 | #endif |
255 | buf++; | 254 | buf++; |
256 | } | 255 | } |
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index 763310165fa0..7f138b3c3c52 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c | |||
@@ -61,6 +61,9 @@ void __init i386_start_kernel(void) | |||
61 | case X86_SUBARCH_MRST: | 61 | case X86_SUBARCH_MRST: |
62 | x86_mrst_early_setup(); | 62 | x86_mrst_early_setup(); |
63 | break; | 63 | break; |
64 | case X86_SUBARCH_CE4100: | ||
65 | x86_ce4100_early_setup(); | ||
66 | break; | ||
64 | default: | 67 | default: |
65 | i386_default_early_setup(); | 68 | i386_default_early_setup(); |
66 | break; | 69 | break; |
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 9af64d9c4b67..01b0f6d06451 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c | |||
@@ -118,21 +118,8 @@ static void __init MP_bus_info(struct mpc_bus *m) | |||
118 | 118 | ||
119 | static void __init MP_ioapic_info(struct mpc_ioapic *m) | 119 | static void __init MP_ioapic_info(struct mpc_ioapic *m) |
120 | { | 120 | { |
121 | if (!(m->flags & MPC_APIC_USABLE)) | 121 | if (m->flags & MPC_APIC_USABLE) |
122 | return; | 122 | mp_register_ioapic(m->apicid, m->apicaddr, gsi_top); |
123 | |||
124 | printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n", | ||
125 | m->apicid, m->apicver, m->apicaddr); | ||
126 | |||
127 | mp_register_ioapic(m->apicid, m->apicaddr, gsi_top); | ||
128 | } | ||
129 | |||
130 | static void print_MP_intsrc_info(struct mpc_intsrc *m) | ||
131 | { | ||
132 | apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x," | ||
133 | " IRQ %02x, APIC ID %x, APIC INT %02x\n", | ||
134 | m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbus, | ||
135 | m->srcbusirq, m->dstapic, m->dstirq); | ||
136 | } | 123 | } |
137 | 124 | ||
138 | static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq) | 125 | 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 | mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq); | 131 | mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq); |
145 | } | 132 | } |
146 | 133 | ||
147 | static void __init assign_to_mp_irq(struct mpc_intsrc *m, | ||
148 | struct mpc_intsrc *mp_irq) | ||
149 | { | ||
150 | mp_irq->dstapic = m->dstapic; | ||
151 | mp_irq->type = m->type; | ||
152 | mp_irq->irqtype = m->irqtype; | ||
153 | mp_irq->irqflag = m->irqflag; | ||
154 | mp_irq->srcbus = m->srcbus; | ||
155 | mp_irq->srcbusirq = m->srcbusirq; | ||
156 | mp_irq->dstirq = m->dstirq; | ||
157 | } | ||
158 | |||
159 | static void __init assign_to_mpc_intsrc(struct mpc_intsrc *mp_irq, | ||
160 | struct mpc_intsrc *m) | ||
161 | { | ||
162 | m->dstapic = mp_irq->dstapic; | ||
163 | m->type = mp_irq->type; | ||
164 | m->irqtype = mp_irq->irqtype; | ||
165 | m->irqflag = mp_irq->irqflag; | ||
166 | m->srcbus = mp_irq->srcbus; | ||
167 | m->srcbusirq = mp_irq->srcbusirq; | ||
168 | m->dstirq = mp_irq->dstirq; | ||
169 | } | ||
170 | |||
171 | static int __init mp_irq_mpc_intsrc_cmp(struct mpc_intsrc *mp_irq, | ||
172 | struct mpc_intsrc *m) | ||
173 | { | ||
174 | if (mp_irq->dstapic != m->dstapic) | ||
175 | return 1; | ||
176 | if (mp_irq->type != m->type) | ||
177 | return 2; | ||
178 | if (mp_irq->irqtype != m->irqtype) | ||
179 | return 3; | ||
180 | if (mp_irq->irqflag != m->irqflag) | ||
181 | return 4; | ||
182 | if (mp_irq->srcbus != m->srcbus) | ||
183 | return 5; | ||
184 | if (mp_irq->srcbusirq != m->srcbusirq) | ||
185 | return 6; | ||
186 | if (mp_irq->dstirq != m->dstirq) | ||
187 | return 7; | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static void __init MP_intsrc_info(struct mpc_intsrc *m) | ||
193 | { | ||
194 | int i; | ||
195 | |||
196 | print_MP_intsrc_info(m); | ||
197 | |||
198 | for (i = 0; i < mp_irq_entries; i++) { | ||
199 | if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m)) | ||
200 | return; | ||
201 | } | ||
202 | |||
203 | assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]); | ||
204 | if (++mp_irq_entries == MAX_IRQ_SOURCES) | ||
205 | panic("Max # of irq sources exceeded!!\n"); | ||
206 | } | ||
207 | #else /* CONFIG_X86_IO_APIC */ | 134 | #else /* CONFIG_X86_IO_APIC */ |
208 | static inline void __init MP_bus_info(struct mpc_bus *m) {} | 135 | static inline void __init MP_bus_info(struct mpc_bus *m) {} |
209 | static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {} | 136 | static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {} |
210 | static inline void __init MP_intsrc_info(struct mpc_intsrc *m) {} | ||
211 | #endif /* CONFIG_X86_IO_APIC */ | 137 | #endif /* CONFIG_X86_IO_APIC */ |
212 | 138 | ||
213 | |||
214 | static void __init MP_lintsrc_info(struct mpc_lintsrc *m) | 139 | static void __init MP_lintsrc_info(struct mpc_lintsrc *m) |
215 | { | 140 | { |
216 | apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x," | 141 | 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 | /* | 147 | /* |
223 | * Read/parse the MPC | 148 | * Read/parse the MPC |
224 | */ | 149 | */ |
225 | |||
226 | static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str) | 150 | static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str) |
227 | { | 151 | { |
228 | 152 | ||
@@ -275,18 +199,6 @@ static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt) | |||
275 | 199 | ||
276 | void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { } | 200 | void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { } |
277 | 201 | ||
278 | static void __init smp_register_lapic_address(unsigned long address) | ||
279 | { | ||
280 | mp_lapic_addr = address; | ||
281 | |||
282 | set_fixmap_nocache(FIX_APIC_BASE, address); | ||
283 | if (boot_cpu_physical_apicid == -1U) { | ||
284 | boot_cpu_physical_apicid = read_apic_id(); | ||
285 | apic_version[boot_cpu_physical_apicid] = | ||
286 | GET_APIC_VERSION(apic_read(APIC_LVR)); | ||
287 | } | ||
288 | } | ||
289 | |||
290 | static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) | 202 | static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) |
291 | { | 203 | { |
292 | char str[16]; | 204 | char str[16]; |
@@ -301,17 +213,13 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) | |||
301 | #ifdef CONFIG_X86_32 | 213 | #ifdef CONFIG_X86_32 |
302 | generic_mps_oem_check(mpc, oem, str); | 214 | generic_mps_oem_check(mpc, oem, str); |
303 | #endif | 215 | #endif |
304 | /* save the local APIC address, it might be non-default */ | 216 | /* Initialize the lapic mapping */ |
305 | if (!acpi_lapic) | 217 | if (!acpi_lapic) |
306 | mp_lapic_addr = mpc->lapic; | 218 | register_lapic_address(mpc->lapic); |
307 | 219 | ||
308 | if (early) | 220 | if (early) |
309 | return 1; | 221 | return 1; |
310 | 222 | ||
311 | /* Initialize the lapic mapping */ | ||
312 | if (!acpi_lapic) | ||
313 | smp_register_lapic_address(mpc->lapic); | ||
314 | |||
315 | if (mpc->oemptr) | 223 | if (mpc->oemptr) |
316 | x86_init.mpparse.smp_read_mpc_oem(mpc); | 224 | x86_init.mpparse.smp_read_mpc_oem(mpc); |
317 | 225 | ||
@@ -337,7 +245,7 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) | |||
337 | skip_entry(&mpt, &count, sizeof(struct mpc_ioapic)); | 245 | skip_entry(&mpt, &count, sizeof(struct mpc_ioapic)); |
338 | break; | 246 | break; |
339 | case MP_INTSRC: | 247 | case MP_INTSRC: |
340 | MP_intsrc_info((struct mpc_intsrc *)mpt); | 248 | mp_save_irq((struct mpc_intsrc *)mpt); |
341 | skip_entry(&mpt, &count, sizeof(struct mpc_intsrc)); | 249 | skip_entry(&mpt, &count, sizeof(struct mpc_intsrc)); |
342 | break; | 250 | break; |
343 | case MP_LINTSRC: | 251 | case MP_LINTSRC: |
@@ -429,13 +337,13 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type) | |||
429 | 337 | ||
430 | intsrc.srcbusirq = i; | 338 | intsrc.srcbusirq = i; |
431 | intsrc.dstirq = i ? i : 2; /* IRQ0 to INTIN2 */ | 339 | intsrc.dstirq = i ? i : 2; /* IRQ0 to INTIN2 */ |
432 | MP_intsrc_info(&intsrc); | 340 | mp_save_irq(&intsrc); |
433 | } | 341 | } |
434 | 342 | ||
435 | intsrc.irqtype = mp_ExtINT; | 343 | intsrc.irqtype = mp_ExtINT; |
436 | intsrc.srcbusirq = 0; | 344 | intsrc.srcbusirq = 0; |
437 | intsrc.dstirq = 0; /* 8259A to INTIN0 */ | 345 | intsrc.dstirq = 0; /* 8259A to INTIN0 */ |
438 | MP_intsrc_info(&intsrc); | 346 | mp_save_irq(&intsrc); |
439 | } | 347 | } |
440 | 348 | ||
441 | 349 | ||
@@ -784,11 +692,11 @@ static void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) | |||
784 | int i; | 692 | int i; |
785 | 693 | ||
786 | apic_printk(APIC_VERBOSE, "OLD "); | 694 | apic_printk(APIC_VERBOSE, "OLD "); |
787 | print_MP_intsrc_info(m); | 695 | print_mp_irq_info(m); |
788 | 696 | ||
789 | i = get_MP_intsrc_index(m); | 697 | i = get_MP_intsrc_index(m); |
790 | if (i > 0) { | 698 | if (i > 0) { |
791 | assign_to_mpc_intsrc(&mp_irqs[i], m); | 699 | memcpy(m, &mp_irqs[i], sizeof(*m)); |
792 | apic_printk(APIC_VERBOSE, "NEW "); | 700 | apic_printk(APIC_VERBOSE, "NEW "); |
793 | print_mp_irq_info(&mp_irqs[i]); | 701 | print_mp_irq_info(&mp_irqs[i]); |
794 | return; | 702 | return; |
@@ -875,14 +783,14 @@ static int __init replace_intsrc_all(struct mpc_table *mpc, | |||
875 | if (nr_m_spare > 0) { | 783 | if (nr_m_spare > 0) { |
876 | apic_printk(APIC_VERBOSE, "*NEW* found\n"); | 784 | apic_printk(APIC_VERBOSE, "*NEW* found\n"); |
877 | nr_m_spare--; | 785 | nr_m_spare--; |
878 | assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]); | 786 | memcpy(m_spare[nr_m_spare], &mp_irqs[i], sizeof(mp_irqs[i])); |
879 | m_spare[nr_m_spare] = NULL; | 787 | m_spare[nr_m_spare] = NULL; |
880 | } else { | 788 | } else { |
881 | struct mpc_intsrc *m = (struct mpc_intsrc *)mpt; | 789 | struct mpc_intsrc *m = (struct mpc_intsrc *)mpt; |
882 | count += sizeof(struct mpc_intsrc); | 790 | count += sizeof(struct mpc_intsrc); |
883 | if (check_slot(mpc_new_phys, mpc_new_length, count) < 0) | 791 | if (check_slot(mpc_new_phys, mpc_new_length, count) < 0) |
884 | goto out; | 792 | goto out; |
885 | assign_to_mpc_intsrc(&mp_irqs[i], m); | 793 | memcpy(m, &mp_irqs[i], sizeof(*m)); |
886 | mpc->length = count; | 794 | mpc->length = count; |
887 | mpt += sizeof(struct mpc_intsrc); | 795 | mpt += sizeof(struct mpc_intsrc); |
888 | } | 796 | } |
diff --git a/arch/x86/kernel/reboot_fixups_32.c b/arch/x86/kernel/reboot_fixups_32.c index fda313ebbb03..c8e41e90f59c 100644 --- a/arch/x86/kernel/reboot_fixups_32.c +++ b/arch/x86/kernel/reboot_fixups_32.c | |||
@@ -43,17 +43,33 @@ static void rdc321x_reset(struct pci_dev *dev) | |||
43 | outb(1, 0x92); | 43 | outb(1, 0x92); |
44 | } | 44 | } |
45 | 45 | ||
46 | static void ce4100_reset(struct pci_dev *dev) | ||
47 | { | ||
48 | int i; | ||
49 | |||
50 | for (i = 0; i < 10; i++) { | ||
51 | outb(0x2, 0xcf9); | ||
52 | udelay(50); | ||
53 | } | ||
54 | } | ||
55 | |||
46 | struct device_fixup { | 56 | struct device_fixup { |
47 | unsigned int vendor; | 57 | unsigned int vendor; |
48 | unsigned int device; | 58 | unsigned int device; |
49 | void (*reboot_fixup)(struct pci_dev *); | 59 | void (*reboot_fixup)(struct pci_dev *); |
50 | }; | 60 | }; |
51 | 61 | ||
62 | /* | ||
63 | * PCI ids solely used for fixups_table go here | ||
64 | */ | ||
65 | #define PCI_DEVICE_ID_INTEL_CE4100 0x0708 | ||
66 | |||
52 | static const struct device_fixup fixups_table[] = { | 67 | static const struct device_fixup fixups_table[] = { |
53 | { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset }, | 68 | { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset }, |
54 | { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, cs5536_warm_reset }, | 69 | { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, cs5536_warm_reset }, |
55 | { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE, cs5530a_warm_reset }, | 70 | { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE, cs5530a_warm_reset }, |
56 | { PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030, rdc321x_reset }, | 71 | { PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030, rdc321x_reset }, |
72 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100, ce4100_reset }, | ||
57 | }; | 73 | }; |
58 | 74 | ||
59 | /* | 75 | /* |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index df172c1e8238..0afb8c7e3803 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -1035,10 +1035,7 @@ void __init setup_arch(char **cmdline_p) | |||
1035 | #endif | 1035 | #endif |
1036 | 1036 | ||
1037 | init_apic_mappings(); | 1037 | init_apic_mappings(); |
1038 | ioapic_init_mappings(); | 1038 | ioapic_and_gsi_init(); |
1039 | |||
1040 | /* need to wait for io_apic is mapped */ | ||
1041 | probe_nr_irqs_gsi(); | ||
1042 | 1039 | ||
1043 | kvm_guest_init(); | 1040 | kvm_guest_init(); |
1044 | 1041 | ||
diff --git a/arch/x86/mm/amdtopology_64.c b/arch/x86/mm/amdtopology_64.c index 0df2623d1039..f21962c435ed 100644 --- a/arch/x86/mm/amdtopology_64.c +++ b/arch/x86/mm/amdtopology_64.c | |||
@@ -67,7 +67,6 @@ static __init void early_get_boot_cpu_id(void) | |||
67 | if (smp_found_config) | 67 | if (smp_found_config) |
68 | early_get_smp_config(); | 68 | early_get_smp_config(); |
69 | #endif | 69 | #endif |
70 | early_init_lapic_mapping(); | ||
71 | } | 70 | } |
72 | 71 | ||
73 | int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) | 72 | int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) |
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile index effd96e33f16..6b8759f7634e 100644 --- a/arch/x86/pci/Makefile +++ b/arch/x86/pci/Makefile | |||
@@ -7,6 +7,7 @@ obj-$(CONFIG_PCI_OLPC) += olpc.o | |||
7 | obj-$(CONFIG_PCI_XEN) += xen.o | 7 | obj-$(CONFIG_PCI_XEN) += xen.o |
8 | 8 | ||
9 | obj-y += fixup.o | 9 | obj-y += fixup.o |
10 | obj-$(CONFIG_X86_INTEL_CE) += ce4100.o | ||
10 | obj-$(CONFIG_ACPI) += acpi.o | 11 | obj-$(CONFIG_ACPI) += acpi.o |
11 | obj-y += legacy.o irq.o | 12 | obj-y += legacy.o irq.o |
12 | 13 | ||
diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c new file mode 100644 index 000000000000..85b68ef5e809 --- /dev/null +++ b/arch/x86/pci/ce4100.c | |||
@@ -0,0 +1,315 @@ | |||
1 | /* | ||
2 | * GPL LICENSE SUMMARY | ||
3 | * | ||
4 | * Copyright(c) 2010 Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of version 2 of the GNU General Public License as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | * The full GNU General Public License is included in this distribution | ||
19 | * in the file called LICENSE.GPL. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Corporation | ||
23 | * 2200 Mission College Blvd. | ||
24 | * Santa Clara, CA 97052 | ||
25 | * | ||
26 | * This provides access methods for PCI registers that mis-behave on | ||
27 | * the CE4100. Each register can be assigned a private init, read and | ||
28 | * write routine. The exception to this is the bridge device. The | ||
29 | * bridge device is the only device on bus zero (0) that requires any | ||
30 | * fixup so it is a special case ATM | ||
31 | */ | ||
32 | |||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/pci.h> | ||
35 | #include <linux/init.h> | ||
36 | |||
37 | #include <asm/pci_x86.h> | ||
38 | |||
39 | struct sim_reg { | ||
40 | u32 value; | ||
41 | u32 mask; | ||
42 | }; | ||
43 | |||
44 | struct sim_dev_reg { | ||
45 | int dev_func; | ||
46 | int reg; | ||
47 | void (*init)(struct sim_dev_reg *reg); | ||
48 | void (*read)(struct sim_dev_reg *reg, u32 *value); | ||
49 | void (*write)(struct sim_dev_reg *reg, u32 value); | ||
50 | struct sim_reg sim_reg; | ||
51 | }; | ||
52 | |||
53 | struct sim_reg_op { | ||
54 | void (*init)(struct sim_dev_reg *reg); | ||
55 | void (*read)(struct sim_dev_reg *reg, u32 value); | ||
56 | void (*write)(struct sim_dev_reg *reg, u32 value); | ||
57 | }; | ||
58 | |||
59 | #define MB (1024 * 1024) | ||
60 | #define KB (1024) | ||
61 | #define SIZE_TO_MASK(size) (~(size - 1)) | ||
62 | |||
63 | #define DEFINE_REG(device, func, offset, size, init_op, read_op, write_op)\ | ||
64 | { PCI_DEVFN(device, func), offset, init_op, read_op, write_op,\ | ||
65 | {0, SIZE_TO_MASK(size)} }, | ||
66 | |||
67 | static void reg_init(struct sim_dev_reg *reg) | ||
68 | { | ||
69 | pci_direct_conf1.read(0, 1, reg->dev_func, reg->reg, 4, | ||
70 | ®->sim_reg.value); | ||
71 | } | ||
72 | |||
73 | static void reg_read(struct sim_dev_reg *reg, u32 *value) | ||
74 | { | ||
75 | unsigned long flags; | ||
76 | |||
77 | raw_spin_lock_irqsave(&pci_config_lock, flags); | ||
78 | *value = reg->sim_reg.value; | ||
79 | raw_spin_unlock_irqrestore(&pci_config_lock, flags); | ||
80 | } | ||
81 | |||
82 | static void reg_write(struct sim_dev_reg *reg, u32 value) | ||
83 | { | ||
84 | unsigned long flags; | ||
85 | |||
86 | raw_spin_lock_irqsave(&pci_config_lock, flags); | ||
87 | reg->sim_reg.value = (value & reg->sim_reg.mask) | | ||
88 | (reg->sim_reg.value & ~reg->sim_reg.mask); | ||
89 | raw_spin_unlock_irqrestore(&pci_config_lock, flags); | ||
90 | } | ||
91 | |||
92 | static void sata_reg_init(struct sim_dev_reg *reg) | ||
93 | { | ||
94 | pci_direct_conf1.read(0, 1, PCI_DEVFN(14, 0), 0x10, 4, | ||
95 | ®->sim_reg.value); | ||
96 | reg->sim_reg.value += 0x400; | ||
97 | } | ||
98 | |||
99 | static void ehci_reg_read(struct sim_dev_reg *reg, u32 *value) | ||
100 | { | ||
101 | reg_read(reg, value); | ||
102 | if (*value != reg->sim_reg.mask) | ||
103 | *value |= 0x100; | ||
104 | } | ||
105 | |||
106 | void sata_revid_init(struct sim_dev_reg *reg) | ||
107 | { | ||
108 | reg->sim_reg.value = 0x01060100; | ||
109 | reg->sim_reg.mask = 0; | ||
110 | } | ||
111 | |||
112 | static void sata_revid_read(struct sim_dev_reg *reg, u32 *value) | ||
113 | { | ||
114 | reg_read(reg, value); | ||
115 | } | ||
116 | |||
117 | static struct sim_dev_reg bus1_fixups[] = { | ||
118 | DEFINE_REG(2, 0, 0x10, (16*MB), reg_init, reg_read, reg_write) | ||
119 | DEFINE_REG(2, 0, 0x14, (256), reg_init, reg_read, reg_write) | ||
120 | DEFINE_REG(2, 1, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
121 | DEFINE_REG(3, 0, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
122 | DEFINE_REG(4, 0, 0x10, (128*KB), reg_init, reg_read, reg_write) | ||
123 | DEFINE_REG(4, 1, 0x10, (128*KB), reg_init, reg_read, reg_write) | ||
124 | DEFINE_REG(6, 0, 0x10, (512*KB), reg_init, reg_read, reg_write) | ||
125 | DEFINE_REG(6, 1, 0x10, (512*KB), reg_init, reg_read, reg_write) | ||
126 | DEFINE_REG(6, 2, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
127 | DEFINE_REG(8, 0, 0x10, (1*MB), reg_init, reg_read, reg_write) | ||
128 | DEFINE_REG(8, 1, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
129 | DEFINE_REG(8, 2, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
130 | DEFINE_REG(9, 0, 0x10 , (1*MB), reg_init, reg_read, reg_write) | ||
131 | DEFINE_REG(9, 0, 0x14, (64*KB), reg_init, reg_read, reg_write) | ||
132 | DEFINE_REG(10, 0, 0x10, (256), reg_init, reg_read, reg_write) | ||
133 | DEFINE_REG(10, 0, 0x14, (256*MB), reg_init, reg_read, reg_write) | ||
134 | DEFINE_REG(11, 0, 0x10, (256), reg_init, reg_read, reg_write) | ||
135 | DEFINE_REG(11, 0, 0x14, (256), reg_init, reg_read, reg_write) | ||
136 | DEFINE_REG(11, 1, 0x10, (256), reg_init, reg_read, reg_write) | ||
137 | DEFINE_REG(11, 2, 0x10, (256), reg_init, reg_read, reg_write) | ||
138 | DEFINE_REG(11, 2, 0x14, (256), reg_init, reg_read, reg_write) | ||
139 | DEFINE_REG(11, 2, 0x18, (256), reg_init, reg_read, reg_write) | ||
140 | DEFINE_REG(11, 3, 0x10, (256), reg_init, reg_read, reg_write) | ||
141 | DEFINE_REG(11, 3, 0x14, (256), reg_init, reg_read, reg_write) | ||
142 | DEFINE_REG(11, 4, 0x10, (256), reg_init, reg_read, reg_write) | ||
143 | DEFINE_REG(11, 5, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
144 | DEFINE_REG(11, 6, 0x10, (256), reg_init, reg_read, reg_write) | ||
145 | DEFINE_REG(11, 7, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
146 | DEFINE_REG(12, 0, 0x10, (128*KB), reg_init, reg_read, reg_write) | ||
147 | DEFINE_REG(12, 0, 0x14, (256), reg_init, reg_read, reg_write) | ||
148 | DEFINE_REG(12, 1, 0x10, (1024), reg_init, reg_read, reg_write) | ||
149 | DEFINE_REG(13, 0, 0x10, (32*KB), reg_init, ehci_reg_read, reg_write) | ||
150 | DEFINE_REG(13, 1, 0x10, (32*KB), reg_init, ehci_reg_read, reg_write) | ||
151 | DEFINE_REG(14, 0, 0x8, 0, sata_revid_init, sata_revid_read, 0) | ||
152 | DEFINE_REG(14, 0, 0x10, 0, reg_init, reg_read, reg_write) | ||
153 | DEFINE_REG(14, 0, 0x14, 0, reg_init, reg_read, reg_write) | ||
154 | DEFINE_REG(14, 0, 0x18, 0, reg_init, reg_read, reg_write) | ||
155 | DEFINE_REG(14, 0, 0x1C, 0, reg_init, reg_read, reg_write) | ||
156 | DEFINE_REG(14, 0, 0x20, 0, reg_init, reg_read, reg_write) | ||
157 | DEFINE_REG(14, 0, 0x24, (0x200), sata_reg_init, reg_read, reg_write) | ||
158 | DEFINE_REG(15, 0, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
159 | DEFINE_REG(15, 0, 0x14, (64*KB), reg_init, reg_read, reg_write) | ||
160 | DEFINE_REG(16, 0, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
161 | DEFINE_REG(16, 0, 0x14, (64*MB), reg_init, reg_read, reg_write) | ||
162 | DEFINE_REG(16, 0, 0x18, (64*MB), reg_init, reg_read, reg_write) | ||
163 | DEFINE_REG(17, 0, 0x10, (128*KB), reg_init, reg_read, reg_write) | ||
164 | DEFINE_REG(18, 0, 0x10, (1*KB), reg_init, reg_read, reg_write) | ||
165 | }; | ||
166 | |||
167 | static void __init init_sim_regs(void) | ||
168 | { | ||
169 | int i; | ||
170 | |||
171 | for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { | ||
172 | if (bus1_fixups[i].init) | ||
173 | bus1_fixups[i].init(&bus1_fixups[i]); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | static inline void extract_bytes(u32 *value, int reg, int len) | ||
178 | { | ||
179 | uint32_t mask; | ||
180 | |||
181 | *value >>= ((reg & 3) * 8); | ||
182 | mask = 0xFFFFFFFF >> ((4 - len) * 8); | ||
183 | *value &= mask; | ||
184 | } | ||
185 | |||
186 | int bridge_read(unsigned int devfn, int reg, int len, u32 *value) | ||
187 | { | ||
188 | u32 av_bridge_base, av_bridge_limit; | ||
189 | int retval = 0; | ||
190 | |||
191 | switch (reg) { | ||
192 | /* Make BARs appear to not request any memory. */ | ||
193 | case PCI_BASE_ADDRESS_0: | ||
194 | case PCI_BASE_ADDRESS_0 + 1: | ||
195 | case PCI_BASE_ADDRESS_0 + 2: | ||
196 | case PCI_BASE_ADDRESS_0 + 3: | ||
197 | *value = 0; | ||
198 | break; | ||
199 | |||
200 | /* Since subordinate bus number register is hardwired | ||
201 | * to zero and read only, so do the simulation. | ||
202 | */ | ||
203 | case PCI_PRIMARY_BUS: | ||
204 | if (len == 4) | ||
205 | *value = 0x00010100; | ||
206 | break; | ||
207 | |||
208 | case PCI_SUBORDINATE_BUS: | ||
209 | *value = 1; | ||
210 | break; | ||
211 | |||
212 | case PCI_MEMORY_BASE: | ||
213 | case PCI_MEMORY_LIMIT: | ||
214 | /* Get the A/V bridge base address. */ | ||
215 | pci_direct_conf1.read(0, 0, devfn, | ||
216 | PCI_BASE_ADDRESS_0, 4, &av_bridge_base); | ||
217 | |||
218 | av_bridge_limit = av_bridge_base + (512*MB - 1); | ||
219 | av_bridge_limit >>= 16; | ||
220 | av_bridge_limit &= 0xFFF0; | ||
221 | |||
222 | av_bridge_base >>= 16; | ||
223 | av_bridge_base &= 0xFFF0; | ||
224 | |||
225 | if (reg == PCI_MEMORY_LIMIT) | ||
226 | *value = av_bridge_limit; | ||
227 | else if (len == 2) | ||
228 | *value = av_bridge_base; | ||
229 | else | ||
230 | *value = (av_bridge_limit << 16) | av_bridge_base; | ||
231 | break; | ||
232 | /* Make prefetchable memory limit smaller than prefetchable | ||
233 | * memory base, so not claim prefetchable memory space. | ||
234 | */ | ||
235 | case PCI_PREF_MEMORY_BASE: | ||
236 | *value = 0xFFF0; | ||
237 | break; | ||
238 | case PCI_PREF_MEMORY_LIMIT: | ||
239 | *value = 0x0; | ||
240 | break; | ||
241 | /* Make IO limit smaller than IO base, so not claim IO space. */ | ||
242 | case PCI_IO_BASE: | ||
243 | *value = 0xF0; | ||
244 | break; | ||
245 | case PCI_IO_LIMIT: | ||
246 | *value = 0; | ||
247 | break; | ||
248 | default: | ||
249 | retval = 1; | ||
250 | } | ||
251 | return retval; | ||
252 | } | ||
253 | |||
254 | static int ce4100_conf_read(unsigned int seg, unsigned int bus, | ||
255 | unsigned int devfn, int reg, int len, u32 *value) | ||
256 | { | ||
257 | int i, retval = 1; | ||
258 | |||
259 | if (bus == 1) { | ||
260 | for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { | ||
261 | if (bus1_fixups[i].dev_func == devfn && | ||
262 | bus1_fixups[i].reg == (reg & ~3) && | ||
263 | bus1_fixups[i].read) { | ||
264 | bus1_fixups[i].read(&(bus1_fixups[i]), | ||
265 | value); | ||
266 | extract_bytes(value, reg, len); | ||
267 | return 0; | ||
268 | } | ||
269 | } | ||
270 | } | ||
271 | |||
272 | if (bus == 0 && (PCI_DEVFN(1, 0) == devfn) && | ||
273 | !bridge_read(devfn, reg, len, value)) | ||
274 | return 0; | ||
275 | |||
276 | return pci_direct_conf1.read(seg, bus, devfn, reg, len, value); | ||
277 | } | ||
278 | |||
279 | static int ce4100_conf_write(unsigned int seg, unsigned int bus, | ||
280 | unsigned int devfn, int reg, int len, u32 value) | ||
281 | { | ||
282 | int i; | ||
283 | |||
284 | if (bus == 1) { | ||
285 | for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { | ||
286 | if (bus1_fixups[i].dev_func == devfn && | ||
287 | bus1_fixups[i].reg == (reg & ~3) && | ||
288 | bus1_fixups[i].write) { | ||
289 | bus1_fixups[i].write(&(bus1_fixups[i]), | ||
290 | value); | ||
291 | return 0; | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
296 | /* Discard writes to A/V bridge BAR. */ | ||
297 | if (bus == 0 && PCI_DEVFN(1, 0) == devfn && | ||
298 | ((reg & ~3) == PCI_BASE_ADDRESS_0)) | ||
299 | return 0; | ||
300 | |||
301 | return pci_direct_conf1.write(seg, bus, devfn, reg, len, value); | ||
302 | } | ||
303 | |||
304 | struct pci_raw_ops ce4100_pci_conf = { | ||
305 | .read = ce4100_conf_read, | ||
306 | .write = ce4100_conf_write, | ||
307 | }; | ||
308 | |||
309 | static int __init ce4100_pci_init(void) | ||
310 | { | ||
311 | init_sim_regs(); | ||
312 | raw_pci_ops = &ce4100_pci_conf; | ||
313 | return 0; | ||
314 | } | ||
315 | subsys_initcall(ce4100_pci_init); | ||
diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile index 7bf70b812fa2..021eee91c056 100644 --- a/arch/x86/platform/Makefile +++ b/arch/x86/platform/Makefile | |||
@@ -1,5 +1,7 @@ | |||
1 | # Platform specific code goes here | 1 | # Platform specific code goes here |
2 | obj-y += ce4100/ | ||
2 | obj-y += efi/ | 3 | obj-y += efi/ |
4 | obj-y += iris/ | ||
3 | obj-y += mrst/ | 5 | obj-y += mrst/ |
4 | obj-y += olpc/ | 6 | obj-y += olpc/ |
5 | obj-y += scx200/ | 7 | obj-y += scx200/ |
diff --git a/arch/x86/platform/ce4100/Makefile b/arch/x86/platform/ce4100/Makefile new file mode 100644 index 000000000000..91fc92971d94 --- /dev/null +++ b/arch/x86/platform/ce4100/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_X86_INTEL_CE) += ce4100.o | |||
diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c new file mode 100644 index 000000000000..d2c0d51a7178 --- /dev/null +++ b/arch/x86/platform/ce4100/ce4100.c | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | * Intel CE4100 platform specific setup code | ||
3 | * | ||
4 | * (C) Copyright 2010 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; version 2 | ||
9 | * of the License. | ||
10 | */ | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/irq.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/serial_reg.h> | ||
16 | #include <linux/serial_8250.h> | ||
17 | |||
18 | #include <asm/setup.h> | ||
19 | #include <asm/io.h> | ||
20 | |||
21 | static int ce4100_i8042_detect(void) | ||
22 | { | ||
23 | return 0; | ||
24 | } | ||
25 | |||
26 | static void __init sdv_find_smp_config(void) | ||
27 | { | ||
28 | } | ||
29 | |||
30 | #ifdef CONFIG_SERIAL_8250 | ||
31 | |||
32 | |||
33 | static unsigned int mem_serial_in(struct uart_port *p, int offset) | ||
34 | { | ||
35 | offset = offset << p->regshift; | ||
36 | return readl(p->membase + offset); | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * The UART Tx interrupts are not set under some conditions and therefore serial | ||
41 | * transmission hangs. This is a silicon issue and has not been root caused. The | ||
42 | * workaround for this silicon issue checks UART_LSR_THRE bit and UART_LSR_TEMT | ||
43 | * bit of LSR register in interrupt handler to see whether at least one of these | ||
44 | * two bits is set, if so then process the transmit request. If this workaround | ||
45 | * is not applied, then the serial transmission may hang. This workaround is for | ||
46 | * errata number 9 in Errata - B step. | ||
47 | */ | ||
48 | |||
49 | static unsigned int ce4100_mem_serial_in(struct uart_port *p, int offset) | ||
50 | { | ||
51 | unsigned int ret, ier, lsr; | ||
52 | |||
53 | if (offset == UART_IIR) { | ||
54 | offset = offset << p->regshift; | ||
55 | ret = readl(p->membase + offset); | ||
56 | if (ret & UART_IIR_NO_INT) { | ||
57 | /* see if the TX interrupt should have really set */ | ||
58 | ier = mem_serial_in(p, UART_IER); | ||
59 | /* see if the UART's XMIT interrupt is enabled */ | ||
60 | if (ier & UART_IER_THRI) { | ||
61 | lsr = mem_serial_in(p, UART_LSR); | ||
62 | /* now check to see if the UART should be | ||
63 | generating an interrupt (but isn't) */ | ||
64 | if (lsr & (UART_LSR_THRE | UART_LSR_TEMT)) | ||
65 | ret &= ~UART_IIR_NO_INT; | ||
66 | } | ||
67 | } | ||
68 | } else | ||
69 | ret = mem_serial_in(p, offset); | ||
70 | return ret; | ||
71 | } | ||
72 | |||
73 | static void ce4100_mem_serial_out(struct uart_port *p, int offset, int value) | ||
74 | { | ||
75 | offset = offset << p->regshift; | ||
76 | writel(value, p->membase + offset); | ||
77 | } | ||
78 | |||
79 | static void ce4100_serial_fixup(int port, struct uart_port *up, | ||
80 | unsigned short *capabilites) | ||
81 | { | ||
82 | #ifdef CONFIG_EARLY_PRINTK | ||
83 | /* | ||
84 | * Over ride the legacy port configuration that comes from | ||
85 | * asm/serial.h. Using the ioport driver then switching to the | ||
86 | * PCI memmaped driver hangs the IOAPIC | ||
87 | */ | ||
88 | if (up->iotype != UPIO_MEM32) { | ||
89 | up->uartclk = 14745600; | ||
90 | up->mapbase = 0xdffe0200; | ||
91 | set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, | ||
92 | up->mapbase & PAGE_MASK); | ||
93 | up->membase = | ||
94 | (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); | ||
95 | up->membase += up->mapbase & ~PAGE_MASK; | ||
96 | up->iotype = UPIO_MEM32; | ||
97 | up->regshift = 2; | ||
98 | } | ||
99 | #endif | ||
100 | up->iobase = 0; | ||
101 | up->serial_in = ce4100_mem_serial_in; | ||
102 | up->serial_out = ce4100_mem_serial_out; | ||
103 | |||
104 | *capabilites |= (1 << 12); | ||
105 | } | ||
106 | |||
107 | static __init void sdv_serial_fixup(void) | ||
108 | { | ||
109 | serial8250_set_isa_configurator(ce4100_serial_fixup); | ||
110 | } | ||
111 | |||
112 | #else | ||
113 | static inline void sdv_serial_fixup(void); | ||
114 | #endif | ||
115 | |||
116 | static void __init sdv_arch_setup(void) | ||
117 | { | ||
118 | sdv_serial_fixup(); | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * CE4100 specific x86_init function overrides and early setup | ||
123 | * calls. | ||
124 | */ | ||
125 | void __init x86_ce4100_early_setup(void) | ||
126 | { | ||
127 | x86_init.oem.arch_setup = sdv_arch_setup; | ||
128 | x86_platform.i8042_detect = ce4100_i8042_detect; | ||
129 | x86_init.resources.probe_roms = x86_init_noop; | ||
130 | x86_init.mpparse.get_smp_config = x86_init_uint_noop; | ||
131 | x86_init.mpparse.find_smp_config = sdv_find_smp_config; | ||
132 | } | ||
diff --git a/arch/x86/platform/iris/Makefile b/arch/x86/platform/iris/Makefile new file mode 100644 index 000000000000..db921983a102 --- /dev/null +++ b/arch/x86/platform/iris/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_X86_32_IRIS) += iris.o | |||
diff --git a/arch/x86/platform/iris/iris.c b/arch/x86/platform/iris/iris.c new file mode 100644 index 000000000000..1ba7f5ed8c9b --- /dev/null +++ b/arch/x86/platform/iris/iris.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * Eurobraille/Iris power off support. | ||
3 | * | ||
4 | * Eurobraille's Iris machine is a PC with no APM or ACPI support. | ||
5 | * It is shutdown by a special I/O sequence which this module provides. | ||
6 | * | ||
7 | * Copyright (C) Shérab <Sebastien.Hinderer@ens-lyon.org> | ||
8 | * | ||
9 | * This program is free software ; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation ; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY ; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with the program ; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/moduleparam.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/pm.h> | ||
31 | #include <asm/io.h> | ||
32 | |||
33 | #define IRIS_GIO_BASE 0x340 | ||
34 | #define IRIS_GIO_INPUT IRIS_GIO_BASE | ||
35 | #define IRIS_GIO_OUTPUT (IRIS_GIO_BASE + 1) | ||
36 | #define IRIS_GIO_PULSE 0x80 /* First byte to send */ | ||
37 | #define IRIS_GIO_REST 0x00 /* Second byte to send */ | ||
38 | #define IRIS_GIO_NODEV 0xff /* Likely not an Iris */ | ||
39 | |||
40 | MODULE_LICENSE("GPL"); | ||
41 | MODULE_AUTHOR("Sébastien Hinderer <Sebastien.Hinderer@ens-lyon.org>"); | ||
42 | MODULE_DESCRIPTION("A power_off handler for Iris devices from EuroBraille"); | ||
43 | MODULE_SUPPORTED_DEVICE("Eurobraille/Iris"); | ||
44 | |||
45 | static int force; | ||
46 | |||
47 | module_param(force, bool, 0); | ||
48 | MODULE_PARM_DESC(force, "Set to one to force poweroff handler installation."); | ||
49 | |||
50 | static void (*old_pm_power_off)(void); | ||
51 | |||
52 | static void iris_power_off(void) | ||
53 | { | ||
54 | outb(IRIS_GIO_PULSE, IRIS_GIO_OUTPUT); | ||
55 | msleep(850); | ||
56 | outb(IRIS_GIO_REST, IRIS_GIO_OUTPUT); | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | * Before installing the power_off handler, try to make sure the OS is | ||
61 | * running on an Iris. Since Iris does not support DMI, this is done | ||
62 | * by reading its input port and seeing whether the read value is | ||
63 | * meaningful. | ||
64 | */ | ||
65 | static int iris_init(void) | ||
66 | { | ||
67 | unsigned char status; | ||
68 | if (force != 1) { | ||
69 | printk(KERN_ERR "The force parameter has not been set to 1 so the Iris poweroff handler will not be installed.\n"); | ||
70 | return -ENODEV; | ||
71 | } | ||
72 | status = inb(IRIS_GIO_INPUT); | ||
73 | if (status == IRIS_GIO_NODEV) { | ||
74 | printk(KERN_ERR "This machine does not seem to be an Iris. Power_off handler not installed.\n"); | ||
75 | return -ENODEV; | ||
76 | } | ||
77 | old_pm_power_off = pm_power_off; | ||
78 | pm_power_off = &iris_power_off; | ||
79 | printk(KERN_INFO "Iris power_off handler installed.\n"); | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static void iris_exit(void) | ||
85 | { | ||
86 | pm_power_off = old_pm_power_off; | ||
87 | printk(KERN_INFO "Iris power_off handler uninstalled.\n"); | ||
88 | } | ||
89 | |||
90 | module_init(iris_init); | ||
91 | module_exit(iris_exit); | ||
diff --git a/arch/x86/platform/mrst/Makefile b/arch/x86/platform/mrst/Makefile index efbbc552fa95..f61ccdd49341 100644 --- a/arch/x86/platform/mrst/Makefile +++ b/arch/x86/platform/mrst/Makefile | |||
@@ -1 +1,3 @@ | |||
1 | obj-$(CONFIG_X86_MRST) += mrst.o | 1 | obj-$(CONFIG_X86_MRST) += mrst.o |
2 | obj-$(CONFIG_X86_MRST) += vrtc.o | ||
3 | obj-$(CONFIG_EARLY_PRINTK_MRST) += early_printk_mrst.o | ||
diff --git a/arch/x86/kernel/early_printk_mrst.c b/arch/x86/platform/mrst/early_printk_mrst.c index 65df603622b2..65df603622b2 100644 --- a/arch/x86/kernel/early_printk_mrst.c +++ b/arch/x86/platform/mrst/early_printk_mrst.c | |||
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c index 79ae68154e87..ea6529e93c6f 100644 --- a/arch/x86/platform/mrst/mrst.c +++ b/arch/x86/platform/mrst/mrst.c | |||
@@ -9,9 +9,19 @@ | |||
9 | * as published by the Free Software Foundation; version 2 | 9 | * as published by the Free Software Foundation; version 2 |
10 | * of the License. | 10 | * of the License. |
11 | */ | 11 | */ |
12 | |||
13 | #define pr_fmt(fmt) "mrst: " fmt | ||
14 | |||
12 | #include <linux/init.h> | 15 | #include <linux/init.h> |
13 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
14 | #include <linux/sfi.h> | 17 | #include <linux/sfi.h> |
18 | #include <linux/intel_pmic_gpio.h> | ||
19 | #include <linux/spi/spi.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/i2c/pca953x.h> | ||
22 | #include <linux/gpio_keys.h> | ||
23 | #include <linux/input.h> | ||
24 | #include <linux/platform_device.h> | ||
15 | #include <linux/irq.h> | 25 | #include <linux/irq.h> |
16 | #include <linux/module.h> | 26 | #include <linux/module.h> |
17 | 27 | ||
@@ -23,7 +33,9 @@ | |||
23 | #include <asm/mrst.h> | 33 | #include <asm/mrst.h> |
24 | #include <asm/io.h> | 34 | #include <asm/io.h> |
25 | #include <asm/i8259.h> | 35 | #include <asm/i8259.h> |
36 | #include <asm/intel_scu_ipc.h> | ||
26 | #include <asm/apb_timer.h> | 37 | #include <asm/apb_timer.h> |
38 | #include <asm/reboot.h> | ||
27 | 39 | ||
28 | /* | 40 | /* |
29 | * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock, | 41 | * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock, |
@@ -59,32 +71,6 @@ struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX]; | |||
59 | EXPORT_SYMBOL_GPL(sfi_mrtc_array); | 71 | EXPORT_SYMBOL_GPL(sfi_mrtc_array); |
60 | int sfi_mrtc_num; | 72 | int sfi_mrtc_num; |
61 | 73 | ||
62 | static inline void assign_to_mp_irq(struct mpc_intsrc *m, | ||
63 | struct mpc_intsrc *mp_irq) | ||
64 | { | ||
65 | memcpy(mp_irq, m, sizeof(struct mpc_intsrc)); | ||
66 | } | ||
67 | |||
68 | static inline int mp_irq_cmp(struct mpc_intsrc *mp_irq, | ||
69 | struct mpc_intsrc *m) | ||
70 | { | ||
71 | return memcmp(mp_irq, m, sizeof(struct mpc_intsrc)); | ||
72 | } | ||
73 | |||
74 | static void save_mp_irq(struct mpc_intsrc *m) | ||
75 | { | ||
76 | int i; | ||
77 | |||
78 | for (i = 0; i < mp_irq_entries; i++) { | ||
79 | if (!mp_irq_cmp(&mp_irqs[i], m)) | ||
80 | return; | ||
81 | } | ||
82 | |||
83 | assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]); | ||
84 | if (++mp_irq_entries == MAX_IRQ_SOURCES) | ||
85 | panic("Max # of irq sources exceeded!!\n"); | ||
86 | } | ||
87 | |||
88 | /* parse all the mtimer info to a static mtimer array */ | 74 | /* parse all the mtimer info to a static mtimer array */ |
89 | static int __init sfi_parse_mtmr(struct sfi_table_header *table) | 75 | static int __init sfi_parse_mtmr(struct sfi_table_header *table) |
90 | { | 76 | { |
@@ -102,10 +88,10 @@ static int __init sfi_parse_mtmr(struct sfi_table_header *table) | |||
102 | memcpy(sfi_mtimer_array, pentry, totallen); | 88 | memcpy(sfi_mtimer_array, pentry, totallen); |
103 | } | 89 | } |
104 | 90 | ||
105 | printk(KERN_INFO "SFI: MTIMER info (num = %d):\n", sfi_mtimer_num); | 91 | pr_debug("SFI MTIMER info (num = %d):\n", sfi_mtimer_num); |
106 | pentry = sfi_mtimer_array; | 92 | pentry = sfi_mtimer_array; |
107 | for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) { | 93 | for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) { |
108 | printk(KERN_INFO "timer[%d]: paddr = 0x%08x, freq = %dHz," | 94 | pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz," |
109 | " irq = %d\n", totallen, (u32)pentry->phys_addr, | 95 | " irq = %d\n", totallen, (u32)pentry->phys_addr, |
110 | pentry->freq_hz, pentry->irq); | 96 | pentry->freq_hz, pentry->irq); |
111 | if (!pentry->irq) | 97 | if (!pentry->irq) |
@@ -118,7 +104,7 @@ static int __init sfi_parse_mtmr(struct sfi_table_header *table) | |||
118 | mp_irq.srcbusirq = pentry->irq; /* IRQ */ | 104 | mp_irq.srcbusirq = pentry->irq; /* IRQ */ |
119 | mp_irq.dstapic = MP_APIC_ALL; | 105 | mp_irq.dstapic = MP_APIC_ALL; |
120 | mp_irq.dstirq = pentry->irq; | 106 | mp_irq.dstirq = pentry->irq; |
121 | save_mp_irq(&mp_irq); | 107 | mp_save_irq(&mp_irq); |
122 | } | 108 | } |
123 | 109 | ||
124 | return 0; | 110 | return 0; |
@@ -176,19 +162,19 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table) | |||
176 | memcpy(sfi_mrtc_array, pentry, totallen); | 162 | memcpy(sfi_mrtc_array, pentry, totallen); |
177 | } | 163 | } |
178 | 164 | ||
179 | printk(KERN_INFO "SFI: RTC info (num = %d):\n", sfi_mrtc_num); | 165 | pr_debug("SFI RTC info (num = %d):\n", sfi_mrtc_num); |
180 | pentry = sfi_mrtc_array; | 166 | pentry = sfi_mrtc_array; |
181 | for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) { | 167 | for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) { |
182 | printk(KERN_INFO "RTC[%d]: paddr = 0x%08x, irq = %d\n", | 168 | pr_debug("RTC[%d]: paddr = 0x%08x, irq = %d\n", |
183 | totallen, (u32)pentry->phys_addr, pentry->irq); | 169 | totallen, (u32)pentry->phys_addr, pentry->irq); |
184 | mp_irq.type = MP_IOAPIC; | 170 | mp_irq.type = MP_IOAPIC; |
185 | mp_irq.irqtype = mp_INT; | 171 | mp_irq.irqtype = mp_INT; |
186 | mp_irq.irqflag = 0; | 172 | mp_irq.irqflag = 0xf; /* level trigger and active low */ |
187 | mp_irq.srcbus = 0; | 173 | mp_irq.srcbus = 0; |
188 | mp_irq.srcbusirq = pentry->irq; /* IRQ */ | 174 | mp_irq.srcbusirq = pentry->irq; /* IRQ */ |
189 | mp_irq.dstapic = MP_APIC_ALL; | 175 | mp_irq.dstapic = MP_APIC_ALL; |
190 | mp_irq.dstirq = pentry->irq; | 176 | mp_irq.dstirq = pentry->irq; |
191 | save_mp_irq(&mp_irq); | 177 | mp_save_irq(&mp_irq); |
192 | } | 178 | } |
193 | return 0; | 179 | return 0; |
194 | } | 180 | } |
@@ -209,6 +195,7 @@ static unsigned long __init mrst_calibrate_tsc(void) | |||
209 | 195 | ||
210 | void __init mrst_time_init(void) | 196 | void __init mrst_time_init(void) |
211 | { | 197 | { |
198 | sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr); | ||
212 | switch (mrst_timer_options) { | 199 | switch (mrst_timer_options) { |
213 | case MRST_TIMER_APBT_ONLY: | 200 | case MRST_TIMER_APBT_ONLY: |
214 | break; | 201 | break; |
@@ -224,16 +211,10 @@ void __init mrst_time_init(void) | |||
224 | return; | 211 | return; |
225 | } | 212 | } |
226 | /* we need at least one APB timer */ | 213 | /* we need at least one APB timer */ |
227 | sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr); | ||
228 | pre_init_apic_IRQ0(); | 214 | pre_init_apic_IRQ0(); |
229 | apbt_time_init(); | 215 | apbt_time_init(); |
230 | } | 216 | } |
231 | 217 | ||
232 | void __init mrst_rtc_init(void) | ||
233 | { | ||
234 | sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc); | ||
235 | } | ||
236 | |||
237 | void __cpuinit mrst_arch_setup(void) | 218 | void __cpuinit mrst_arch_setup(void) |
238 | { | 219 | { |
239 | if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27) | 220 | if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27) |
@@ -256,6 +237,17 @@ static int mrst_i8042_detect(void) | |||
256 | return 0; | 237 | return 0; |
257 | } | 238 | } |
258 | 239 | ||
240 | /* Reboot and power off are handled by the SCU on a MID device */ | ||
241 | static void mrst_power_off(void) | ||
242 | { | ||
243 | intel_scu_ipc_simple_command(0xf1, 1); | ||
244 | } | ||
245 | |||
246 | static void mrst_reboot(void) | ||
247 | { | ||
248 | intel_scu_ipc_simple_command(0xf1, 0); | ||
249 | } | ||
250 | |||
259 | /* | 251 | /* |
260 | * Moorestown specific x86_init function overrides and early setup | 252 | * Moorestown specific x86_init function overrides and early setup |
261 | * calls. | 253 | * calls. |
@@ -281,6 +273,10 @@ void __init x86_mrst_early_setup(void) | |||
281 | 273 | ||
282 | legacy_pic = &null_legacy_pic; | 274 | legacy_pic = &null_legacy_pic; |
283 | 275 | ||
276 | /* Moorestown specific power_off/restart method */ | ||
277 | pm_power_off = mrst_power_off; | ||
278 | machine_ops.emergency_restart = mrst_reboot; | ||
279 | |||
284 | /* Avoid searching for BIOS MP tables */ | 280 | /* Avoid searching for BIOS MP tables */ |
285 | x86_init.mpparse.find_smp_config = x86_init_noop; | 281 | x86_init.mpparse.find_smp_config = x86_init_noop; |
286 | x86_init.mpparse.get_smp_config = x86_init_uint_noop; | 282 | x86_init.mpparse.get_smp_config = x86_init_uint_noop; |
@@ -309,3 +305,505 @@ static inline int __init setup_x86_mrst_timer(char *arg) | |||
309 | return 0; | 305 | return 0; |
310 | } | 306 | } |
311 | __setup("x86_mrst_timer=", setup_x86_mrst_timer); | 307 | __setup("x86_mrst_timer=", setup_x86_mrst_timer); |
308 | |||
309 | /* | ||
310 | * Parsing GPIO table first, since the DEVS table will need this table | ||
311 | * to map the pin name to the actual pin. | ||
312 | */ | ||
313 | static struct sfi_gpio_table_entry *gpio_table; | ||
314 | static int gpio_num_entry; | ||
315 | |||
316 | static int __init sfi_parse_gpio(struct sfi_table_header *table) | ||
317 | { | ||
318 | struct sfi_table_simple *sb; | ||
319 | struct sfi_gpio_table_entry *pentry; | ||
320 | int num, i; | ||
321 | |||
322 | if (gpio_table) | ||
323 | return 0; | ||
324 | sb = (struct sfi_table_simple *)table; | ||
325 | num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry); | ||
326 | pentry = (struct sfi_gpio_table_entry *)sb->pentry; | ||
327 | |||
328 | gpio_table = (struct sfi_gpio_table_entry *) | ||
329 | kmalloc(num * sizeof(*pentry), GFP_KERNEL); | ||
330 | if (!gpio_table) | ||
331 | return -1; | ||
332 | memcpy(gpio_table, pentry, num * sizeof(*pentry)); | ||
333 | gpio_num_entry = num; | ||
334 | |||
335 | pr_debug("GPIO pin info:\n"); | ||
336 | for (i = 0; i < num; i++, pentry++) | ||
337 | pr_debug("info[%2d]: controller = %16.16s, pin_name = %16.16s," | ||
338 | " pin = %d\n", i, | ||
339 | pentry->controller_name, | ||
340 | pentry->pin_name, | ||
341 | pentry->pin_no); | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int get_gpio_by_name(const char *name) | ||
346 | { | ||
347 | struct sfi_gpio_table_entry *pentry = gpio_table; | ||
348 | int i; | ||
349 | |||
350 | if (!pentry) | ||
351 | return -1; | ||
352 | for (i = 0; i < gpio_num_entry; i++, pentry++) { | ||
353 | if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN)) | ||
354 | return pentry->pin_no; | ||
355 | } | ||
356 | return -1; | ||
357 | } | ||
358 | |||
359 | /* | ||
360 | * Here defines the array of devices platform data that IAFW would export | ||
361 | * through SFI "DEVS" table, we use name and type to match the device and | ||
362 | * its platform data. | ||
363 | */ | ||
364 | struct devs_id { | ||
365 | char name[SFI_NAME_LEN + 1]; | ||
366 | u8 type; | ||
367 | u8 delay; | ||
368 | void *(*get_platform_data)(void *info); | ||
369 | }; | ||
370 | |||
371 | /* the offset for the mapping of global gpio pin to irq */ | ||
372 | #define MRST_IRQ_OFFSET 0x100 | ||
373 | |||
374 | static void __init *pmic_gpio_platform_data(void *info) | ||
375 | { | ||
376 | static struct intel_pmic_gpio_platform_data pmic_gpio_pdata; | ||
377 | int gpio_base = get_gpio_by_name("pmic_gpio_base"); | ||
378 | |||
379 | if (gpio_base == -1) | ||
380 | gpio_base = 64; | ||
381 | pmic_gpio_pdata.gpio_base = gpio_base; | ||
382 | pmic_gpio_pdata.irq_base = gpio_base + MRST_IRQ_OFFSET; | ||
383 | pmic_gpio_pdata.gpiointr = 0xffffeff8; | ||
384 | |||
385 | return &pmic_gpio_pdata; | ||
386 | } | ||
387 | |||
388 | static void __init *max3111_platform_data(void *info) | ||
389 | { | ||
390 | struct spi_board_info *spi_info = info; | ||
391 | int intr = get_gpio_by_name("max3111_int"); | ||
392 | |||
393 | if (intr == -1) | ||
394 | return NULL; | ||
395 | spi_info->irq = intr + MRST_IRQ_OFFSET; | ||
396 | return NULL; | ||
397 | } | ||
398 | |||
399 | /* we have multiple max7315 on the board ... */ | ||
400 | #define MAX7315_NUM 2 | ||
401 | static void __init *max7315_platform_data(void *info) | ||
402 | { | ||
403 | static struct pca953x_platform_data max7315_pdata[MAX7315_NUM]; | ||
404 | static int nr; | ||
405 | struct pca953x_platform_data *max7315 = &max7315_pdata[nr]; | ||
406 | struct i2c_board_info *i2c_info = info; | ||
407 | int gpio_base, intr; | ||
408 | char base_pin_name[SFI_NAME_LEN + 1]; | ||
409 | char intr_pin_name[SFI_NAME_LEN + 1]; | ||
410 | |||
411 | if (nr == MAX7315_NUM) { | ||
412 | pr_err("too many max7315s, we only support %d\n", | ||
413 | MAX7315_NUM); | ||
414 | return NULL; | ||
415 | } | ||
416 | /* we have several max7315 on the board, we only need load several | ||
417 | * instances of the same pca953x driver to cover them | ||
418 | */ | ||
419 | strcpy(i2c_info->type, "max7315"); | ||
420 | if (nr++) { | ||
421 | sprintf(base_pin_name, "max7315_%d_base", nr); | ||
422 | sprintf(intr_pin_name, "max7315_%d_int", nr); | ||
423 | } else { | ||
424 | strcpy(base_pin_name, "max7315_base"); | ||
425 | strcpy(intr_pin_name, "max7315_int"); | ||
426 | } | ||
427 | |||
428 | gpio_base = get_gpio_by_name(base_pin_name); | ||
429 | intr = get_gpio_by_name(intr_pin_name); | ||
430 | |||
431 | if (gpio_base == -1) | ||
432 | return NULL; | ||
433 | max7315->gpio_base = gpio_base; | ||
434 | if (intr != -1) { | ||
435 | i2c_info->irq = intr + MRST_IRQ_OFFSET; | ||
436 | max7315->irq_base = gpio_base + MRST_IRQ_OFFSET; | ||
437 | } else { | ||
438 | i2c_info->irq = -1; | ||
439 | max7315->irq_base = -1; | ||
440 | } | ||
441 | return max7315; | ||
442 | } | ||
443 | |||
444 | static void __init *emc1403_platform_data(void *info) | ||
445 | { | ||
446 | static short intr2nd_pdata; | ||
447 | struct i2c_board_info *i2c_info = info; | ||
448 | int intr = get_gpio_by_name("thermal_int"); | ||
449 | int intr2nd = get_gpio_by_name("thermal_alert"); | ||
450 | |||
451 | if (intr == -1 || intr2nd == -1) | ||
452 | return NULL; | ||
453 | |||
454 | i2c_info->irq = intr + MRST_IRQ_OFFSET; | ||
455 | intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET; | ||
456 | |||
457 | return &intr2nd_pdata; | ||
458 | } | ||
459 | |||
460 | static void __init *lis331dl_platform_data(void *info) | ||
461 | { | ||
462 | static short intr2nd_pdata; | ||
463 | struct i2c_board_info *i2c_info = info; | ||
464 | int intr = get_gpio_by_name("accel_int"); | ||
465 | int intr2nd = get_gpio_by_name("accel_2"); | ||
466 | |||
467 | if (intr == -1 || intr2nd == -1) | ||
468 | return NULL; | ||
469 | |||
470 | i2c_info->irq = intr + MRST_IRQ_OFFSET; | ||
471 | intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET; | ||
472 | |||
473 | return &intr2nd_pdata; | ||
474 | } | ||
475 | |||
476 | static void __init *no_platform_data(void *info) | ||
477 | { | ||
478 | return NULL; | ||
479 | } | ||
480 | |||
481 | static const struct devs_id __initconst device_ids[] = { | ||
482 | {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data}, | ||
483 | {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data}, | ||
484 | {"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, | ||
485 | {"i2c_max7315_2", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, | ||
486 | {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data}, | ||
487 | {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data}, | ||
488 | {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, | ||
489 | {"msic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, | ||
490 | {}, | ||
491 | }; | ||
492 | |||
493 | #define MAX_IPCDEVS 24 | ||
494 | static struct platform_device *ipc_devs[MAX_IPCDEVS]; | ||
495 | static int ipc_next_dev; | ||
496 | |||
497 | #define MAX_SCU_SPI 24 | ||
498 | static struct spi_board_info *spi_devs[MAX_SCU_SPI]; | ||
499 | static int spi_next_dev; | ||
500 | |||
501 | #define MAX_SCU_I2C 24 | ||
502 | static struct i2c_board_info *i2c_devs[MAX_SCU_I2C]; | ||
503 | static int i2c_bus[MAX_SCU_I2C]; | ||
504 | static int i2c_next_dev; | ||
505 | |||
506 | static void __init intel_scu_device_register(struct platform_device *pdev) | ||
507 | { | ||
508 | if(ipc_next_dev == MAX_IPCDEVS) | ||
509 | pr_err("too many SCU IPC devices"); | ||
510 | else | ||
511 | ipc_devs[ipc_next_dev++] = pdev; | ||
512 | } | ||
513 | |||
514 | static void __init intel_scu_spi_device_register(struct spi_board_info *sdev) | ||
515 | { | ||
516 | struct spi_board_info *new_dev; | ||
517 | |||
518 | if (spi_next_dev == MAX_SCU_SPI) { | ||
519 | pr_err("too many SCU SPI devices"); | ||
520 | return; | ||
521 | } | ||
522 | |||
523 | new_dev = kzalloc(sizeof(*sdev), GFP_KERNEL); | ||
524 | if (!new_dev) { | ||
525 | pr_err("failed to alloc mem for delayed spi dev %s\n", | ||
526 | sdev->modalias); | ||
527 | return; | ||
528 | } | ||
529 | memcpy(new_dev, sdev, sizeof(*sdev)); | ||
530 | |||
531 | spi_devs[spi_next_dev++] = new_dev; | ||
532 | } | ||
533 | |||
534 | static void __init intel_scu_i2c_device_register(int bus, | ||
535 | struct i2c_board_info *idev) | ||
536 | { | ||
537 | struct i2c_board_info *new_dev; | ||
538 | |||
539 | if (i2c_next_dev == MAX_SCU_I2C) { | ||
540 | pr_err("too many SCU I2C devices"); | ||
541 | return; | ||
542 | } | ||
543 | |||
544 | new_dev = kzalloc(sizeof(*idev), GFP_KERNEL); | ||
545 | if (!new_dev) { | ||
546 | pr_err("failed to alloc mem for delayed i2c dev %s\n", | ||
547 | idev->type); | ||
548 | return; | ||
549 | } | ||
550 | memcpy(new_dev, idev, sizeof(*idev)); | ||
551 | |||
552 | i2c_bus[i2c_next_dev] = bus; | ||
553 | i2c_devs[i2c_next_dev++] = new_dev; | ||
554 | } | ||
555 | |||
556 | /* Called by IPC driver */ | ||
557 | void intel_scu_devices_create(void) | ||
558 | { | ||
559 | int i; | ||
560 | |||
561 | for (i = 0; i < ipc_next_dev; i++) | ||
562 | platform_device_add(ipc_devs[i]); | ||
563 | |||
564 | for (i = 0; i < spi_next_dev; i++) | ||
565 | spi_register_board_info(spi_devs[i], 1); | ||
566 | |||
567 | for (i = 0; i < i2c_next_dev; i++) { | ||
568 | struct i2c_adapter *adapter; | ||
569 | struct i2c_client *client; | ||
570 | |||
571 | adapter = i2c_get_adapter(i2c_bus[i]); | ||
572 | if (adapter) { | ||
573 | client = i2c_new_device(adapter, i2c_devs[i]); | ||
574 | if (!client) | ||
575 | pr_err("can't create i2c device %s\n", | ||
576 | i2c_devs[i]->type); | ||
577 | } else | ||
578 | i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1); | ||
579 | } | ||
580 | } | ||
581 | EXPORT_SYMBOL_GPL(intel_scu_devices_create); | ||
582 | |||
583 | /* Called by IPC driver */ | ||
584 | void intel_scu_devices_destroy(void) | ||
585 | { | ||
586 | int i; | ||
587 | |||
588 | for (i = 0; i < ipc_next_dev; i++) | ||
589 | platform_device_del(ipc_devs[i]); | ||
590 | } | ||
591 | EXPORT_SYMBOL_GPL(intel_scu_devices_destroy); | ||
592 | |||
593 | static void __init install_irq_resource(struct platform_device *pdev, int irq) | ||
594 | { | ||
595 | /* Single threaded */ | ||
596 | static struct resource __initdata res = { | ||
597 | .name = "IRQ", | ||
598 | .flags = IORESOURCE_IRQ, | ||
599 | }; | ||
600 | res.start = irq; | ||
601 | platform_device_add_resources(pdev, &res, 1); | ||
602 | } | ||
603 | |||
604 | static void __init sfi_handle_ipc_dev(struct platform_device *pdev) | ||
605 | { | ||
606 | const struct devs_id *dev = device_ids; | ||
607 | void *pdata = NULL; | ||
608 | |||
609 | while (dev->name[0]) { | ||
610 | if (dev->type == SFI_DEV_TYPE_IPC && | ||
611 | !strncmp(dev->name, pdev->name, SFI_NAME_LEN)) { | ||
612 | pdata = dev->get_platform_data(pdev); | ||
613 | break; | ||
614 | } | ||
615 | dev++; | ||
616 | } | ||
617 | pdev->dev.platform_data = pdata; | ||
618 | intel_scu_device_register(pdev); | ||
619 | } | ||
620 | |||
621 | static void __init sfi_handle_spi_dev(struct spi_board_info *spi_info) | ||
622 | { | ||
623 | const struct devs_id *dev = device_ids; | ||
624 | void *pdata = NULL; | ||
625 | |||
626 | while (dev->name[0]) { | ||
627 | if (dev->type == SFI_DEV_TYPE_SPI && | ||
628 | !strncmp(dev->name, spi_info->modalias, SFI_NAME_LEN)) { | ||
629 | pdata = dev->get_platform_data(spi_info); | ||
630 | break; | ||
631 | } | ||
632 | dev++; | ||
633 | } | ||
634 | spi_info->platform_data = pdata; | ||
635 | if (dev->delay) | ||
636 | intel_scu_spi_device_register(spi_info); | ||
637 | else | ||
638 | spi_register_board_info(spi_info, 1); | ||
639 | } | ||
640 | |||
641 | static void __init sfi_handle_i2c_dev(int bus, struct i2c_board_info *i2c_info) | ||
642 | { | ||
643 | const struct devs_id *dev = device_ids; | ||
644 | void *pdata = NULL; | ||
645 | |||
646 | while (dev->name[0]) { | ||
647 | if (dev->type == SFI_DEV_TYPE_I2C && | ||
648 | !strncmp(dev->name, i2c_info->type, SFI_NAME_LEN)) { | ||
649 | pdata = dev->get_platform_data(i2c_info); | ||
650 | break; | ||
651 | } | ||
652 | dev++; | ||
653 | } | ||
654 | i2c_info->platform_data = pdata; | ||
655 | |||
656 | if (dev->delay) | ||
657 | intel_scu_i2c_device_register(bus, i2c_info); | ||
658 | else | ||
659 | i2c_register_board_info(bus, i2c_info, 1); | ||
660 | } | ||
661 | |||
662 | |||
663 | static int __init sfi_parse_devs(struct sfi_table_header *table) | ||
664 | { | ||
665 | struct sfi_table_simple *sb; | ||
666 | struct sfi_device_table_entry *pentry; | ||
667 | struct spi_board_info spi_info; | ||
668 | struct i2c_board_info i2c_info; | ||
669 | struct platform_device *pdev; | ||
670 | int num, i, bus; | ||
671 | int ioapic; | ||
672 | struct io_apic_irq_attr irq_attr; | ||
673 | |||
674 | sb = (struct sfi_table_simple *)table; | ||
675 | num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry); | ||
676 | pentry = (struct sfi_device_table_entry *)sb->pentry; | ||
677 | |||
678 | for (i = 0; i < num; i++, pentry++) { | ||
679 | if (pentry->irq != (u8)0xff) { /* native RTE case */ | ||
680 | /* these SPI2 devices are not exposed to system as PCI | ||
681 | * devices, but they have separate RTE entry in IOAPIC | ||
682 | * so we have to enable them one by one here | ||
683 | */ | ||
684 | ioapic = mp_find_ioapic(pentry->irq); | ||
685 | irq_attr.ioapic = ioapic; | ||
686 | irq_attr.ioapic_pin = pentry->irq; | ||
687 | irq_attr.trigger = 1; | ||
688 | irq_attr.polarity = 1; | ||
689 | io_apic_set_pci_routing(NULL, pentry->irq, &irq_attr); | ||
690 | } | ||
691 | switch (pentry->type) { | ||
692 | case SFI_DEV_TYPE_IPC: | ||
693 | /* ID as IRQ is a hack that will go away */ | ||
694 | pdev = platform_device_alloc(pentry->name, pentry->irq); | ||
695 | if (pdev == NULL) { | ||
696 | pr_err("out of memory for SFI platform device '%s'.\n", | ||
697 | pentry->name); | ||
698 | continue; | ||
699 | } | ||
700 | install_irq_resource(pdev, pentry->irq); | ||
701 | pr_debug("info[%2d]: IPC bus, name = %16.16s, " | ||
702 | "irq = 0x%2x\n", i, pentry->name, pentry->irq); | ||
703 | sfi_handle_ipc_dev(pdev); | ||
704 | break; | ||
705 | case SFI_DEV_TYPE_SPI: | ||
706 | memset(&spi_info, 0, sizeof(spi_info)); | ||
707 | strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN); | ||
708 | spi_info.irq = pentry->irq; | ||
709 | spi_info.bus_num = pentry->host_num; | ||
710 | spi_info.chip_select = pentry->addr; | ||
711 | spi_info.max_speed_hz = pentry->max_freq; | ||
712 | pr_debug("info[%2d]: SPI bus = %d, name = %16.16s, " | ||
713 | "irq = 0x%2x, max_freq = %d, cs = %d\n", i, | ||
714 | spi_info.bus_num, | ||
715 | spi_info.modalias, | ||
716 | spi_info.irq, | ||
717 | spi_info.max_speed_hz, | ||
718 | spi_info.chip_select); | ||
719 | sfi_handle_spi_dev(&spi_info); | ||
720 | break; | ||
721 | case SFI_DEV_TYPE_I2C: | ||
722 | memset(&i2c_info, 0, sizeof(i2c_info)); | ||
723 | bus = pentry->host_num; | ||
724 | strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN); | ||
725 | i2c_info.irq = pentry->irq; | ||
726 | i2c_info.addr = pentry->addr; | ||
727 | pr_debug("info[%2d]: I2C bus = %d, name = %16.16s, " | ||
728 | "irq = 0x%2x, addr = 0x%x\n", i, bus, | ||
729 | i2c_info.type, | ||
730 | i2c_info.irq, | ||
731 | i2c_info.addr); | ||
732 | sfi_handle_i2c_dev(bus, &i2c_info); | ||
733 | break; | ||
734 | case SFI_DEV_TYPE_UART: | ||
735 | case SFI_DEV_TYPE_HSI: | ||
736 | default: | ||
737 | ; | ||
738 | } | ||
739 | } | ||
740 | return 0; | ||
741 | } | ||
742 | |||
743 | static int __init mrst_platform_init(void) | ||
744 | { | ||
745 | sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, sfi_parse_gpio); | ||
746 | sfi_table_parse(SFI_SIG_DEVS, NULL, NULL, sfi_parse_devs); | ||
747 | return 0; | ||
748 | } | ||
749 | arch_initcall(mrst_platform_init); | ||
750 | |||
751 | /* | ||
752 | * we will search these buttons in SFI GPIO table (by name) | ||
753 | * and register them dynamically. Please add all possible | ||
754 | * buttons here, we will shrink them if no GPIO found. | ||
755 | */ | ||
756 | static struct gpio_keys_button gpio_button[] = { | ||
757 | {KEY_POWER, -1, 1, "power_btn", EV_KEY, 0, 3000}, | ||
758 | {KEY_PROG1, -1, 1, "prog_btn1", EV_KEY, 0, 20}, | ||
759 | {KEY_PROG2, -1, 1, "prog_btn2", EV_KEY, 0, 20}, | ||
760 | {SW_LID, -1, 1, "lid_switch", EV_SW, 0, 20}, | ||
761 | {KEY_VOLUMEUP, -1, 1, "vol_up", EV_KEY, 0, 20}, | ||
762 | {KEY_VOLUMEDOWN, -1, 1, "vol_down", EV_KEY, 0, 20}, | ||
763 | {KEY_CAMERA, -1, 1, "camera_full", EV_KEY, 0, 20}, | ||
764 | {KEY_CAMERA_FOCUS, -1, 1, "camera_half", EV_KEY, 0, 20}, | ||
765 | {SW_KEYPAD_SLIDE, -1, 1, "MagSw1", EV_SW, 0, 20}, | ||
766 | {SW_KEYPAD_SLIDE, -1, 1, "MagSw2", EV_SW, 0, 20}, | ||
767 | }; | ||
768 | |||
769 | static struct gpio_keys_platform_data mrst_gpio_keys = { | ||
770 | .buttons = gpio_button, | ||
771 | .rep = 1, | ||
772 | .nbuttons = -1, /* will fill it after search */ | ||
773 | }; | ||
774 | |||
775 | static struct platform_device pb_device = { | ||
776 | .name = "gpio-keys", | ||
777 | .id = -1, | ||
778 | .dev = { | ||
779 | .platform_data = &mrst_gpio_keys, | ||
780 | }, | ||
781 | }; | ||
782 | |||
783 | /* | ||
784 | * Shrink the non-existent buttons, register the gpio button | ||
785 | * device if there is some | ||
786 | */ | ||
787 | static int __init pb_keys_init(void) | ||
788 | { | ||
789 | struct gpio_keys_button *gb = gpio_button; | ||
790 | int i, num, good = 0; | ||
791 | |||
792 | num = sizeof(gpio_button) / sizeof(struct gpio_keys_button); | ||
793 | for (i = 0; i < num; i++) { | ||
794 | gb[i].gpio = get_gpio_by_name(gb[i].desc); | ||
795 | if (gb[i].gpio == -1) | ||
796 | continue; | ||
797 | |||
798 | if (i != good) | ||
799 | gb[good] = gb[i]; | ||
800 | good++; | ||
801 | } | ||
802 | |||
803 | if (good) { | ||
804 | mrst_gpio_keys.nbuttons = good; | ||
805 | return platform_device_register(&pb_device); | ||
806 | } | ||
807 | return 0; | ||
808 | } | ||
809 | late_initcall(pb_keys_init); | ||
diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/mrst/vrtc.c new file mode 100644 index 000000000000..32cd7edd71a0 --- /dev/null +++ b/arch/x86/platform/mrst/vrtc.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * vrtc.c: Driver for virtual RTC device on Intel MID platform | ||
3 | * | ||
4 | * (C) Copyright 2009 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; version 2 | ||
9 | * of the License. | ||
10 | * | ||
11 | * Note: | ||
12 | * VRTC is emulated by system controller firmware, the real HW | ||
13 | * RTC is located in the PMIC device. SCU FW shadows PMIC RTC | ||
14 | * in a memory mapped IO space that is visible to the host IA | ||
15 | * processor. | ||
16 | * | ||
17 | * This driver is based on RTC CMOS driver. | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/sfi.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | |||
25 | #include <asm/mrst.h> | ||
26 | #include <asm/mrst-vrtc.h> | ||
27 | #include <asm/time.h> | ||
28 | #include <asm/fixmap.h> | ||
29 | |||
30 | static unsigned char __iomem *vrtc_virt_base; | ||
31 | |||
32 | unsigned char vrtc_cmos_read(unsigned char reg) | ||
33 | { | ||
34 | unsigned char retval; | ||
35 | |||
36 | /* vRTC's registers range from 0x0 to 0xD */ | ||
37 | if (reg > 0xd || !vrtc_virt_base) | ||
38 | return 0xff; | ||
39 | |||
40 | lock_cmos_prefix(reg); | ||
41 | retval = __raw_readb(vrtc_virt_base + (reg << 2)); | ||
42 | lock_cmos_suffix(reg); | ||
43 | return retval; | ||
44 | } | ||
45 | EXPORT_SYMBOL_GPL(vrtc_cmos_read); | ||
46 | |||
47 | void vrtc_cmos_write(unsigned char val, unsigned char reg) | ||
48 | { | ||
49 | if (reg > 0xd || !vrtc_virt_base) | ||
50 | return; | ||
51 | |||
52 | lock_cmos_prefix(reg); | ||
53 | __raw_writeb(val, vrtc_virt_base + (reg << 2)); | ||
54 | lock_cmos_suffix(reg); | ||
55 | } | ||
56 | EXPORT_SYMBOL_GPL(vrtc_cmos_write); | ||
57 | |||
58 | unsigned long vrtc_get_time(void) | ||
59 | { | ||
60 | u8 sec, min, hour, mday, mon; | ||
61 | u32 year; | ||
62 | |||
63 | while ((vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP)) | ||
64 | cpu_relax(); | ||
65 | |||
66 | sec = vrtc_cmos_read(RTC_SECONDS); | ||
67 | min = vrtc_cmos_read(RTC_MINUTES); | ||
68 | hour = vrtc_cmos_read(RTC_HOURS); | ||
69 | mday = vrtc_cmos_read(RTC_DAY_OF_MONTH); | ||
70 | mon = vrtc_cmos_read(RTC_MONTH); | ||
71 | year = vrtc_cmos_read(RTC_YEAR); | ||
72 | |||
73 | /* vRTC YEAR reg contains the offset to 1960 */ | ||
74 | year += 1960; | ||
75 | |||
76 | printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d " | ||
77 | "mon: %d year: %d\n", sec, min, hour, mday, mon, year); | ||
78 | |||
79 | return mktime(year, mon, mday, hour, min, sec); | ||
80 | } | ||
81 | |||
82 | /* Only care about the minutes and seconds */ | ||
83 | int vrtc_set_mmss(unsigned long nowtime) | ||
84 | { | ||
85 | int real_sec, real_min; | ||
86 | int vrtc_min; | ||
87 | |||
88 | vrtc_min = vrtc_cmos_read(RTC_MINUTES); | ||
89 | |||
90 | real_sec = nowtime % 60; | ||
91 | real_min = nowtime / 60; | ||
92 | if (((abs(real_min - vrtc_min) + 15)/30) & 1) | ||
93 | real_min += 30; | ||
94 | real_min %= 60; | ||
95 | |||
96 | vrtc_cmos_write(real_sec, RTC_SECONDS); | ||
97 | vrtc_cmos_write(real_min, RTC_MINUTES); | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | void __init mrst_rtc_init(void) | ||
102 | { | ||
103 | unsigned long rtc_paddr; | ||
104 | void __iomem *virt_base; | ||
105 | |||
106 | sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc); | ||
107 | if (!sfi_mrtc_num) | ||
108 | return; | ||
109 | |||
110 | rtc_paddr = sfi_mrtc_array[0].phys_addr; | ||
111 | |||
112 | /* vRTC's register address may not be page aligned */ | ||
113 | set_fixmap_nocache(FIX_LNW_VRTC, rtc_paddr); | ||
114 | |||
115 | virt_base = (void __iomem *)__fix_to_virt(FIX_LNW_VRTC); | ||
116 | virt_base += rtc_paddr & ~PAGE_MASK; | ||
117 | vrtc_virt_base = virt_base; | ||
118 | |||
119 | x86_platform.get_wallclock = vrtc_get_time; | ||
120 | x86_platform.set_wallclock = vrtc_set_mmss; | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * The Moorestown platform has a memory mapped virtual RTC device that emulates | ||
125 | * the programming interface of the RTC. | ||
126 | */ | ||
127 | |||
128 | static struct resource vrtc_resources[] = { | ||
129 | [0] = { | ||
130 | .flags = IORESOURCE_MEM, | ||
131 | }, | ||
132 | [1] = { | ||
133 | .flags = IORESOURCE_IRQ, | ||
134 | } | ||
135 | }; | ||
136 | |||
137 | static struct platform_device vrtc_device = { | ||
138 | .name = "rtc_mrst", | ||
139 | .id = -1, | ||
140 | .resource = vrtc_resources, | ||
141 | .num_resources = ARRAY_SIZE(vrtc_resources), | ||
142 | }; | ||
143 | |||
144 | /* Register the RTC device if appropriate */ | ||
145 | static int __init mrst_device_create(void) | ||
146 | { | ||
147 | /* No Moorestown, no device */ | ||
148 | if (!mrst_identify_cpu()) | ||
149 | return -ENODEV; | ||
150 | /* No timer, no device */ | ||
151 | if (!sfi_mrtc_num) | ||
152 | return -ENODEV; | ||
153 | |||
154 | /* iomem resource */ | ||
155 | vrtc_resources[0].start = sfi_mrtc_array[0].phys_addr; | ||
156 | vrtc_resources[0].end = sfi_mrtc_array[0].phys_addr + | ||
157 | MRST_VRTC_MAP_SZ; | ||
158 | /* irq resource */ | ||
159 | vrtc_resources[1].start = sfi_mrtc_array[0].irq; | ||
160 | vrtc_resources[1].end = sfi_mrtc_array[0].irq; | ||
161 | |||
162 | return platform_device_register(&vrtc_device); | ||
163 | } | ||
164 | |||
165 | module_init(mrst_device_create); | ||
diff --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c index dd4c281ffe57..cc822a29b227 100644 --- a/arch/x86/platform/sfi/sfi.c +++ b/arch/x86/platform/sfi/sfi.c | |||
@@ -34,17 +34,6 @@ | |||
34 | #ifdef CONFIG_X86_LOCAL_APIC | 34 | #ifdef CONFIG_X86_LOCAL_APIC |
35 | static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; | 35 | static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; |
36 | 36 | ||
37 | static void __init mp_sfi_register_lapic_address(unsigned long address) | ||
38 | { | ||
39 | mp_lapic_addr = address; | ||
40 | |||
41 | set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); | ||
42 | if (boot_cpu_physical_apicid == -1U) | ||
43 | boot_cpu_physical_apicid = read_apic_id(); | ||
44 | |||
45 | pr_info("Boot CPU = %d\n", boot_cpu_physical_apicid); | ||
46 | } | ||
47 | |||
48 | /* All CPUs enumerated by SFI must be present and enabled */ | 37 | /* All CPUs enumerated by SFI must be present and enabled */ |
49 | static void __cpuinit mp_sfi_register_lapic(u8 id) | 38 | static void __cpuinit mp_sfi_register_lapic(u8 id) |
50 | { | 39 | { |
@@ -110,7 +99,7 @@ static int __init sfi_parse_ioapic(struct sfi_table_header *table) | |||
110 | int __init sfi_platform_init(void) | 99 | int __init sfi_platform_init(void) |
111 | { | 100 | { |
112 | #ifdef CONFIG_X86_LOCAL_APIC | 101 | #ifdef CONFIG_X86_LOCAL_APIC |
113 | mp_sfi_register_lapic_address(sfi_lapic_addr); | 102 | register_lapic_address(sfi_lapic_addr); |
114 | sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, sfi_parse_cpus); | 103 | sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, sfi_parse_cpus); |
115 | #endif | 104 | #endif |
116 | #ifdef CONFIG_X86_IO_APIC | 105 | #ifdef CONFIG_X86_IO_APIC |