10b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt/* 20b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * Copyright 2011 IBM Corporation. 30b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * 40b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * This program is free software; you can redistribute it and/or 50b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * modify it under the terms of the GNU General Public License 60b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * as published by the Free Software Foundation; either version 70b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * 2 of the License, or (at your option) any later version. 80b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * 90b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt */ 100b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/types.h> 110b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/threads.h> 120b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/kernel.h> 130b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/irq.h> 140b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/debugfs.h> 150b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/smp.h> 160b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/interrupt.h> 170b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/seq_file.h> 180b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/init.h> 190b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/cpu.h> 200b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/of.h> 210b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/slab.h> 220b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/spinlock.h> 230b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 240b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/prom.h> 250b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/io.h> 260b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/smp.h> 270b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/machdep.h> 280b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/irq.h> 290b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/errno.h> 300b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/rtas.h> 310b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/xics.h> 320b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/firmware.h> 330b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 340b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt/* Globals common to all ICP/ICS implementations */ 350b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtconst struct icp_ops *icp_ops; 360b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 370b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtunsigned int xics_default_server = 0xff; 380b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtunsigned int xics_default_distrib_server = 0; 390b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtunsigned int xics_interrupt_server_size = 8; 400b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 410b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin HerrenschmidtDEFINE_PER_CPU(struct xics_cppr, xics_cppr); 420b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 43bae1d8f19983fbfa25559aa3cb6a81a84aa82a18Grant Likelystruct irq_domain *xics_host; 440b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 450b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic LIST_HEAD(ics_list); 460b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 470b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtvoid xics_update_irq_servers(void) 480b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 490b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt int i, j; 500b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt struct device_node *np; 510b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt u32 ilen; 52d213dd5348532051e19150797aeef36099a4ade9Anton Blanchard const __be32 *ireg; 530b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt u32 hcpuid; 540b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 550b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Find the server numbers for the boot cpu. */ 560b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt np = of_get_cpu_node(boot_cpuid, NULL); 570b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt BUG_ON(!np); 580b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 590b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt hcpuid = get_hard_smp_processor_id(boot_cpuid); 60f6e17f9b0bf172a5813dfef0c03d0a25ba83b0deBenjamin Herrenschmidt xics_default_server = xics_default_distrib_server = hcpuid; 61f6e17f9b0bf172a5813dfef0c03d0a25ba83b0deBenjamin Herrenschmidt 62f6e17f9b0bf172a5813dfef0c03d0a25ba83b0deBenjamin Herrenschmidt pr_devel("xics: xics_default_server = 0x%x\n", xics_default_server); 630b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 640b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); 650b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (!ireg) { 660b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt of_node_put(np); 670b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return; 680b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt } 690b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 700b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt i = ilen / sizeof(int); 710b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 720b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Global interrupt distribution server is specified in the last 730b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last 740b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * entry fom this property for current boot cpu id and use it as 750b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * default distribution server 760b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt */ 770b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt for (j = 0; j < i; j += 2) { 78d213dd5348532051e19150797aeef36099a4ade9Anton Blanchard if (be32_to_cpu(ireg[j]) == hcpuid) { 79d213dd5348532051e19150797aeef36099a4ade9Anton Blanchard xics_default_distrib_server = be32_to_cpu(ireg[j+1]); 80f6e17f9b0bf172a5813dfef0c03d0a25ba83b0deBenjamin Herrenschmidt break; 810b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt } 820b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt } 83f6e17f9b0bf172a5813dfef0c03d0a25ba83b0deBenjamin Herrenschmidt pr_devel("xics: xics_default_distrib_server = 0x%x\n", 84f6e17f9b0bf172a5813dfef0c03d0a25ba83b0deBenjamin Herrenschmidt xics_default_distrib_server); 850b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt of_node_put(np); 860b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 870b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 880b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt/* GIQ stuff, currently only supported on RTAS setups, will have 890b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * to be sorted properly for bare metal 900b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt */ 910b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtvoid xics_set_cpu_giq(unsigned int gserver, unsigned int join) 920b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 930b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#ifdef CONFIG_PPC_RTAS 940b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt int index; 950b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt int status; 960b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 970b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (!rtas_indicator_present(GLOBAL_INTERRUPT_QUEUE, NULL)) 980b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return; 990b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1000b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt index = (1UL << xics_interrupt_server_size) - 1 - gserver; 1010b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1020b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE, index, join); 1030b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1040b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt WARN(status < 0, "set-indicator(%d, %d, %u) returned %d\n", 1050b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt GLOBAL_INTERRUPT_QUEUE, index, join, status); 1060b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#endif 1070b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 1080b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1090b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtvoid xics_setup_cpu(void) 1100b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 1110b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt icp_ops->set_priority(LOWEST_PRIORITY); 1120b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1130b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt xics_set_cpu_giq(xics_default_distrib_server, 1); 1140b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 1150b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1160b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtvoid xics_mask_unknown_vec(unsigned int vec) 1170b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 1180b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt struct ics *ics; 1190b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 120f6e17f9b0bf172a5813dfef0c03d0a25ba83b0deBenjamin Herrenschmidt pr_err("Interrupt 0x%x (real) is invalid, disabling it.\n", vec); 1210b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1220b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt list_for_each_entry(ics, &ics_list, link) 1230b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt ics->mask_unknown(ics, vec); 1240b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 1250b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1260b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1270b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#ifdef CONFIG_SMP 1280b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1290b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic void xics_request_ipi(void) 1300b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 1310b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt unsigned int ipi; 1320b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1330b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt ipi = irq_create_mapping(xics_host, XICS_IPI); 1340b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt BUG_ON(ipi == NO_IRQ); 1350b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1360b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* 137a3a9f3b47d12b5f6dfc9c7ed9d7b193d77812195Yong Zhang * IPIs are marked IRQF_PERCPU. The handler was set in map. 1380b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt */ 1390b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt BUG_ON(request_irq(ipi, icp_ops->ipi_action, 1403b5e16d7ad0cf4b03a0650092a6fdcb27b536a82Thomas Gleixner IRQF_PERCPU | IRQF_NO_THREAD, "IPI", NULL)); 1410b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 1420b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1430b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtint __init xics_smp_probe(void) 1440b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 14523d72bfd8f9f24aa9efafed3586a99f5669c23d7Milton Miller /* Setup cause_ipi callback based on which ICP is used */ 14623d72bfd8f9f24aa9efafed3586a99f5669c23d7Milton Miller smp_ops->cause_ipi = icp_ops->cause_ipi; 1470b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1480b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Register all the IPIs */ 1490b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt xics_request_ipi(); 1500b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1510b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return cpumask_weight(cpu_possible_mask); 1520b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 1530b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1540b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#endif /* CONFIG_SMP */ 1550b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1560b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtvoid xics_teardown_cpu(void) 1570b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 1580b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); 1590b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1600b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* 1610b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * we have to reset the cppr index to 0 because we're 1620b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * not going to return from the IPI 1630b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt */ 1640b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt os_cppr->index = 0; 1650b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt icp_ops->set_priority(0); 1660b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt icp_ops->teardown_cpu(); 1670b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 1680b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1690b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtvoid xics_kexec_teardown_cpu(int secondary) 1700b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 1710b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt xics_teardown_cpu(); 1720b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1730b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt icp_ops->flush_ipi(); 1740b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1750b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* 1760b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * Some machines need to have at least one cpu in the GIQ, 1770b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * so leave the master cpu in the group. 1780b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt */ 1790b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (secondary) 1800b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt xics_set_cpu_giq(xics_default_distrib_server, 0); 1810b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 1820b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1830b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1840b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#ifdef CONFIG_HOTPLUG_CPU 1850b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1860b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt/* Interrupts are disabled. */ 1870b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtvoid xics_migrate_irqs_away(void) 1880b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 1890b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id(); 1900b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt unsigned int irq, virq; 1914013369f3782af9a488e37c2b603f1dcf008ea76Grant Likely struct irq_desc *desc; 1920b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1930b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* If we used to be the default server, move to the new "boot_cpuid" */ 1940b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (hw_cpu == xics_default_server) 1950b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt xics_update_irq_servers(); 1960b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1970b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Reject any interrupt that was queued to us... */ 1980b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt icp_ops->set_priority(0); 1990b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2000b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Remove ourselves from the global interrupt queue */ 2010b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt xics_set_cpu_giq(xics_default_distrib_server, 0); 2020b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2030b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Allow IPIs again... */ 2040b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt icp_ops->set_priority(DEFAULT_PRIORITY); 2050b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2064013369f3782af9a488e37c2b603f1dcf008ea76Grant Likely for_each_irq_desc(virq, desc) { 2070b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt struct irq_chip *chip; 2080b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt long server; 2090b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt unsigned long flags; 2100b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt struct ics *ics; 2110b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2120b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* We can't set affinity on ISA interrupts */ 2130b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (virq < NUM_ISA_INTERRUPTS) 2140b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt continue; 2150b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* We only need to migrate enabled IRQS */ 2164013369f3782af9a488e37c2b603f1dcf008ea76Grant Likely if (!desc->action) 2170b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt continue; 2186d9285b00f776eebe459a858ebf07b56c36c60d2Grant Likely if (desc->irq_data.domain != xics_host) 2196d9285b00f776eebe459a858ebf07b56c36c60d2Grant Likely continue; 2206d9285b00f776eebe459a858ebf07b56c36c60d2Grant Likely irq = desc->irq_data.hwirq; 2216d9285b00f776eebe459a858ebf07b56c36c60d2Grant Likely /* We need to get IPIs still. */ 2226d9285b00f776eebe459a858ebf07b56c36c60d2Grant Likely if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) 2236d9285b00f776eebe459a858ebf07b56c36c60d2Grant Likely continue; 2240b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt chip = irq_desc_get_chip(desc); 2250b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (!chip || !chip->irq_set_affinity) 2260b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt continue; 2270b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2280b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt raw_spin_lock_irqsave(&desc->lock, flags); 2290b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2300b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Locate interrupt server */ 2310b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt server = -1; 2320b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt ics = irq_get_chip_data(virq); 2330b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (ics) 2340b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt server = ics->get_server(ics, irq); 2350b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (server < 0) { 2360b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt printk(KERN_ERR "%s: Can't find server for irq %d\n", 2370b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt __func__, irq); 2380b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt goto unlock; 2390b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt } 2400b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2410b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* We only support delivery to all cpus or to one cpu. 2420b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * The irq has to be migrated only in the single cpu 2430b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * case. 2440b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt */ 2450b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (server != hw_cpu) 2460b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt goto unlock; 2470b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2480b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* This is expected during cpu offline. */ 2490b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (cpu_online(cpu)) 2500b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt pr_warning("IRQ %u affinity broken off cpu %u\n", 2510b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt virq, cpu); 2520b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2530b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Reset affinity to all cpus */ 2540b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&desc->lock, flags); 2550b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt irq_set_affinity(virq, cpu_all_mask); 2560b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt continue; 2570b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtunlock: 2580b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&desc->lock, flags); 2590b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt } 2600b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 2610b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#endif /* CONFIG_HOTPLUG_CPU */ 2620b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2630b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#ifdef CONFIG_SMP 2640b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt/* 2650b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * For the moment we only implement delivery to all cpus or one cpu. 2660b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * 2670b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * If the requested affinity is cpu_all_mask, we set global affinity. 2680b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * If not we set it to the first cpu in the mask, even if multiple cpus 2690b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * are set. This is so things like irqbalance (which set core and package 2700b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * wide affinities) do the right thing. 271f6e17f9b0bf172a5813dfef0c03d0a25ba83b0deBenjamin Herrenschmidt * 272f6e17f9b0bf172a5813dfef0c03d0a25ba83b0deBenjamin Herrenschmidt * We need to fix this to implement support for the links 2730b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt */ 2740b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtint xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask, 2750b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt unsigned int strict_check) 2760b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 2770b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2780b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (!distribute_irqs) 2790b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return xics_default_server; 2800b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2810b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (!cpumask_subset(cpu_possible_mask, cpumask)) { 2820b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt int server = cpumask_first_and(cpu_online_mask, cpumask); 2830b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2840b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (server < nr_cpu_ids) 2850b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return get_hard_smp_processor_id(server); 2860b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2870b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (strict_check) 2880b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return -1; 2890b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt } 2900b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2910b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* 2920b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * Workaround issue with some versions of JS20 firmware that 2930b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * deliver interrupts to cpus which haven't been started. This 2940b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * happens when using the maxcpus= boot option. 2950b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt */ 2960b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (cpumask_equal(cpu_online_mask, cpu_present_mask)) 2970b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return xics_default_distrib_server; 2980b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2990b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return xics_default_server; 3000b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 3010b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#endif /* CONFIG_SMP */ 3020b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 303bae1d8f19983fbfa25559aa3cb6a81a84aa82a18Grant Likelystatic int xics_host_match(struct irq_domain *h, struct device_node *node) 3040b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 3055ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman struct ics *ics; 3065ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman 3075ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman list_for_each_entry(ics, &ics_list, link) 3085ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman if (ics->host_match(ics, node)) 3095ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman return 1; 3105ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman 3115ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman return 0; 3120b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 3130b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 3140b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt/* Dummies */ 3150b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic void xics_ipi_unmask(struct irq_data *d) { } 3160b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic void xics_ipi_mask(struct irq_data *d) { } 3170b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 3180b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic struct irq_chip xics_ipi_chip = { 3190b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .name = "XICS", 3200b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .irq_eoi = NULL, /* Patched at init time */ 3210b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .irq_mask = xics_ipi_mask, 3220b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .irq_unmask = xics_ipi_unmask, 3230b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt}; 3240b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 325bae1d8f19983fbfa25559aa3cb6a81a84aa82a18Grant Likelystatic int xics_host_map(struct irq_domain *h, unsigned int virq, 3260b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt irq_hw_number_t hw) 3270b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 3280b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt struct ics *ics; 3290b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 3300b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw); 3310b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 3320b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* They aren't all level sensitive but we just don't really know */ 3330b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt irq_set_status_flags(virq, IRQ_LEVEL); 3340b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 3350b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Don't call into ICS for IPIs */ 3360b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (hw == XICS_IPI) { 3370b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt irq_set_chip_and_handler(virq, &xics_ipi_chip, 338e085255ebce87c0b85d4752638d8a7d4f35f5b64Milton Miller handle_percpu_irq); 3390b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return 0; 3400b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt } 3410b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 3420b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Let the ICS setup the chip data */ 3430b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt list_for_each_entry(ics, &ics_list, link) 3440b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (ics->map(ics, virq) == 0) 345e085255ebce87c0b85d4752638d8a7d4f35f5b64Milton Miller return 0; 346e085255ebce87c0b85d4752638d8a7d4f35f5b64Milton Miller 347e085255ebce87c0b85d4752638d8a7d4f35f5b64Milton Miller return -EINVAL; 3480b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 3490b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 350bae1d8f19983fbfa25559aa3cb6a81a84aa82a18Grant Likelystatic int xics_host_xlate(struct irq_domain *h, struct device_node *ct, 3510b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt const u32 *intspec, unsigned int intsize, 3520b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt irq_hw_number_t *out_hwirq, unsigned int *out_flags) 3530b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 3540b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 3550b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Current xics implementation translates everything 3560b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * to level. It is not technically right for MSIs but this 3570b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * is irrelevant at this point. We might get smarter in the future 3580b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt */ 3590b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt *out_hwirq = intspec[0]; 3600b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt *out_flags = IRQ_TYPE_LEVEL_LOW; 3610b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 3620b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return 0; 3630b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 3640b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 365bae1d8f19983fbfa25559aa3cb6a81a84aa82a18Grant Likelystatic struct irq_domain_ops xics_host_ops = { 3660b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .match = xics_host_match, 3670b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .map = xics_host_map, 3680b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .xlate = xics_host_xlate, 3690b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt}; 3700b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 3710b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic void __init xics_init_host(void) 3720b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 373a8db8cf0d894df5f1dcfd4bce9894e0dbcc01c96Grant Likely xics_host = irq_domain_add_tree(NULL, &xics_host_ops, NULL); 3740b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt BUG_ON(xics_host == NULL); 3750b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt irq_set_default_host(xics_host); 3760b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 3770b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 3780b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtvoid __init xics_register_ics(struct ics *ics) 3790b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 3800b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt list_add(&ics->link, &ics_list); 3810b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 3820b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 3830b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic void __init xics_get_server_size(void) 3840b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 3850b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt struct device_node *np; 386d213dd5348532051e19150797aeef36099a4ade9Anton Blanchard const __be32 *isize; 3870b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 3880b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* We fetch the interrupt server size from the first ICS node 3890b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * we find if any 3900b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt */ 3910b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt np = of_find_compatible_node(NULL, NULL, "ibm,ppc-xics"); 3920b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (!np) 3930b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return; 3940b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt isize = of_get_property(np, "ibm,interrupt-server#-size", NULL); 3950b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (!isize) 3960b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return; 397d213dd5348532051e19150797aeef36099a4ade9Anton Blanchard xics_interrupt_server_size = be32_to_cpu(*isize); 3980b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt of_node_put(np); 3990b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 4000b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 4010b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtvoid __init xics_init(void) 4020b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 4030b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt int rc = -1; 4040b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 4050b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Fist locate ICP */ 4060b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (firmware_has_feature(FW_FEATURE_LPAR)) 4070b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt rc = icp_hv_init(); 4080b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (rc < 0) 4090b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt rc = icp_native_init(); 4100b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (rc < 0) { 4110b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt pr_warning("XICS: Cannot find a Presentation Controller !\n"); 4120b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return; 4130b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt } 4140b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 4150b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Copy get_irq callback over to ppc_md */ 4160b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt ppc_md.get_irq = icp_ops->get_irq; 4170b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 4180b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Patch up IPI chip EOI */ 4190b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt xics_ipi_chip.irq_eoi = icp_ops->eoi; 4200b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 4210b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Now locate ICS */ 4220b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt rc = ics_rtas_init(); 4235c7c1e9444d8bfb721a27a35bba3eeb5236c75d8Benjamin Herrenschmidt if (rc < 0) 4245c7c1e9444d8bfb721a27a35bba3eeb5236c75d8Benjamin Herrenschmidt rc = ics_opal_init(); 4250b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (rc < 0) 4260b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt pr_warning("XICS: Cannot find a Source Controller !\n"); 4270b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 4280b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Initialize common bits */ 4290b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt xics_get_server_size(); 4300b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt xics_update_irq_servers(); 4310b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt xics_init_host(); 4320b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt xics_setup_cpu(); 4330b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 434