162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * arch/powerpc/sysdev/ipic.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * IPIC routines implementations. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright 2005 Freescale Semiconductor, Inc. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci#include <linux/kernel.h> 1062306a36Sopenharmony_ci#include <linux/init.h> 1162306a36Sopenharmony_ci#include <linux/errno.h> 1262306a36Sopenharmony_ci#include <linux/reboot.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/stddef.h> 1562306a36Sopenharmony_ci#include <linux/sched.h> 1662306a36Sopenharmony_ci#include <linux/signal.h> 1762306a36Sopenharmony_ci#include <linux/syscore_ops.h> 1862306a36Sopenharmony_ci#include <linux/device.h> 1962306a36Sopenharmony_ci#include <linux/spinlock.h> 2062306a36Sopenharmony_ci#include <linux/fsl_devices.h> 2162306a36Sopenharmony_ci#include <linux/irqdomain.h> 2262306a36Sopenharmony_ci#include <linux/of_address.h> 2362306a36Sopenharmony_ci#include <asm/irq.h> 2462306a36Sopenharmony_ci#include <asm/io.h> 2562306a36Sopenharmony_ci#include <asm/ipic.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#include "ipic.h" 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistatic struct ipic * primary_ipic; 3062306a36Sopenharmony_cistatic struct irq_chip ipic_level_irq_chip, ipic_edge_irq_chip; 3162306a36Sopenharmony_cistatic DEFINE_RAW_SPINLOCK(ipic_lock); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic struct ipic_info ipic_info[] = { 3462306a36Sopenharmony_ci [1] = { 3562306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 3662306a36Sopenharmony_ci .prio = IPIC_SIPRR_C, 3762306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 3862306a36Sopenharmony_ci .bit = 16, 3962306a36Sopenharmony_ci .prio_mask = 0, 4062306a36Sopenharmony_ci }, 4162306a36Sopenharmony_ci [2] = { 4262306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 4362306a36Sopenharmony_ci .prio = IPIC_SIPRR_C, 4462306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 4562306a36Sopenharmony_ci .bit = 17, 4662306a36Sopenharmony_ci .prio_mask = 1, 4762306a36Sopenharmony_ci }, 4862306a36Sopenharmony_ci [3] = { 4962306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 5062306a36Sopenharmony_ci .prio = IPIC_SIPRR_C, 5162306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 5262306a36Sopenharmony_ci .bit = 18, 5362306a36Sopenharmony_ci .prio_mask = 2, 5462306a36Sopenharmony_ci }, 5562306a36Sopenharmony_ci [4] = { 5662306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 5762306a36Sopenharmony_ci .prio = IPIC_SIPRR_C, 5862306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 5962306a36Sopenharmony_ci .bit = 19, 6062306a36Sopenharmony_ci .prio_mask = 3, 6162306a36Sopenharmony_ci }, 6262306a36Sopenharmony_ci [5] = { 6362306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 6462306a36Sopenharmony_ci .prio = IPIC_SIPRR_C, 6562306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 6662306a36Sopenharmony_ci .bit = 20, 6762306a36Sopenharmony_ci .prio_mask = 4, 6862306a36Sopenharmony_ci }, 6962306a36Sopenharmony_ci [6] = { 7062306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 7162306a36Sopenharmony_ci .prio = IPIC_SIPRR_C, 7262306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 7362306a36Sopenharmony_ci .bit = 21, 7462306a36Sopenharmony_ci .prio_mask = 5, 7562306a36Sopenharmony_ci }, 7662306a36Sopenharmony_ci [7] = { 7762306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 7862306a36Sopenharmony_ci .prio = IPIC_SIPRR_C, 7962306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 8062306a36Sopenharmony_ci .bit = 22, 8162306a36Sopenharmony_ci .prio_mask = 6, 8262306a36Sopenharmony_ci }, 8362306a36Sopenharmony_ci [8] = { 8462306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 8562306a36Sopenharmony_ci .prio = IPIC_SIPRR_C, 8662306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 8762306a36Sopenharmony_ci .bit = 23, 8862306a36Sopenharmony_ci .prio_mask = 7, 8962306a36Sopenharmony_ci }, 9062306a36Sopenharmony_ci [9] = { 9162306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 9262306a36Sopenharmony_ci .prio = IPIC_SIPRR_D, 9362306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 9462306a36Sopenharmony_ci .bit = 24, 9562306a36Sopenharmony_ci .prio_mask = 0, 9662306a36Sopenharmony_ci }, 9762306a36Sopenharmony_ci [10] = { 9862306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 9962306a36Sopenharmony_ci .prio = IPIC_SIPRR_D, 10062306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 10162306a36Sopenharmony_ci .bit = 25, 10262306a36Sopenharmony_ci .prio_mask = 1, 10362306a36Sopenharmony_ci }, 10462306a36Sopenharmony_ci [11] = { 10562306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 10662306a36Sopenharmony_ci .prio = IPIC_SIPRR_D, 10762306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 10862306a36Sopenharmony_ci .bit = 26, 10962306a36Sopenharmony_ci .prio_mask = 2, 11062306a36Sopenharmony_ci }, 11162306a36Sopenharmony_ci [12] = { 11262306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 11362306a36Sopenharmony_ci .prio = IPIC_SIPRR_D, 11462306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 11562306a36Sopenharmony_ci .bit = 27, 11662306a36Sopenharmony_ci .prio_mask = 3, 11762306a36Sopenharmony_ci }, 11862306a36Sopenharmony_ci [13] = { 11962306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 12062306a36Sopenharmony_ci .prio = IPIC_SIPRR_D, 12162306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 12262306a36Sopenharmony_ci .bit = 28, 12362306a36Sopenharmony_ci .prio_mask = 4, 12462306a36Sopenharmony_ci }, 12562306a36Sopenharmony_ci [14] = { 12662306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 12762306a36Sopenharmony_ci .prio = IPIC_SIPRR_D, 12862306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 12962306a36Sopenharmony_ci .bit = 29, 13062306a36Sopenharmony_ci .prio_mask = 5, 13162306a36Sopenharmony_ci }, 13262306a36Sopenharmony_ci [15] = { 13362306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 13462306a36Sopenharmony_ci .prio = IPIC_SIPRR_D, 13562306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 13662306a36Sopenharmony_ci .bit = 30, 13762306a36Sopenharmony_ci .prio_mask = 6, 13862306a36Sopenharmony_ci }, 13962306a36Sopenharmony_ci [16] = { 14062306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 14162306a36Sopenharmony_ci .prio = IPIC_SIPRR_D, 14262306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 14362306a36Sopenharmony_ci .bit = 31, 14462306a36Sopenharmony_ci .prio_mask = 7, 14562306a36Sopenharmony_ci }, 14662306a36Sopenharmony_ci [17] = { 14762306a36Sopenharmony_ci .ack = IPIC_SEPNR, 14862306a36Sopenharmony_ci .mask = IPIC_SEMSR, 14962306a36Sopenharmony_ci .prio = IPIC_SMPRR_A, 15062306a36Sopenharmony_ci .force = IPIC_SEFCR, 15162306a36Sopenharmony_ci .bit = 1, 15262306a36Sopenharmony_ci .prio_mask = 5, 15362306a36Sopenharmony_ci }, 15462306a36Sopenharmony_ci [18] = { 15562306a36Sopenharmony_ci .ack = IPIC_SEPNR, 15662306a36Sopenharmony_ci .mask = IPIC_SEMSR, 15762306a36Sopenharmony_ci .prio = IPIC_SMPRR_A, 15862306a36Sopenharmony_ci .force = IPIC_SEFCR, 15962306a36Sopenharmony_ci .bit = 2, 16062306a36Sopenharmony_ci .prio_mask = 6, 16162306a36Sopenharmony_ci }, 16262306a36Sopenharmony_ci [19] = { 16362306a36Sopenharmony_ci .ack = IPIC_SEPNR, 16462306a36Sopenharmony_ci .mask = IPIC_SEMSR, 16562306a36Sopenharmony_ci .prio = IPIC_SMPRR_A, 16662306a36Sopenharmony_ci .force = IPIC_SEFCR, 16762306a36Sopenharmony_ci .bit = 3, 16862306a36Sopenharmony_ci .prio_mask = 7, 16962306a36Sopenharmony_ci }, 17062306a36Sopenharmony_ci [20] = { 17162306a36Sopenharmony_ci .ack = IPIC_SEPNR, 17262306a36Sopenharmony_ci .mask = IPIC_SEMSR, 17362306a36Sopenharmony_ci .prio = IPIC_SMPRR_B, 17462306a36Sopenharmony_ci .force = IPIC_SEFCR, 17562306a36Sopenharmony_ci .bit = 4, 17662306a36Sopenharmony_ci .prio_mask = 4, 17762306a36Sopenharmony_ci }, 17862306a36Sopenharmony_ci [21] = { 17962306a36Sopenharmony_ci .ack = IPIC_SEPNR, 18062306a36Sopenharmony_ci .mask = IPIC_SEMSR, 18162306a36Sopenharmony_ci .prio = IPIC_SMPRR_B, 18262306a36Sopenharmony_ci .force = IPIC_SEFCR, 18362306a36Sopenharmony_ci .bit = 5, 18462306a36Sopenharmony_ci .prio_mask = 5, 18562306a36Sopenharmony_ci }, 18662306a36Sopenharmony_ci [22] = { 18762306a36Sopenharmony_ci .ack = IPIC_SEPNR, 18862306a36Sopenharmony_ci .mask = IPIC_SEMSR, 18962306a36Sopenharmony_ci .prio = IPIC_SMPRR_B, 19062306a36Sopenharmony_ci .force = IPIC_SEFCR, 19162306a36Sopenharmony_ci .bit = 6, 19262306a36Sopenharmony_ci .prio_mask = 6, 19362306a36Sopenharmony_ci }, 19462306a36Sopenharmony_ci [23] = { 19562306a36Sopenharmony_ci .ack = IPIC_SEPNR, 19662306a36Sopenharmony_ci .mask = IPIC_SEMSR, 19762306a36Sopenharmony_ci .prio = IPIC_SMPRR_B, 19862306a36Sopenharmony_ci .force = IPIC_SEFCR, 19962306a36Sopenharmony_ci .bit = 7, 20062306a36Sopenharmony_ci .prio_mask = 7, 20162306a36Sopenharmony_ci }, 20262306a36Sopenharmony_ci [32] = { 20362306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 20462306a36Sopenharmony_ci .prio = IPIC_SIPRR_A, 20562306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 20662306a36Sopenharmony_ci .bit = 0, 20762306a36Sopenharmony_ci .prio_mask = 0, 20862306a36Sopenharmony_ci }, 20962306a36Sopenharmony_ci [33] = { 21062306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 21162306a36Sopenharmony_ci .prio = IPIC_SIPRR_A, 21262306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 21362306a36Sopenharmony_ci .bit = 1, 21462306a36Sopenharmony_ci .prio_mask = 1, 21562306a36Sopenharmony_ci }, 21662306a36Sopenharmony_ci [34] = { 21762306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 21862306a36Sopenharmony_ci .prio = IPIC_SIPRR_A, 21962306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 22062306a36Sopenharmony_ci .bit = 2, 22162306a36Sopenharmony_ci .prio_mask = 2, 22262306a36Sopenharmony_ci }, 22362306a36Sopenharmony_ci [35] = { 22462306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 22562306a36Sopenharmony_ci .prio = IPIC_SIPRR_A, 22662306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 22762306a36Sopenharmony_ci .bit = 3, 22862306a36Sopenharmony_ci .prio_mask = 3, 22962306a36Sopenharmony_ci }, 23062306a36Sopenharmony_ci [36] = { 23162306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 23262306a36Sopenharmony_ci .prio = IPIC_SIPRR_A, 23362306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 23462306a36Sopenharmony_ci .bit = 4, 23562306a36Sopenharmony_ci .prio_mask = 4, 23662306a36Sopenharmony_ci }, 23762306a36Sopenharmony_ci [37] = { 23862306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 23962306a36Sopenharmony_ci .prio = IPIC_SIPRR_A, 24062306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 24162306a36Sopenharmony_ci .bit = 5, 24262306a36Sopenharmony_ci .prio_mask = 5, 24362306a36Sopenharmony_ci }, 24462306a36Sopenharmony_ci [38] = { 24562306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 24662306a36Sopenharmony_ci .prio = IPIC_SIPRR_A, 24762306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 24862306a36Sopenharmony_ci .bit = 6, 24962306a36Sopenharmony_ci .prio_mask = 6, 25062306a36Sopenharmony_ci }, 25162306a36Sopenharmony_ci [39] = { 25262306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 25362306a36Sopenharmony_ci .prio = IPIC_SIPRR_A, 25462306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 25562306a36Sopenharmony_ci .bit = 7, 25662306a36Sopenharmony_ci .prio_mask = 7, 25762306a36Sopenharmony_ci }, 25862306a36Sopenharmony_ci [40] = { 25962306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 26062306a36Sopenharmony_ci .prio = IPIC_SIPRR_B, 26162306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 26262306a36Sopenharmony_ci .bit = 8, 26362306a36Sopenharmony_ci .prio_mask = 0, 26462306a36Sopenharmony_ci }, 26562306a36Sopenharmony_ci [41] = { 26662306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 26762306a36Sopenharmony_ci .prio = IPIC_SIPRR_B, 26862306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 26962306a36Sopenharmony_ci .bit = 9, 27062306a36Sopenharmony_ci .prio_mask = 1, 27162306a36Sopenharmony_ci }, 27262306a36Sopenharmony_ci [42] = { 27362306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 27462306a36Sopenharmony_ci .prio = IPIC_SIPRR_B, 27562306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 27662306a36Sopenharmony_ci .bit = 10, 27762306a36Sopenharmony_ci .prio_mask = 2, 27862306a36Sopenharmony_ci }, 27962306a36Sopenharmony_ci [43] = { 28062306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 28162306a36Sopenharmony_ci .prio = IPIC_SIPRR_B, 28262306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 28362306a36Sopenharmony_ci .bit = 11, 28462306a36Sopenharmony_ci .prio_mask = 3, 28562306a36Sopenharmony_ci }, 28662306a36Sopenharmony_ci [44] = { 28762306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 28862306a36Sopenharmony_ci .prio = IPIC_SIPRR_B, 28962306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 29062306a36Sopenharmony_ci .bit = 12, 29162306a36Sopenharmony_ci .prio_mask = 4, 29262306a36Sopenharmony_ci }, 29362306a36Sopenharmony_ci [45] = { 29462306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 29562306a36Sopenharmony_ci .prio = IPIC_SIPRR_B, 29662306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 29762306a36Sopenharmony_ci .bit = 13, 29862306a36Sopenharmony_ci .prio_mask = 5, 29962306a36Sopenharmony_ci }, 30062306a36Sopenharmony_ci [46] = { 30162306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 30262306a36Sopenharmony_ci .prio = IPIC_SIPRR_B, 30362306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 30462306a36Sopenharmony_ci .bit = 14, 30562306a36Sopenharmony_ci .prio_mask = 6, 30662306a36Sopenharmony_ci }, 30762306a36Sopenharmony_ci [47] = { 30862306a36Sopenharmony_ci .mask = IPIC_SIMSR_H, 30962306a36Sopenharmony_ci .prio = IPIC_SIPRR_B, 31062306a36Sopenharmony_ci .force = IPIC_SIFCR_H, 31162306a36Sopenharmony_ci .bit = 15, 31262306a36Sopenharmony_ci .prio_mask = 7, 31362306a36Sopenharmony_ci }, 31462306a36Sopenharmony_ci [48] = { 31562306a36Sopenharmony_ci .ack = IPIC_SEPNR, 31662306a36Sopenharmony_ci .mask = IPIC_SEMSR, 31762306a36Sopenharmony_ci .prio = IPIC_SMPRR_A, 31862306a36Sopenharmony_ci .force = IPIC_SEFCR, 31962306a36Sopenharmony_ci .bit = 0, 32062306a36Sopenharmony_ci .prio_mask = 4, 32162306a36Sopenharmony_ci }, 32262306a36Sopenharmony_ci [64] = { 32362306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 32462306a36Sopenharmony_ci .prio = IPIC_SMPRR_A, 32562306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 32662306a36Sopenharmony_ci .bit = 0, 32762306a36Sopenharmony_ci .prio_mask = 0, 32862306a36Sopenharmony_ci }, 32962306a36Sopenharmony_ci [65] = { 33062306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 33162306a36Sopenharmony_ci .prio = IPIC_SMPRR_A, 33262306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 33362306a36Sopenharmony_ci .bit = 1, 33462306a36Sopenharmony_ci .prio_mask = 1, 33562306a36Sopenharmony_ci }, 33662306a36Sopenharmony_ci [66] = { 33762306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 33862306a36Sopenharmony_ci .prio = IPIC_SMPRR_A, 33962306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 34062306a36Sopenharmony_ci .bit = 2, 34162306a36Sopenharmony_ci .prio_mask = 2, 34262306a36Sopenharmony_ci }, 34362306a36Sopenharmony_ci [67] = { 34462306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 34562306a36Sopenharmony_ci .prio = IPIC_SMPRR_A, 34662306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 34762306a36Sopenharmony_ci .bit = 3, 34862306a36Sopenharmony_ci .prio_mask = 3, 34962306a36Sopenharmony_ci }, 35062306a36Sopenharmony_ci [68] = { 35162306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 35262306a36Sopenharmony_ci .prio = IPIC_SMPRR_B, 35362306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 35462306a36Sopenharmony_ci .bit = 4, 35562306a36Sopenharmony_ci .prio_mask = 0, 35662306a36Sopenharmony_ci }, 35762306a36Sopenharmony_ci [69] = { 35862306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 35962306a36Sopenharmony_ci .prio = IPIC_SMPRR_B, 36062306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 36162306a36Sopenharmony_ci .bit = 5, 36262306a36Sopenharmony_ci .prio_mask = 1, 36362306a36Sopenharmony_ci }, 36462306a36Sopenharmony_ci [70] = { 36562306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 36662306a36Sopenharmony_ci .prio = IPIC_SMPRR_B, 36762306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 36862306a36Sopenharmony_ci .bit = 6, 36962306a36Sopenharmony_ci .prio_mask = 2, 37062306a36Sopenharmony_ci }, 37162306a36Sopenharmony_ci [71] = { 37262306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 37362306a36Sopenharmony_ci .prio = IPIC_SMPRR_B, 37462306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 37562306a36Sopenharmony_ci .bit = 7, 37662306a36Sopenharmony_ci .prio_mask = 3, 37762306a36Sopenharmony_ci }, 37862306a36Sopenharmony_ci [72] = { 37962306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 38062306a36Sopenharmony_ci .prio = 0, 38162306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 38262306a36Sopenharmony_ci .bit = 8, 38362306a36Sopenharmony_ci }, 38462306a36Sopenharmony_ci [73] = { 38562306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 38662306a36Sopenharmony_ci .prio = 0, 38762306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 38862306a36Sopenharmony_ci .bit = 9, 38962306a36Sopenharmony_ci }, 39062306a36Sopenharmony_ci [74] = { 39162306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 39262306a36Sopenharmony_ci .prio = 0, 39362306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 39462306a36Sopenharmony_ci .bit = 10, 39562306a36Sopenharmony_ci }, 39662306a36Sopenharmony_ci [75] = { 39762306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 39862306a36Sopenharmony_ci .prio = 0, 39962306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 40062306a36Sopenharmony_ci .bit = 11, 40162306a36Sopenharmony_ci }, 40262306a36Sopenharmony_ci [76] = { 40362306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 40462306a36Sopenharmony_ci .prio = 0, 40562306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 40662306a36Sopenharmony_ci .bit = 12, 40762306a36Sopenharmony_ci }, 40862306a36Sopenharmony_ci [77] = { 40962306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 41062306a36Sopenharmony_ci .prio = 0, 41162306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 41262306a36Sopenharmony_ci .bit = 13, 41362306a36Sopenharmony_ci }, 41462306a36Sopenharmony_ci [78] = { 41562306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 41662306a36Sopenharmony_ci .prio = 0, 41762306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 41862306a36Sopenharmony_ci .bit = 14, 41962306a36Sopenharmony_ci }, 42062306a36Sopenharmony_ci [79] = { 42162306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 42262306a36Sopenharmony_ci .prio = 0, 42362306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 42462306a36Sopenharmony_ci .bit = 15, 42562306a36Sopenharmony_ci }, 42662306a36Sopenharmony_ci [80] = { 42762306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 42862306a36Sopenharmony_ci .prio = 0, 42962306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 43062306a36Sopenharmony_ci .bit = 16, 43162306a36Sopenharmony_ci }, 43262306a36Sopenharmony_ci [81] = { 43362306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 43462306a36Sopenharmony_ci .prio = 0, 43562306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 43662306a36Sopenharmony_ci .bit = 17, 43762306a36Sopenharmony_ci }, 43862306a36Sopenharmony_ci [82] = { 43962306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 44062306a36Sopenharmony_ci .prio = 0, 44162306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 44262306a36Sopenharmony_ci .bit = 18, 44362306a36Sopenharmony_ci }, 44462306a36Sopenharmony_ci [83] = { 44562306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 44662306a36Sopenharmony_ci .prio = 0, 44762306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 44862306a36Sopenharmony_ci .bit = 19, 44962306a36Sopenharmony_ci }, 45062306a36Sopenharmony_ci [84] = { 45162306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 45262306a36Sopenharmony_ci .prio = 0, 45362306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 45462306a36Sopenharmony_ci .bit = 20, 45562306a36Sopenharmony_ci }, 45662306a36Sopenharmony_ci [85] = { 45762306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 45862306a36Sopenharmony_ci .prio = 0, 45962306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 46062306a36Sopenharmony_ci .bit = 21, 46162306a36Sopenharmony_ci }, 46262306a36Sopenharmony_ci [86] = { 46362306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 46462306a36Sopenharmony_ci .prio = 0, 46562306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 46662306a36Sopenharmony_ci .bit = 22, 46762306a36Sopenharmony_ci }, 46862306a36Sopenharmony_ci [87] = { 46962306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 47062306a36Sopenharmony_ci .prio = 0, 47162306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 47262306a36Sopenharmony_ci .bit = 23, 47362306a36Sopenharmony_ci }, 47462306a36Sopenharmony_ci [88] = { 47562306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 47662306a36Sopenharmony_ci .prio = 0, 47762306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 47862306a36Sopenharmony_ci .bit = 24, 47962306a36Sopenharmony_ci }, 48062306a36Sopenharmony_ci [89] = { 48162306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 48262306a36Sopenharmony_ci .prio = 0, 48362306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 48462306a36Sopenharmony_ci .bit = 25, 48562306a36Sopenharmony_ci }, 48662306a36Sopenharmony_ci [90] = { 48762306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 48862306a36Sopenharmony_ci .prio = 0, 48962306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 49062306a36Sopenharmony_ci .bit = 26, 49162306a36Sopenharmony_ci }, 49262306a36Sopenharmony_ci [91] = { 49362306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 49462306a36Sopenharmony_ci .prio = 0, 49562306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 49662306a36Sopenharmony_ci .bit = 27, 49762306a36Sopenharmony_ci }, 49862306a36Sopenharmony_ci [94] = { 49962306a36Sopenharmony_ci .mask = IPIC_SIMSR_L, 50062306a36Sopenharmony_ci .prio = 0, 50162306a36Sopenharmony_ci .force = IPIC_SIFCR_L, 50262306a36Sopenharmony_ci .bit = 30, 50362306a36Sopenharmony_ci }, 50462306a36Sopenharmony_ci}; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_cistatic inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg) 50762306a36Sopenharmony_ci{ 50862306a36Sopenharmony_ci return in_be32(base + (reg >> 2)); 50962306a36Sopenharmony_ci} 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_cistatic inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value) 51262306a36Sopenharmony_ci{ 51362306a36Sopenharmony_ci out_be32(base + (reg >> 2), value); 51462306a36Sopenharmony_ci} 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_cistatic inline struct ipic * ipic_from_irq(unsigned int virq) 51762306a36Sopenharmony_ci{ 51862306a36Sopenharmony_ci return primary_ipic; 51962306a36Sopenharmony_ci} 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_cistatic void ipic_unmask_irq(struct irq_data *d) 52262306a36Sopenharmony_ci{ 52362306a36Sopenharmony_ci struct ipic *ipic = ipic_from_irq(d->irq); 52462306a36Sopenharmony_ci unsigned int src = irqd_to_hwirq(d); 52562306a36Sopenharmony_ci unsigned long flags; 52662306a36Sopenharmony_ci u32 temp; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci raw_spin_lock_irqsave(&ipic_lock, flags); 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci temp = ipic_read(ipic->regs, ipic_info[src].mask); 53162306a36Sopenharmony_ci temp |= (1 << (31 - ipic_info[src].bit)); 53262306a36Sopenharmony_ci ipic_write(ipic->regs, ipic_info[src].mask, temp); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci raw_spin_unlock_irqrestore(&ipic_lock, flags); 53562306a36Sopenharmony_ci} 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_cistatic void ipic_mask_irq(struct irq_data *d) 53862306a36Sopenharmony_ci{ 53962306a36Sopenharmony_ci struct ipic *ipic = ipic_from_irq(d->irq); 54062306a36Sopenharmony_ci unsigned int src = irqd_to_hwirq(d); 54162306a36Sopenharmony_ci unsigned long flags; 54262306a36Sopenharmony_ci u32 temp; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci raw_spin_lock_irqsave(&ipic_lock, flags); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci temp = ipic_read(ipic->regs, ipic_info[src].mask); 54762306a36Sopenharmony_ci temp &= ~(1 << (31 - ipic_info[src].bit)); 54862306a36Sopenharmony_ci ipic_write(ipic->regs, ipic_info[src].mask, temp); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci /* mb() can't guarantee that masking is finished. But it does finish 55162306a36Sopenharmony_ci * for nearly all cases. */ 55262306a36Sopenharmony_ci mb(); 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci raw_spin_unlock_irqrestore(&ipic_lock, flags); 55562306a36Sopenharmony_ci} 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_cistatic void ipic_ack_irq(struct irq_data *d) 55862306a36Sopenharmony_ci{ 55962306a36Sopenharmony_ci struct ipic *ipic = ipic_from_irq(d->irq); 56062306a36Sopenharmony_ci unsigned int src = irqd_to_hwirq(d); 56162306a36Sopenharmony_ci unsigned long flags; 56262306a36Sopenharmony_ci u32 temp; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci raw_spin_lock_irqsave(&ipic_lock, flags); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci temp = 1 << (31 - ipic_info[src].bit); 56762306a36Sopenharmony_ci ipic_write(ipic->regs, ipic_info[src].ack, temp); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci /* mb() can't guarantee that ack is finished. But it does finish 57062306a36Sopenharmony_ci * for nearly all cases. */ 57162306a36Sopenharmony_ci mb(); 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci raw_spin_unlock_irqrestore(&ipic_lock, flags); 57462306a36Sopenharmony_ci} 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_cistatic void ipic_mask_irq_and_ack(struct irq_data *d) 57762306a36Sopenharmony_ci{ 57862306a36Sopenharmony_ci struct ipic *ipic = ipic_from_irq(d->irq); 57962306a36Sopenharmony_ci unsigned int src = irqd_to_hwirq(d); 58062306a36Sopenharmony_ci unsigned long flags; 58162306a36Sopenharmony_ci u32 temp; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci raw_spin_lock_irqsave(&ipic_lock, flags); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci temp = ipic_read(ipic->regs, ipic_info[src].mask); 58662306a36Sopenharmony_ci temp &= ~(1 << (31 - ipic_info[src].bit)); 58762306a36Sopenharmony_ci ipic_write(ipic->regs, ipic_info[src].mask, temp); 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci temp = 1 << (31 - ipic_info[src].bit); 59062306a36Sopenharmony_ci ipic_write(ipic->regs, ipic_info[src].ack, temp); 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci /* mb() can't guarantee that ack is finished. But it does finish 59362306a36Sopenharmony_ci * for nearly all cases. */ 59462306a36Sopenharmony_ci mb(); 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci raw_spin_unlock_irqrestore(&ipic_lock, flags); 59762306a36Sopenharmony_ci} 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_cistatic int ipic_set_irq_type(struct irq_data *d, unsigned int flow_type) 60062306a36Sopenharmony_ci{ 60162306a36Sopenharmony_ci struct ipic *ipic = ipic_from_irq(d->irq); 60262306a36Sopenharmony_ci unsigned int src = irqd_to_hwirq(d); 60362306a36Sopenharmony_ci unsigned int vold, vnew, edibit; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci if (flow_type == IRQ_TYPE_NONE) 60662306a36Sopenharmony_ci flow_type = IRQ_TYPE_LEVEL_LOW; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci /* ipic supports only low assertion and high-to-low change senses 60962306a36Sopenharmony_ci */ 61062306a36Sopenharmony_ci if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) { 61162306a36Sopenharmony_ci printk(KERN_ERR "ipic: sense type 0x%x not supported\n", 61262306a36Sopenharmony_ci flow_type); 61362306a36Sopenharmony_ci return -EINVAL; 61462306a36Sopenharmony_ci } 61562306a36Sopenharmony_ci /* ipic supports only edge mode on external interrupts */ 61662306a36Sopenharmony_ci if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !ipic_info[src].ack) { 61762306a36Sopenharmony_ci printk(KERN_ERR "ipic: edge sense not supported on internal " 61862306a36Sopenharmony_ci "interrupts\n"); 61962306a36Sopenharmony_ci return -EINVAL; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci } 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci irqd_set_trigger_type(d, flow_type); 62462306a36Sopenharmony_ci if (flow_type & IRQ_TYPE_LEVEL_LOW) { 62562306a36Sopenharmony_ci irq_set_handler_locked(d, handle_level_irq); 62662306a36Sopenharmony_ci d->chip = &ipic_level_irq_chip; 62762306a36Sopenharmony_ci } else { 62862306a36Sopenharmony_ci irq_set_handler_locked(d, handle_edge_irq); 62962306a36Sopenharmony_ci d->chip = &ipic_edge_irq_chip; 63062306a36Sopenharmony_ci } 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci /* only EXT IRQ senses are programmable on ipic 63362306a36Sopenharmony_ci * internal IRQ senses are LEVEL_LOW 63462306a36Sopenharmony_ci */ 63562306a36Sopenharmony_ci if (src == IPIC_IRQ_EXT0) 63662306a36Sopenharmony_ci edibit = 15; 63762306a36Sopenharmony_ci else 63862306a36Sopenharmony_ci if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7) 63962306a36Sopenharmony_ci edibit = (14 - (src - IPIC_IRQ_EXT1)); 64062306a36Sopenharmony_ci else 64162306a36Sopenharmony_ci return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci vold = ipic_read(ipic->regs, IPIC_SECNR); 64462306a36Sopenharmony_ci if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) { 64562306a36Sopenharmony_ci vnew = vold | (1 << edibit); 64662306a36Sopenharmony_ci } else { 64762306a36Sopenharmony_ci vnew = vold & ~(1 << edibit); 64862306a36Sopenharmony_ci } 64962306a36Sopenharmony_ci if (vold != vnew) 65062306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SECNR, vnew); 65162306a36Sopenharmony_ci return IRQ_SET_MASK_OK_NOCOPY; 65262306a36Sopenharmony_ci} 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci/* level interrupts and edge interrupts have different ack operations */ 65562306a36Sopenharmony_cistatic struct irq_chip ipic_level_irq_chip = { 65662306a36Sopenharmony_ci .name = "IPIC", 65762306a36Sopenharmony_ci .irq_unmask = ipic_unmask_irq, 65862306a36Sopenharmony_ci .irq_mask = ipic_mask_irq, 65962306a36Sopenharmony_ci .irq_mask_ack = ipic_mask_irq, 66062306a36Sopenharmony_ci .irq_set_type = ipic_set_irq_type, 66162306a36Sopenharmony_ci}; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_cistatic struct irq_chip ipic_edge_irq_chip = { 66462306a36Sopenharmony_ci .name = "IPIC", 66562306a36Sopenharmony_ci .irq_unmask = ipic_unmask_irq, 66662306a36Sopenharmony_ci .irq_mask = ipic_mask_irq, 66762306a36Sopenharmony_ci .irq_mask_ack = ipic_mask_irq_and_ack, 66862306a36Sopenharmony_ci .irq_ack = ipic_ack_irq, 66962306a36Sopenharmony_ci .irq_set_type = ipic_set_irq_type, 67062306a36Sopenharmony_ci}; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_cistatic int ipic_host_match(struct irq_domain *h, struct device_node *node, 67362306a36Sopenharmony_ci enum irq_domain_bus_token bus_token) 67462306a36Sopenharmony_ci{ 67562306a36Sopenharmony_ci /* Exact match, unless ipic node is NULL */ 67662306a36Sopenharmony_ci struct device_node *of_node = irq_domain_get_of_node(h); 67762306a36Sopenharmony_ci return of_node == NULL || of_node == node; 67862306a36Sopenharmony_ci} 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_cistatic int ipic_host_map(struct irq_domain *h, unsigned int virq, 68162306a36Sopenharmony_ci irq_hw_number_t hw) 68262306a36Sopenharmony_ci{ 68362306a36Sopenharmony_ci struct ipic *ipic = h->host_data; 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci irq_set_chip_data(virq, ipic); 68662306a36Sopenharmony_ci irq_set_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq); 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci /* Set default irq type */ 68962306a36Sopenharmony_ci irq_set_irq_type(virq, IRQ_TYPE_NONE); 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci return 0; 69262306a36Sopenharmony_ci} 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_cistatic const struct irq_domain_ops ipic_host_ops = { 69562306a36Sopenharmony_ci .match = ipic_host_match, 69662306a36Sopenharmony_ci .map = ipic_host_map, 69762306a36Sopenharmony_ci .xlate = irq_domain_xlate_onetwocell, 69862306a36Sopenharmony_ci}; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_cistruct ipic * __init ipic_init(struct device_node *node, unsigned int flags) 70162306a36Sopenharmony_ci{ 70262306a36Sopenharmony_ci struct ipic *ipic; 70362306a36Sopenharmony_ci struct resource res; 70462306a36Sopenharmony_ci u32 temp = 0, ret; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci ret = of_address_to_resource(node, 0, &res); 70762306a36Sopenharmony_ci if (ret) 70862306a36Sopenharmony_ci return NULL; 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci ipic = kzalloc(sizeof(*ipic), GFP_KERNEL); 71162306a36Sopenharmony_ci if (ipic == NULL) 71262306a36Sopenharmony_ci return NULL; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci ipic->irqhost = irq_domain_add_linear(node, NR_IPIC_INTS, 71562306a36Sopenharmony_ci &ipic_host_ops, ipic); 71662306a36Sopenharmony_ci if (ipic->irqhost == NULL) { 71762306a36Sopenharmony_ci kfree(ipic); 71862306a36Sopenharmony_ci return NULL; 71962306a36Sopenharmony_ci } 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci ipic->regs = ioremap(res.start, resource_size(&res)); 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci /* init hw */ 72462306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SICNR, 0x0); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci /* default priority scheme is grouped. If spread mode is required 72762306a36Sopenharmony_ci * configure SICFR accordingly */ 72862306a36Sopenharmony_ci if (flags & IPIC_SPREADMODE_GRP_A) 72962306a36Sopenharmony_ci temp |= SICFR_IPSA; 73062306a36Sopenharmony_ci if (flags & IPIC_SPREADMODE_GRP_B) 73162306a36Sopenharmony_ci temp |= SICFR_IPSB; 73262306a36Sopenharmony_ci if (flags & IPIC_SPREADMODE_GRP_C) 73362306a36Sopenharmony_ci temp |= SICFR_IPSC; 73462306a36Sopenharmony_ci if (flags & IPIC_SPREADMODE_GRP_D) 73562306a36Sopenharmony_ci temp |= SICFR_IPSD; 73662306a36Sopenharmony_ci if (flags & IPIC_SPREADMODE_MIX_A) 73762306a36Sopenharmony_ci temp |= SICFR_MPSA; 73862306a36Sopenharmony_ci if (flags & IPIC_SPREADMODE_MIX_B) 73962306a36Sopenharmony_ci temp |= SICFR_MPSB; 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SICFR, temp); 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci /* handle MCP route */ 74462306a36Sopenharmony_ci temp = 0; 74562306a36Sopenharmony_ci if (flags & IPIC_DISABLE_MCP_OUT) 74662306a36Sopenharmony_ci temp = SERCR_MCPR; 74762306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SERCR, temp); 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci /* handle routing of IRQ0 to MCP */ 75062306a36Sopenharmony_ci temp = ipic_read(ipic->regs, IPIC_SEMSR); 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci if (flags & IPIC_IRQ0_MCP) 75362306a36Sopenharmony_ci temp |= SEMSR_SIRQ0; 75462306a36Sopenharmony_ci else 75562306a36Sopenharmony_ci temp &= ~SEMSR_SIRQ0; 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SEMSR, temp); 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci primary_ipic = ipic; 76062306a36Sopenharmony_ci irq_set_default_host(primary_ipic->irqhost); 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SIMSR_H, 0); 76362306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SIMSR_L, 0); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS, 76662306a36Sopenharmony_ci primary_ipic->regs); 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci return ipic; 76962306a36Sopenharmony_ci} 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_civoid __init ipic_set_default_priority(void) 77262306a36Sopenharmony_ci{ 77362306a36Sopenharmony_ci ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_PRIORITY_DEFAULT); 77462306a36Sopenharmony_ci ipic_write(primary_ipic->regs, IPIC_SIPRR_B, IPIC_PRIORITY_DEFAULT); 77562306a36Sopenharmony_ci ipic_write(primary_ipic->regs, IPIC_SIPRR_C, IPIC_PRIORITY_DEFAULT); 77662306a36Sopenharmony_ci ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_PRIORITY_DEFAULT); 77762306a36Sopenharmony_ci ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_PRIORITY_DEFAULT); 77862306a36Sopenharmony_ci ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_PRIORITY_DEFAULT); 77962306a36Sopenharmony_ci} 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ciu32 ipic_get_mcp_status(void) 78262306a36Sopenharmony_ci{ 78362306a36Sopenharmony_ci return primary_ipic ? ipic_read(primary_ipic->regs, IPIC_SERSR) : 0; 78462306a36Sopenharmony_ci} 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_civoid ipic_clear_mcp_status(u32 mask) 78762306a36Sopenharmony_ci{ 78862306a36Sopenharmony_ci ipic_write(primary_ipic->regs, IPIC_SERSR, mask); 78962306a36Sopenharmony_ci} 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci/* Return an interrupt vector or 0 if no interrupt is pending. */ 79262306a36Sopenharmony_ciunsigned int ipic_get_irq(void) 79362306a36Sopenharmony_ci{ 79462306a36Sopenharmony_ci int irq; 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci BUG_ON(primary_ipic == NULL); 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci#define IPIC_SIVCR_VECTOR_MASK 0x7f 79962306a36Sopenharmony_ci irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci if (irq == 0) /* 0 --> no irq is pending */ 80262306a36Sopenharmony_ci return 0; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci return irq_linear_revmap(primary_ipic->irqhost, irq); 80562306a36Sopenharmony_ci} 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci#ifdef CONFIG_SUSPEND 80862306a36Sopenharmony_cistatic struct { 80962306a36Sopenharmony_ci u32 sicfr; 81062306a36Sopenharmony_ci u32 siprr[2]; 81162306a36Sopenharmony_ci u32 simsr[2]; 81262306a36Sopenharmony_ci u32 sicnr; 81362306a36Sopenharmony_ci u32 smprr[2]; 81462306a36Sopenharmony_ci u32 semsr; 81562306a36Sopenharmony_ci u32 secnr; 81662306a36Sopenharmony_ci u32 sermr; 81762306a36Sopenharmony_ci u32 sercr; 81862306a36Sopenharmony_ci} ipic_saved_state; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_cistatic int ipic_suspend(void) 82162306a36Sopenharmony_ci{ 82262306a36Sopenharmony_ci struct ipic *ipic = primary_ipic; 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci ipic_saved_state.sicfr = ipic_read(ipic->regs, IPIC_SICFR); 82562306a36Sopenharmony_ci ipic_saved_state.siprr[0] = ipic_read(ipic->regs, IPIC_SIPRR_A); 82662306a36Sopenharmony_ci ipic_saved_state.siprr[1] = ipic_read(ipic->regs, IPIC_SIPRR_D); 82762306a36Sopenharmony_ci ipic_saved_state.simsr[0] = ipic_read(ipic->regs, IPIC_SIMSR_H); 82862306a36Sopenharmony_ci ipic_saved_state.simsr[1] = ipic_read(ipic->regs, IPIC_SIMSR_L); 82962306a36Sopenharmony_ci ipic_saved_state.sicnr = ipic_read(ipic->regs, IPIC_SICNR); 83062306a36Sopenharmony_ci ipic_saved_state.smprr[0] = ipic_read(ipic->regs, IPIC_SMPRR_A); 83162306a36Sopenharmony_ci ipic_saved_state.smprr[1] = ipic_read(ipic->regs, IPIC_SMPRR_B); 83262306a36Sopenharmony_ci ipic_saved_state.semsr = ipic_read(ipic->regs, IPIC_SEMSR); 83362306a36Sopenharmony_ci ipic_saved_state.secnr = ipic_read(ipic->regs, IPIC_SECNR); 83462306a36Sopenharmony_ci ipic_saved_state.sermr = ipic_read(ipic->regs, IPIC_SERMR); 83562306a36Sopenharmony_ci ipic_saved_state.sercr = ipic_read(ipic->regs, IPIC_SERCR); 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci if (fsl_deep_sleep()) { 83862306a36Sopenharmony_ci /* In deep sleep, make sure there can be no 83962306a36Sopenharmony_ci * pending interrupts, as this can cause 84062306a36Sopenharmony_ci * problems on 831x. 84162306a36Sopenharmony_ci */ 84262306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SIMSR_H, 0); 84362306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SIMSR_L, 0); 84462306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SEMSR, 0); 84562306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SERMR, 0); 84662306a36Sopenharmony_ci } 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci return 0; 84962306a36Sopenharmony_ci} 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_cistatic void ipic_resume(void) 85262306a36Sopenharmony_ci{ 85362306a36Sopenharmony_ci struct ipic *ipic = primary_ipic; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SICFR, ipic_saved_state.sicfr); 85662306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SIPRR_A, ipic_saved_state.siprr[0]); 85762306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SIPRR_D, ipic_saved_state.siprr[1]); 85862306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SIMSR_H, ipic_saved_state.simsr[0]); 85962306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SIMSR_L, ipic_saved_state.simsr[1]); 86062306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SICNR, ipic_saved_state.sicnr); 86162306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SMPRR_A, ipic_saved_state.smprr[0]); 86262306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SMPRR_B, ipic_saved_state.smprr[1]); 86362306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SEMSR, ipic_saved_state.semsr); 86462306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SECNR, ipic_saved_state.secnr); 86562306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SERMR, ipic_saved_state.sermr); 86662306a36Sopenharmony_ci ipic_write(ipic->regs, IPIC_SERCR, ipic_saved_state.sercr); 86762306a36Sopenharmony_ci} 86862306a36Sopenharmony_ci#else 86962306a36Sopenharmony_ci#define ipic_suspend NULL 87062306a36Sopenharmony_ci#define ipic_resume NULL 87162306a36Sopenharmony_ci#endif 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_cistatic struct syscore_ops ipic_syscore_ops = { 87462306a36Sopenharmony_ci .suspend = ipic_suspend, 87562306a36Sopenharmony_ci .resume = ipic_resume, 87662306a36Sopenharmony_ci}; 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_cistatic int __init init_ipic_syscore(void) 87962306a36Sopenharmony_ci{ 88062306a36Sopenharmony_ci if (!primary_ipic || !primary_ipic->regs) 88162306a36Sopenharmony_ci return -ENODEV; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci printk(KERN_DEBUG "Registering ipic system core operations\n"); 88462306a36Sopenharmony_ci register_syscore_ops(&ipic_syscore_ops); 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci return 0; 88762306a36Sopenharmony_ci} 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_cisubsys_initcall(init_ipic_syscore); 890