18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * arch/powerpc/sysdev/ipic.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * IPIC routines implementations.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Copyright 2005 Freescale Semiconductor, Inc.
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci#include <linux/kernel.h>
108c2ecf20Sopenharmony_ci#include <linux/init.h>
118c2ecf20Sopenharmony_ci#include <linux/errno.h>
128c2ecf20Sopenharmony_ci#include <linux/reboot.h>
138c2ecf20Sopenharmony_ci#include <linux/slab.h>
148c2ecf20Sopenharmony_ci#include <linux/stddef.h>
158c2ecf20Sopenharmony_ci#include <linux/sched.h>
168c2ecf20Sopenharmony_ci#include <linux/signal.h>
178c2ecf20Sopenharmony_ci#include <linux/syscore_ops.h>
188c2ecf20Sopenharmony_ci#include <linux/device.h>
198c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
208c2ecf20Sopenharmony_ci#include <linux/fsl_devices.h>
218c2ecf20Sopenharmony_ci#include <asm/irq.h>
228c2ecf20Sopenharmony_ci#include <asm/io.h>
238c2ecf20Sopenharmony_ci#include <asm/prom.h>
248c2ecf20Sopenharmony_ci#include <asm/ipic.h>
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#include "ipic.h"
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistatic struct ipic * primary_ipic;
298c2ecf20Sopenharmony_cistatic struct irq_chip ipic_level_irq_chip, ipic_edge_irq_chip;
308c2ecf20Sopenharmony_cistatic DEFINE_RAW_SPINLOCK(ipic_lock);
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic struct ipic_info ipic_info[] = {
338c2ecf20Sopenharmony_ci	[1] = {
348c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
358c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_C,
368c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
378c2ecf20Sopenharmony_ci		.bit	= 16,
388c2ecf20Sopenharmony_ci		.prio_mask = 0,
398c2ecf20Sopenharmony_ci	},
408c2ecf20Sopenharmony_ci	[2] = {
418c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
428c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_C,
438c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
448c2ecf20Sopenharmony_ci		.bit	= 17,
458c2ecf20Sopenharmony_ci		.prio_mask = 1,
468c2ecf20Sopenharmony_ci	},
478c2ecf20Sopenharmony_ci	[3] = {
488c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
498c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_C,
508c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
518c2ecf20Sopenharmony_ci		.bit	= 18,
528c2ecf20Sopenharmony_ci		.prio_mask = 2,
538c2ecf20Sopenharmony_ci	},
548c2ecf20Sopenharmony_ci	[4] = {
558c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
568c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_C,
578c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
588c2ecf20Sopenharmony_ci		.bit	= 19,
598c2ecf20Sopenharmony_ci		.prio_mask = 3,
608c2ecf20Sopenharmony_ci	},
618c2ecf20Sopenharmony_ci	[5] = {
628c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
638c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_C,
648c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
658c2ecf20Sopenharmony_ci		.bit	= 20,
668c2ecf20Sopenharmony_ci		.prio_mask = 4,
678c2ecf20Sopenharmony_ci	},
688c2ecf20Sopenharmony_ci	[6] = {
698c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
708c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_C,
718c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
728c2ecf20Sopenharmony_ci		.bit	= 21,
738c2ecf20Sopenharmony_ci		.prio_mask = 5,
748c2ecf20Sopenharmony_ci	},
758c2ecf20Sopenharmony_ci	[7] = {
768c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
778c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_C,
788c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
798c2ecf20Sopenharmony_ci		.bit	= 22,
808c2ecf20Sopenharmony_ci		.prio_mask = 6,
818c2ecf20Sopenharmony_ci	},
828c2ecf20Sopenharmony_ci	[8] = {
838c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
848c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_C,
858c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
868c2ecf20Sopenharmony_ci		.bit	= 23,
878c2ecf20Sopenharmony_ci		.prio_mask = 7,
888c2ecf20Sopenharmony_ci	},
898c2ecf20Sopenharmony_ci	[9] = {
908c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
918c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_D,
928c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
938c2ecf20Sopenharmony_ci		.bit	= 24,
948c2ecf20Sopenharmony_ci		.prio_mask = 0,
958c2ecf20Sopenharmony_ci	},
968c2ecf20Sopenharmony_ci	[10] = {
978c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
988c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_D,
998c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
1008c2ecf20Sopenharmony_ci		.bit	= 25,
1018c2ecf20Sopenharmony_ci		.prio_mask = 1,
1028c2ecf20Sopenharmony_ci	},
1038c2ecf20Sopenharmony_ci	[11] = {
1048c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
1058c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_D,
1068c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
1078c2ecf20Sopenharmony_ci		.bit	= 26,
1088c2ecf20Sopenharmony_ci		.prio_mask = 2,
1098c2ecf20Sopenharmony_ci	},
1108c2ecf20Sopenharmony_ci	[12] = {
1118c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
1128c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_D,
1138c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
1148c2ecf20Sopenharmony_ci		.bit	= 27,
1158c2ecf20Sopenharmony_ci		.prio_mask = 3,
1168c2ecf20Sopenharmony_ci	},
1178c2ecf20Sopenharmony_ci	[13] = {
1188c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
1198c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_D,
1208c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
1218c2ecf20Sopenharmony_ci		.bit	= 28,
1228c2ecf20Sopenharmony_ci		.prio_mask = 4,
1238c2ecf20Sopenharmony_ci	},
1248c2ecf20Sopenharmony_ci	[14] = {
1258c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
1268c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_D,
1278c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
1288c2ecf20Sopenharmony_ci		.bit	= 29,
1298c2ecf20Sopenharmony_ci		.prio_mask = 5,
1308c2ecf20Sopenharmony_ci	},
1318c2ecf20Sopenharmony_ci	[15] = {
1328c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
1338c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_D,
1348c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
1358c2ecf20Sopenharmony_ci		.bit	= 30,
1368c2ecf20Sopenharmony_ci		.prio_mask = 6,
1378c2ecf20Sopenharmony_ci	},
1388c2ecf20Sopenharmony_ci	[16] = {
1398c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
1408c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_D,
1418c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
1428c2ecf20Sopenharmony_ci		.bit	= 31,
1438c2ecf20Sopenharmony_ci		.prio_mask = 7,
1448c2ecf20Sopenharmony_ci	},
1458c2ecf20Sopenharmony_ci	[17] = {
1468c2ecf20Sopenharmony_ci		.ack	= IPIC_SEPNR,
1478c2ecf20Sopenharmony_ci		.mask	= IPIC_SEMSR,
1488c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_A,
1498c2ecf20Sopenharmony_ci		.force	= IPIC_SEFCR,
1508c2ecf20Sopenharmony_ci		.bit	= 1,
1518c2ecf20Sopenharmony_ci		.prio_mask = 5,
1528c2ecf20Sopenharmony_ci	},
1538c2ecf20Sopenharmony_ci	[18] = {
1548c2ecf20Sopenharmony_ci		.ack	= IPIC_SEPNR,
1558c2ecf20Sopenharmony_ci		.mask	= IPIC_SEMSR,
1568c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_A,
1578c2ecf20Sopenharmony_ci		.force	= IPIC_SEFCR,
1588c2ecf20Sopenharmony_ci		.bit	= 2,
1598c2ecf20Sopenharmony_ci		.prio_mask = 6,
1608c2ecf20Sopenharmony_ci	},
1618c2ecf20Sopenharmony_ci	[19] = {
1628c2ecf20Sopenharmony_ci		.ack	= IPIC_SEPNR,
1638c2ecf20Sopenharmony_ci		.mask	= IPIC_SEMSR,
1648c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_A,
1658c2ecf20Sopenharmony_ci		.force	= IPIC_SEFCR,
1668c2ecf20Sopenharmony_ci		.bit	= 3,
1678c2ecf20Sopenharmony_ci		.prio_mask = 7,
1688c2ecf20Sopenharmony_ci	},
1698c2ecf20Sopenharmony_ci	[20] = {
1708c2ecf20Sopenharmony_ci		.ack	= IPIC_SEPNR,
1718c2ecf20Sopenharmony_ci		.mask	= IPIC_SEMSR,
1728c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_B,
1738c2ecf20Sopenharmony_ci		.force	= IPIC_SEFCR,
1748c2ecf20Sopenharmony_ci		.bit	= 4,
1758c2ecf20Sopenharmony_ci		.prio_mask = 4,
1768c2ecf20Sopenharmony_ci	},
1778c2ecf20Sopenharmony_ci	[21] = {
1788c2ecf20Sopenharmony_ci		.ack	= IPIC_SEPNR,
1798c2ecf20Sopenharmony_ci		.mask	= IPIC_SEMSR,
1808c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_B,
1818c2ecf20Sopenharmony_ci		.force	= IPIC_SEFCR,
1828c2ecf20Sopenharmony_ci		.bit	= 5,
1838c2ecf20Sopenharmony_ci		.prio_mask = 5,
1848c2ecf20Sopenharmony_ci	},
1858c2ecf20Sopenharmony_ci	[22] = {
1868c2ecf20Sopenharmony_ci		.ack	= IPIC_SEPNR,
1878c2ecf20Sopenharmony_ci		.mask	= IPIC_SEMSR,
1888c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_B,
1898c2ecf20Sopenharmony_ci		.force	= IPIC_SEFCR,
1908c2ecf20Sopenharmony_ci		.bit	= 6,
1918c2ecf20Sopenharmony_ci		.prio_mask = 6,
1928c2ecf20Sopenharmony_ci	},
1938c2ecf20Sopenharmony_ci	[23] = {
1948c2ecf20Sopenharmony_ci		.ack	= IPIC_SEPNR,
1958c2ecf20Sopenharmony_ci		.mask	= IPIC_SEMSR,
1968c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_B,
1978c2ecf20Sopenharmony_ci		.force	= IPIC_SEFCR,
1988c2ecf20Sopenharmony_ci		.bit	= 7,
1998c2ecf20Sopenharmony_ci		.prio_mask = 7,
2008c2ecf20Sopenharmony_ci	},
2018c2ecf20Sopenharmony_ci	[32] = {
2028c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
2038c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_A,
2048c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
2058c2ecf20Sopenharmony_ci		.bit	= 0,
2068c2ecf20Sopenharmony_ci		.prio_mask = 0,
2078c2ecf20Sopenharmony_ci	},
2088c2ecf20Sopenharmony_ci	[33] = {
2098c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
2108c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_A,
2118c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
2128c2ecf20Sopenharmony_ci		.bit	= 1,
2138c2ecf20Sopenharmony_ci		.prio_mask = 1,
2148c2ecf20Sopenharmony_ci	},
2158c2ecf20Sopenharmony_ci	[34] = {
2168c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
2178c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_A,
2188c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
2198c2ecf20Sopenharmony_ci		.bit	= 2,
2208c2ecf20Sopenharmony_ci		.prio_mask = 2,
2218c2ecf20Sopenharmony_ci	},
2228c2ecf20Sopenharmony_ci	[35] = {
2238c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
2248c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_A,
2258c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
2268c2ecf20Sopenharmony_ci		.bit	= 3,
2278c2ecf20Sopenharmony_ci		.prio_mask = 3,
2288c2ecf20Sopenharmony_ci	},
2298c2ecf20Sopenharmony_ci	[36] = {
2308c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
2318c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_A,
2328c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
2338c2ecf20Sopenharmony_ci		.bit	= 4,
2348c2ecf20Sopenharmony_ci		.prio_mask = 4,
2358c2ecf20Sopenharmony_ci	},
2368c2ecf20Sopenharmony_ci	[37] = {
2378c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
2388c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_A,
2398c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
2408c2ecf20Sopenharmony_ci		.bit	= 5,
2418c2ecf20Sopenharmony_ci		.prio_mask = 5,
2428c2ecf20Sopenharmony_ci	},
2438c2ecf20Sopenharmony_ci	[38] = {
2448c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
2458c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_A,
2468c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
2478c2ecf20Sopenharmony_ci		.bit	= 6,
2488c2ecf20Sopenharmony_ci		.prio_mask = 6,
2498c2ecf20Sopenharmony_ci	},
2508c2ecf20Sopenharmony_ci	[39] = {
2518c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
2528c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_A,
2538c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
2548c2ecf20Sopenharmony_ci		.bit	= 7,
2558c2ecf20Sopenharmony_ci		.prio_mask = 7,
2568c2ecf20Sopenharmony_ci	},
2578c2ecf20Sopenharmony_ci	[40] = {
2588c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
2598c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_B,
2608c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
2618c2ecf20Sopenharmony_ci		.bit	= 8,
2628c2ecf20Sopenharmony_ci		.prio_mask = 0,
2638c2ecf20Sopenharmony_ci	},
2648c2ecf20Sopenharmony_ci	[41] = {
2658c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
2668c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_B,
2678c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
2688c2ecf20Sopenharmony_ci		.bit	= 9,
2698c2ecf20Sopenharmony_ci		.prio_mask = 1,
2708c2ecf20Sopenharmony_ci	},
2718c2ecf20Sopenharmony_ci	[42] = {
2728c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
2738c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_B,
2748c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
2758c2ecf20Sopenharmony_ci		.bit	= 10,
2768c2ecf20Sopenharmony_ci		.prio_mask = 2,
2778c2ecf20Sopenharmony_ci	},
2788c2ecf20Sopenharmony_ci	[43] = {
2798c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
2808c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_B,
2818c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
2828c2ecf20Sopenharmony_ci		.bit	= 11,
2838c2ecf20Sopenharmony_ci		.prio_mask = 3,
2848c2ecf20Sopenharmony_ci	},
2858c2ecf20Sopenharmony_ci	[44] = {
2868c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
2878c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_B,
2888c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
2898c2ecf20Sopenharmony_ci		.bit	= 12,
2908c2ecf20Sopenharmony_ci		.prio_mask = 4,
2918c2ecf20Sopenharmony_ci	},
2928c2ecf20Sopenharmony_ci	[45] = {
2938c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
2948c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_B,
2958c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
2968c2ecf20Sopenharmony_ci		.bit	= 13,
2978c2ecf20Sopenharmony_ci		.prio_mask = 5,
2988c2ecf20Sopenharmony_ci	},
2998c2ecf20Sopenharmony_ci	[46] = {
3008c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
3018c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_B,
3028c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
3038c2ecf20Sopenharmony_ci		.bit	= 14,
3048c2ecf20Sopenharmony_ci		.prio_mask = 6,
3058c2ecf20Sopenharmony_ci	},
3068c2ecf20Sopenharmony_ci	[47] = {
3078c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_H,
3088c2ecf20Sopenharmony_ci		.prio	= IPIC_SIPRR_B,
3098c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_H,
3108c2ecf20Sopenharmony_ci		.bit	= 15,
3118c2ecf20Sopenharmony_ci		.prio_mask = 7,
3128c2ecf20Sopenharmony_ci	},
3138c2ecf20Sopenharmony_ci	[48] = {
3148c2ecf20Sopenharmony_ci		.ack	= IPIC_SEPNR,
3158c2ecf20Sopenharmony_ci		.mask	= IPIC_SEMSR,
3168c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_A,
3178c2ecf20Sopenharmony_ci		.force	= IPIC_SEFCR,
3188c2ecf20Sopenharmony_ci		.bit	= 0,
3198c2ecf20Sopenharmony_ci		.prio_mask = 4,
3208c2ecf20Sopenharmony_ci	},
3218c2ecf20Sopenharmony_ci	[64] = {
3228c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
3238c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_A,
3248c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
3258c2ecf20Sopenharmony_ci		.bit	= 0,
3268c2ecf20Sopenharmony_ci		.prio_mask = 0,
3278c2ecf20Sopenharmony_ci	},
3288c2ecf20Sopenharmony_ci	[65] = {
3298c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
3308c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_A,
3318c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
3328c2ecf20Sopenharmony_ci		.bit	= 1,
3338c2ecf20Sopenharmony_ci		.prio_mask = 1,
3348c2ecf20Sopenharmony_ci	},
3358c2ecf20Sopenharmony_ci	[66] = {
3368c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
3378c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_A,
3388c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
3398c2ecf20Sopenharmony_ci		.bit	= 2,
3408c2ecf20Sopenharmony_ci		.prio_mask = 2,
3418c2ecf20Sopenharmony_ci	},
3428c2ecf20Sopenharmony_ci	[67] = {
3438c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
3448c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_A,
3458c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
3468c2ecf20Sopenharmony_ci		.bit	= 3,
3478c2ecf20Sopenharmony_ci		.prio_mask = 3,
3488c2ecf20Sopenharmony_ci	},
3498c2ecf20Sopenharmony_ci	[68] = {
3508c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
3518c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_B,
3528c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
3538c2ecf20Sopenharmony_ci		.bit	= 4,
3548c2ecf20Sopenharmony_ci		.prio_mask = 0,
3558c2ecf20Sopenharmony_ci	},
3568c2ecf20Sopenharmony_ci	[69] = {
3578c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
3588c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_B,
3598c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
3608c2ecf20Sopenharmony_ci		.bit	= 5,
3618c2ecf20Sopenharmony_ci		.prio_mask = 1,
3628c2ecf20Sopenharmony_ci	},
3638c2ecf20Sopenharmony_ci	[70] = {
3648c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
3658c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_B,
3668c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
3678c2ecf20Sopenharmony_ci		.bit	= 6,
3688c2ecf20Sopenharmony_ci		.prio_mask = 2,
3698c2ecf20Sopenharmony_ci	},
3708c2ecf20Sopenharmony_ci	[71] = {
3718c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
3728c2ecf20Sopenharmony_ci		.prio	= IPIC_SMPRR_B,
3738c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
3748c2ecf20Sopenharmony_ci		.bit	= 7,
3758c2ecf20Sopenharmony_ci		.prio_mask = 3,
3768c2ecf20Sopenharmony_ci	},
3778c2ecf20Sopenharmony_ci	[72] = {
3788c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
3798c2ecf20Sopenharmony_ci		.prio	= 0,
3808c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
3818c2ecf20Sopenharmony_ci		.bit	= 8,
3828c2ecf20Sopenharmony_ci	},
3838c2ecf20Sopenharmony_ci	[73] = {
3848c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
3858c2ecf20Sopenharmony_ci		.prio	= 0,
3868c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
3878c2ecf20Sopenharmony_ci		.bit	= 9,
3888c2ecf20Sopenharmony_ci	},
3898c2ecf20Sopenharmony_ci	[74] = {
3908c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
3918c2ecf20Sopenharmony_ci		.prio	= 0,
3928c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
3938c2ecf20Sopenharmony_ci		.bit	= 10,
3948c2ecf20Sopenharmony_ci	},
3958c2ecf20Sopenharmony_ci	[75] = {
3968c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
3978c2ecf20Sopenharmony_ci		.prio	= 0,
3988c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
3998c2ecf20Sopenharmony_ci		.bit	= 11,
4008c2ecf20Sopenharmony_ci	},
4018c2ecf20Sopenharmony_ci	[76] = {
4028c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4038c2ecf20Sopenharmony_ci		.prio	= 0,
4048c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4058c2ecf20Sopenharmony_ci		.bit	= 12,
4068c2ecf20Sopenharmony_ci	},
4078c2ecf20Sopenharmony_ci	[77] = {
4088c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4098c2ecf20Sopenharmony_ci		.prio	= 0,
4108c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4118c2ecf20Sopenharmony_ci		.bit	= 13,
4128c2ecf20Sopenharmony_ci	},
4138c2ecf20Sopenharmony_ci	[78] = {
4148c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4158c2ecf20Sopenharmony_ci		.prio	= 0,
4168c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4178c2ecf20Sopenharmony_ci		.bit	= 14,
4188c2ecf20Sopenharmony_ci	},
4198c2ecf20Sopenharmony_ci	[79] = {
4208c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4218c2ecf20Sopenharmony_ci		.prio	= 0,
4228c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4238c2ecf20Sopenharmony_ci		.bit	= 15,
4248c2ecf20Sopenharmony_ci	},
4258c2ecf20Sopenharmony_ci	[80] = {
4268c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4278c2ecf20Sopenharmony_ci		.prio	= 0,
4288c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4298c2ecf20Sopenharmony_ci		.bit	= 16,
4308c2ecf20Sopenharmony_ci	},
4318c2ecf20Sopenharmony_ci	[81] = {
4328c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4338c2ecf20Sopenharmony_ci		.prio	= 0,
4348c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4358c2ecf20Sopenharmony_ci		.bit	= 17,
4368c2ecf20Sopenharmony_ci	},
4378c2ecf20Sopenharmony_ci	[82] = {
4388c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4398c2ecf20Sopenharmony_ci		.prio	= 0,
4408c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4418c2ecf20Sopenharmony_ci		.bit	= 18,
4428c2ecf20Sopenharmony_ci	},
4438c2ecf20Sopenharmony_ci	[83] = {
4448c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4458c2ecf20Sopenharmony_ci		.prio	= 0,
4468c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4478c2ecf20Sopenharmony_ci		.bit	= 19,
4488c2ecf20Sopenharmony_ci	},
4498c2ecf20Sopenharmony_ci	[84] = {
4508c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4518c2ecf20Sopenharmony_ci		.prio	= 0,
4528c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4538c2ecf20Sopenharmony_ci		.bit	= 20,
4548c2ecf20Sopenharmony_ci	},
4558c2ecf20Sopenharmony_ci	[85] = {
4568c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4578c2ecf20Sopenharmony_ci		.prio	= 0,
4588c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4598c2ecf20Sopenharmony_ci		.bit	= 21,
4608c2ecf20Sopenharmony_ci	},
4618c2ecf20Sopenharmony_ci	[86] = {
4628c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4638c2ecf20Sopenharmony_ci		.prio	= 0,
4648c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4658c2ecf20Sopenharmony_ci		.bit	= 22,
4668c2ecf20Sopenharmony_ci	},
4678c2ecf20Sopenharmony_ci	[87] = {
4688c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4698c2ecf20Sopenharmony_ci		.prio	= 0,
4708c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4718c2ecf20Sopenharmony_ci		.bit	= 23,
4728c2ecf20Sopenharmony_ci	},
4738c2ecf20Sopenharmony_ci	[88] = {
4748c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4758c2ecf20Sopenharmony_ci		.prio	= 0,
4768c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4778c2ecf20Sopenharmony_ci		.bit	= 24,
4788c2ecf20Sopenharmony_ci	},
4798c2ecf20Sopenharmony_ci	[89] = {
4808c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4818c2ecf20Sopenharmony_ci		.prio	= 0,
4828c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4838c2ecf20Sopenharmony_ci		.bit	= 25,
4848c2ecf20Sopenharmony_ci	},
4858c2ecf20Sopenharmony_ci	[90] = {
4868c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4878c2ecf20Sopenharmony_ci		.prio	= 0,
4888c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4898c2ecf20Sopenharmony_ci		.bit	= 26,
4908c2ecf20Sopenharmony_ci	},
4918c2ecf20Sopenharmony_ci	[91] = {
4928c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4938c2ecf20Sopenharmony_ci		.prio	= 0,
4948c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
4958c2ecf20Sopenharmony_ci		.bit	= 27,
4968c2ecf20Sopenharmony_ci	},
4978c2ecf20Sopenharmony_ci	[94] = {
4988c2ecf20Sopenharmony_ci		.mask	= IPIC_SIMSR_L,
4998c2ecf20Sopenharmony_ci		.prio	= 0,
5008c2ecf20Sopenharmony_ci		.force	= IPIC_SIFCR_L,
5018c2ecf20Sopenharmony_ci		.bit	= 30,
5028c2ecf20Sopenharmony_ci	},
5038c2ecf20Sopenharmony_ci};
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_cistatic inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
5068c2ecf20Sopenharmony_ci{
5078c2ecf20Sopenharmony_ci	return in_be32(base + (reg >> 2));
5088c2ecf20Sopenharmony_ci}
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_cistatic inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
5118c2ecf20Sopenharmony_ci{
5128c2ecf20Sopenharmony_ci	out_be32(base + (reg >> 2), value);
5138c2ecf20Sopenharmony_ci}
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_cistatic inline struct ipic * ipic_from_irq(unsigned int virq)
5168c2ecf20Sopenharmony_ci{
5178c2ecf20Sopenharmony_ci	return primary_ipic;
5188c2ecf20Sopenharmony_ci}
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_cistatic void ipic_unmask_irq(struct irq_data *d)
5218c2ecf20Sopenharmony_ci{
5228c2ecf20Sopenharmony_ci	struct ipic *ipic = ipic_from_irq(d->irq);
5238c2ecf20Sopenharmony_ci	unsigned int src = irqd_to_hwirq(d);
5248c2ecf20Sopenharmony_ci	unsigned long flags;
5258c2ecf20Sopenharmony_ci	u32 temp;
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&ipic_lock, flags);
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	temp = ipic_read(ipic->regs, ipic_info[src].mask);
5308c2ecf20Sopenharmony_ci	temp |= (1 << (31 - ipic_info[src].bit));
5318c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, ipic_info[src].mask, temp);
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&ipic_lock, flags);
5348c2ecf20Sopenharmony_ci}
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_cistatic void ipic_mask_irq(struct irq_data *d)
5378c2ecf20Sopenharmony_ci{
5388c2ecf20Sopenharmony_ci	struct ipic *ipic = ipic_from_irq(d->irq);
5398c2ecf20Sopenharmony_ci	unsigned int src = irqd_to_hwirq(d);
5408c2ecf20Sopenharmony_ci	unsigned long flags;
5418c2ecf20Sopenharmony_ci	u32 temp;
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&ipic_lock, flags);
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	temp = ipic_read(ipic->regs, ipic_info[src].mask);
5468c2ecf20Sopenharmony_ci	temp &= ~(1 << (31 - ipic_info[src].bit));
5478c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, ipic_info[src].mask, temp);
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	/* mb() can't guarantee that masking is finished.  But it does finish
5508c2ecf20Sopenharmony_ci	 * for nearly all cases. */
5518c2ecf20Sopenharmony_ci	mb();
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&ipic_lock, flags);
5548c2ecf20Sopenharmony_ci}
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_cistatic void ipic_ack_irq(struct irq_data *d)
5578c2ecf20Sopenharmony_ci{
5588c2ecf20Sopenharmony_ci	struct ipic *ipic = ipic_from_irq(d->irq);
5598c2ecf20Sopenharmony_ci	unsigned int src = irqd_to_hwirq(d);
5608c2ecf20Sopenharmony_ci	unsigned long flags;
5618c2ecf20Sopenharmony_ci	u32 temp;
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&ipic_lock, flags);
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	temp = 1 << (31 - ipic_info[src].bit);
5668c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, ipic_info[src].ack, temp);
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	/* mb() can't guarantee that ack is finished.  But it does finish
5698c2ecf20Sopenharmony_ci	 * for nearly all cases. */
5708c2ecf20Sopenharmony_ci	mb();
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&ipic_lock, flags);
5738c2ecf20Sopenharmony_ci}
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_cistatic void ipic_mask_irq_and_ack(struct irq_data *d)
5768c2ecf20Sopenharmony_ci{
5778c2ecf20Sopenharmony_ci	struct ipic *ipic = ipic_from_irq(d->irq);
5788c2ecf20Sopenharmony_ci	unsigned int src = irqd_to_hwirq(d);
5798c2ecf20Sopenharmony_ci	unsigned long flags;
5808c2ecf20Sopenharmony_ci	u32 temp;
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&ipic_lock, flags);
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	temp = ipic_read(ipic->regs, ipic_info[src].mask);
5858c2ecf20Sopenharmony_ci	temp &= ~(1 << (31 - ipic_info[src].bit));
5868c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, ipic_info[src].mask, temp);
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	temp = 1 << (31 - ipic_info[src].bit);
5898c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, ipic_info[src].ack, temp);
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	/* mb() can't guarantee that ack is finished.  But it does finish
5928c2ecf20Sopenharmony_ci	 * for nearly all cases. */
5938c2ecf20Sopenharmony_ci	mb();
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&ipic_lock, flags);
5968c2ecf20Sopenharmony_ci}
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_cistatic int ipic_set_irq_type(struct irq_data *d, unsigned int flow_type)
5998c2ecf20Sopenharmony_ci{
6008c2ecf20Sopenharmony_ci	struct ipic *ipic = ipic_from_irq(d->irq);
6018c2ecf20Sopenharmony_ci	unsigned int src = irqd_to_hwirq(d);
6028c2ecf20Sopenharmony_ci	unsigned int vold, vnew, edibit;
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	if (flow_type == IRQ_TYPE_NONE)
6058c2ecf20Sopenharmony_ci		flow_type = IRQ_TYPE_LEVEL_LOW;
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	/* ipic supports only low assertion and high-to-low change senses
6088c2ecf20Sopenharmony_ci	 */
6098c2ecf20Sopenharmony_ci	if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) {
6108c2ecf20Sopenharmony_ci		printk(KERN_ERR "ipic: sense type 0x%x not supported\n",
6118c2ecf20Sopenharmony_ci			flow_type);
6128c2ecf20Sopenharmony_ci		return -EINVAL;
6138c2ecf20Sopenharmony_ci	}
6148c2ecf20Sopenharmony_ci	/* ipic supports only edge mode on external interrupts */
6158c2ecf20Sopenharmony_ci	if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !ipic_info[src].ack) {
6168c2ecf20Sopenharmony_ci		printk(KERN_ERR "ipic: edge sense not supported on internal "
6178c2ecf20Sopenharmony_ci				"interrupts\n");
6188c2ecf20Sopenharmony_ci		return -EINVAL;
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	irqd_set_trigger_type(d, flow_type);
6238c2ecf20Sopenharmony_ci	if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
6248c2ecf20Sopenharmony_ci		irq_set_handler_locked(d, handle_level_irq);
6258c2ecf20Sopenharmony_ci		d->chip = &ipic_level_irq_chip;
6268c2ecf20Sopenharmony_ci	} else {
6278c2ecf20Sopenharmony_ci		irq_set_handler_locked(d, handle_edge_irq);
6288c2ecf20Sopenharmony_ci		d->chip = &ipic_edge_irq_chip;
6298c2ecf20Sopenharmony_ci	}
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci	/* only EXT IRQ senses are programmable on ipic
6328c2ecf20Sopenharmony_ci	 * internal IRQ senses are LEVEL_LOW
6338c2ecf20Sopenharmony_ci	 */
6348c2ecf20Sopenharmony_ci	if (src == IPIC_IRQ_EXT0)
6358c2ecf20Sopenharmony_ci		edibit = 15;
6368c2ecf20Sopenharmony_ci	else
6378c2ecf20Sopenharmony_ci		if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7)
6388c2ecf20Sopenharmony_ci			edibit = (14 - (src - IPIC_IRQ_EXT1));
6398c2ecf20Sopenharmony_ci		else
6408c2ecf20Sopenharmony_ci			return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	vold = ipic_read(ipic->regs, IPIC_SECNR);
6438c2ecf20Sopenharmony_ci	if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) {
6448c2ecf20Sopenharmony_ci		vnew = vold | (1 << edibit);
6458c2ecf20Sopenharmony_ci	} else {
6468c2ecf20Sopenharmony_ci		vnew = vold & ~(1 << edibit);
6478c2ecf20Sopenharmony_ci	}
6488c2ecf20Sopenharmony_ci	if (vold != vnew)
6498c2ecf20Sopenharmony_ci		ipic_write(ipic->regs, IPIC_SECNR, vnew);
6508c2ecf20Sopenharmony_ci	return IRQ_SET_MASK_OK_NOCOPY;
6518c2ecf20Sopenharmony_ci}
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci/* level interrupts and edge interrupts have different ack operations */
6548c2ecf20Sopenharmony_cistatic struct irq_chip ipic_level_irq_chip = {
6558c2ecf20Sopenharmony_ci	.name		= "IPIC",
6568c2ecf20Sopenharmony_ci	.irq_unmask	= ipic_unmask_irq,
6578c2ecf20Sopenharmony_ci	.irq_mask	= ipic_mask_irq,
6588c2ecf20Sopenharmony_ci	.irq_mask_ack	= ipic_mask_irq,
6598c2ecf20Sopenharmony_ci	.irq_set_type	= ipic_set_irq_type,
6608c2ecf20Sopenharmony_ci};
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_cistatic struct irq_chip ipic_edge_irq_chip = {
6638c2ecf20Sopenharmony_ci	.name		= "IPIC",
6648c2ecf20Sopenharmony_ci	.irq_unmask	= ipic_unmask_irq,
6658c2ecf20Sopenharmony_ci	.irq_mask	= ipic_mask_irq,
6668c2ecf20Sopenharmony_ci	.irq_mask_ack	= ipic_mask_irq_and_ack,
6678c2ecf20Sopenharmony_ci	.irq_ack	= ipic_ack_irq,
6688c2ecf20Sopenharmony_ci	.irq_set_type	= ipic_set_irq_type,
6698c2ecf20Sopenharmony_ci};
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_cistatic int ipic_host_match(struct irq_domain *h, struct device_node *node,
6728c2ecf20Sopenharmony_ci			   enum irq_domain_bus_token bus_token)
6738c2ecf20Sopenharmony_ci{
6748c2ecf20Sopenharmony_ci	/* Exact match, unless ipic node is NULL */
6758c2ecf20Sopenharmony_ci	struct device_node *of_node = irq_domain_get_of_node(h);
6768c2ecf20Sopenharmony_ci	return of_node == NULL || of_node == node;
6778c2ecf20Sopenharmony_ci}
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_cistatic int ipic_host_map(struct irq_domain *h, unsigned int virq,
6808c2ecf20Sopenharmony_ci			 irq_hw_number_t hw)
6818c2ecf20Sopenharmony_ci{
6828c2ecf20Sopenharmony_ci	struct ipic *ipic = h->host_data;
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	irq_set_chip_data(virq, ipic);
6858c2ecf20Sopenharmony_ci	irq_set_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq);
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	/* Set default irq type */
6888c2ecf20Sopenharmony_ci	irq_set_irq_type(virq, IRQ_TYPE_NONE);
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	return 0;
6918c2ecf20Sopenharmony_ci}
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_cistatic const struct irq_domain_ops ipic_host_ops = {
6948c2ecf20Sopenharmony_ci	.match	= ipic_host_match,
6958c2ecf20Sopenharmony_ci	.map	= ipic_host_map,
6968c2ecf20Sopenharmony_ci	.xlate	= irq_domain_xlate_onetwocell,
6978c2ecf20Sopenharmony_ci};
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_cistruct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
7008c2ecf20Sopenharmony_ci{
7018c2ecf20Sopenharmony_ci	struct ipic	*ipic;
7028c2ecf20Sopenharmony_ci	struct resource res;
7038c2ecf20Sopenharmony_ci	u32 temp = 0, ret;
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	ret = of_address_to_resource(node, 0, &res);
7068c2ecf20Sopenharmony_ci	if (ret)
7078c2ecf20Sopenharmony_ci		return NULL;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	ipic = kzalloc(sizeof(*ipic), GFP_KERNEL);
7108c2ecf20Sopenharmony_ci	if (ipic == NULL)
7118c2ecf20Sopenharmony_ci		return NULL;
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	ipic->irqhost = irq_domain_add_linear(node, NR_IPIC_INTS,
7148c2ecf20Sopenharmony_ci					      &ipic_host_ops, ipic);
7158c2ecf20Sopenharmony_ci	if (ipic->irqhost == NULL) {
7168c2ecf20Sopenharmony_ci		kfree(ipic);
7178c2ecf20Sopenharmony_ci		return NULL;
7188c2ecf20Sopenharmony_ci	}
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	ipic->regs = ioremap(res.start, resource_size(&res));
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	/* init hw */
7238c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SICNR, 0x0);
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	/* default priority scheme is grouped. If spread mode is required
7268c2ecf20Sopenharmony_ci	 * configure SICFR accordingly */
7278c2ecf20Sopenharmony_ci	if (flags & IPIC_SPREADMODE_GRP_A)
7288c2ecf20Sopenharmony_ci		temp |= SICFR_IPSA;
7298c2ecf20Sopenharmony_ci	if (flags & IPIC_SPREADMODE_GRP_B)
7308c2ecf20Sopenharmony_ci		temp |= SICFR_IPSB;
7318c2ecf20Sopenharmony_ci	if (flags & IPIC_SPREADMODE_GRP_C)
7328c2ecf20Sopenharmony_ci		temp |= SICFR_IPSC;
7338c2ecf20Sopenharmony_ci	if (flags & IPIC_SPREADMODE_GRP_D)
7348c2ecf20Sopenharmony_ci		temp |= SICFR_IPSD;
7358c2ecf20Sopenharmony_ci	if (flags & IPIC_SPREADMODE_MIX_A)
7368c2ecf20Sopenharmony_ci		temp |= SICFR_MPSA;
7378c2ecf20Sopenharmony_ci	if (flags & IPIC_SPREADMODE_MIX_B)
7388c2ecf20Sopenharmony_ci		temp |= SICFR_MPSB;
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SICFR, temp);
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	/* handle MCP route */
7438c2ecf20Sopenharmony_ci	temp = 0;
7448c2ecf20Sopenharmony_ci	if (flags & IPIC_DISABLE_MCP_OUT)
7458c2ecf20Sopenharmony_ci		temp = SERCR_MCPR;
7468c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SERCR, temp);
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	/* handle routing of IRQ0 to MCP */
7498c2ecf20Sopenharmony_ci	temp = ipic_read(ipic->regs, IPIC_SEMSR);
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	if (flags & IPIC_IRQ0_MCP)
7528c2ecf20Sopenharmony_ci		temp |= SEMSR_SIRQ0;
7538c2ecf20Sopenharmony_ci	else
7548c2ecf20Sopenharmony_ci		temp &= ~SEMSR_SIRQ0;
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SEMSR, temp);
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci	primary_ipic = ipic;
7598c2ecf20Sopenharmony_ci	irq_set_default_host(primary_ipic->irqhost);
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SIMSR_H, 0);
7628c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SIMSR_L, 0);
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS,
7658c2ecf20Sopenharmony_ci			primary_ipic->regs);
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	return ipic;
7688c2ecf20Sopenharmony_ci}
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_civoid ipic_set_default_priority(void)
7718c2ecf20Sopenharmony_ci{
7728c2ecf20Sopenharmony_ci	ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_PRIORITY_DEFAULT);
7738c2ecf20Sopenharmony_ci	ipic_write(primary_ipic->regs, IPIC_SIPRR_B, IPIC_PRIORITY_DEFAULT);
7748c2ecf20Sopenharmony_ci	ipic_write(primary_ipic->regs, IPIC_SIPRR_C, IPIC_PRIORITY_DEFAULT);
7758c2ecf20Sopenharmony_ci	ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_PRIORITY_DEFAULT);
7768c2ecf20Sopenharmony_ci	ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_PRIORITY_DEFAULT);
7778c2ecf20Sopenharmony_ci	ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_PRIORITY_DEFAULT);
7788c2ecf20Sopenharmony_ci}
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ciu32 ipic_get_mcp_status(void)
7818c2ecf20Sopenharmony_ci{
7828c2ecf20Sopenharmony_ci	return primary_ipic ? ipic_read(primary_ipic->regs, IPIC_SERSR) : 0;
7838c2ecf20Sopenharmony_ci}
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_civoid ipic_clear_mcp_status(u32 mask)
7868c2ecf20Sopenharmony_ci{
7878c2ecf20Sopenharmony_ci	ipic_write(primary_ipic->regs, IPIC_SERSR, mask);
7888c2ecf20Sopenharmony_ci}
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci/* Return an interrupt vector or 0 if no interrupt is pending. */
7918c2ecf20Sopenharmony_ciunsigned int ipic_get_irq(void)
7928c2ecf20Sopenharmony_ci{
7938c2ecf20Sopenharmony_ci	int irq;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	BUG_ON(primary_ipic == NULL);
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci#define IPIC_SIVCR_VECTOR_MASK	0x7f
7988c2ecf20Sopenharmony_ci	irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK;
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci	if (irq == 0)    /* 0 --> no irq is pending */
8018c2ecf20Sopenharmony_ci		return 0;
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	return irq_linear_revmap(primary_ipic->irqhost, irq);
8048c2ecf20Sopenharmony_ci}
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci#ifdef CONFIG_SUSPEND
8078c2ecf20Sopenharmony_cistatic struct {
8088c2ecf20Sopenharmony_ci	u32 sicfr;
8098c2ecf20Sopenharmony_ci	u32 siprr[2];
8108c2ecf20Sopenharmony_ci	u32 simsr[2];
8118c2ecf20Sopenharmony_ci	u32 sicnr;
8128c2ecf20Sopenharmony_ci	u32 smprr[2];
8138c2ecf20Sopenharmony_ci	u32 semsr;
8148c2ecf20Sopenharmony_ci	u32 secnr;
8158c2ecf20Sopenharmony_ci	u32 sermr;
8168c2ecf20Sopenharmony_ci	u32 sercr;
8178c2ecf20Sopenharmony_ci} ipic_saved_state;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_cistatic int ipic_suspend(void)
8208c2ecf20Sopenharmony_ci{
8218c2ecf20Sopenharmony_ci	struct ipic *ipic = primary_ipic;
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	ipic_saved_state.sicfr = ipic_read(ipic->regs, IPIC_SICFR);
8248c2ecf20Sopenharmony_ci	ipic_saved_state.siprr[0] = ipic_read(ipic->regs, IPIC_SIPRR_A);
8258c2ecf20Sopenharmony_ci	ipic_saved_state.siprr[1] = ipic_read(ipic->regs, IPIC_SIPRR_D);
8268c2ecf20Sopenharmony_ci	ipic_saved_state.simsr[0] = ipic_read(ipic->regs, IPIC_SIMSR_H);
8278c2ecf20Sopenharmony_ci	ipic_saved_state.simsr[1] = ipic_read(ipic->regs, IPIC_SIMSR_L);
8288c2ecf20Sopenharmony_ci	ipic_saved_state.sicnr = ipic_read(ipic->regs, IPIC_SICNR);
8298c2ecf20Sopenharmony_ci	ipic_saved_state.smprr[0] = ipic_read(ipic->regs, IPIC_SMPRR_A);
8308c2ecf20Sopenharmony_ci	ipic_saved_state.smprr[1] = ipic_read(ipic->regs, IPIC_SMPRR_B);
8318c2ecf20Sopenharmony_ci	ipic_saved_state.semsr = ipic_read(ipic->regs, IPIC_SEMSR);
8328c2ecf20Sopenharmony_ci	ipic_saved_state.secnr = ipic_read(ipic->regs, IPIC_SECNR);
8338c2ecf20Sopenharmony_ci	ipic_saved_state.sermr = ipic_read(ipic->regs, IPIC_SERMR);
8348c2ecf20Sopenharmony_ci	ipic_saved_state.sercr = ipic_read(ipic->regs, IPIC_SERCR);
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	if (fsl_deep_sleep()) {
8378c2ecf20Sopenharmony_ci		/* In deep sleep, make sure there can be no
8388c2ecf20Sopenharmony_ci		 * pending interrupts, as this can cause
8398c2ecf20Sopenharmony_ci		 * problems on 831x.
8408c2ecf20Sopenharmony_ci		 */
8418c2ecf20Sopenharmony_ci		ipic_write(ipic->regs, IPIC_SIMSR_H, 0);
8428c2ecf20Sopenharmony_ci		ipic_write(ipic->regs, IPIC_SIMSR_L, 0);
8438c2ecf20Sopenharmony_ci		ipic_write(ipic->regs, IPIC_SEMSR, 0);
8448c2ecf20Sopenharmony_ci		ipic_write(ipic->regs, IPIC_SERMR, 0);
8458c2ecf20Sopenharmony_ci	}
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	return 0;
8488c2ecf20Sopenharmony_ci}
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_cistatic void ipic_resume(void)
8518c2ecf20Sopenharmony_ci{
8528c2ecf20Sopenharmony_ci	struct ipic *ipic = primary_ipic;
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SICFR, ipic_saved_state.sicfr);
8558c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SIPRR_A, ipic_saved_state.siprr[0]);
8568c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SIPRR_D, ipic_saved_state.siprr[1]);
8578c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SIMSR_H, ipic_saved_state.simsr[0]);
8588c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SIMSR_L, ipic_saved_state.simsr[1]);
8598c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SICNR, ipic_saved_state.sicnr);
8608c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SMPRR_A, ipic_saved_state.smprr[0]);
8618c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SMPRR_B, ipic_saved_state.smprr[1]);
8628c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SEMSR, ipic_saved_state.semsr);
8638c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SECNR, ipic_saved_state.secnr);
8648c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SERMR, ipic_saved_state.sermr);
8658c2ecf20Sopenharmony_ci	ipic_write(ipic->regs, IPIC_SERCR, ipic_saved_state.sercr);
8668c2ecf20Sopenharmony_ci}
8678c2ecf20Sopenharmony_ci#else
8688c2ecf20Sopenharmony_ci#define ipic_suspend NULL
8698c2ecf20Sopenharmony_ci#define ipic_resume NULL
8708c2ecf20Sopenharmony_ci#endif
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_cistatic struct syscore_ops ipic_syscore_ops = {
8738c2ecf20Sopenharmony_ci	.suspend = ipic_suspend,
8748c2ecf20Sopenharmony_ci	.resume = ipic_resume,
8758c2ecf20Sopenharmony_ci};
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_cistatic int __init init_ipic_syscore(void)
8788c2ecf20Sopenharmony_ci{
8798c2ecf20Sopenharmony_ci	if (!primary_ipic || !primary_ipic->regs)
8808c2ecf20Sopenharmony_ci		return -ENODEV;
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	printk(KERN_DEBUG "Registering ipic system core operations\n");
8838c2ecf20Sopenharmony_ci	register_syscore_ops(&ipic_syscore_ops);
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	return 0;
8868c2ecf20Sopenharmony_ci}
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_cisubsys_initcall(init_ipic_syscore);
889