1efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang/*
2efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * sfi.c - x86 architecture SFI support.
3efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang *
4efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * Copyright (c) 2009, Intel Corporation.
5efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang *
6efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * This program is free software; you can redistribute it and/or modify it
7efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * under the terms and conditions of the GNU General Public License,
8efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * version 2, as published by the Free Software Foundation.
9efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang *
10efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * This program is distributed in the hope it will be useful, but WITHOUT
11efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * more details.
14efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang *
15efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * You should have received a copy of the GNU General Public License along with
16efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * this program; if not, write to the Free Software Foundation, Inc.,
17efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang *
19efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang */
20efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
21efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#define KMSG_COMPONENT "SFI"
22efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
23efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
24efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <linux/acpi.h>
25efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <linux/init.h>
26efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <linux/sfi.h>
27efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <linux/io.h>
28efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
29efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <asm/io_apic.h>
30efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <asm/mpspec.h>
31efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <asm/setup.h>
32efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <asm/apic.h>
33efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
34efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#ifdef CONFIG_X86_LOCAL_APIC
35efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tangstatic unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
36efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
37efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang/* All CPUs enumerated by SFI must be present and enabled */
38940b3c7b193ec54141976a8642c00582f423690cThomas Gleixnerstatic void __cpuinit mp_sfi_register_lapic(u8 id)
39efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang{
40cb2ded37fd2e1039f96c8c892da024a8f033add5Yinghai Lu	if (MAX_LOCAL_APIC - id <= 0) {
41efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang		pr_warning("Processor #%d invalid (max %d)\n",
42cb2ded37fd2e1039f96c8c892da024a8f033add5Yinghai Lu			id, MAX_LOCAL_APIC);
43efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang		return;
44efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	}
45efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
46efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	pr_info("registering lapic[%d]\n", id);
47efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
48efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	generic_processor_info(id, GET_APIC_VERSION(apic_read(APIC_LVR)));
49efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang}
50efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
51efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tangstatic int __init sfi_parse_cpus(struct sfi_table_header *table)
52efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang{
53efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	struct sfi_table_simple *sb;
54efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	struct sfi_cpu_table_entry *pentry;
55efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	int i;
56efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	int cpu_num;
57efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
58efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	sb = (struct sfi_table_simple *)table;
59efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	cpu_num = SFI_GET_NUM_ENTRIES(sb, struct sfi_cpu_table_entry);
60efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	pentry = (struct sfi_cpu_table_entry *)sb->pentry;
61efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
62efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	for (i = 0; i < cpu_num; i++) {
63efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang		mp_sfi_register_lapic(pentry->apic_id);
64efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang		pentry++;
65efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	}
66efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
67efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	smp_found_config = 1;
68efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	return 0;
69efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang}
70efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#endif /* CONFIG_X86_LOCAL_APIC */
71efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
72efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#ifdef CONFIG_X86_IO_APIC
73efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
74efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tangstatic int __init sfi_parse_ioapic(struct sfi_table_header *table)
75efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang{
76efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	struct sfi_table_simple *sb;
77efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	struct sfi_apic_table_entry *pentry;
78efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	int i, num;
79efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
80efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	sb = (struct sfi_table_simple *)table;
81efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	num = SFI_GET_NUM_ENTRIES(sb, struct sfi_apic_table_entry);
82efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	pentry = (struct sfi_apic_table_entry *)sb->pentry;
83efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
84efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	for (i = 0; i < num; i++) {
85a4384df3e24579d6292a1b3b41d500349948f30bEric W. Biederman		mp_register_ioapic(i, pentry->phys_addr, gsi_top);
86efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang		pentry++;
87efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	}
88efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
89efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	WARN(pic_mode, KERN_WARNING
90efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang		"SFI: pic_mod shouldn't be 1 when IOAPIC table is present\n");
91efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	pic_mode = 0;
92efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	return 0;
93efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang}
94efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#endif /* CONFIG_X86_IO_APIC */
95efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang
96efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang/*
97efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * sfi_platform_init(): register lapics & io-apics
98efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang */
99efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tangint __init sfi_platform_init(void)
100efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang{
101efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#ifdef CONFIG_X86_LOCAL_APIC
10253301f36f316a6519c464b0ef2a155386c20be19Yinghai Lu	register_lapic_address(sfi_lapic_addr);
103efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, sfi_parse_cpus);
104efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#endif
105efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#ifdef CONFIG_X86_IO_APIC
106efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	sfi_table_parse(SFI_SIG_APIC, NULL, NULL, sfi_parse_ioapic);
107efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#endif
108efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang	return 0;
109efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang}
110