Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'x86-mrst-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'x86-mrst-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (30 commits)
x86, mrst: Fix whitespace breakage in apb_timer.c
x86, mrst: Fix APB timer per cpu clockevent
x86, mrst: Remove X86_MRST dependency on PCI_IOAPIC
x86, olpc: Use pci subarch init for OLPC
x86, pci: Add arch_init to x86_init abstraction
x86, mrst: Add Kconfig dependencies for Moorestown
x86, pci: Exclude Moorestown PCI code if CONFIG_X86_MRST=n
x86, numaq: Make CONFIG_X86_NUMAQ depend on CONFIG_PCI
x86, pci: Add sanity check for PCI fixed bar probing
x86, legacy_irq: Remove duplicate vector assigment
x86, legacy_irq: Remove left over nr_legacy_irqs
x86, mrst: Platform clock setup code
x86, apbt: Moorestown APB system timer driver
x86, mrst: Add vrtc platform data setup code
x86, mrst: Add platform timer info parsing code
x86, mrst: Fill in PCI functions in x86_init layer
x86, mrst: Add dummy legacy pic to platform setup
x86/PCI: Moorestown PCI support
x86, ioapic: Add dummy ioapic functions
x86, ioapic: Early enable ioapic for timer irq
...

Fixed up semantic conflict of new clocksources due to commit
17622339af25 ("clocksource: add argument to resume callback").

+1662 -162
+6
Documentation/kernel-parameters.txt
··· 2834 2834 default x2apic cluster mode on platforms 2835 2835 supporting x2apic. 2836 2836 2837 + x86_mrst_timer= [X86-32,APBT] 2838 + Choose timer option for x86 Moorestown MID platform. 2839 + Two valid options are apbt timer only and lapic timer 2840 + plus one apbt timer for broadcast timer. 2841 + x86_mrst_timer=apbt_only | lapic_and_apbt 2842 + 2837 2843 xd= [HW,XT] Original XT pre-IDE (RLL encoded) disks. 2838 2844 xd_geo= See header of drivers/block/xd.c. 2839 2845
+15
arch/x86/Kconfig
··· 393 393 394 394 config X86_MRST 395 395 bool "Moorestown MID platform" 396 + depends on PCI 397 + depends on PCI_GOANY 396 398 depends on X86_32 397 399 depends on X86_EXTENDED_PLATFORM 400 + depends on X86_IO_APIC 401 + select APB_TIMER 398 402 ---help--- 399 403 Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin 400 404 Internet Device(MID) platform. Moorestown consists of two chips: ··· 433 429 config X86_NUMAQ 434 430 bool "NUMAQ (IBM/Sequent)" 435 431 depends on X86_32_NON_STANDARD 432 + depends on PCI 436 433 select NUMA 437 434 select X86_MPPARSE 438 435 ---help--- ··· 633 628 config HPET_EMULATE_RTC 634 629 def_bool y 635 630 depends on HPET_TIMER && (RTC=y || RTC=m || RTC_DRV_CMOS=m || RTC_DRV_CMOS=y) 631 + 632 + config APB_TIMER 633 + def_bool y if MRST 634 + prompt "Langwell APB Timer Support" if X86_MRST 635 + help 636 + APB timer is the replacement for 8254, HPET on X86 MID platforms. 637 + The APBT provides a stable time base on SMP 638 + systems, unlike the TSC, but it is more expensive to access, 639 + as it is off-chip. APB timers are always running regardless of CPU 640 + C states, they are used as per CPU clockevent device when possible. 636 641 637 642 # Mark as embedded because too many people got it wrong. 638 643 # The code disables itself when not needed.
+70
arch/x86/include/asm/apb_timer.h
··· 1 + /* 2 + * apb_timer.h: Driver for Langwell APB timer based on Synopsis DesignWare 3 + * 4 + * (C) Copyright 2009 Intel Corporation 5 + * Author: Jacob Pan (jacob.jun.pan@intel.com) 6 + * 7 + * This program is free software; you can redistribute it and/or 8 + * modify it under the terms of the GNU General Public License 9 + * as published by the Free Software Foundation; version 2 10 + * of the License. 11 + * 12 + * Note: 13 + */ 14 + 15 + #ifndef ASM_X86_APBT_H 16 + #define ASM_X86_APBT_H 17 + #include <linux/sfi.h> 18 + 19 + #ifdef CONFIG_APB_TIMER 20 + 21 + /* Langwell DW APB timer registers */ 22 + #define APBTMR_N_LOAD_COUNT 0x00 23 + #define APBTMR_N_CURRENT_VALUE 0x04 24 + #define APBTMR_N_CONTROL 0x08 25 + #define APBTMR_N_EOI 0x0c 26 + #define APBTMR_N_INT_STATUS 0x10 27 + 28 + #define APBTMRS_INT_STATUS 0xa0 29 + #define APBTMRS_EOI 0xa4 30 + #define APBTMRS_RAW_INT_STATUS 0xa8 31 + #define APBTMRS_COMP_VERSION 0xac 32 + #define APBTMRS_REG_SIZE 0x14 33 + 34 + /* register bits */ 35 + #define APBTMR_CONTROL_ENABLE (1<<0) 36 + #define APBTMR_CONTROL_MODE_PERIODIC (1<<1) /*1: periodic 0:free running */ 37 + #define APBTMR_CONTROL_INT (1<<2) 38 + 39 + /* default memory mapped register base */ 40 + #define LNW_SCU_ADDR 0xFF100000 41 + #define LNW_EXT_TIMER_OFFSET 0x1B800 42 + #define APBT_DEFAULT_BASE (LNW_SCU_ADDR+LNW_EXT_TIMER_OFFSET) 43 + #define LNW_EXT_TIMER_PGOFFSET 0x800 44 + 45 + /* APBT clock speed range from PCLK to fabric base, 25-100MHz */ 46 + #define APBT_MAX_FREQ 50 47 + #define APBT_MIN_FREQ 1 48 + #define APBT_MMAP_SIZE 1024 49 + 50 + #define APBT_DEV_USED 1 51 + 52 + extern void apbt_time_init(void); 53 + extern struct clock_event_device *global_clock_event; 54 + extern unsigned long apbt_quick_calibrate(void); 55 + extern int arch_setup_apbt_irqs(int irq, int trigger, int mask, int cpu); 56 + extern void apbt_setup_secondary_clock(void); 57 + extern unsigned int boot_cpu_id; 58 + extern int disable_apbt_percpu; 59 + 60 + extern struct sfi_timer_table_entry *sfi_get_mtmr(int hint); 61 + extern void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr); 62 + extern int sfi_mtimer_num; 63 + 64 + #else /* CONFIG_APB_TIMER */ 65 + 66 + static inline unsigned long apbt_quick_calibrate(void) {return 0; } 67 + static inline void apbt_time_init(void) {return 0; } 68 + 69 + #endif 70 + #endif /* ASM_X86_APBT_H */
-7
arch/x86/include/asm/hw_irq.h
··· 53 53 extern void call_function_interrupt(void); 54 54 extern void call_function_single_interrupt(void); 55 55 56 - /* PIC specific functions */ 57 - extern void disable_8259A_irq(unsigned int irq); 58 - extern void enable_8259A_irq(unsigned int irq); 59 - extern int i8259A_irq_pending(unsigned int irq); 60 - extern void make_8259A_irq(unsigned int irq); 61 - extern void init_8259A(int aeoi); 62 - 63 56 /* IOAPIC */ 64 57 #define IO_APIC_IRQ(x) (((x) >= NR_IRQS_LEGACY) || ((1<<(x)) & io_apic_irqs)) 65 58 extern unsigned long io_apic_irqs;
+12 -7
arch/x86/include/asm/i8259.h
··· 26 26 27 27 extern raw_spinlock_t i8259A_lock; 28 28 29 - extern void init_8259A(int auto_eoi); 30 - extern void enable_8259A_irq(unsigned int irq); 31 - extern void disable_8259A_irq(unsigned int irq); 32 - extern unsigned int startup_8259A_irq(unsigned int irq); 33 - 34 29 /* the PIC may need a careful delay on some platforms, hence specific calls */ 35 30 static inline unsigned char inb_pic(unsigned int port) 36 31 { ··· 52 57 53 58 extern struct irq_chip i8259A_chip; 54 59 55 - extern void mask_8259A(void); 56 - extern void unmask_8259A(void); 60 + struct legacy_pic { 61 + int nr_legacy_irqs; 62 + struct irq_chip *chip; 63 + void (*mask_all)(void); 64 + void (*restore_mask)(void); 65 + void (*init)(int auto_eoi); 66 + int (*irq_pending)(unsigned int irq); 67 + void (*make_irq)(unsigned int irq); 68 + }; 69 + 70 + extern struct legacy_pic *legacy_pic; 71 + extern struct legacy_pic null_legacy_pic; 57 72 58 73 #endif /* _ASM_X86_I8259_H */
+5 -2
arch/x86/include/asm/io_apic.h
··· 143 143 /* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */ 144 144 extern int timer_through_8259; 145 145 146 - extern void io_apic_disable_legacy(void); 147 - 148 146 /* 149 147 * If we use the IO-APIC for IRQ routing, disable automatic 150 148 * assignment of PCI IRQ's. ··· 187 189 int mp_find_ioapic(int gsi); 188 190 int mp_find_ioapic_pin(int ioapic, int gsi); 189 191 void __init mp_register_ioapic(int id, u32 address, u32 gsi_base); 192 + extern void __init pre_init_apic_IRQ0(void); 190 193 191 194 #else /* !CONFIG_X86_IO_APIC */ 192 195 ··· 197 198 static inline void ioapic_init_mappings(void) { } 198 199 static inline void ioapic_insert_resources(void) { } 199 200 static inline void probe_nr_irqs_gsi(void) { } 201 + static inline int mp_find_ioapic(int gsi) { return 0; } 200 202 203 + struct io_apic_irq_attr; 204 + static inline int io_apic_set_pci_routing(struct device *dev, int irq, 205 + struct io_apic_irq_attr *irq_attr) { return 0; } 201 206 #endif 202 207 203 208 #endif /* _ASM_X86_IO_APIC_H */
-1
arch/x86/include/asm/irq.h
··· 48 48 extern int vector_used_by_percpu_irq(unsigned int vector); 49 49 50 50 extern void init_ISA_irqs(void); 51 - extern int nr_legacy_irqs; 52 51 53 52 #endif /* _ASM_X86_IRQ_H */
+19
arch/x86/include/asm/mrst.h
··· 1 + /* 2 + * mrst.h: Intel Moorestown platform specific setup code 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 + #ifndef _ASM_X86_MRST_H 12 + #define _ASM_X86_MRST_H 13 + extern int pci_mrst_init(void); 14 + int __init sfi_parse_mrtc(struct sfi_table_header *table); 15 + 16 + #define SFI_MTMR_MAX_NUM 8 17 + #define SFI_MRTC_MAX 8 18 + 19 + #endif /* _ASM_X86_MRST_H */
+1
arch/x86/include/asm/numaq.h
··· 30 30 31 31 extern int found_numaq; 32 32 extern int get_memcfg_numaq(void); 33 + extern int pci_numaq_init(void); 33 34 34 35 extern void *xquad_portio; 35 36
+2 -18
arch/x86/include/asm/olpc.h
··· 13 13 14 14 #define OLPC_F_PRESENT 0x01 15 15 #define OLPC_F_DCON 0x02 16 - #define OLPC_F_VSA 0x04 17 16 18 17 #ifdef CONFIG_OLPC 19 18 ··· 50 51 } 51 52 52 53 /* 53 - * The VSA is software from AMD that typical Geode bioses will include. 54 - * It is used to emulate the PCI bus, VGA, etc. OLPC's Open Firmware does 55 - * not include the VSA; instead, PCI is emulated by the kernel. 56 - * 57 - * The VSA is described further in arch/x86/pci/olpc.c. 58 - */ 59 - static inline int olpc_has_vsa(void) 60 - { 61 - return (olpc_platform_info.flags & OLPC_F_VSA) ? 1 : 0; 62 - } 63 - 64 - /* 65 54 * The "Mass Production" version of OLPC's XO is identified as being model 66 55 * C2. During the prototype phase, the following models (in chronological 67 56 * order) were created: A1, B1, B2, B3, B4, C1. The A1 through B2 models ··· 74 87 return 0; 75 88 } 76 89 77 - static inline int olpc_has_vsa(void) 78 - { 79 - return 0; 80 - } 81 - 82 90 #endif 91 + 92 + extern int pci_olpc_init(void); 83 93 84 94 /* EC related functions */ 85 95
+8 -1
arch/x86/include/asm/pci.h
··· 45 45 46 46 #ifdef CONFIG_PCI 47 47 extern unsigned int pcibios_assign_all_busses(void); 48 + extern int pci_legacy_init(void); 49 + # ifdef CONFIG_ACPI 50 + # define x86_default_pci_init pci_acpi_init 51 + # else 52 + # define x86_default_pci_init pci_legacy_init 53 + # endif 48 54 #else 49 - #define pcibios_assign_all_busses() 0 55 + # define pcibios_assign_all_busses() 0 56 + # define x86_default_pci_init NULL 50 57 #endif 51 58 52 59 extern unsigned long pci_mem_start;
+17 -5
arch/x86/include/asm/pci_x86.h
··· 83 83 84 84 extern unsigned int pcibios_irq_mask; 85 85 86 - extern int pcibios_scanned; 87 86 extern spinlock_t pci_config_lock; 88 87 89 88 extern int (*pcibios_enable_irq)(struct pci_dev *dev); ··· 105 106 extern int pci_direct_probe(void); 106 107 extern void pci_direct_init(int type); 107 108 extern void pci_pcbios_init(void); 108 - extern int pci_olpc_init(void); 109 109 extern void __init dmi_check_pciprobe(void); 110 110 extern void __init dmi_check_skip_isa_align(void); 111 111 112 112 /* some common used subsys_initcalls */ 113 113 extern int __init pci_acpi_init(void); 114 - extern int __init pcibios_irq_init(void); 115 - extern int __init pci_visws_init(void); 116 - extern int __init pci_numaq_init(void); 114 + extern void __init pcibios_irq_init(void); 117 115 extern int __init pcibios_init(void); 116 + extern int pci_legacy_init(void); 117 + extern void pcibios_fixup_irqs(void); 118 118 119 119 /* pci-mmconfig.c */ 120 120 ··· 181 183 { 182 184 asm volatile("movl %%eax,(%1)" : : "a" (val), "r" (pos) : "memory"); 183 185 } 186 + 187 + #ifdef CONFIG_PCI 188 + # ifdef CONFIG_ACPI 189 + # define x86_default_pci_init pci_acpi_init 190 + # else 191 + # define x86_default_pci_init pci_legacy_init 192 + # endif 193 + # define x86_default_pci_init_irq pcibios_irq_init 194 + # define x86_default_pci_fixup_irqs pcibios_fixup_irqs 195 + #else 196 + # define x86_default_pci_init NULL 197 + # define x86_default_pci_init_irq NULL 198 + # define x86_default_pci_fixup_irqs NULL 199 + #endif
-2
arch/x86/include/asm/setup.h
··· 37 37 38 38 #ifdef CONFIG_X86_VISWS 39 39 extern void visws_early_detect(void); 40 - extern int is_visws_box(void); 41 40 #else 42 41 static inline void visws_early_detect(void) { } 43 - static inline int is_visws_box(void) { return 0; } 44 42 #endif 45 43 46 44 extern unsigned long saved_video_mode;
+2
arch/x86/include/asm/visws/cobalt.h
··· 122 122 123 123 extern char visws_board_rev; 124 124 125 + extern int pci_visws_init(void); 126 + 125 127 #endif /* _ASM_X86_VISWS_COBALT_H */
+15
arch/x86/include/asm/x86_init.h
··· 99 99 }; 100 100 101 101 /** 102 + * struct x86_init_pci - platform specific pci init functions 103 + * @arch_init: platform specific pci arch init call 104 + * @init: platform specific pci subsystem init 105 + * @init_irq: platform specific pci irq init 106 + * @fixup_irqs: platform specific pci irq fixup 107 + */ 108 + struct x86_init_pci { 109 + int (*arch_init)(void); 110 + int (*init)(void); 111 + void (*init_irq)(void); 112 + void (*fixup_irqs)(void); 113 + }; 114 + 115 + /** 102 116 * struct x86_init_ops - functions for platform specific setup 103 117 * 104 118 */ ··· 124 110 struct x86_init_paging paging; 125 111 struct x86_init_timers timers; 126 112 struct x86_init_iommu iommu; 113 + struct x86_init_pci pci; 127 114 }; 128 115 129 116 /**
+1
arch/x86/kernel/Makefile
··· 87 87 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 88 88 89 89 obj-$(CONFIG_HPET_TIMER) += hpet.o 90 + obj-$(CONFIG_APB_TIMER) += apb_timer.o 90 91 91 92 obj-$(CONFIG_K8_NB) += k8.o 92 93 obj-$(CONFIG_DEBUG_RODATA_TEST) += test_rodata.o
+4
arch/x86/kernel/acpi/boot.c
··· 35 35 #include <linux/ioport.h> 36 36 #include <linux/pci.h> 37 37 38 + #include <asm/pci_x86.h> 38 39 #include <asm/pgtable.h> 39 40 #include <asm/io_apic.h> 40 41 #include <asm/apic.h> ··· 1624 1623 acpi_process_madt(); 1625 1624 1626 1625 acpi_table_parse(ACPI_SIG_HPET, acpi_parse_hpet); 1626 + 1627 + if (!acpi_noirq) 1628 + x86_init.pci.init = pci_acpi_init; 1627 1629 1628 1630 return 0; 1629 1631 }
+784
arch/x86/kernel/apb_timer.c
··· 1 + /* 2 + * apb_timer.c: Driver for Langwell APB timers 3 + * 4 + * (C) Copyright 2009 Intel Corporation 5 + * Author: Jacob Pan (jacob.jun.pan@intel.com) 6 + * 7 + * This program is free software; you can redistribute it and/or 8 + * modify it under the terms of the GNU General Public License 9 + * as published by the Free Software Foundation; version 2 10 + * of the License. 11 + * 12 + * Note: 13 + * Langwell is the south complex of Intel Moorestown MID platform. There are 14 + * eight external timers in total that can be used by the operating system. 15 + * The timer information, such as frequency and addresses, is provided to the 16 + * OS via SFI tables. 17 + * Timer interrupts are routed via FW/HW emulated IOAPIC independently via 18 + * individual redirection table entries (RTE). 19 + * Unlike HPET, there is no master counter, therefore one of the timers are 20 + * used as clocksource. The overall allocation looks like: 21 + * - timer 0 - NR_CPUs for per cpu timer 22 + * - one timer for clocksource 23 + * - one timer for watchdog driver. 24 + * It is also worth notice that APB timer does not support true one-shot mode, 25 + * free-running mode will be used here to emulate one-shot mode. 26 + * APB timer can also be used as broadcast timer along with per cpu local APIC 27 + * timer, but by default APB timer has higher rating than local APIC timers. 28 + */ 29 + 30 + #include <linux/clocksource.h> 31 + #include <linux/clockchips.h> 32 + #include <linux/delay.h> 33 + #include <linux/errno.h> 34 + #include <linux/init.h> 35 + #include <linux/sysdev.h> 36 + #include <linux/pm.h> 37 + #include <linux/pci.h> 38 + #include <linux/sfi.h> 39 + #include <linux/interrupt.h> 40 + #include <linux/cpu.h> 41 + #include <linux/irq.h> 42 + 43 + #include <asm/fixmap.h> 44 + #include <asm/apb_timer.h> 45 + 46 + #define APBT_MASK CLOCKSOURCE_MASK(32) 47 + #define APBT_SHIFT 22 48 + #define APBT_CLOCKEVENT_RATING 150 49 + #define APBT_CLOCKSOURCE_RATING 250 50 + #define APBT_MIN_DELTA_USEC 200 51 + 52 + #define EVT_TO_APBT_DEV(evt) container_of(evt, struct apbt_dev, evt) 53 + #define APBT_CLOCKEVENT0_NUM (0) 54 + #define APBT_CLOCKEVENT1_NUM (1) 55 + #define APBT_CLOCKSOURCE_NUM (2) 56 + 57 + static unsigned long apbt_address; 58 + static int apb_timer_block_enabled; 59 + static void __iomem *apbt_virt_address; 60 + static int phy_cs_timer_id; 61 + 62 + /* 63 + * Common DW APB timer info 64 + */ 65 + static uint64_t apbt_freq; 66 + 67 + static void apbt_set_mode(enum clock_event_mode mode, 68 + struct clock_event_device *evt); 69 + static int apbt_next_event(unsigned long delta, 70 + struct clock_event_device *evt); 71 + static cycle_t apbt_read_clocksource(struct clocksource *cs); 72 + static void apbt_restart_clocksource(struct clocksource *cs); 73 + 74 + struct apbt_dev { 75 + struct clock_event_device evt; 76 + unsigned int num; 77 + int cpu; 78 + unsigned int irq; 79 + unsigned int tick; 80 + unsigned int count; 81 + unsigned int flags; 82 + char name[10]; 83 + }; 84 + 85 + int disable_apbt_percpu __cpuinitdata; 86 + 87 + static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev); 88 + 89 + #ifdef CONFIG_SMP 90 + static unsigned int apbt_num_timers_used; 91 + static struct apbt_dev *apbt_devs; 92 + #endif 93 + 94 + static inline unsigned long apbt_readl_reg(unsigned long a) 95 + { 96 + return readl(apbt_virt_address + a); 97 + } 98 + 99 + static inline void apbt_writel_reg(unsigned long d, unsigned long a) 100 + { 101 + writel(d, apbt_virt_address + a); 102 + } 103 + 104 + static inline unsigned long apbt_readl(int n, unsigned long a) 105 + { 106 + return readl(apbt_virt_address + a + n * APBTMRS_REG_SIZE); 107 + } 108 + 109 + static inline void apbt_writel(int n, unsigned long d, unsigned long a) 110 + { 111 + writel(d, apbt_virt_address + a + n * APBTMRS_REG_SIZE); 112 + } 113 + 114 + static inline void apbt_set_mapping(void) 115 + { 116 + struct sfi_timer_table_entry *mtmr; 117 + 118 + if (apbt_virt_address) { 119 + pr_debug("APBT base already mapped\n"); 120 + return; 121 + } 122 + mtmr = sfi_get_mtmr(APBT_CLOCKEVENT0_NUM); 123 + if (mtmr == NULL) { 124 + printk(KERN_ERR "Failed to get MTMR %d from SFI\n", 125 + APBT_CLOCKEVENT0_NUM); 126 + return; 127 + } 128 + apbt_address = (unsigned long)mtmr->phys_addr; 129 + if (!apbt_address) { 130 + printk(KERN_WARNING "No timer base from SFI, use default\n"); 131 + apbt_address = APBT_DEFAULT_BASE; 132 + } 133 + apbt_virt_address = ioremap_nocache(apbt_address, APBT_MMAP_SIZE); 134 + if (apbt_virt_address) { 135 + pr_debug("Mapped APBT physical addr %p at virtual addr %p\n",\ 136 + (void *)apbt_address, (void *)apbt_virt_address); 137 + } else { 138 + pr_debug("Failed mapping APBT phy address at %p\n",\ 139 + (void *)apbt_address); 140 + goto panic_noapbt; 141 + } 142 + apbt_freq = mtmr->freq_hz / USEC_PER_SEC; 143 + sfi_free_mtmr(mtmr); 144 + 145 + /* Now figure out the physical timer id for clocksource device */ 146 + mtmr = sfi_get_mtmr(APBT_CLOCKSOURCE_NUM); 147 + if (mtmr == NULL) 148 + goto panic_noapbt; 149 + 150 + /* Now figure out the physical timer id */ 151 + phy_cs_timer_id = (unsigned int)(mtmr->phys_addr & 0xff) 152 + / APBTMRS_REG_SIZE; 153 + pr_debug("Use timer %d for clocksource\n", phy_cs_timer_id); 154 + return; 155 + 156 + panic_noapbt: 157 + panic("Failed to setup APB system timer\n"); 158 + 159 + } 160 + 161 + static inline void apbt_clear_mapping(void) 162 + { 163 + iounmap(apbt_virt_address); 164 + apbt_virt_address = NULL; 165 + } 166 + 167 + /* 168 + * APBT timer interrupt enable / disable 169 + */ 170 + static inline int is_apbt_capable(void) 171 + { 172 + return apbt_virt_address ? 1 : 0; 173 + } 174 + 175 + static struct clocksource clocksource_apbt = { 176 + .name = "apbt", 177 + .rating = APBT_CLOCKSOURCE_RATING, 178 + .read = apbt_read_clocksource, 179 + .mask = APBT_MASK, 180 + .shift = APBT_SHIFT, 181 + .flags = CLOCK_SOURCE_IS_CONTINUOUS, 182 + .resume = apbt_restart_clocksource, 183 + }; 184 + 185 + /* boot APB clock event device */ 186 + static struct clock_event_device apbt_clockevent = { 187 + .name = "apbt0", 188 + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 189 + .set_mode = apbt_set_mode, 190 + .set_next_event = apbt_next_event, 191 + .shift = APBT_SHIFT, 192 + .irq = 0, 193 + .rating = APBT_CLOCKEVENT_RATING, 194 + }; 195 + 196 + /* 197 + * if user does not want to use per CPU apb timer, just give it a lower rating 198 + * than local apic timer and skip the late per cpu timer init. 199 + */ 200 + static inline int __init setup_x86_mrst_timer(char *arg) 201 + { 202 + if (!arg) 203 + return -EINVAL; 204 + 205 + if (strcmp("apbt_only", arg) == 0) 206 + disable_apbt_percpu = 0; 207 + else if (strcmp("lapic_and_apbt", arg) == 0) 208 + disable_apbt_percpu = 1; 209 + else { 210 + pr_warning("X86 MRST timer option %s not recognised" 211 + " use x86_mrst_timer=apbt_only or lapic_and_apbt\n", 212 + arg); 213 + return -EINVAL; 214 + } 215 + return 0; 216 + } 217 + __setup("x86_mrst_timer=", setup_x86_mrst_timer); 218 + 219 + /* 220 + * start count down from 0xffff_ffff. this is done by toggling the enable bit 221 + * then load initial load count to ~0. 222 + */ 223 + static void apbt_start_counter(int n) 224 + { 225 + unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL); 226 + 227 + ctrl &= ~APBTMR_CONTROL_ENABLE; 228 + apbt_writel(n, ctrl, APBTMR_N_CONTROL); 229 + apbt_writel(n, ~0, APBTMR_N_LOAD_COUNT); 230 + /* enable, mask interrupt */ 231 + ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC; 232 + ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT); 233 + apbt_writel(n, ctrl, APBTMR_N_CONTROL); 234 + /* read it once to get cached counter value initialized */ 235 + apbt_read_clocksource(&clocksource_apbt); 236 + } 237 + 238 + static irqreturn_t apbt_interrupt_handler(int irq, void *data) 239 + { 240 + struct apbt_dev *dev = (struct apbt_dev *)data; 241 + struct clock_event_device *aevt = &dev->evt; 242 + 243 + if (!aevt->event_handler) { 244 + printk(KERN_INFO "Spurious APBT timer interrupt on %d\n", 245 + dev->num); 246 + return IRQ_NONE; 247 + } 248 + aevt->event_handler(aevt); 249 + return IRQ_HANDLED; 250 + } 251 + 252 + static void apbt_restart_clocksource(struct clocksource *cs) 253 + { 254 + apbt_start_counter(phy_cs_timer_id); 255 + } 256 + 257 + /* Setup IRQ routing via IOAPIC */ 258 + #ifdef CONFIG_SMP 259 + static void apbt_setup_irq(struct apbt_dev *adev) 260 + { 261 + struct irq_chip *chip; 262 + struct irq_desc *desc; 263 + 264 + /* timer0 irq has been setup early */ 265 + if (adev->irq == 0) 266 + return; 267 + desc = irq_to_desc(adev->irq); 268 + chip = get_irq_chip(adev->irq); 269 + disable_irq(adev->irq); 270 + desc->status |= IRQ_MOVE_PCNTXT; 271 + irq_set_affinity(adev->irq, cpumask_of(adev->cpu)); 272 + /* APB timer irqs are set up as mp_irqs, timer is edge triggerred */ 273 + set_irq_chip_and_handler_name(adev->irq, chip, handle_edge_irq, "edge"); 274 + enable_irq(adev->irq); 275 + if (system_state == SYSTEM_BOOTING) 276 + if (request_irq(adev->irq, apbt_interrupt_handler, 277 + IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING, 278 + adev->name, adev)) { 279 + printk(KERN_ERR "Failed request IRQ for APBT%d\n", 280 + adev->num); 281 + } 282 + } 283 + #endif 284 + 285 + static void apbt_enable_int(int n) 286 + { 287 + unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL); 288 + /* clear pending intr */ 289 + apbt_readl(n, APBTMR_N_EOI); 290 + ctrl &= ~APBTMR_CONTROL_INT; 291 + apbt_writel(n, ctrl, APBTMR_N_CONTROL); 292 + } 293 + 294 + static void apbt_disable_int(int n) 295 + { 296 + unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL); 297 + 298 + ctrl |= APBTMR_CONTROL_INT; 299 + apbt_writel(n, ctrl, APBTMR_N_CONTROL); 300 + } 301 + 302 + 303 + static int __init apbt_clockevent_register(void) 304 + { 305 + struct sfi_timer_table_entry *mtmr; 306 + struct apbt_dev *adev = &__get_cpu_var(cpu_apbt_dev); 307 + 308 + mtmr = sfi_get_mtmr(APBT_CLOCKEVENT0_NUM); 309 + if (mtmr == NULL) { 310 + printk(KERN_ERR "Failed to get MTMR %d from SFI\n", 311 + APBT_CLOCKEVENT0_NUM); 312 + return -ENODEV; 313 + } 314 + 315 + /* 316 + * We need to calculate the scaled math multiplication factor for 317 + * nanosecond to apbt tick conversion. 318 + * mult = (nsec/cycle)*2^APBT_SHIFT 319 + */ 320 + apbt_clockevent.mult = div_sc((unsigned long) mtmr->freq_hz 321 + , NSEC_PER_SEC, APBT_SHIFT); 322 + 323 + /* Calculate the min / max delta */ 324 + apbt_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, 325 + &apbt_clockevent); 326 + apbt_clockevent.min_delta_ns = clockevent_delta2ns( 327 + APBT_MIN_DELTA_USEC*apbt_freq, 328 + &apbt_clockevent); 329 + /* 330 + * Start apbt with the boot cpu mask and make it 331 + * global if not used for per cpu timer. 332 + */ 333 + apbt_clockevent.cpumask = cpumask_of(smp_processor_id()); 334 + adev->num = smp_processor_id(); 335 + memcpy(&adev->evt, &apbt_clockevent, sizeof(struct clock_event_device)); 336 + 337 + if (disable_apbt_percpu) { 338 + apbt_clockevent.rating = APBT_CLOCKEVENT_RATING - 100; 339 + global_clock_event = &adev->evt; 340 + printk(KERN_DEBUG "%s clockevent registered as global\n", 341 + global_clock_event->name); 342 + } 343 + 344 + if (request_irq(apbt_clockevent.irq, apbt_interrupt_handler, 345 + IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING, 346 + apbt_clockevent.name, adev)) { 347 + printk(KERN_ERR "Failed request IRQ for APBT%d\n", 348 + apbt_clockevent.irq); 349 + } 350 + 351 + clockevents_register_device(&adev->evt); 352 + /* Start APBT 0 interrupts */ 353 + apbt_enable_int(APBT_CLOCKEVENT0_NUM); 354 + 355 + sfi_free_mtmr(mtmr); 356 + return 0; 357 + } 358 + 359 + #ifdef CONFIG_SMP 360 + /* Should be called with per cpu */ 361 + void apbt_setup_secondary_clock(void) 362 + { 363 + struct apbt_dev *adev; 364 + struct clock_event_device *aevt; 365 + int cpu; 366 + 367 + /* Don't register boot CPU clockevent */ 368 + cpu = smp_processor_id(); 369 + if (cpu == boot_cpu_id) 370 + return; 371 + /* 372 + * We need to calculate the scaled math multiplication factor for 373 + * nanosecond to apbt tick conversion. 374 + * mult = (nsec/cycle)*2^APBT_SHIFT 375 + */ 376 + printk(KERN_INFO "Init per CPU clockevent %d\n", cpu); 377 + adev = &per_cpu(cpu_apbt_dev, cpu); 378 + aevt = &adev->evt; 379 + 380 + memcpy(aevt, &apbt_clockevent, sizeof(*aevt)); 381 + aevt->cpumask = cpumask_of(cpu); 382 + aevt->name = adev->name; 383 + aevt->mode = CLOCK_EVT_MODE_UNUSED; 384 + 385 + printk(KERN_INFO "Registering CPU %d clockevent device %s, mask %08x\n", 386 + cpu, aevt->name, *(u32 *)aevt->cpumask); 387 + 388 + apbt_setup_irq(adev); 389 + 390 + clockevents_register_device(aevt); 391 + 392 + apbt_enable_int(cpu); 393 + 394 + return; 395 + } 396 + 397 + /* 398 + * this notify handler process CPU hotplug events. in case of S0i3, nonboot 399 + * cpus are disabled/enabled frequently, for performance reasons, we keep the 400 + * per cpu timer irq registered so that we do need to do free_irq/request_irq. 401 + * 402 + * TODO: it might be more reliable to directly disable percpu clockevent device 403 + * without the notifier chain. currently, cpu 0 may get interrupts from other 404 + * cpu timers during the offline process due to the ordering of notification. 405 + * the extra interrupt is harmless. 406 + */ 407 + static int apbt_cpuhp_notify(struct notifier_block *n, 408 + unsigned long action, void *hcpu) 409 + { 410 + unsigned long cpu = (unsigned long)hcpu; 411 + struct apbt_dev *adev = &per_cpu(cpu_apbt_dev, cpu); 412 + 413 + switch (action & 0xf) { 414 + case CPU_DEAD: 415 + apbt_disable_int(cpu); 416 + if (system_state == SYSTEM_RUNNING) 417 + pr_debug("skipping APBT CPU %lu offline\n", cpu); 418 + else if (adev) { 419 + pr_debug("APBT clockevent for cpu %lu offline\n", cpu); 420 + free_irq(adev->irq, adev); 421 + } 422 + break; 423 + default: 424 + pr_debug(KERN_INFO "APBT notified %lu, no action\n", action); 425 + } 426 + return NOTIFY_OK; 427 + } 428 + 429 + static __init int apbt_late_init(void) 430 + { 431 + if (disable_apbt_percpu) 432 + return 0; 433 + /* This notifier should be called after workqueue is ready */ 434 + hotcpu_notifier(apbt_cpuhp_notify, -20); 435 + return 0; 436 + } 437 + fs_initcall(apbt_late_init); 438 + #else 439 + 440 + void apbt_setup_secondary_clock(void) {} 441 + 442 + #endif /* CONFIG_SMP */ 443 + 444 + static void apbt_set_mode(enum clock_event_mode mode, 445 + struct clock_event_device *evt) 446 + { 447 + unsigned long ctrl; 448 + uint64_t delta; 449 + int timer_num; 450 + struct apbt_dev *adev = EVT_TO_APBT_DEV(evt); 451 + 452 + timer_num = adev->num; 453 + pr_debug("%s CPU %d timer %d mode=%d\n", 454 + __func__, first_cpu(*evt->cpumask), timer_num, mode); 455 + 456 + switch (mode) { 457 + case CLOCK_EVT_MODE_PERIODIC: 458 + delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * apbt_clockevent.mult; 459 + delta >>= apbt_clockevent.shift; 460 + ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL); 461 + ctrl |= APBTMR_CONTROL_MODE_PERIODIC; 462 + apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); 463 + /* 464 + * DW APB p. 46, have to disable timer before load counter, 465 + * may cause sync problem. 466 + */ 467 + ctrl &= ~APBTMR_CONTROL_ENABLE; 468 + apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); 469 + udelay(1); 470 + pr_debug("Setting clock period %d for HZ %d\n", (int)delta, HZ); 471 + apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT); 472 + ctrl |= APBTMR_CONTROL_ENABLE; 473 + apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); 474 + break; 475 + /* APB timer does not have one-shot mode, use free running mode */ 476 + case CLOCK_EVT_MODE_ONESHOT: 477 + ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL); 478 + /* 479 + * set free running mode, this mode will let timer reload max 480 + * timeout which will give time (3min on 25MHz clock) to rearm 481 + * the next event, therefore emulate the one-shot mode. 482 + */ 483 + ctrl &= ~APBTMR_CONTROL_ENABLE; 484 + ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC; 485 + 486 + apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); 487 + /* write again to set free running mode */ 488 + apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); 489 + 490 + /* 491 + * DW APB p. 46, load counter with all 1s before starting free 492 + * running mode. 493 + */ 494 + apbt_writel(timer_num, ~0, APBTMR_N_LOAD_COUNT); 495 + ctrl &= ~APBTMR_CONTROL_INT; 496 + ctrl |= APBTMR_CONTROL_ENABLE; 497 + apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); 498 + break; 499 + 500 + case CLOCK_EVT_MODE_UNUSED: 501 + case CLOCK_EVT_MODE_SHUTDOWN: 502 + apbt_disable_int(timer_num); 503 + ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL); 504 + ctrl &= ~APBTMR_CONTROL_ENABLE; 505 + apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); 506 + break; 507 + 508 + case CLOCK_EVT_MODE_RESUME: 509 + apbt_enable_int(timer_num); 510 + break; 511 + } 512 + } 513 + 514 + static int apbt_next_event(unsigned long delta, 515 + struct clock_event_device *evt) 516 + { 517 + unsigned long ctrl; 518 + int timer_num; 519 + 520 + struct apbt_dev *adev = EVT_TO_APBT_DEV(evt); 521 + 522 + timer_num = adev->num; 523 + /* Disable timer */ 524 + ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL); 525 + ctrl &= ~APBTMR_CONTROL_ENABLE; 526 + apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); 527 + /* write new count */ 528 + apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT); 529 + ctrl |= APBTMR_CONTROL_ENABLE; 530 + apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); 531 + return 0; 532 + } 533 + 534 + /* 535 + * APB timer clock is not in sync with pclk on Langwell, which translates to 536 + * unreliable read value caused by sampling error. the error does not add up 537 + * overtime and only happens when sampling a 0 as a 1 by mistake. so the time 538 + * would go backwards. the following code is trying to prevent time traveling 539 + * backwards. little bit paranoid. 540 + */ 541 + static cycle_t apbt_read_clocksource(struct clocksource *cs) 542 + { 543 + unsigned long t0, t1, t2; 544 + static unsigned long last_read; 545 + 546 + bad_count: 547 + t1 = apbt_readl(phy_cs_timer_id, 548 + APBTMR_N_CURRENT_VALUE); 549 + t2 = apbt_readl(phy_cs_timer_id, 550 + APBTMR_N_CURRENT_VALUE); 551 + if (unlikely(t1 < t2)) { 552 + pr_debug("APBT: read current count error %lx:%lx:%lx\n", 553 + t1, t2, t2 - t1); 554 + goto bad_count; 555 + } 556 + /* 557 + * check against cached last read, makes sure time does not go back. 558 + * it could be a normal rollover but we will do tripple check anyway 559 + */ 560 + if (unlikely(t2 > last_read)) { 561 + /* check if we have a normal rollover */ 562 + unsigned long raw_intr_status = 563 + apbt_readl_reg(APBTMRS_RAW_INT_STATUS); 564 + /* 565 + * cs timer interrupt is masked but raw intr bit is set if 566 + * rollover occurs. then we read EOI reg to clear it. 567 + */ 568 + if (raw_intr_status & (1 << phy_cs_timer_id)) { 569 + apbt_readl(phy_cs_timer_id, APBTMR_N_EOI); 570 + goto out; 571 + } 572 + pr_debug("APB CS going back %lx:%lx:%lx ", 573 + t2, last_read, t2 - last_read); 574 + bad_count_x3: 575 + pr_debug(KERN_INFO "tripple check enforced\n"); 576 + t0 = apbt_readl(phy_cs_timer_id, 577 + APBTMR_N_CURRENT_VALUE); 578 + udelay(1); 579 + t1 = apbt_readl(phy_cs_timer_id, 580 + APBTMR_N_CURRENT_VALUE); 581 + udelay(1); 582 + t2 = apbt_readl(phy_cs_timer_id, 583 + APBTMR_N_CURRENT_VALUE); 584 + if ((t2 > t1) || (t1 > t0)) { 585 + printk(KERN_ERR "Error: APB CS tripple check failed\n"); 586 + goto bad_count_x3; 587 + } 588 + } 589 + out: 590 + last_read = t2; 591 + return (cycle_t)~t2; 592 + } 593 + 594 + static int apbt_clocksource_register(void) 595 + { 596 + u64 start, now; 597 + cycle_t t1; 598 + 599 + /* Start the counter, use timer 2 as source, timer 0/1 for event */ 600 + apbt_start_counter(phy_cs_timer_id); 601 + 602 + /* Verify whether apbt counter works */ 603 + t1 = apbt_read_clocksource(&clocksource_apbt); 604 + rdtscll(start); 605 + 606 + /* 607 + * We don't know the TSC frequency yet, but waiting for 608 + * 200000 TSC cycles is safe: 609 + * 4 GHz == 50us 610 + * 1 GHz == 200us 611 + */ 612 + do { 613 + rep_nop(); 614 + rdtscll(now); 615 + } while ((now - start) < 200000UL); 616 + 617 + /* APBT is the only always on clocksource, it has to work! */ 618 + if (t1 == apbt_read_clocksource(&clocksource_apbt)) 619 + panic("APBT counter not counting. APBT disabled\n"); 620 + 621 + /* 622 + * initialize and register APBT clocksource 623 + * convert that to ns/clock cycle 624 + * mult = (ns/c) * 2^APBT_SHIFT 625 + */ 626 + clocksource_apbt.mult = div_sc(MSEC_PER_SEC, 627 + (unsigned long) apbt_freq, APBT_SHIFT); 628 + clocksource_register(&clocksource_apbt); 629 + 630 + return 0; 631 + } 632 + 633 + /* 634 + * Early setup the APBT timer, only use timer 0 for booting then switch to 635 + * per CPU timer if possible. 636 + * returns 1 if per cpu apbt is setup 637 + * returns 0 if no per cpu apbt is chosen 638 + * panic if set up failed, this is the only platform timer on Moorestown. 639 + */ 640 + void __init apbt_time_init(void) 641 + { 642 + #ifdef CONFIG_SMP 643 + int i; 644 + struct sfi_timer_table_entry *p_mtmr; 645 + unsigned int percpu_timer; 646 + struct apbt_dev *adev; 647 + #endif 648 + 649 + if (apb_timer_block_enabled) 650 + return; 651 + apbt_set_mapping(); 652 + if (apbt_virt_address) { 653 + pr_debug("Found APBT version 0x%lx\n",\ 654 + apbt_readl_reg(APBTMRS_COMP_VERSION)); 655 + } else 656 + goto out_noapbt; 657 + /* 658 + * Read the frequency and check for a sane value, for ESL model 659 + * we extend the possible clock range to allow time scaling. 660 + */ 661 + 662 + if (apbt_freq < APBT_MIN_FREQ || apbt_freq > APBT_MAX_FREQ) { 663 + pr_debug("APBT has invalid freq 0x%llx\n", apbt_freq); 664 + goto out_noapbt; 665 + } 666 + if (apbt_clocksource_register()) { 667 + pr_debug("APBT has failed to register clocksource\n"); 668 + goto out_noapbt; 669 + } 670 + if (!apbt_clockevent_register()) 671 + apb_timer_block_enabled = 1; 672 + else { 673 + pr_debug("APBT has failed to register clockevent\n"); 674 + goto out_noapbt; 675 + } 676 + #ifdef CONFIG_SMP 677 + /* kernel cmdline disable apb timer, so we will use lapic timers */ 678 + if (disable_apbt_percpu) { 679 + printk(KERN_INFO "apbt: disabled per cpu timer\n"); 680 + return; 681 + } 682 + pr_debug("%s: %d CPUs online\n", __func__, num_online_cpus()); 683 + if (num_possible_cpus() <= sfi_mtimer_num) { 684 + percpu_timer = 1; 685 + apbt_num_timers_used = num_possible_cpus(); 686 + } else { 687 + percpu_timer = 0; 688 + apbt_num_timers_used = 1; 689 + adev = &per_cpu(cpu_apbt_dev, 0); 690 + adev->flags &= ~APBT_DEV_USED; 691 + } 692 + pr_debug("%s: %d APB timers used\n", __func__, apbt_num_timers_used); 693 + 694 + /* here we set up per CPU timer data structure */ 695 + apbt_devs = kzalloc(sizeof(struct apbt_dev) * apbt_num_timers_used, 696 + GFP_KERNEL); 697 + if (!apbt_devs) { 698 + printk(KERN_ERR "Failed to allocate APB timer devices\n"); 699 + return; 700 + } 701 + for (i = 0; i < apbt_num_timers_used; i++) { 702 + adev = &per_cpu(cpu_apbt_dev, i); 703 + adev->num = i; 704 + adev->cpu = i; 705 + p_mtmr = sfi_get_mtmr(i); 706 + if (p_mtmr) { 707 + adev->tick = p_mtmr->freq_hz; 708 + adev->irq = p_mtmr->irq; 709 + } else 710 + printk(KERN_ERR "Failed to get timer for cpu %d\n", i); 711 + adev->count = 0; 712 + sprintf(adev->name, "apbt%d", i); 713 + } 714 + #endif 715 + 716 + return; 717 + 718 + out_noapbt: 719 + apbt_clear_mapping(); 720 + apb_timer_block_enabled = 0; 721 + panic("failed to enable APB timer\n"); 722 + } 723 + 724 + static inline void apbt_disable(int n) 725 + { 726 + if (is_apbt_capable()) { 727 + unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL); 728 + ctrl &= ~APBTMR_CONTROL_ENABLE; 729 + apbt_writel(n, ctrl, APBTMR_N_CONTROL); 730 + } 731 + } 732 + 733 + /* called before apb_timer_enable, use early map */ 734 + unsigned long apbt_quick_calibrate() 735 + { 736 + int i, scale; 737 + u64 old, new; 738 + cycle_t t1, t2; 739 + unsigned long khz = 0; 740 + u32 loop, shift; 741 + 742 + apbt_set_mapping(); 743 + apbt_start_counter(phy_cs_timer_id); 744 + 745 + /* check if the timer can count down, otherwise return */ 746 + old = apbt_read_clocksource(&clocksource_apbt); 747 + i = 10000; 748 + while (--i) { 749 + if (old != apbt_read_clocksource(&clocksource_apbt)) 750 + break; 751 + } 752 + if (!i) 753 + goto failed; 754 + 755 + /* count 16 ms */ 756 + loop = (apbt_freq * 1000) << 4; 757 + 758 + /* restart the timer to ensure it won't get to 0 in the calibration */ 759 + apbt_start_counter(phy_cs_timer_id); 760 + 761 + old = apbt_read_clocksource(&clocksource_apbt); 762 + old += loop; 763 + 764 + t1 = __native_read_tsc(); 765 + 766 + do { 767 + new = apbt_read_clocksource(&clocksource_apbt); 768 + } while (new < old); 769 + 770 + t2 = __native_read_tsc(); 771 + 772 + shift = 5; 773 + if (unlikely(loop >> shift == 0)) { 774 + printk(KERN_INFO 775 + "APBT TSC calibration failed, not enough resolution\n"); 776 + return 0; 777 + } 778 + scale = (int)div_u64((t2 - t1), loop >> shift); 779 + khz = (scale * apbt_freq * 1000) >> shift; 780 + printk(KERN_INFO "TSC freq calculated by APB timer is %lu khz\n", khz); 781 + return khz; 782 + failed: 783 + return 0; 784 + }
+4 -4
arch/x86/kernel/apic/apic.c
··· 1390 1390 } 1391 1391 1392 1392 local_irq_save(flags); 1393 - mask_8259A(); 1393 + legacy_pic->mask_all(); 1394 1394 mask_IO_APIC_setup(ioapic_entries); 1395 1395 1396 1396 if (dmar_table_init_ret) ··· 1422 1422 nox2apic: 1423 1423 if (!ret) /* IR enabling failed */ 1424 1424 restore_IO_APIC_setup(ioapic_entries); 1425 - unmask_8259A(); 1425 + legacy_pic->restore_mask(); 1426 1426 local_irq_restore(flags); 1427 1427 1428 1428 out: ··· 2018 2018 } 2019 2019 2020 2020 mask_IO_APIC_setup(ioapic_entries); 2021 - mask_8259A(); 2021 + legacy_pic->mask_all(); 2022 2022 } 2023 2023 2024 2024 if (x2apic_mode) ··· 2062 2062 2063 2063 if (intr_remapping_enabled) { 2064 2064 reenable_intr_remapping(x2apic_mode); 2065 - unmask_8259A(); 2065 + legacy_pic->restore_mask(); 2066 2066 restore_IO_APIC_setup(ioapic_entries); 2067 2067 free_ioapic_entries(ioapic_entries); 2068 2068 }
+53 -33
arch/x86/kernel/apic/io_apic.c
··· 143 143 static struct irq_cfg irq_cfgx[NR_IRQS]; 144 144 #endif 145 145 146 - void __init io_apic_disable_legacy(void) 147 - { 148 - nr_legacy_irqs = 0; 149 - nr_irqs_gsi = 0; 150 - } 151 - 152 146 int __init arch_early_irq_init(void) 153 147 { 154 148 struct irq_cfg *cfg; ··· 150 156 int count; 151 157 int node; 152 158 int i; 159 + 160 + if (!legacy_pic->nr_legacy_irqs) { 161 + nr_irqs_gsi = 0; 162 + io_apic_irqs = ~0UL; 163 + } 153 164 154 165 cfg = irq_cfgx; 155 166 count = ARRAY_SIZE(irq_cfgx); ··· 169 170 * For legacy IRQ's, start with assigning irq0 to irq15 to 170 171 * IRQ0_VECTOR to IRQ15_VECTOR on cpu 0. 171 172 */ 172 - if (i < nr_legacy_irqs) { 173 + if (i < legacy_pic->nr_legacy_irqs) { 173 174 cfg[i].vector = IRQ0_VECTOR + i; 174 175 cpumask_set_cpu(0, cfg[i].domain); 175 176 } ··· 851 852 */ 852 853 static int EISA_ELCR(unsigned int irq) 853 854 { 854 - if (irq < nr_legacy_irqs) { 855 + if (irq < legacy_pic->nr_legacy_irqs) { 855 856 unsigned int port = 0x4d0 + (irq >> 3); 856 857 return (inb(port) >> (irq & 7)) & 1; 857 858 } ··· 1438 1439 * controllers like 8259. Now that IO-APIC can handle this irq, update 1439 1440 * the cfg->domain. 1440 1441 */ 1441 - if (irq < nr_legacy_irqs && cpumask_test_cpu(0, cfg->domain)) 1442 + if (irq < legacy_pic->nr_legacy_irqs && cpumask_test_cpu(0, cfg->domain)) 1442 1443 apic->vector_allocation_domain(0, cfg->domain); 1443 1444 1444 1445 if (assign_irq_vector(irq, cfg, apic->target_cpus())) ··· 1462 1463 } 1463 1464 1464 1465 ioapic_register_intr(irq, desc, trigger); 1465 - if (irq < nr_legacy_irqs) 1466 - disable_8259A_irq(irq); 1466 + if (irq < legacy_pic->nr_legacy_irqs) 1467 + legacy_pic->chip->mask(irq); 1467 1468 1468 1469 ioapic_write_entry(apic_id, pin, entry); 1469 1470 } ··· 1872 1873 unsigned int v; 1873 1874 unsigned long flags; 1874 1875 1875 - if (!nr_legacy_irqs) 1876 + if (!legacy_pic->nr_legacy_irqs) 1876 1877 return; 1877 1878 1878 1879 printk(KERN_DEBUG "\nprinting PIC contents\n"); ··· 1956 1957 nr_ioapic_registers[apic] = reg_01.bits.entries+1; 1957 1958 } 1958 1959 1959 - if (!nr_legacy_irqs) 1960 + if (!legacy_pic->nr_legacy_irqs) 1960 1961 return; 1961 1962 1962 1963 for(apic = 0; apic < nr_ioapics; apic++) { ··· 2013 2014 */ 2014 2015 clear_IO_APIC(); 2015 2016 2016 - if (!nr_legacy_irqs) 2017 + if (!legacy_pic->nr_legacy_irqs) 2017 2018 return; 2018 2019 2019 2020 /* ··· 2246 2247 struct irq_cfg *cfg; 2247 2248 2248 2249 raw_spin_lock_irqsave(&ioapic_lock, flags); 2249 - if (irq < nr_legacy_irqs) { 2250 - disable_8259A_irq(irq); 2251 - if (i8259A_irq_pending(irq)) 2250 + if (irq < legacy_pic->nr_legacy_irqs) { 2251 + legacy_pic->chip->mask(irq); 2252 + if (legacy_pic->irq_pending(irq)) 2252 2253 was_pending = 1; 2253 2254 } 2254 2255 cfg = irq_cfg(irq); ··· 2781 2782 * so default to an old-fashioned 8259 2782 2783 * interrupt if we can.. 2783 2784 */ 2784 - if (irq < nr_legacy_irqs) 2785 - make_8259A_irq(irq); 2785 + if (irq < legacy_pic->nr_legacy_irqs) 2786 + legacy_pic->make_irq(irq); 2786 2787 else 2787 2788 /* Strange. Oh, well.. */ 2788 2789 desc->chip = &no_irq_chip; ··· 2939 2940 /* 2940 2941 * get/set the timer IRQ vector: 2941 2942 */ 2942 - disable_8259A_irq(0); 2943 + legacy_pic->chip->mask(0); 2943 2944 assign_irq_vector(0, cfg, apic->target_cpus()); 2944 2945 2945 2946 /* ··· 2952 2953 * automatically. 2953 2954 */ 2954 2955 apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); 2955 - init_8259A(1); 2956 + legacy_pic->init(1); 2956 2957 #ifdef CONFIG_X86_32 2957 2958 { 2958 2959 unsigned int ver; ··· 3011 3012 if (timer_irq_works()) { 3012 3013 if (nmi_watchdog == NMI_IO_APIC) { 3013 3014 setup_nmi(); 3014 - enable_8259A_irq(0); 3015 + legacy_pic->chip->unmask(0); 3015 3016 } 3016 3017 if (disable_timer_pin_1 > 0) 3017 3018 clear_IO_APIC_pin(0, pin1); ··· 3034 3035 */ 3035 3036 replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2); 3036 3037 setup_timer_IRQ0_pin(apic2, pin2, cfg->vector); 3037 - enable_8259A_irq(0); 3038 + legacy_pic->chip->unmask(0); 3038 3039 if (timer_irq_works()) { 3039 3040 apic_printk(APIC_QUIET, KERN_INFO "....... works.\n"); 3040 3041 timer_through_8259 = 1; 3041 3042 if (nmi_watchdog == NMI_IO_APIC) { 3042 - disable_8259A_irq(0); 3043 + legacy_pic->chip->mask(0); 3043 3044 setup_nmi(); 3044 - enable_8259A_irq(0); 3045 + legacy_pic->chip->unmask(0); 3045 3046 } 3046 3047 goto out; 3047 3048 } ··· 3049 3050 * Cleanup, just in case ... 3050 3051 */ 3051 3052 local_irq_disable(); 3052 - disable_8259A_irq(0); 3053 + legacy_pic->chip->mask(0); 3053 3054 clear_IO_APIC_pin(apic2, pin2); 3054 3055 apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n"); 3055 3056 } ··· 3068 3069 3069 3070 lapic_register_intr(0, desc); 3070 3071 apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */ 3071 - enable_8259A_irq(0); 3072 + legacy_pic->chip->unmask(0); 3072 3073 3073 3074 if (timer_irq_works()) { 3074 3075 apic_printk(APIC_QUIET, KERN_INFO "..... works.\n"); 3075 3076 goto out; 3076 3077 } 3077 3078 local_irq_disable(); 3078 - disable_8259A_irq(0); 3079 + legacy_pic->chip->mask(0); 3079 3080 apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector); 3080 3081 apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n"); 3081 3082 3082 3083 apic_printk(APIC_QUIET, KERN_INFO 3083 3084 "...trying to set up timer as ExtINT IRQ...\n"); 3084 3085 3085 - init_8259A(0); 3086 - make_8259A_irq(0); 3086 + legacy_pic->init(0); 3087 + legacy_pic->make_irq(0); 3087 3088 apic_write(APIC_LVT0, APIC_DM_EXTINT); 3088 3089 3089 3090 unlock_ExtINT_logic(); ··· 3125 3126 /* 3126 3127 * calling enable_IO_APIC() is moved to setup_local_APIC for BP 3127 3128 */ 3128 - io_apic_irqs = nr_legacy_irqs ? ~PIC_IRQS : ~0UL; 3129 + io_apic_irqs = legacy_pic->nr_legacy_irqs ? ~PIC_IRQS : ~0UL; 3129 3130 3130 3131 apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n"); 3131 3132 /* ··· 3136 3137 sync_Arb_IDs(); 3137 3138 setup_IO_APIC_irqs(); 3138 3139 init_IO_APIC_traps(); 3139 - if (nr_legacy_irqs) 3140 + if (legacy_pic->nr_legacy_irqs) 3140 3141 check_timer(); 3141 3142 } 3142 3143 ··· 3927 3928 /* 3928 3929 * IRQs < 16 are already in the irq_2_pin[] map 3929 3930 */ 3930 - if (irq >= nr_legacy_irqs) { 3931 + if (irq >= legacy_pic->nr_legacy_irqs) { 3931 3932 cfg = desc->chip_data; 3932 3933 if (add_pin_to_irq_node_nopanic(cfg, node, ioapic, pin)) { 3933 3934 printk(KERN_INFO "can not add pin %d for irq %d\n", ··· 4300 4301 mp_gsi_routing[idx].gsi_base, mp_gsi_routing[idx].gsi_end); 4301 4302 4302 4303 nr_ioapics++; 4304 + } 4305 + 4306 + /* Enable IOAPIC early just for system timer */ 4307 + void __init pre_init_apic_IRQ0(void) 4308 + { 4309 + struct irq_cfg *cfg; 4310 + struct irq_desc *desc; 4311 + 4312 + printk(KERN_INFO "Early APIC setup for system timer0\n"); 4313 + #ifndef CONFIG_SMP 4314 + phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); 4315 + #endif 4316 + desc = irq_to_desc_alloc_node(0, 0); 4317 + 4318 + setup_local_APIC(); 4319 + 4320 + cfg = irq_cfg(0); 4321 + add_pin_to_irq_node(cfg, 0, 0, 0); 4322 + set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge"); 4323 + 4324 + setup_IO_APIC_irq(0, 0, 0, desc, 0, 0); 4303 4325 }
+1 -1
arch/x86/kernel/apic/nmi.c
··· 177 177 error: 178 178 if (nmi_watchdog == NMI_IO_APIC) { 179 179 if (!timer_through_8259) 180 - disable_8259A_irq(0); 180 + legacy_pic->chip->mask(0); 181 181 on_each_cpu(__acpi_nmi_disable, NULL, 1); 182 182 } 183 183
+1
arch/x86/kernel/apic/numaq_32.c
··· 277 277 x86_init.mpparse.mpc_oem_pci_bus = mpc_oem_pci_bus; 278 278 x86_init.mpparse.mpc_oem_bus_info = mpc_oem_bus_info; 279 279 x86_init.timers.tsc_pre_init = numaq_tsc_init; 280 + x86_init.pci.init = pci_numaq_init; 280 281 } 281 282 } 282 283
+57 -7
arch/x86/kernel/i8259.c
··· 34 34 static int i8259A_auto_eoi; 35 35 DEFINE_RAW_SPINLOCK(i8259A_lock); 36 36 static void mask_and_ack_8259A(unsigned int); 37 + static void mask_8259A(void); 38 + static void unmask_8259A(void); 39 + static void disable_8259A_irq(unsigned int irq); 40 + static void enable_8259A_irq(unsigned int irq); 41 + static void init_8259A(int auto_eoi); 42 + static int i8259A_irq_pending(unsigned int irq); 37 43 38 44 struct irq_chip i8259A_chip = { 39 45 .name = "XT-PIC", ··· 69 63 */ 70 64 unsigned long io_apic_irqs; 71 65 72 - void disable_8259A_irq(unsigned int irq) 66 + static void disable_8259A_irq(unsigned int irq) 73 67 { 74 68 unsigned int mask = 1 << irq; 75 69 unsigned long flags; ··· 83 77 raw_spin_unlock_irqrestore(&i8259A_lock, flags); 84 78 } 85 79 86 - void enable_8259A_irq(unsigned int irq) 80 + static void enable_8259A_irq(unsigned int irq) 87 81 { 88 82 unsigned int mask = ~(1 << irq); 89 83 unsigned long flags; ··· 97 91 raw_spin_unlock_irqrestore(&i8259A_lock, flags); 98 92 } 99 93 100 - int i8259A_irq_pending(unsigned int irq) 94 + static int i8259A_irq_pending(unsigned int irq) 101 95 { 102 96 unsigned int mask = 1<<irq; 103 97 unsigned long flags; ··· 113 107 return ret; 114 108 } 115 109 116 - void make_8259A_irq(unsigned int irq) 110 + static void make_8259A_irq(unsigned int irq) 117 111 { 118 112 disable_irq_nosync(irq); 119 113 io_apic_irqs &= ~(1<<irq); ··· 287 281 288 282 device_initcall(i8259A_init_sysfs); 289 283 290 - void mask_8259A(void) 284 + static void mask_8259A(void) 291 285 { 292 286 unsigned long flags; 293 287 ··· 299 293 raw_spin_unlock_irqrestore(&i8259A_lock, flags); 300 294 } 301 295 302 - void unmask_8259A(void) 296 + static void unmask_8259A(void) 303 297 { 304 298 unsigned long flags; 305 299 ··· 311 305 raw_spin_unlock_irqrestore(&i8259A_lock, flags); 312 306 } 313 307 314 - void init_8259A(int auto_eoi) 308 + static void init_8259A(int auto_eoi) 315 309 { 316 310 unsigned long flags; 317 311 ··· 364 358 365 359 raw_spin_unlock_irqrestore(&i8259A_lock, flags); 366 360 } 361 + 362 + /* 363 + * make i8259 a driver so that we can select pic functions at run time. the goal 364 + * is to make x86 binary compatible among pc compatible and non-pc compatible 365 + * platforms, such as x86 MID. 366 + */ 367 + 368 + static void legacy_pic_noop(void) { }; 369 + static void legacy_pic_uint_noop(unsigned int unused) { }; 370 + static void legacy_pic_int_noop(int unused) { }; 371 + 372 + static struct irq_chip dummy_pic_chip = { 373 + .name = "dummy pic", 374 + .mask = legacy_pic_uint_noop, 375 + .unmask = legacy_pic_uint_noop, 376 + .disable = legacy_pic_uint_noop, 377 + .mask_ack = legacy_pic_uint_noop, 378 + }; 379 + static int legacy_pic_irq_pending_noop(unsigned int irq) 380 + { 381 + return 0; 382 + } 383 + 384 + struct legacy_pic null_legacy_pic = { 385 + .nr_legacy_irqs = 0, 386 + .chip = &dummy_pic_chip, 387 + .mask_all = legacy_pic_noop, 388 + .restore_mask = legacy_pic_noop, 389 + .init = legacy_pic_int_noop, 390 + .irq_pending = legacy_pic_irq_pending_noop, 391 + .make_irq = legacy_pic_uint_noop, 392 + }; 393 + 394 + struct legacy_pic default_legacy_pic = { 395 + .nr_legacy_irqs = NR_IRQS_LEGACY, 396 + .chip = &i8259A_chip, 397 + .mask_all = mask_8259A, 398 + .restore_mask = unmask_8259A, 399 + .init = init_8259A, 400 + .irq_pending = i8259A_irq_pending, 401 + .make_irq = make_8259A_irq, 402 + }; 403 + 404 + struct legacy_pic *legacy_pic = &default_legacy_pic;
+3 -6
arch/x86/kernel/irqinit.c
··· 99 99 return 0; 100 100 } 101 101 102 - /* Number of legacy interrupts */ 103 - int nr_legacy_irqs __read_mostly = NR_IRQS_LEGACY; 104 - 105 102 void __init init_ISA_irqs(void) 106 103 { 107 104 int i; ··· 106 109 #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC) 107 110 init_bsp_APIC(); 108 111 #endif 109 - init_8259A(0); 112 + legacy_pic->init(0); 110 113 111 114 /* 112 115 * 16 old-style INTA-cycle interrupts: 113 116 */ 114 - for (i = 0; i < NR_IRQS_LEGACY; i++) { 117 + for (i = 0; i < legacy_pic->nr_legacy_irqs; i++) { 115 118 struct irq_desc *desc = irq_to_desc(i); 116 119 117 120 desc->status = IRQ_DISABLED; ··· 135 138 * then this vector space can be freed and re-used dynamically as the 136 139 * irq's migrate etc. 137 140 */ 138 - for (i = 0; i < nr_legacy_irqs; i++) 141 + for (i = 0; i < legacy_pic->nr_legacy_irqs; i++) 139 142 per_cpu(vector_irq, 0)[IRQ0_VECTOR + i] = i; 140 143 141 144 x86_init.irqs.intr_init();
+216
arch/x86/kernel/mrst.c
··· 10 10 * of the License. 11 11 */ 12 12 #include <linux/init.h> 13 + #include <linux/kernel.h> 14 + #include <linux/sfi.h> 15 + #include <linux/irq.h> 16 + #include <linux/module.h> 13 17 14 18 #include <asm/setup.h> 19 + #include <asm/mpspec_def.h> 20 + #include <asm/hw_irq.h> 21 + #include <asm/apic.h> 22 + #include <asm/io_apic.h> 23 + #include <asm/mrst.h> 24 + #include <asm/io.h> 25 + #include <asm/i8259.h> 26 + #include <asm/apb_timer.h> 27 + 28 + static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM]; 29 + static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM]; 30 + int sfi_mtimer_num; 31 + 32 + struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX]; 33 + EXPORT_SYMBOL_GPL(sfi_mrtc_array); 34 + int sfi_mrtc_num; 35 + 36 + static inline void assign_to_mp_irq(struct mpc_intsrc *m, 37 + struct mpc_intsrc *mp_irq) 38 + { 39 + memcpy(mp_irq, m, sizeof(struct mpc_intsrc)); 40 + } 41 + 42 + static inline int mp_irq_cmp(struct mpc_intsrc *mp_irq, 43 + struct mpc_intsrc *m) 44 + { 45 + return memcmp(mp_irq, m, sizeof(struct mpc_intsrc)); 46 + } 47 + 48 + static void save_mp_irq(struct mpc_intsrc *m) 49 + { 50 + int i; 51 + 52 + for (i = 0; i < mp_irq_entries; i++) { 53 + if (!mp_irq_cmp(&mp_irqs[i], m)) 54 + return; 55 + } 56 + 57 + assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]); 58 + if (++mp_irq_entries == MAX_IRQ_SOURCES) 59 + panic("Max # of irq sources exceeded!!\n"); 60 + } 61 + 62 + /* parse all the mtimer info to a static mtimer array */ 63 + static int __init sfi_parse_mtmr(struct sfi_table_header *table) 64 + { 65 + struct sfi_table_simple *sb; 66 + struct sfi_timer_table_entry *pentry; 67 + struct mpc_intsrc mp_irq; 68 + int totallen; 69 + 70 + sb = (struct sfi_table_simple *)table; 71 + if (!sfi_mtimer_num) { 72 + sfi_mtimer_num = SFI_GET_NUM_ENTRIES(sb, 73 + struct sfi_timer_table_entry); 74 + pentry = (struct sfi_timer_table_entry *) sb->pentry; 75 + totallen = sfi_mtimer_num * sizeof(*pentry); 76 + memcpy(sfi_mtimer_array, pentry, totallen); 77 + } 78 + 79 + printk(KERN_INFO "SFI: MTIMER info (num = %d):\n", sfi_mtimer_num); 80 + pentry = sfi_mtimer_array; 81 + for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) { 82 + printk(KERN_INFO "timer[%d]: paddr = 0x%08x, freq = %dHz," 83 + " irq = %d\n", totallen, (u32)pentry->phys_addr, 84 + pentry->freq_hz, pentry->irq); 85 + if (!pentry->irq) 86 + continue; 87 + mp_irq.type = MP_IOAPIC; 88 + mp_irq.irqtype = mp_INT; 89 + /* triggering mode edge bit 2-3, active high polarity bit 0-1 */ 90 + mp_irq.irqflag = 5; 91 + mp_irq.srcbus = 0; 92 + mp_irq.srcbusirq = pentry->irq; /* IRQ */ 93 + mp_irq.dstapic = MP_APIC_ALL; 94 + mp_irq.dstirq = pentry->irq; 95 + save_mp_irq(&mp_irq); 96 + } 97 + 98 + return 0; 99 + } 100 + 101 + struct sfi_timer_table_entry *sfi_get_mtmr(int hint) 102 + { 103 + int i; 104 + if (hint < sfi_mtimer_num) { 105 + if (!sfi_mtimer_usage[hint]) { 106 + pr_debug("hint taken for timer %d irq %d\n",\ 107 + hint, sfi_mtimer_array[hint].irq); 108 + sfi_mtimer_usage[hint] = 1; 109 + return &sfi_mtimer_array[hint]; 110 + } 111 + } 112 + /* take the first timer available */ 113 + for (i = 0; i < sfi_mtimer_num;) { 114 + if (!sfi_mtimer_usage[i]) { 115 + sfi_mtimer_usage[i] = 1; 116 + return &sfi_mtimer_array[i]; 117 + } 118 + i++; 119 + } 120 + return NULL; 121 + } 122 + 123 + void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr) 124 + { 125 + int i; 126 + for (i = 0; i < sfi_mtimer_num;) { 127 + if (mtmr->irq == sfi_mtimer_array[i].irq) { 128 + sfi_mtimer_usage[i] = 0; 129 + return; 130 + } 131 + i++; 132 + } 133 + } 134 + 135 + /* parse all the mrtc info to a global mrtc array */ 136 + int __init sfi_parse_mrtc(struct sfi_table_header *table) 137 + { 138 + struct sfi_table_simple *sb; 139 + struct sfi_rtc_table_entry *pentry; 140 + struct mpc_intsrc mp_irq; 141 + 142 + int totallen; 143 + 144 + sb = (struct sfi_table_simple *)table; 145 + if (!sfi_mrtc_num) { 146 + sfi_mrtc_num = SFI_GET_NUM_ENTRIES(sb, 147 + struct sfi_rtc_table_entry); 148 + pentry = (struct sfi_rtc_table_entry *)sb->pentry; 149 + totallen = sfi_mrtc_num * sizeof(*pentry); 150 + memcpy(sfi_mrtc_array, pentry, totallen); 151 + } 152 + 153 + printk(KERN_INFO "SFI: RTC info (num = %d):\n", sfi_mrtc_num); 154 + pentry = sfi_mrtc_array; 155 + for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) { 156 + printk(KERN_INFO "RTC[%d]: paddr = 0x%08x, irq = %d\n", 157 + totallen, (u32)pentry->phys_addr, pentry->irq); 158 + mp_irq.type = MP_IOAPIC; 159 + mp_irq.irqtype = mp_INT; 160 + mp_irq.irqflag = 0; 161 + mp_irq.srcbus = 0; 162 + mp_irq.srcbusirq = pentry->irq; /* IRQ */ 163 + mp_irq.dstapic = MP_APIC_ALL; 164 + mp_irq.dstirq = pentry->irq; 165 + save_mp_irq(&mp_irq); 166 + } 167 + return 0; 168 + } 169 + 170 + /* 171 + * the secondary clock in Moorestown can be APBT or LAPIC clock, default to 172 + * APBT but cmdline option can also override it. 173 + */ 174 + static void __cpuinit mrst_setup_secondary_clock(void) 175 + { 176 + /* restore default lapic clock if disabled by cmdline */ 177 + if (disable_apbt_percpu) 178 + return setup_secondary_APIC_clock(); 179 + apbt_setup_secondary_clock(); 180 + } 181 + 182 + static unsigned long __init mrst_calibrate_tsc(void) 183 + { 184 + unsigned long flags, fast_calibrate; 185 + 186 + local_irq_save(flags); 187 + fast_calibrate = apbt_quick_calibrate(); 188 + local_irq_restore(flags); 189 + 190 + if (fast_calibrate) 191 + return fast_calibrate; 192 + 193 + return 0; 194 + } 195 + 196 + void __init mrst_time_init(void) 197 + { 198 + sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr); 199 + pre_init_apic_IRQ0(); 200 + apbt_time_init(); 201 + } 202 + 203 + void __init mrst_rtc_init(void) 204 + { 205 + sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc); 206 + } 207 + 208 + /* 209 + * if we use per cpu apb timer, the bootclock already setup. if we use lapic 210 + * timer and one apbt timer for broadcast, we need to set up lapic boot clock. 211 + */ 212 + static void __init mrst_setup_boot_clock(void) 213 + { 214 + pr_info("%s: per cpu apbt flag %d \n", __func__, disable_apbt_percpu); 215 + if (disable_apbt_percpu) 216 + setup_boot_APIC_clock(); 217 + }; 15 218 16 219 /* 17 220 * Moorestown specific x86_init function overrides and early setup ··· 224 21 { 225 22 x86_init.resources.probe_roms = x86_init_noop; 226 23 x86_init.resources.reserve_resources = x86_init_noop; 24 + 25 + x86_init.timers.timer_init = mrst_time_init; 26 + x86_init.timers.setup_percpu_clockev = mrst_setup_boot_clock; 27 + 28 + x86_init.irqs.pre_vector_init = x86_init_noop; 29 + 30 + x86_cpuinit.setup_percpu_clockev = mrst_setup_secondary_clock; 31 + 32 + x86_platform.calibrate_tsc = mrst_calibrate_tsc; 33 + x86_init.pci.init = pci_mrst_init; 34 + x86_init.pci.fixup_irqs = x86_init_noop; 35 + 36 + legacy_pic = &null_legacy_pic; 227 37 }
+7 -3
arch/x86/kernel/olpc.c
··· 17 17 #include <linux/spinlock.h> 18 18 #include <linux/io.h> 19 19 #include <linux/string.h> 20 + 20 21 #include <asm/geode.h> 22 + #include <asm/setup.h> 21 23 #include <asm/olpc.h> 22 24 23 25 #ifdef CONFIG_OPEN_FIRMWARE ··· 245 243 olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, 246 244 (unsigned char *) &olpc_platform_info.ecver, 1); 247 245 248 - /* check to see if the VSA exists */ 249 - if (cs5535_has_vsa2()) 250 - olpc_platform_info.flags |= OLPC_F_VSA; 246 + #ifdef CONFIG_PCI_OLPC 247 + /* If the VSA exists let it emulate PCI, if not emulate in kernel */ 248 + if (!cs5535_has_vsa2()) 249 + x86_init.pci.arch_init = pci_olpc_init; 250 + #endif 251 251 252 252 printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n", 253 253 ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
+7 -2
arch/x86/kernel/smpboot.c
··· 48 48 #include <linux/err.h> 49 49 #include <linux/nmi.h> 50 50 #include <linux/tboot.h> 51 + #include <linux/stackprotector.h> 51 52 52 53 #include <asm/acpi.h> 53 54 #include <asm/desc.h> ··· 68 67 #include <linux/mc146818rtc.h> 69 68 70 69 #include <asm/smpboot_hooks.h> 70 + #include <asm/i8259.h> 71 71 72 72 #ifdef CONFIG_X86_32 73 73 u8 apicid_2_node[MAX_APICID]; ··· 293 291 check_tsc_sync_target(); 294 292 295 293 if (nmi_watchdog == NMI_IO_APIC) { 296 - disable_8259A_irq(0); 294 + legacy_pic->chip->mask(0); 297 295 enable_NMI_through_LVT0(); 298 - enable_8259A_irq(0); 296 + legacy_pic->chip->unmask(0); 299 297 } 300 298 301 299 #ifdef CONFIG_X86_32 ··· 330 328 331 329 /* enable local interrupts */ 332 330 local_irq_enable(); 331 + 332 + /* to prevent fake stack check failure in clock setup */ 333 + boot_init_stack_canary(); 333 334 334 335 x86_cpuinit.setup_percpu_clockev(); 335 336
+11 -10
arch/x86/kernel/visws_quirks.c
··· 49 49 char visws_board_type = -1; 50 50 char visws_board_rev = -1; 51 51 52 - int is_visws_box(void) 53 - { 54 - return visws_board_type >= 0; 55 - } 56 - 57 52 static void __init visws_time_init(void) 58 53 { 59 54 printk(KERN_INFO "Starting Cobalt Timer system clock\n"); ··· 237 242 x86_init.irqs.pre_vector_init = visws_pre_intr_init; 238 243 x86_init.irqs.trap_init = visws_trap_init; 239 244 x86_init.timers.timer_init = visws_time_init; 245 + x86_init.pci.init = pci_visws_init; 246 + x86_init.pci.init_irq = x86_init_noop; 240 247 241 248 /* 242 249 * Install reboot quirks: ··· 505 508 */ 506 509 static unsigned int startup_piix4_master_irq(unsigned int irq) 507 510 { 508 - init_8259A(0); 511 + legacy_pic->init(0); 509 512 510 513 return startup_cobalt_irq(irq); 511 514 } ··· 529 532 530 533 static struct irq_chip piix4_virtual_irq_type = { 531 534 .name = "PIIX4-virtual", 532 - .shutdown = disable_8259A_irq, 533 - .enable = enable_8259A_irq, 534 - .disable = disable_8259A_irq, 535 535 }; 536 536 537 537 ··· 603 609 handle_IRQ_event(realirq, desc->action); 604 610 605 611 if (!(desc->status & IRQ_DISABLED)) 606 - enable_8259A_irq(realirq); 612 + legacy_pic->chip->unmask(realirq); 607 613 608 614 return IRQ_HANDLED; 609 615 ··· 622 628 .name = "cascade", 623 629 }; 624 630 631 + static inline void set_piix4_virtual_irq_type(void) 632 + { 633 + piix4_virtual_irq_type.shutdown = i8259A_chip.mask; 634 + piix4_virtual_irq_type.enable = i8259A_chip.unmask; 635 + piix4_virtual_irq_type.disable = i8259A_chip.mask; 636 + } 625 637 626 638 void init_VISWS_APIC_irqs(void) 627 639 { ··· 653 653 desc->chip = &piix4_master_irq_type; 654 654 } 655 655 else if (i < CO_IRQ_APIC0) { 656 + set_piix4_virtual_irq_type(); 656 657 desc->chip = &piix4_virtual_irq_type; 657 658 } 658 659 else if (IS_CO_APIC(i)) {
+8
arch/x86/kernel/x86_init.c
··· 4 4 * For licencing details see kernel-base/COPYING 5 5 */ 6 6 #include <linux/init.h> 7 + #include <linux/ioport.h> 7 8 8 9 #include <asm/bios_ebda.h> 9 10 #include <asm/paravirt.h> 11 + #include <asm/pci_x86.h> 10 12 #include <asm/mpspec.h> 11 13 #include <asm/setup.h> 12 14 #include <asm/apic.h> ··· 71 69 72 70 .iommu = { 73 71 .iommu_init = iommu_init_noop, 72 + }, 73 + 74 + .pci = { 75 + .init = x86_default_pci_init, 76 + .init_irq = x86_default_pci_init_irq, 77 + .fixup_irqs = x86_default_pci_fixup_irqs, 74 78 }, 75 79 }; 76 80
+2
arch/x86/pci/Makefile
··· 13 13 14 14 obj-$(CONFIG_X86_NUMAQ) += numaq_32.o 15 15 16 + obj-$(CONFIG_X86_MRST) += mrst.o 17 + 16 18 obj-y += common.o early.o 17 19 obj-y += amd_bus.o bus_numa.o 18 20
+2 -5
arch/x86/pci/acpi.c
··· 298 298 { 299 299 struct pci_dev *dev = NULL; 300 300 301 - if (pcibios_scanned) 302 - return 0; 303 - 304 301 if (acpi_noirq) 305 - return 0; 302 + return -ENODEV; 306 303 307 304 printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); 308 305 acpi_irq_penalty_init(); 309 - pcibios_scanned++; 310 306 pcibios_enable_irq = acpi_pci_irq_enable; 311 307 pcibios_disable_irq = acpi_pci_irq_disable; 308 + x86_init.pci.init_irq = x86_init_noop; 312 309 313 310 if (pci_routeirq) { 314 311 /*
-6
arch/x86/pci/common.c
··· 72 72 }; 73 73 74 74 /* 75 - * legacy, numa, and acpi all want to call pcibios_scan_root 76 - * from their initcalls. This flag prevents that. 77 - */ 78 - int pcibios_scanned; 79 - 80 - /* 81 75 * This interrupt-safe spinlock protects all accesses to PCI 82 76 * configuration space. 83 77 */
+4 -4
arch/x86/pci/init.c
··· 1 1 #include <linux/pci.h> 2 2 #include <linux/init.h> 3 3 #include <asm/pci_x86.h> 4 + #include <asm/x86_init.h> 4 5 5 6 /* arch_initcall has too random ordering, so call the initializers 6 7 in the right sequence from here. */ ··· 16 15 if (!(pci_probe & PCI_PROBE_NOEARLY)) 17 16 pci_mmcfg_early_init(); 18 17 19 - #ifdef CONFIG_PCI_OLPC 20 - if (!pci_olpc_init()) 21 - return 0; /* skip additional checks if it's an XO */ 22 - #endif 18 + if (x86_init.pci.arch_init && !x86_init.pci.arch_init()) 19 + return 0; 20 + 23 21 #ifdef CONFIG_PCI_BIOS 24 22 pci_pcbios_init(); 25 23 #endif
+6 -10
arch/x86/pci/irq.c
··· 53 53 int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device); 54 54 }; 55 55 56 - int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; 56 + int (*pcibios_enable_irq)(struct pci_dev *dev) = pirq_enable_irq; 57 57 void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL; 58 58 59 59 /* ··· 1018 1018 return 1; 1019 1019 } 1020 1020 1021 - static void __init pcibios_fixup_irqs(void) 1021 + void __init pcibios_fixup_irqs(void) 1022 1022 { 1023 1023 struct pci_dev *dev = NULL; 1024 1024 u8 pin; ··· 1112 1112 { } 1113 1113 }; 1114 1114 1115 - int __init pcibios_irq_init(void) 1115 + void __init pcibios_irq_init(void) 1116 1116 { 1117 1117 DBG(KERN_DEBUG "PCI: IRQ init\n"); 1118 1118 1119 - if (pcibios_enable_irq || raw_pci_ops == NULL) 1120 - return 0; 1119 + if (raw_pci_ops == NULL) 1120 + return; 1121 1121 1122 1122 dmi_check_system(pciirq_dmi_table); 1123 1123 ··· 1144 1144 pirq_table = NULL; 1145 1145 } 1146 1146 1147 - pcibios_enable_irq = pirq_enable_irq; 1148 - 1149 - pcibios_fixup_irqs(); 1147 + x86_init.pci.fixup_irqs(); 1150 1148 1151 1149 if (io_apic_assign_pci_irqs && pci_routeirq) { 1152 1150 struct pci_dev *dev = NULL; ··· 1157 1159 for_each_pci_dev(dev) 1158 1160 pirq_enable_irq(dev); 1159 1161 } 1160 - 1161 - return 0; 1162 1162 } 1163 1163 1164 1164 static void pirq_penalize_isa_irq(int irq, int active)
+9 -15
arch/x86/pci/legacy.c
··· 35 35 } 36 36 } 37 37 38 - static int __init pci_legacy_init(void) 38 + int __init pci_legacy_init(void) 39 39 { 40 40 if (!raw_pci_ops) { 41 41 printk("PCI: System does not support PCI\n"); 42 42 return 0; 43 43 } 44 - 45 - if (pcibios_scanned++) 46 - return 0; 47 44 48 45 printk("PCI: Probing PCI hardware\n"); 49 46 pci_root_bus = pcibios_scan_root(0); ··· 52 55 53 56 int __init pci_subsys_init(void) 54 57 { 55 - #ifdef CONFIG_X86_NUMAQ 56 - pci_numaq_init(); 57 - #endif 58 - #ifdef CONFIG_ACPI 59 - pci_acpi_init(); 60 - #endif 61 - #ifdef CONFIG_X86_VISWS 62 - pci_visws_init(); 63 - #endif 64 - pci_legacy_init(); 58 + /* 59 + * The init function returns an non zero value when 60 + * pci_legacy_init should be invoked. 61 + */ 62 + if (x86_init.pci.init()) 63 + pci_legacy_init(); 64 + 65 65 pcibios_fixup_peer_bridges(); 66 - pcibios_irq_init(); 66 + x86_init.pci.init_irq(); 67 67 pcibios_init(); 68 68 69 69 return 0;
+262
arch/x86/pci/mrst.c
··· 1 + /* 2 + * Moorestown PCI support 3 + * Copyright (c) 2008 Intel Corporation 4 + * Jesse Barnes <jesse.barnes@intel.com> 5 + * 6 + * Moorestown has an interesting PCI implementation: 7 + * - configuration space is memory mapped (as defined by MCFG) 8 + * - Lincroft devices also have a real, type 1 configuration space 9 + * - Early Lincroft silicon has a type 1 access bug that will cause 10 + * a hang if non-existent devices are accessed 11 + * - some devices have the "fixed BAR" capability, which means 12 + * they can't be relocated or modified; check for that during 13 + * BAR sizing 14 + * 15 + * So, we use the MCFG space for all reads and writes, but also send 16 + * Lincroft writes to type 1 space. But only read/write if the device 17 + * actually exists, otherwise return all 1s for reads and bit bucket 18 + * the writes. 19 + */ 20 + 21 + #include <linux/sched.h> 22 + #include <linux/pci.h> 23 + #include <linux/ioport.h> 24 + #include <linux/init.h> 25 + #include <linux/dmi.h> 26 + 27 + #include <asm/acpi.h> 28 + #include <asm/segment.h> 29 + #include <asm/io.h> 30 + #include <asm/smp.h> 31 + #include <asm/pci_x86.h> 32 + #include <asm/hw_irq.h> 33 + #include <asm/io_apic.h> 34 + 35 + #define PCIE_CAP_OFFSET 0x100 36 + 37 + /* Fixed BAR fields */ 38 + #define PCIE_VNDR_CAP_ID_FIXED_BAR 0x00 /* Fixed BAR (TBD) */ 39 + #define PCI_FIXED_BAR_0_SIZE 0x04 40 + #define PCI_FIXED_BAR_1_SIZE 0x08 41 + #define PCI_FIXED_BAR_2_SIZE 0x0c 42 + #define PCI_FIXED_BAR_3_SIZE 0x10 43 + #define PCI_FIXED_BAR_4_SIZE 0x14 44 + #define PCI_FIXED_BAR_5_SIZE 0x1c 45 + 46 + /** 47 + * fixed_bar_cap - return the offset of the fixed BAR cap if found 48 + * @bus: PCI bus 49 + * @devfn: device in question 50 + * 51 + * Look for the fixed BAR cap on @bus and @devfn, returning its offset 52 + * if found or 0 otherwise. 53 + */ 54 + static int fixed_bar_cap(struct pci_bus *bus, unsigned int devfn) 55 + { 56 + int pos; 57 + u32 pcie_cap = 0, cap_data; 58 + 59 + pos = PCIE_CAP_OFFSET; 60 + 61 + if (!raw_pci_ext_ops) 62 + return 0; 63 + 64 + while (pos) { 65 + if (raw_pci_ext_ops->read(pci_domain_nr(bus), bus->number, 66 + devfn, pos, 4, &pcie_cap)) 67 + return 0; 68 + 69 + if (pcie_cap == 0xffffffff) 70 + return 0; 71 + 72 + if (PCI_EXT_CAP_ID(pcie_cap) == PCI_EXT_CAP_ID_VNDR) { 73 + raw_pci_ext_ops->read(pci_domain_nr(bus), bus->number, 74 + devfn, pos + 4, 4, &cap_data); 75 + if ((cap_data & 0xffff) == PCIE_VNDR_CAP_ID_FIXED_BAR) 76 + return pos; 77 + } 78 + 79 + pos = pcie_cap >> 20; 80 + } 81 + 82 + return 0; 83 + } 84 + 85 + static int pci_device_update_fixed(struct pci_bus *bus, unsigned int devfn, 86 + int reg, int len, u32 val, int offset) 87 + { 88 + u32 size; 89 + unsigned int domain, busnum; 90 + int bar = (reg - PCI_BASE_ADDRESS_0) >> 2; 91 + 92 + domain = pci_domain_nr(bus); 93 + busnum = bus->number; 94 + 95 + if (val == ~0 && len == 4) { 96 + unsigned long decode; 97 + 98 + raw_pci_ext_ops->read(domain, busnum, devfn, 99 + offset + 8 + (bar * 4), 4, &size); 100 + 101 + /* Turn the size into a decode pattern for the sizing code */ 102 + if (size) { 103 + decode = size - 1; 104 + decode |= decode >> 1; 105 + decode |= decode >> 2; 106 + decode |= decode >> 4; 107 + decode |= decode >> 8; 108 + decode |= decode >> 16; 109 + decode++; 110 + decode = ~(decode - 1); 111 + } else { 112 + decode = ~0; 113 + } 114 + 115 + /* 116 + * If val is all ones, the core code is trying to size the reg, 117 + * so update the mmconfig space with the real size. 118 + * 119 + * Note: this assumes the fixed size we got is a power of two. 120 + */ 121 + return raw_pci_ext_ops->write(domain, busnum, devfn, reg, 4, 122 + decode); 123 + } 124 + 125 + /* This is some other kind of BAR write, so just do it. */ 126 + return raw_pci_ext_ops->write(domain, busnum, devfn, reg, len, val); 127 + } 128 + 129 + /** 130 + * type1_access_ok - check whether to use type 1 131 + * @bus: bus number 132 + * @devfn: device & function in question 133 + * 134 + * If the bus is on a Lincroft chip and it exists, or is not on a Lincroft at 135 + * all, the we can go ahead with any reads & writes. If it's on a Lincroft, 136 + * but doesn't exist, avoid the access altogether to keep the chip from 137 + * hanging. 138 + */ 139 + static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg) 140 + { 141 + /* This is a workaround for A0 LNC bug where PCI status register does 142 + * not have new CAP bit set. can not be written by SW either. 143 + * 144 + * PCI header type in real LNC indicates a single function device, this 145 + * will prevent probing other devices under the same function in PCI 146 + * shim. Therefore, use the header type in shim instead. 147 + */ 148 + if (reg >= 0x100 || reg == PCI_STATUS || reg == PCI_HEADER_TYPE) 149 + return 0; 150 + if (bus == 0 && (devfn == PCI_DEVFN(2, 0) || devfn == PCI_DEVFN(0, 0))) 151 + return 1; 152 + return 0; /* langwell on others */ 153 + } 154 + 155 + static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, 156 + int size, u32 *value) 157 + { 158 + if (type1_access_ok(bus->number, devfn, where)) 159 + return pci_direct_conf1.read(pci_domain_nr(bus), bus->number, 160 + devfn, where, size, value); 161 + return raw_pci_ext_ops->read(pci_domain_nr(bus), bus->number, 162 + devfn, where, size, value); 163 + } 164 + 165 + static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, 166 + int size, u32 value) 167 + { 168 + int offset; 169 + 170 + /* On MRST, there is no PCI ROM BAR, this will cause a subsequent read 171 + * to ROM BAR return 0 then being ignored. 172 + */ 173 + if (where == PCI_ROM_ADDRESS) 174 + return 0; 175 + 176 + /* 177 + * Devices with fixed BARs need special handling: 178 + * - BAR sizing code will save, write ~0, read size, restore 179 + * - so writes to fixed BARs need special handling 180 + * - other writes to fixed BAR devices should go through mmconfig 181 + */ 182 + offset = fixed_bar_cap(bus, devfn); 183 + if (offset && 184 + (where >= PCI_BASE_ADDRESS_0 && where <= PCI_BASE_ADDRESS_5)) { 185 + return pci_device_update_fixed(bus, devfn, where, size, value, 186 + offset); 187 + } 188 + 189 + /* 190 + * On Moorestown update both real & mmconfig space 191 + * Note: early Lincroft silicon can't handle type 1 accesses to 192 + * non-existent devices, so just eat the write in that case. 193 + */ 194 + if (type1_access_ok(bus->number, devfn, where)) 195 + return pci_direct_conf1.write(pci_domain_nr(bus), bus->number, 196 + devfn, where, size, value); 197 + return raw_pci_ext_ops->write(pci_domain_nr(bus), bus->number, devfn, 198 + where, size, value); 199 + } 200 + 201 + static int mrst_pci_irq_enable(struct pci_dev *dev) 202 + { 203 + u8 pin; 204 + struct io_apic_irq_attr irq_attr; 205 + 206 + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); 207 + 208 + /* MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to 209 + * IOAPIC RTE entries, so we just enable RTE for the device. 210 + */ 211 + irq_attr.ioapic = mp_find_ioapic(dev->irq); 212 + irq_attr.ioapic_pin = dev->irq; 213 + irq_attr.trigger = 1; /* level */ 214 + irq_attr.polarity = 1; /* active low */ 215 + io_apic_set_pci_routing(&dev->dev, dev->irq, &irq_attr); 216 + 217 + return 0; 218 + } 219 + 220 + struct pci_ops pci_mrst_ops = { 221 + .read = pci_read, 222 + .write = pci_write, 223 + }; 224 + 225 + /** 226 + * pci_mrst_init - installs pci_mrst_ops 227 + * 228 + * Moorestown has an interesting PCI implementation (see above). 229 + * Called when the early platform detection installs it. 230 + */ 231 + int __init pci_mrst_init(void) 232 + { 233 + printk(KERN_INFO "Moorestown platform detected, using MRST PCI ops\n"); 234 + pci_mmcfg_late_init(); 235 + pcibios_enable_irq = mrst_pci_irq_enable; 236 + pci_root_ops = pci_mrst_ops; 237 + /* Continue with standard init */ 238 + return 1; 239 + } 240 + 241 + /* 242 + * Langwell devices reside at fixed offsets, don't try to move them. 243 + */ 244 + static void __devinit pci_fixed_bar_fixup(struct pci_dev *dev) 245 + { 246 + unsigned long offset; 247 + u32 size; 248 + int i; 249 + 250 + /* Fixup the BAR sizes for fixed BAR devices and make them unmoveable */ 251 + offset = fixed_bar_cap(dev->bus, dev->devfn); 252 + if (!offset || PCI_DEVFN(2, 0) == dev->devfn || 253 + PCI_DEVFN(2, 2) == dev->devfn) 254 + return; 255 + 256 + for (i = 0; i < PCI_ROM_RESOURCE; i++) { 257 + pci_read_config_dword(dev, offset + 8 + (i * 4), &size); 258 + dev->resource[i].end = dev->resource[i].start + size - 1; 259 + dev->resource[i].flags |= IORESOURCE_PCI_FIXED; 260 + } 261 + } 262 + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixed_bar_fixup);
-6
arch/x86/pci/numaq_32.c
··· 148 148 { 149 149 int quad; 150 150 151 - if (!found_numaq) 152 - return 0; 153 - 154 151 raw_pci_ops = &pci_direct_conf1_mq; 155 - 156 - if (pcibios_scanned++) 157 - return 0; 158 152 159 153 pci_root_bus = pcibios_scan_root(0); 160 154 if (pci_root_bus)
-3
arch/x86/pci/olpc.c
··· 304 304 305 305 int __init pci_olpc_init(void) 306 306 { 307 - if (!machine_is_olpc() || olpc_has_vsa()) 308 - return -ENODEV; 309 - 310 307 printk(KERN_INFO "PCI: Using configuration type OLPC\n"); 311 308 raw_pci_ops = &pci_olpc_conf; 312 309 is_lx = is_geode_lx();
+2 -4
arch/x86/pci/visws.c
··· 69 69 70 70 int __init pci_visws_init(void) 71 71 { 72 - if (!is_visws_box()) 73 - return -1; 74 - 75 72 pcibios_enable_irq = &pci_visws_enable_irq; 76 73 pcibios_disable_irq = &pci_visws_disable_irq; 77 74 ··· 87 90 pci_scan_bus_with_sysdata(pci_bus1); 88 91 pci_fixup_irqs(pci_common_swizzle, visws_map_irq); 89 92 pcibios_resource_survey(); 90 - return 0; 93 + /* Request bus scan */ 94 + return 1; 91 95 }
+43
drivers/pci/pci.c
··· 303 303 } 304 304 EXPORT_SYMBOL_GPL(pci_find_ext_capability); 305 305 306 + /** 307 + * pci_bus_find_ext_capability - find an extended capability 308 + * @bus: the PCI bus to query 309 + * @devfn: PCI device to query 310 + * @cap: capability code 311 + * 312 + * Like pci_find_ext_capability() but works for pci devices that do not have a 313 + * pci_dev structure set up yet. 314 + * 315 + * Returns the address of the requested capability structure within the 316 + * device's PCI configuration space or 0 in case the device does not 317 + * support it. 318 + */ 319 + int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn, 320 + int cap) 321 + { 322 + u32 header; 323 + int ttl; 324 + int pos = PCI_CFG_SPACE_SIZE; 325 + 326 + /* minimum 8 bytes per capability */ 327 + ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8; 328 + 329 + if (!pci_bus_read_config_dword(bus, devfn, pos, &header)) 330 + return 0; 331 + if (header == 0xffffffff || header == 0) 332 + return 0; 333 + 334 + while (ttl-- > 0) { 335 + if (PCI_EXT_CAP_ID(header) == cap) 336 + return pos; 337 + 338 + pos = PCI_EXT_CAP_NEXT(header); 339 + if (pos < PCI_CFG_SPACE_SIZE) 340 + break; 341 + 342 + if (!pci_bus_read_config_dword(bus, devfn, pos, &header)) 343 + break; 344 + } 345 + 346 + return 0; 347 + } 348 + 306 349 static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap) 307 350 { 308 351 int rc, ttl = PCI_FIND_CAP_TTL;
+2
include/linux/pci.h
··· 678 678 int pci_find_capability(struct pci_dev *dev, int cap); 679 679 int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap); 680 680 int pci_find_ext_capability(struct pci_dev *dev, int cap); 681 + int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn, 682 + int cap); 681 683 int pci_find_ht_capability(struct pci_dev *dev, int ht_cap); 682 684 int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap); 683 685 struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
+1
include/linux/pci_regs.h
··· 507 507 #define PCI_EXT_CAP_ID_VC 2 508 508 #define PCI_EXT_CAP_ID_DSN 3 509 509 #define PCI_EXT_CAP_ID_PWR 4 510 + #define PCI_EXT_CAP_ID_VNDR 11 510 511 #define PCI_EXT_CAP_ID_ACS 13 511 512 #define PCI_EXT_CAP_ID_ARI 14 512 513 #define PCI_EXT_CAP_ID_ATS 15