Path: blob/master/arch/powerpc/platforms/powermac/pic.c
26481 views
// SPDX-License-Identifier: GPL-2.0-or-later1/*2* Support for the interrupt controllers found on Power Macintosh,3* currently Apple's "Grand Central" interrupt controller in all4* its incarnations. OpenPIC support used on newer machines is5* in a separate file6*7* Copyright (C) 1997 Paul Mackerras ([email protected])8* Copyright (C) 2005 Benjamin Herrenschmidt ([email protected])9* IBM, Corp.10*/1112#include <linux/stddef.h>13#include <linux/init.h>14#include <linux/sched.h>15#include <linux/signal.h>16#include <linux/pci.h>17#include <linux/interrupt.h>18#include <linux/syscore_ops.h>19#include <linux/adb.h>20#include <linux/minmax.h>21#include <linux/pmu.h>22#include <linux/irqdomain.h>23#include <linux/of_address.h>24#include <linux/of_irq.h>2526#include <asm/sections.h>27#include <asm/io.h>28#include <asm/smp.h>29#include <asm/pci-bridge.h>30#include <asm/time.h>31#include <asm/pmac_feature.h>32#include <asm/mpic.h>33#include <asm/xmon.h>3435#include "pmac.h"3637#ifdef CONFIG_PPC3238struct pmac_irq_hw {39unsigned int event;40unsigned int enable;41unsigned int ack;42unsigned int level;43};4445/* Workaround flags for 32bit powermac machines */46unsigned int of_irq_workarounds;47struct device_node *of_irq_dflt_pic;4849/* Default addresses */50static volatile struct pmac_irq_hw __iomem *pmac_irq_hw[4];5152static int max_irqs;53static int max_real_irqs;5455static DEFINE_RAW_SPINLOCK(pmac_pic_lock);5657/* The max irq number this driver deals with is 128; see max_irqs */58static DECLARE_BITMAP(ppc_lost_interrupts, 128);59static DECLARE_BITMAP(ppc_cached_irq_mask, 128);60static int pmac_irq_cascade = -1;61static struct irq_domain *pmac_pic_host;6263static void __pmac_retrigger(unsigned int irq_nr)64{65if (irq_nr >= max_real_irqs && pmac_irq_cascade > 0) {66__set_bit(irq_nr, ppc_lost_interrupts);67irq_nr = pmac_irq_cascade;68mb();69}70if (!__test_and_set_bit(irq_nr, ppc_lost_interrupts)) {71atomic_inc(&ppc_n_lost_interrupts);72set_dec(1);73}74}7576static void pmac_mask_and_ack_irq(struct irq_data *d)77{78unsigned int src = irqd_to_hwirq(d);79unsigned long bit = 1UL << (src & 0x1f);80int i = src >> 5;81unsigned long flags;8283raw_spin_lock_irqsave(&pmac_pic_lock, flags);84__clear_bit(src, ppc_cached_irq_mask);85if (__test_and_clear_bit(src, ppc_lost_interrupts))86atomic_dec(&ppc_n_lost_interrupts);87out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);88out_le32(&pmac_irq_hw[i]->ack, bit);89do {90/* make sure ack gets to controller before we enable91interrupts */92mb();93} while((in_le32(&pmac_irq_hw[i]->enable) & bit)94!= (ppc_cached_irq_mask[i] & bit));95raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);96}9798static void pmac_ack_irq(struct irq_data *d)99{100unsigned int src = irqd_to_hwirq(d);101unsigned long bit = 1UL << (src & 0x1f);102int i = src >> 5;103unsigned long flags;104105raw_spin_lock_irqsave(&pmac_pic_lock, flags);106if (__test_and_clear_bit(src, ppc_lost_interrupts))107atomic_dec(&ppc_n_lost_interrupts);108out_le32(&pmac_irq_hw[i]->ack, bit);109(void)in_le32(&pmac_irq_hw[i]->ack);110raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);111}112113static void __pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)114{115unsigned long bit = 1UL << (irq_nr & 0x1f);116int i = irq_nr >> 5;117118if ((unsigned)irq_nr >= max_irqs)119return;120121/* enable unmasked interrupts */122out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);123124do {125/* make sure mask gets to controller before we126return to user */127mb();128} while((in_le32(&pmac_irq_hw[i]->enable) & bit)129!= (ppc_cached_irq_mask[i] & bit));130131/*132* Unfortunately, setting the bit in the enable register133* when the device interrupt is already on *doesn't* set134* the bit in the flag register or request another interrupt.135*/136if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level))137__pmac_retrigger(irq_nr);138}139140/* When an irq gets requested for the first client, if it's an141* edge interrupt, we clear any previous one on the controller142*/143static unsigned int pmac_startup_irq(struct irq_data *d)144{145unsigned long flags;146unsigned int src = irqd_to_hwirq(d);147unsigned long bit = 1UL << (src & 0x1f);148int i = src >> 5;149150raw_spin_lock_irqsave(&pmac_pic_lock, flags);151if (!irqd_is_level_type(d))152out_le32(&pmac_irq_hw[i]->ack, bit);153__set_bit(src, ppc_cached_irq_mask);154__pmac_set_irq_mask(src, 0);155raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);156157return 0;158}159160static void pmac_mask_irq(struct irq_data *d)161{162unsigned long flags;163unsigned int src = irqd_to_hwirq(d);164165raw_spin_lock_irqsave(&pmac_pic_lock, flags);166__clear_bit(src, ppc_cached_irq_mask);167__pmac_set_irq_mask(src, 1);168raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);169}170171static void pmac_unmask_irq(struct irq_data *d)172{173unsigned long flags;174unsigned int src = irqd_to_hwirq(d);175176raw_spin_lock_irqsave(&pmac_pic_lock, flags);177__set_bit(src, ppc_cached_irq_mask);178__pmac_set_irq_mask(src, 0);179raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);180}181182static int pmac_retrigger(struct irq_data *d)183{184unsigned long flags;185186raw_spin_lock_irqsave(&pmac_pic_lock, flags);187__pmac_retrigger(irqd_to_hwirq(d));188raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);189return 1;190}191192static struct irq_chip pmac_pic = {193.name = "PMAC-PIC",194.irq_startup = pmac_startup_irq,195.irq_mask = pmac_mask_irq,196.irq_ack = pmac_ack_irq,197.irq_mask_ack = pmac_mask_and_ack_irq,198.irq_unmask = pmac_unmask_irq,199.irq_retrigger = pmac_retrigger,200};201202static irqreturn_t gatwick_action(int cpl, void *dev_id)203{204unsigned long flags;205int irq, bits;206int rc = IRQ_NONE;207208raw_spin_lock_irqsave(&pmac_pic_lock, flags);209for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {210int i = irq >> 5;211bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];212bits |= in_le32(&pmac_irq_hw[i]->level);213bits &= ppc_cached_irq_mask[i];214if (bits == 0)215continue;216irq += __ilog2(bits);217raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);218generic_handle_irq(irq);219raw_spin_lock_irqsave(&pmac_pic_lock, flags);220rc = IRQ_HANDLED;221}222raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);223return rc;224}225226static unsigned int pmac_pic_get_irq(void)227{228int irq;229unsigned long bits = 0;230unsigned long flags;231232#ifdef CONFIG_PPC_PMAC32_PSURGE233/* IPI's are a hack on the powersurge -- Cort */234if (smp_processor_id() != 0) {235return psurge_secondary_virq;236}237#endif /* CONFIG_PPC_PMAC32_PSURGE */238raw_spin_lock_irqsave(&pmac_pic_lock, flags);239for (irq = max_real_irqs; (irq -= 32) >= 0; ) {240int i = irq >> 5;241bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];242bits |= in_le32(&pmac_irq_hw[i]->level);243bits &= ppc_cached_irq_mask[i];244if (bits == 0)245continue;246irq += __ilog2(bits);247break;248}249raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);250if (unlikely(irq < 0))251return 0;252return irq_find_mapping(pmac_pic_host, irq);253}254255static int pmac_pic_host_match(struct irq_domain *h, struct device_node *node,256enum irq_domain_bus_token bus_token)257{258/* We match all, we don't always have a node anyway */259return 1;260}261262static int pmac_pic_host_map(struct irq_domain *h, unsigned int virq,263irq_hw_number_t hw)264{265if (hw >= max_irqs)266return -EINVAL;267268/* Mark level interrupts, set delayed disable for edge ones and set269* handlers270*/271irq_set_status_flags(virq, IRQ_LEVEL);272irq_set_chip_and_handler(virq, &pmac_pic, handle_level_irq);273return 0;274}275276static const struct irq_domain_ops pmac_pic_host_ops = {277.match = pmac_pic_host_match,278.map = pmac_pic_host_map,279.xlate = irq_domain_xlate_onecell,280};281282static void __init pmac_pic_probe_oldstyle(void)283{284int i;285struct device_node *master = NULL;286struct device_node *slave = NULL;287u8 __iomem *addr;288struct resource r;289290/* Set our get_irq function */291ppc_md.get_irq = pmac_pic_get_irq;292293/*294* Find the interrupt controller type & node295*/296297if ((master = of_find_node_by_name(NULL, "gc")) != NULL) {298max_irqs = max_real_irqs = 32;299} else if ((master = of_find_node_by_name(NULL, "ohare")) != NULL) {300max_irqs = max_real_irqs = 32;301/* We might have a second cascaded ohare */302slave = of_find_node_by_name(NULL, "pci106b,7");303if (slave)304max_irqs = 64;305} else if ((master = of_find_node_by_name(NULL, "mac-io")) != NULL) {306max_irqs = max_real_irqs = 64;307308/* We might have a second cascaded heathrow */309310/* Compensate for of_node_put() in of_find_node_by_name() */311of_node_get(master);312slave = of_find_node_by_name(master, "mac-io");313314/* Check ordering of master & slave */315if (of_device_is_compatible(master, "gatwick")) {316BUG_ON(slave == NULL);317swap(master, slave);318}319320/* We found a slave */321if (slave)322max_irqs = 128;323}324BUG_ON(master == NULL);325326/*327* Allocate an irq host328*/329pmac_pic_host = irq_domain_create_linear(of_fwnode_handle(master),330max_irqs,331&pmac_pic_host_ops, NULL);332BUG_ON(pmac_pic_host == NULL);333irq_set_default_domain(pmac_pic_host);334335/* Get addresses of first controller if we have a node for it */336BUG_ON(of_address_to_resource(master, 0, &r));337338/* Map interrupts of primary controller */339addr = (u8 __iomem *) ioremap(r.start, 0x40);340i = 0;341pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *)342(addr + 0x20);343if (max_real_irqs > 32)344pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *)345(addr + 0x10);346of_node_put(master);347348printk(KERN_INFO "irq: Found primary Apple PIC %pOF for %d irqs\n",349master, max_real_irqs);350351/* Map interrupts of cascaded controller */352if (slave && !of_address_to_resource(slave, 0, &r)) {353addr = (u8 __iomem *)ioremap(r.start, 0x40);354pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *)355(addr + 0x20);356if (max_irqs > 64)357pmac_irq_hw[i++] =358(volatile struct pmac_irq_hw __iomem *)359(addr + 0x10);360pmac_irq_cascade = irq_of_parse_and_map(slave, 0);361362printk(KERN_INFO "irq: Found slave Apple PIC %pOF for %d irqs"363" cascade: %d\n", slave,364max_irqs - max_real_irqs, pmac_irq_cascade);365}366of_node_put(slave);367368/* Disable all interrupts in all controllers */369for (i = 0; i * 32 < max_irqs; ++i)370out_le32(&pmac_irq_hw[i]->enable, 0);371372/* Hookup cascade irq */373if (slave && pmac_irq_cascade) {374if (request_irq(pmac_irq_cascade, gatwick_action,375IRQF_NO_THREAD, "cascade", NULL))376pr_err("Failed to register cascade interrupt\n");377}378379printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs);380#ifdef CONFIG_XMON381i = irq_create_mapping(NULL, 20);382if (request_irq(i, xmon_irq, IRQF_NO_THREAD, "NMI - XMON", NULL))383pr_err("Failed to register NMI-XMON interrupt\n");384#endif385}386387int of_irq_parse_oldworld(const struct device_node *device, int index,388struct of_phandle_args *out_irq)389{390const u32 *ints = NULL;391int intlen;392393/*394* Old machines just have a list of interrupt numbers395* and no interrupt-controller nodes. We also have dodgy396* cases where the APPL,interrupts property is completely397* missing behind pci-pci bridges and we have to get it398* from the parent (the bridge itself, as apple just wired399* everything together on these)400*/401while (device) {402ints = of_get_property(device, "AAPL,interrupts", &intlen);403if (ints != NULL)404break;405device = device->parent;406if (!of_node_is_type(device, "pci"))407break;408}409if (ints == NULL)410return -EINVAL;411intlen /= sizeof(u32);412413if (index >= intlen)414return -EINVAL;415416out_irq->np = NULL;417out_irq->args[0] = ints[index];418out_irq->args_count = 1;419420return 0;421}422#endif /* CONFIG_PPC32 */423424static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)425{426#if defined(CONFIG_XMON) && defined(CONFIG_PPC32)427struct device_node* pswitch;428int nmi_irq;429430pswitch = of_find_node_by_name(NULL, "programmer-switch");431if (pswitch) {432nmi_irq = irq_of_parse_and_map(pswitch, 0);433if (nmi_irq) {434mpic_irq_set_priority(nmi_irq, 9);435if (request_irq(nmi_irq, xmon_irq, IRQF_NO_THREAD,436"NMI - XMON", NULL))437pr_err("Failed to register NMI-XMON interrupt\n");438}439of_node_put(pswitch);440}441#endif /* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */442}443444static struct mpic * __init pmac_setup_one_mpic(struct device_node *np,445int master)446{447const char *name = master ? " MPIC 1 " : " MPIC 2 ";448struct mpic *mpic;449unsigned int flags = master ? 0 : MPIC_SECONDARY;450451pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0);452453if (of_property_read_bool(np, "big-endian"))454flags |= MPIC_BIG_ENDIAN;455456/* Primary Big Endian means HT interrupts. This is quite dodgy457* but works until I find a better way458*/459if (master && (flags & MPIC_BIG_ENDIAN))460flags |= MPIC_U3_HT_IRQS;461462mpic = mpic_alloc(np, 0, flags, 0, 0, name);463if (mpic == NULL)464return NULL;465466mpic_init(mpic);467468return mpic;469}470471static int __init pmac_pic_probe_mpic(void)472{473struct mpic *mpic1, *mpic2;474struct device_node *np, *master = NULL, *slave = NULL;475476/* We can have up to 2 MPICs cascaded */477for_each_node_by_type(np, "open-pic") {478if (master == NULL && !of_property_present(np, "interrupts"))479master = of_node_get(np);480else if (slave == NULL)481slave = of_node_get(np);482if (master && slave) {483of_node_put(np);484break;485}486}487488/* Check for bogus setups */489if (master == NULL && slave != NULL) {490master = slave;491slave = NULL;492}493494/* Not found, default to good old pmac pic */495if (master == NULL)496return -ENODEV;497498/* Set master handler */499ppc_md.get_irq = mpic_get_irq;500501/* Setup master */502mpic1 = pmac_setup_one_mpic(master, 1);503BUG_ON(mpic1 == NULL);504505/* Install NMI if any */506pmac_pic_setup_mpic_nmi(mpic1);507508of_node_put(master);509510/* Set up a cascaded controller, if present */511if (slave) {512mpic2 = pmac_setup_one_mpic(slave, 0);513if (mpic2 == NULL)514printk(KERN_ERR "Failed to setup slave MPIC\n");515of_node_put(slave);516}517518return 0;519}520521522void __init pmac_pic_init(void)523{524/* We configure the OF parsing based on our oldworld vs. newworld525* platform type and whether we were booted by BootX.526*/527#ifdef CONFIG_PPC32528if (!pmac_newworld)529of_irq_workarounds |= OF_IMAP_OLDWORLD_MAC;530if (of_property_read_bool(of_chosen, "linux,bootx"))531of_irq_workarounds |= OF_IMAP_NO_PHANDLE;532533/* If we don't have phandles on a newworld, then try to locate a534* default interrupt controller (happens when booting with BootX).535* We do a first match here, hopefully, that only ever happens on536* machines with one controller.537*/538if (pmac_newworld && (of_irq_workarounds & OF_IMAP_NO_PHANDLE)) {539struct device_node *np;540541for_each_node_with_property(np, "interrupt-controller") {542/* Skip /chosen/interrupt-controller */543if (of_node_name_eq(np, "chosen"))544continue;545/* It seems like at least one person wants546* to use BootX on a machine with an AppleKiwi547* controller which happens to pretend to be an548* interrupt controller too. */549if (of_node_name_eq(np, "AppleKiwi"))550continue;551/* I think we found one ! */552of_irq_dflt_pic = np;553break;554}555}556#endif /* CONFIG_PPC32 */557558/* We first try to detect Apple's new Core99 chipset, since mac-io559* is quite different on those machines and contains an IBM MPIC2.560*/561if (pmac_pic_probe_mpic() == 0)562return;563564#ifdef CONFIG_PPC32565pmac_pic_probe_oldstyle();566#endif567}568569#if defined(CONFIG_PM) && defined(CONFIG_PPC32)570/*571* These procedures are used in implementing sleep on the powerbooks.572* sleep_save_intrs() saves the states of all interrupt enables573* and disables all interrupts except for the nominated one.574* sleep_restore_intrs() restores the states of all interrupt enables.575*/576unsigned long sleep_save_mask[2];577578/* This used to be passed by the PMU driver but that link got579* broken with the new driver model. We use this tweak for now...580* We really want to do things differently though...581*/582static int pmacpic_find_viaint(void)583{584int viaint = -1;585586#ifdef CONFIG_ADB_PMU587struct device_node *np;588589if (pmu_get_model() != PMU_OHARE_BASED)590goto not_found;591np = of_find_node_by_name(NULL, "via-pmu");592if (np == NULL)593goto not_found;594viaint = irq_of_parse_and_map(np, 0);595of_node_put(np);596597not_found:598#endif /* CONFIG_ADB_PMU */599return viaint;600}601602static int pmacpic_suspend(void)603{604int viaint = pmacpic_find_viaint();605606sleep_save_mask[0] = ppc_cached_irq_mask[0];607sleep_save_mask[1] = ppc_cached_irq_mask[1];608ppc_cached_irq_mask[0] = 0;609ppc_cached_irq_mask[1] = 0;610if (viaint > 0)611set_bit(viaint, ppc_cached_irq_mask);612out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]);613if (max_real_irqs > 32)614out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);615(void)in_le32(&pmac_irq_hw[0]->event);616/* make sure mask gets to controller before we return to caller */617mb();618(void)in_le32(&pmac_irq_hw[0]->enable);619620return 0;621}622623static void pmacpic_resume(void)624{625int i;626627out_le32(&pmac_irq_hw[0]->enable, 0);628if (max_real_irqs > 32)629out_le32(&pmac_irq_hw[1]->enable, 0);630mb();631for (i = 0; i < max_real_irqs; ++i)632if (test_bit(i, sleep_save_mask))633pmac_unmask_irq(irq_get_irq_data(i));634}635636static struct syscore_ops pmacpic_syscore_ops = {637.suspend = pmacpic_suspend,638.resume = pmacpic_resume,639};640641static int __init init_pmacpic_syscore(void)642{643if (pmac_irq_hw[0])644register_syscore_ops(&pmacpic_syscore_ops);645return 0;646}647648machine_subsys_initcall(powermac, init_pmacpic_syscore);649650#endif /* CONFIG_PM && CONFIG_PPC32 */651652653