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> 281b5d3e00d45e093fa0551c588034c3355b362f66Jiang Liu#include <linux/irqdomain.h> 29efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 30efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <asm/io_apic.h> 31efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <asm/mpspec.h> 32efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <asm/setup.h> 33efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <asm/apic.h> 34efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 35efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#ifdef CONFIG_X86_LOCAL_APIC 36efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tangstatic unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; 37efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 38efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang/* All CPUs enumerated by SFI must be present and enabled */ 399611dc7a8de8a5c6244886dad020995b1a896236Jan Beulichstatic void __init mp_sfi_register_lapic(u8 id) 40efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang{ 41cb2ded37fd2e1039f96c8c892da024a8f033add5Yinghai Lu if (MAX_LOCAL_APIC - id <= 0) { 42efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang pr_warning("Processor #%d invalid (max %d)\n", 43cb2ded37fd2e1039f96c8c892da024a8f033add5Yinghai Lu id, MAX_LOCAL_APIC); 44efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang return; 45efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang } 46efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 47efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang pr_info("registering lapic[%d]\n", id); 48efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 49efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang generic_processor_info(id, GET_APIC_VERSION(apic_read(APIC_LVR))); 50efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang} 51efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 52efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tangstatic int __init sfi_parse_cpus(struct sfi_table_header *table) 53efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang{ 54efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang struct sfi_table_simple *sb; 55efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang struct sfi_cpu_table_entry *pentry; 56efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang int i; 57efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang int cpu_num; 58efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 59efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang sb = (struct sfi_table_simple *)table; 60efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang cpu_num = SFI_GET_NUM_ENTRIES(sb, struct sfi_cpu_table_entry); 61efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang pentry = (struct sfi_cpu_table_entry *)sb->pentry; 62efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 63efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang for (i = 0; i < cpu_num; i++) { 64efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang mp_sfi_register_lapic(pentry->apic_id); 65efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang pentry++; 66efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang } 67efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 68efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang smp_found_config = 1; 69efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang return 0; 70efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang} 71efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#endif /* CONFIG_X86_LOCAL_APIC */ 72efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 73efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#ifdef CONFIG_X86_IO_APIC 74ecc527d560cd87c74cc0bc7aff36eb72f7e18615Jiang Liustatic struct irq_domain_ops sfi_ioapic_irqdomain_ops = { 75ecc527d560cd87c74cc0bc7aff36eb72f7e18615Jiang Liu .map = mp_irqdomain_map, 76ecc527d560cd87c74cc0bc7aff36eb72f7e18615Jiang Liu}; 77efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 78efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tangstatic int __init sfi_parse_ioapic(struct sfi_table_header *table) 79efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang{ 80efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang struct sfi_table_simple *sb; 81efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang struct sfi_apic_table_entry *pentry; 82efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang int i, num; 831b5d3e00d45e093fa0551c588034c3355b362f66Jiang Liu struct ioapic_domain_cfg cfg = { 841b5d3e00d45e093fa0551c588034c3355b362f66Jiang Liu .type = IOAPIC_DOMAIN_STRICT, 851b5d3e00d45e093fa0551c588034c3355b362f66Jiang Liu .ops = &sfi_ioapic_irqdomain_ops, 861b5d3e00d45e093fa0551c588034c3355b362f66Jiang Liu }; 87efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 88efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang sb = (struct sfi_table_simple *)table; 89efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang num = SFI_GET_NUM_ENTRIES(sb, struct sfi_apic_table_entry); 90efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang pentry = (struct sfi_apic_table_entry *)sb->pentry; 91efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 92efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang for (i = 0; i < num; i++) { 931b5d3e00d45e093fa0551c588034c3355b362f66Jiang Liu mp_register_ioapic(i, pentry->phys_addr, gsi_top, &cfg); 94efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang pentry++; 95efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang } 96efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 97efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang WARN(pic_mode, KERN_WARNING 98efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang "SFI: pic_mod shouldn't be 1 when IOAPIC table is present\n"); 99efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang pic_mode = 0; 100efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang return 0; 101efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang} 102efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#endif /* CONFIG_X86_IO_APIC */ 103efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 104efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang/* 105efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * sfi_platform_init(): register lapics & io-apics 106efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang */ 107efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tangint __init sfi_platform_init(void) 108efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang{ 109efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#ifdef CONFIG_X86_LOCAL_APIC 11053301f36f316a6519c464b0ef2a155386c20be19Yinghai Lu register_lapic_address(sfi_lapic_addr); 111efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, sfi_parse_cpus); 112efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#endif 113efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#ifdef CONFIG_X86_IO_APIC 114efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang sfi_table_parse(SFI_SIG_APIC, NULL, NULL, sfi_parse_ioapic); 115efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#endif 116efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang return 0; 117efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang} 118