11cd8e506SKumar Gala /* 2f30c2269SUwe Zeisberger * arch/powerpc/sysdev/ipic.c 31cd8e506SKumar Gala * 41cd8e506SKumar Gala * IPIC routines implementations. 51cd8e506SKumar Gala * 61cd8e506SKumar Gala * Copyright 2005 Freescale Semiconductor, Inc. 71cd8e506SKumar Gala * 81cd8e506SKumar Gala * This program is free software; you can redistribute it and/or modify it 91cd8e506SKumar Gala * under the terms of the GNU General Public License as published by the 101cd8e506SKumar Gala * Free Software Foundation; either version 2 of the License, or (at your 111cd8e506SKumar Gala * option) any later version. 121cd8e506SKumar Gala */ 131cd8e506SKumar Gala #include <linux/kernel.h> 141cd8e506SKumar Gala #include <linux/init.h> 151cd8e506SKumar Gala #include <linux/errno.h> 161cd8e506SKumar Gala #include <linux/reboot.h> 171cd8e506SKumar Gala #include <linux/slab.h> 181cd8e506SKumar Gala #include <linux/stddef.h> 191cd8e506SKumar Gala #include <linux/sched.h> 201cd8e506SKumar Gala #include <linux/signal.h> 211cd8e506SKumar Gala #include <linux/sysdev.h> 22b9f0f1bbSKim Phillips #include <linux/device.h> 23b9f0f1bbSKim Phillips #include <linux/bootmem.h> 24b9f0f1bbSKim Phillips #include <linux/spinlock.h> 251cd8e506SKumar Gala #include <asm/irq.h> 261cd8e506SKumar Gala #include <asm/io.h> 27b9f0f1bbSKim Phillips #include <asm/prom.h> 281cd8e506SKumar Gala #include <asm/ipic.h> 291cd8e506SKumar Gala 301cd8e506SKumar Gala #include "ipic.h" 311cd8e506SKumar Gala 321cd8e506SKumar Gala static struct ipic * primary_ipic; 33*77d4309eSLi Yang static struct irq_chip ipic_level_irq_chip, ipic_edge_irq_chip; 34b9f0f1bbSKim Phillips static DEFINE_SPINLOCK(ipic_lock); 351cd8e506SKumar Gala 361cd8e506SKumar Gala static struct ipic_info ipic_info[] = { 37f03ca957SLi Yang [1] = { 38f03ca957SLi Yang .mask = IPIC_SIMSR_H, 39f03ca957SLi Yang .prio = IPIC_SIPRR_C, 40f03ca957SLi Yang .force = IPIC_SIFCR_H, 41f03ca957SLi Yang .bit = 16, 42f03ca957SLi Yang .prio_mask = 0, 43f03ca957SLi Yang }, 44f03ca957SLi Yang [2] = { 45f03ca957SLi Yang .mask = IPIC_SIMSR_H, 46f03ca957SLi Yang .prio = IPIC_SIPRR_C, 47f03ca957SLi Yang .force = IPIC_SIFCR_H, 48f03ca957SLi Yang .bit = 17, 49f03ca957SLi Yang .prio_mask = 1, 50f03ca957SLi Yang }, 51f03ca957SLi Yang [4] = { 52f03ca957SLi Yang .mask = IPIC_SIMSR_H, 53f03ca957SLi Yang .prio = IPIC_SIPRR_C, 54f03ca957SLi Yang .force = IPIC_SIFCR_H, 55f03ca957SLi Yang .bit = 19, 56f03ca957SLi Yang .prio_mask = 3, 57f03ca957SLi Yang }, 581cd8e506SKumar Gala [9] = { 591cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 601cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 611cd8e506SKumar Gala .force = IPIC_SIFCR_H, 621cd8e506SKumar Gala .bit = 24, 631cd8e506SKumar Gala .prio_mask = 0, 641cd8e506SKumar Gala }, 651cd8e506SKumar Gala [10] = { 661cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 671cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 681cd8e506SKumar Gala .force = IPIC_SIFCR_H, 691cd8e506SKumar Gala .bit = 25, 701cd8e506SKumar Gala .prio_mask = 1, 711cd8e506SKumar Gala }, 721cd8e506SKumar Gala [11] = { 731cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 741cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 751cd8e506SKumar Gala .force = IPIC_SIFCR_H, 761cd8e506SKumar Gala .bit = 26, 771cd8e506SKumar Gala .prio_mask = 2, 781cd8e506SKumar Gala }, 79f03ca957SLi Yang [12] = { 80f03ca957SLi Yang .mask = IPIC_SIMSR_H, 81f03ca957SLi Yang .prio = IPIC_SIPRR_D, 82f03ca957SLi Yang .force = IPIC_SIFCR_H, 83f03ca957SLi Yang .bit = 27, 84f03ca957SLi Yang .prio_mask = 3, 85f03ca957SLi Yang }, 86f03ca957SLi Yang [13] = { 87f03ca957SLi Yang .mask = IPIC_SIMSR_H, 88f03ca957SLi Yang .prio = IPIC_SIPRR_D, 89f03ca957SLi Yang .force = IPIC_SIFCR_H, 90f03ca957SLi Yang .bit = 28, 91f03ca957SLi Yang .prio_mask = 4, 92f03ca957SLi Yang }, 931cd8e506SKumar Gala [14] = { 941cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 951cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 961cd8e506SKumar Gala .force = IPIC_SIFCR_H, 971cd8e506SKumar Gala .bit = 29, 981cd8e506SKumar Gala .prio_mask = 5, 991cd8e506SKumar Gala }, 1001cd8e506SKumar Gala [15] = { 1011cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1021cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 1031cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1041cd8e506SKumar Gala .bit = 30, 1051cd8e506SKumar Gala .prio_mask = 6, 1061cd8e506SKumar Gala }, 1071cd8e506SKumar Gala [16] = { 1081cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1091cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 1101cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1111cd8e506SKumar Gala .bit = 31, 1121cd8e506SKumar Gala .prio_mask = 7, 1131cd8e506SKumar Gala }, 1141cd8e506SKumar Gala [17] = { 115*77d4309eSLi Yang .ack = IPIC_SEPNR, 1161cd8e506SKumar Gala .mask = IPIC_SEMSR, 1171cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 1181cd8e506SKumar Gala .force = IPIC_SEFCR, 1191cd8e506SKumar Gala .bit = 1, 1201cd8e506SKumar Gala .prio_mask = 5, 1211cd8e506SKumar Gala }, 1221cd8e506SKumar Gala [18] = { 123*77d4309eSLi Yang .ack = IPIC_SEPNR, 1241cd8e506SKumar Gala .mask = IPIC_SEMSR, 1251cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 1261cd8e506SKumar Gala .force = IPIC_SEFCR, 1271cd8e506SKumar Gala .bit = 2, 1281cd8e506SKumar Gala .prio_mask = 6, 1291cd8e506SKumar Gala }, 1301cd8e506SKumar Gala [19] = { 131*77d4309eSLi Yang .ack = IPIC_SEPNR, 1321cd8e506SKumar Gala .mask = IPIC_SEMSR, 1331cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 1341cd8e506SKumar Gala .force = IPIC_SEFCR, 1351cd8e506SKumar Gala .bit = 3, 1361cd8e506SKumar Gala .prio_mask = 7, 1371cd8e506SKumar Gala }, 1381cd8e506SKumar Gala [20] = { 139*77d4309eSLi Yang .ack = IPIC_SEPNR, 1401cd8e506SKumar Gala .mask = IPIC_SEMSR, 1411cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 1421cd8e506SKumar Gala .force = IPIC_SEFCR, 1431cd8e506SKumar Gala .bit = 4, 1441cd8e506SKumar Gala .prio_mask = 4, 1451cd8e506SKumar Gala }, 1461cd8e506SKumar Gala [21] = { 147*77d4309eSLi Yang .ack = IPIC_SEPNR, 1481cd8e506SKumar Gala .mask = IPIC_SEMSR, 1491cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 1501cd8e506SKumar Gala .force = IPIC_SEFCR, 1511cd8e506SKumar Gala .bit = 5, 1521cd8e506SKumar Gala .prio_mask = 5, 1531cd8e506SKumar Gala }, 1541cd8e506SKumar Gala [22] = { 155*77d4309eSLi Yang .ack = IPIC_SEPNR, 1561cd8e506SKumar Gala .mask = IPIC_SEMSR, 1571cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 1581cd8e506SKumar Gala .force = IPIC_SEFCR, 1591cd8e506SKumar Gala .bit = 6, 1601cd8e506SKumar Gala .prio_mask = 6, 1611cd8e506SKumar Gala }, 1621cd8e506SKumar Gala [23] = { 163*77d4309eSLi Yang .ack = IPIC_SEPNR, 1641cd8e506SKumar Gala .mask = IPIC_SEMSR, 1651cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 1661cd8e506SKumar Gala .force = IPIC_SEFCR, 1671cd8e506SKumar Gala .bit = 7, 1681cd8e506SKumar Gala .prio_mask = 7, 1691cd8e506SKumar Gala }, 1701cd8e506SKumar Gala [32] = { 1711cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1721cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 1731cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1741cd8e506SKumar Gala .bit = 0, 1751cd8e506SKumar Gala .prio_mask = 0, 1761cd8e506SKumar Gala }, 1771cd8e506SKumar Gala [33] = { 1781cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1791cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 1801cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1811cd8e506SKumar Gala .bit = 1, 1821cd8e506SKumar Gala .prio_mask = 1, 1831cd8e506SKumar Gala }, 1841cd8e506SKumar Gala [34] = { 1851cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1861cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 1871cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1881cd8e506SKumar Gala .bit = 2, 1891cd8e506SKumar Gala .prio_mask = 2, 1901cd8e506SKumar Gala }, 1911cd8e506SKumar Gala [35] = { 1921cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1931cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 1941cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1951cd8e506SKumar Gala .bit = 3, 1961cd8e506SKumar Gala .prio_mask = 3, 1971cd8e506SKumar Gala }, 1981cd8e506SKumar Gala [36] = { 1991cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 2001cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 2011cd8e506SKumar Gala .force = IPIC_SIFCR_H, 2021cd8e506SKumar Gala .bit = 4, 2031cd8e506SKumar Gala .prio_mask = 4, 2041cd8e506SKumar Gala }, 2051cd8e506SKumar Gala [37] = { 2061cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 2071cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 2081cd8e506SKumar Gala .force = IPIC_SIFCR_H, 2091cd8e506SKumar Gala .bit = 5, 2101cd8e506SKumar Gala .prio_mask = 5, 2111cd8e506SKumar Gala }, 2121cd8e506SKumar Gala [38] = { 2131cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 2141cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 2151cd8e506SKumar Gala .force = IPIC_SIFCR_H, 2161cd8e506SKumar Gala .bit = 6, 2171cd8e506SKumar Gala .prio_mask = 6, 2181cd8e506SKumar Gala }, 2191cd8e506SKumar Gala [39] = { 2201cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 2211cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 2221cd8e506SKumar Gala .force = IPIC_SIFCR_H, 2231cd8e506SKumar Gala .bit = 7, 2241cd8e506SKumar Gala .prio_mask = 7, 2251cd8e506SKumar Gala }, 226f03ca957SLi Yang [42] = { 227f03ca957SLi Yang .mask = IPIC_SIMSR_H, 228f03ca957SLi Yang .prio = IPIC_SIPRR_B, 229f03ca957SLi Yang .force = IPIC_SIFCR_H, 230f03ca957SLi Yang .bit = 10, 231f03ca957SLi Yang .prio_mask = 2, 232f03ca957SLi Yang }, 233f03ca957SLi Yang [44] = { 234f03ca957SLi Yang .mask = IPIC_SIMSR_H, 235f03ca957SLi Yang .prio = IPIC_SIPRR_B, 236f03ca957SLi Yang .force = IPIC_SIFCR_H, 237f03ca957SLi Yang .bit = 12, 238f03ca957SLi Yang .prio_mask = 4, 239f03ca957SLi Yang }, 240f03ca957SLi Yang [45] = { 241f03ca957SLi Yang .mask = IPIC_SIMSR_H, 242f03ca957SLi Yang .prio = IPIC_SIPRR_B, 243f03ca957SLi Yang .force = IPIC_SIFCR_H, 244f03ca957SLi Yang .bit = 13, 245f03ca957SLi Yang .prio_mask = 5, 246f03ca957SLi Yang }, 247f03ca957SLi Yang [46] = { 248f03ca957SLi Yang .mask = IPIC_SIMSR_H, 249f03ca957SLi Yang .prio = IPIC_SIPRR_B, 250f03ca957SLi Yang .force = IPIC_SIFCR_H, 251f03ca957SLi Yang .bit = 14, 252f03ca957SLi Yang .prio_mask = 6, 253f03ca957SLi Yang }, 254f03ca957SLi Yang [47] = { 255f03ca957SLi Yang .mask = IPIC_SIMSR_H, 256f03ca957SLi Yang .prio = IPIC_SIPRR_B, 257f03ca957SLi Yang .force = IPIC_SIFCR_H, 258f03ca957SLi Yang .bit = 15, 259f03ca957SLi Yang .prio_mask = 7, 260f03ca957SLi Yang }, 2611cd8e506SKumar Gala [48] = { 2621cd8e506SKumar Gala .mask = IPIC_SEMSR, 2631cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 2641cd8e506SKumar Gala .force = IPIC_SEFCR, 2651cd8e506SKumar Gala .bit = 0, 2661cd8e506SKumar Gala .prio_mask = 4, 2671cd8e506SKumar Gala }, 2681cd8e506SKumar Gala [64] = { 2691cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2701cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 2711cd8e506SKumar Gala .force = IPIC_SIFCR_L, 2721cd8e506SKumar Gala .bit = 0, 2731cd8e506SKumar Gala .prio_mask = 0, 2741cd8e506SKumar Gala }, 2751cd8e506SKumar Gala [65] = { 2761cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2771cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 2781cd8e506SKumar Gala .force = IPIC_SIFCR_L, 2791cd8e506SKumar Gala .bit = 1, 2801cd8e506SKumar Gala .prio_mask = 1, 2811cd8e506SKumar Gala }, 2821cd8e506SKumar Gala [66] = { 2831cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2841cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 2851cd8e506SKumar Gala .force = IPIC_SIFCR_L, 2861cd8e506SKumar Gala .bit = 2, 2871cd8e506SKumar Gala .prio_mask = 2, 2881cd8e506SKumar Gala }, 2891cd8e506SKumar Gala [67] = { 2901cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2911cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 2921cd8e506SKumar Gala .force = IPIC_SIFCR_L, 2931cd8e506SKumar Gala .bit = 3, 2941cd8e506SKumar Gala .prio_mask = 3, 2951cd8e506SKumar Gala }, 2961cd8e506SKumar Gala [68] = { 2971cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2981cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 2991cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3001cd8e506SKumar Gala .bit = 4, 3011cd8e506SKumar Gala .prio_mask = 0, 3021cd8e506SKumar Gala }, 3031cd8e506SKumar Gala [69] = { 3041cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3051cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 3061cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3071cd8e506SKumar Gala .bit = 5, 3081cd8e506SKumar Gala .prio_mask = 1, 3091cd8e506SKumar Gala }, 3101cd8e506SKumar Gala [70] = { 3111cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3121cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 3131cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3141cd8e506SKumar Gala .bit = 6, 3151cd8e506SKumar Gala .prio_mask = 2, 3161cd8e506SKumar Gala }, 3171cd8e506SKumar Gala [71] = { 3181cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3191cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 3201cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3211cd8e506SKumar Gala .bit = 7, 3221cd8e506SKumar Gala .prio_mask = 3, 3231cd8e506SKumar Gala }, 3241cd8e506SKumar Gala [72] = { 3251cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3261cd8e506SKumar Gala .prio = 0, 3271cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3281cd8e506SKumar Gala .bit = 8, 3291cd8e506SKumar Gala }, 3301cd8e506SKumar Gala [73] = { 3311cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3321cd8e506SKumar Gala .prio = 0, 3331cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3341cd8e506SKumar Gala .bit = 9, 3351cd8e506SKumar Gala }, 3361cd8e506SKumar Gala [74] = { 3371cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3381cd8e506SKumar Gala .prio = 0, 3391cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3401cd8e506SKumar Gala .bit = 10, 3411cd8e506SKumar Gala }, 3421cd8e506SKumar Gala [75] = { 3431cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3441cd8e506SKumar Gala .prio = 0, 3451cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3461cd8e506SKumar Gala .bit = 11, 3471cd8e506SKumar Gala }, 3481cd8e506SKumar Gala [76] = { 3491cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3501cd8e506SKumar Gala .prio = 0, 3511cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3521cd8e506SKumar Gala .bit = 12, 3531cd8e506SKumar Gala }, 3541cd8e506SKumar Gala [77] = { 3551cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3561cd8e506SKumar Gala .prio = 0, 3571cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3581cd8e506SKumar Gala .bit = 13, 3591cd8e506SKumar Gala }, 3601cd8e506SKumar Gala [78] = { 3611cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3621cd8e506SKumar Gala .prio = 0, 3631cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3641cd8e506SKumar Gala .bit = 14, 3651cd8e506SKumar Gala }, 3661cd8e506SKumar Gala [79] = { 3671cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3681cd8e506SKumar Gala .prio = 0, 3691cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3701cd8e506SKumar Gala .bit = 15, 3711cd8e506SKumar Gala }, 3721cd8e506SKumar Gala [80] = { 3731cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3741cd8e506SKumar Gala .prio = 0, 3751cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3761cd8e506SKumar Gala .bit = 16, 3771cd8e506SKumar Gala }, 378f03ca957SLi Yang [81] = { 379f03ca957SLi Yang .mask = IPIC_SIMSR_L, 380f03ca957SLi Yang .prio = 0, 381f03ca957SLi Yang .force = IPIC_SIFCR_L, 382f03ca957SLi Yang .bit = 17, 383f03ca957SLi Yang }, 384f03ca957SLi Yang [82] = { 385f03ca957SLi Yang .mask = IPIC_SIMSR_L, 386f03ca957SLi Yang .prio = 0, 387f03ca957SLi Yang .force = IPIC_SIFCR_L, 388f03ca957SLi Yang .bit = 18, 389f03ca957SLi Yang }, 3901cd8e506SKumar Gala [84] = { 3911cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3921cd8e506SKumar Gala .prio = 0, 3931cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3941cd8e506SKumar Gala .bit = 20, 3951cd8e506SKumar Gala }, 3961cd8e506SKumar Gala [85] = { 3971cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3981cd8e506SKumar Gala .prio = 0, 3991cd8e506SKumar Gala .force = IPIC_SIFCR_L, 4001cd8e506SKumar Gala .bit = 21, 4011cd8e506SKumar Gala }, 402f03ca957SLi Yang [86] = { 403f03ca957SLi Yang .mask = IPIC_SIMSR_L, 404f03ca957SLi Yang .prio = 0, 405f03ca957SLi Yang .force = IPIC_SIFCR_L, 406f03ca957SLi Yang .bit = 22, 407f03ca957SLi Yang }, 408f03ca957SLi Yang [87] = { 409f03ca957SLi Yang .mask = IPIC_SIMSR_L, 410f03ca957SLi Yang .prio = 0, 411f03ca957SLi Yang .force = IPIC_SIFCR_L, 412f03ca957SLi Yang .bit = 23, 413f03ca957SLi Yang }, 414f03ca957SLi Yang [88] = { 415f03ca957SLi Yang .mask = IPIC_SIMSR_L, 416f03ca957SLi Yang .prio = 0, 417f03ca957SLi Yang .force = IPIC_SIFCR_L, 418f03ca957SLi Yang .bit = 24, 419f03ca957SLi Yang }, 420f03ca957SLi Yang [89] = { 421f03ca957SLi Yang .mask = IPIC_SIMSR_L, 422f03ca957SLi Yang .prio = 0, 423f03ca957SLi Yang .force = IPIC_SIFCR_L, 424f03ca957SLi Yang .bit = 25, 425f03ca957SLi Yang }, 4261cd8e506SKumar Gala [90] = { 4271cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 4281cd8e506SKumar Gala .prio = 0, 4291cd8e506SKumar Gala .force = IPIC_SIFCR_L, 4301cd8e506SKumar Gala .bit = 26, 4311cd8e506SKumar Gala }, 4321cd8e506SKumar Gala [91] = { 4331cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 4341cd8e506SKumar Gala .prio = 0, 4351cd8e506SKumar Gala .force = IPIC_SIFCR_L, 4361cd8e506SKumar Gala .bit = 27, 4371cd8e506SKumar Gala }, 4381cd8e506SKumar Gala }; 4391cd8e506SKumar Gala 4401cd8e506SKumar Gala static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg) 4411cd8e506SKumar Gala { 4421cd8e506SKumar Gala return in_be32(base + (reg >> 2)); 4431cd8e506SKumar Gala } 4441cd8e506SKumar Gala 4451cd8e506SKumar Gala static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value) 4461cd8e506SKumar Gala { 4471cd8e506SKumar Gala out_be32(base + (reg >> 2), value); 4481cd8e506SKumar Gala } 4491cd8e506SKumar Gala 450b9f0f1bbSKim Phillips static inline struct ipic * ipic_from_irq(unsigned int virq) 4511cd8e506SKumar Gala { 4521cd8e506SKumar Gala return primary_ipic; 4531cd8e506SKumar Gala } 4541cd8e506SKumar Gala 455b9f0f1bbSKim Phillips #define ipic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) 456b9f0f1bbSKim Phillips 457b9f0f1bbSKim Phillips static void ipic_unmask_irq(unsigned int virq) 4581cd8e506SKumar Gala { 459b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 460b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 461b9f0f1bbSKim Phillips unsigned long flags; 4621cd8e506SKumar Gala u32 temp; 4631cd8e506SKumar Gala 464b9f0f1bbSKim Phillips spin_lock_irqsave(&ipic_lock, flags); 465b9f0f1bbSKim Phillips 4661cd8e506SKumar Gala temp = ipic_read(ipic->regs, ipic_info[src].mask); 4671cd8e506SKumar Gala temp |= (1 << (31 - ipic_info[src].bit)); 4681cd8e506SKumar Gala ipic_write(ipic->regs, ipic_info[src].mask, temp); 469b9f0f1bbSKim Phillips 470b9f0f1bbSKim Phillips spin_unlock_irqrestore(&ipic_lock, flags); 4711cd8e506SKumar Gala } 4721cd8e506SKumar Gala 473b9f0f1bbSKim Phillips static void ipic_mask_irq(unsigned int virq) 4741cd8e506SKumar Gala { 475b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 476b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 477b9f0f1bbSKim Phillips unsigned long flags; 4781cd8e506SKumar Gala u32 temp; 4791cd8e506SKumar Gala 480b9f0f1bbSKim Phillips spin_lock_irqsave(&ipic_lock, flags); 481b9f0f1bbSKim Phillips 4821cd8e506SKumar Gala temp = ipic_read(ipic->regs, ipic_info[src].mask); 4831cd8e506SKumar Gala temp &= ~(1 << (31 - ipic_info[src].bit)); 4841cd8e506SKumar Gala ipic_write(ipic->regs, ipic_info[src].mask, temp); 485b9f0f1bbSKim Phillips 486*77d4309eSLi Yang /* mb() can't guarantee that masking is finished. But it does finish 487*77d4309eSLi Yang * for nearly all cases. */ 488*77d4309eSLi Yang mb(); 489*77d4309eSLi Yang 490b9f0f1bbSKim Phillips spin_unlock_irqrestore(&ipic_lock, flags); 4911cd8e506SKumar Gala } 4921cd8e506SKumar Gala 493b9f0f1bbSKim Phillips static void ipic_ack_irq(unsigned int virq) 4941cd8e506SKumar Gala { 495b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 496b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 497b9f0f1bbSKim Phillips unsigned long flags; 4981cd8e506SKumar Gala u32 temp; 4991cd8e506SKumar Gala 500b9f0f1bbSKim Phillips spin_lock_irqsave(&ipic_lock, flags); 5011cd8e506SKumar Gala 502*77d4309eSLi Yang temp = ipic_read(ipic->regs, ipic_info[src].ack); 5031cd8e506SKumar Gala temp |= (1 << (31 - ipic_info[src].bit)); 504*77d4309eSLi Yang ipic_write(ipic->regs, ipic_info[src].ack, temp); 505*77d4309eSLi Yang 506*77d4309eSLi Yang /* mb() can't guarantee that ack is finished. But it does finish 507*77d4309eSLi Yang * for nearly all cases. */ 508*77d4309eSLi Yang mb(); 509b9f0f1bbSKim Phillips 510b9f0f1bbSKim Phillips spin_unlock_irqrestore(&ipic_lock, flags); 5111cd8e506SKumar Gala } 5121cd8e506SKumar Gala 513b9f0f1bbSKim Phillips static void ipic_mask_irq_and_ack(unsigned int virq) 5141cd8e506SKumar Gala { 515b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 516b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 517b9f0f1bbSKim Phillips unsigned long flags; 518b9f0f1bbSKim Phillips u32 temp; 519b9f0f1bbSKim Phillips 520b9f0f1bbSKim Phillips spin_lock_irqsave(&ipic_lock, flags); 521b9f0f1bbSKim Phillips 522b9f0f1bbSKim Phillips temp = ipic_read(ipic->regs, ipic_info[src].mask); 523b9f0f1bbSKim Phillips temp &= ~(1 << (31 - ipic_info[src].bit)); 524b9f0f1bbSKim Phillips ipic_write(ipic->regs, ipic_info[src].mask, temp); 525b9f0f1bbSKim Phillips 526*77d4309eSLi Yang temp = ipic_read(ipic->regs, ipic_info[src].ack); 527b9f0f1bbSKim Phillips temp |= (1 << (31 - ipic_info[src].bit)); 528*77d4309eSLi Yang ipic_write(ipic->regs, ipic_info[src].ack, temp); 529*77d4309eSLi Yang 530*77d4309eSLi Yang /* mb() can't guarantee that ack is finished. But it does finish 531*77d4309eSLi Yang * for nearly all cases. */ 532*77d4309eSLi Yang mb(); 533b9f0f1bbSKim Phillips 534b9f0f1bbSKim Phillips spin_unlock_irqrestore(&ipic_lock, flags); 5351cd8e506SKumar Gala } 5361cd8e506SKumar Gala 537b9f0f1bbSKim Phillips static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) 538b9f0f1bbSKim Phillips { 539b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 540b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 541b9f0f1bbSKim Phillips struct irq_desc *desc = get_irq_desc(virq); 542b9f0f1bbSKim Phillips unsigned int vold, vnew, edibit; 543b9f0f1bbSKim Phillips 544b9f0f1bbSKim Phillips if (flow_type == IRQ_TYPE_NONE) 545b9f0f1bbSKim Phillips flow_type = IRQ_TYPE_LEVEL_LOW; 546b9f0f1bbSKim Phillips 547b9f0f1bbSKim Phillips /* ipic supports only low assertion and high-to-low change senses 548b9f0f1bbSKim Phillips */ 549b9f0f1bbSKim Phillips if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) { 550b9f0f1bbSKim Phillips printk(KERN_ERR "ipic: sense type 0x%x not supported\n", 551b9f0f1bbSKim Phillips flow_type); 552b9f0f1bbSKim Phillips return -EINVAL; 553b9f0f1bbSKim Phillips } 554*77d4309eSLi Yang /* ipic supports only edge mode on external interrupts */ 555*77d4309eSLi Yang if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !ipic_info[src].ack) { 556*77d4309eSLi Yang printk(KERN_ERR "ipic: edge sense not supported on internal " 557*77d4309eSLi Yang "interrupts\n"); 558*77d4309eSLi Yang return -EINVAL; 559*77d4309eSLi Yang } 560b9f0f1bbSKim Phillips 561b9f0f1bbSKim Phillips desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); 562b9f0f1bbSKim Phillips desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; 563b9f0f1bbSKim Phillips if (flow_type & IRQ_TYPE_LEVEL_LOW) { 564b9f0f1bbSKim Phillips desc->status |= IRQ_LEVEL; 565f49196a5SScott Wood desc->handle_irq = handle_level_irq; 566*77d4309eSLi Yang desc->chip = &ipic_level_irq_chip; 567b9f0f1bbSKim Phillips } else { 568f49196a5SScott Wood desc->handle_irq = handle_edge_irq; 569*77d4309eSLi Yang desc->chip = &ipic_edge_irq_chip; 570b9f0f1bbSKim Phillips } 571b9f0f1bbSKim Phillips 572b9f0f1bbSKim Phillips /* only EXT IRQ senses are programmable on ipic 573b9f0f1bbSKim Phillips * internal IRQ senses are LEVEL_LOW 574b9f0f1bbSKim Phillips */ 575b9f0f1bbSKim Phillips if (src == IPIC_IRQ_EXT0) 576b9f0f1bbSKim Phillips edibit = 15; 577b9f0f1bbSKim Phillips else 578b9f0f1bbSKim Phillips if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7) 579b9f0f1bbSKim Phillips edibit = (14 - (src - IPIC_IRQ_EXT1)); 580b9f0f1bbSKim Phillips else 581b9f0f1bbSKim Phillips return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL; 582b9f0f1bbSKim Phillips 583b9f0f1bbSKim Phillips vold = ipic_read(ipic->regs, IPIC_SECNR); 584b9f0f1bbSKim Phillips if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) { 585b9f0f1bbSKim Phillips vnew = vold | (1 << edibit); 586b9f0f1bbSKim Phillips } else { 587b9f0f1bbSKim Phillips vnew = vold & ~(1 << edibit); 588b9f0f1bbSKim Phillips } 589b9f0f1bbSKim Phillips if (vold != vnew) 590b9f0f1bbSKim Phillips ipic_write(ipic->regs, IPIC_SECNR, vnew); 591b9f0f1bbSKim Phillips return 0; 592b9f0f1bbSKim Phillips } 593b9f0f1bbSKim Phillips 594*77d4309eSLi Yang /* level interrupts and edge interrupts have different ack operations */ 595*77d4309eSLi Yang static struct irq_chip ipic_level_irq_chip = { 596*77d4309eSLi Yang .typename = " IPIC ", 597*77d4309eSLi Yang .unmask = ipic_unmask_irq, 598*77d4309eSLi Yang .mask = ipic_mask_irq, 599*77d4309eSLi Yang .mask_ack = ipic_mask_irq, 600*77d4309eSLi Yang .set_type = ipic_set_irq_type, 601*77d4309eSLi Yang }; 602*77d4309eSLi Yang 603*77d4309eSLi Yang static struct irq_chip ipic_edge_irq_chip = { 6041cd8e506SKumar Gala .typename = " IPIC ", 605b9f0f1bbSKim Phillips .unmask = ipic_unmask_irq, 606b9f0f1bbSKim Phillips .mask = ipic_mask_irq, 607b9f0f1bbSKim Phillips .mask_ack = ipic_mask_irq_and_ack, 608b9f0f1bbSKim Phillips .ack = ipic_ack_irq, 609b9f0f1bbSKim Phillips .set_type = ipic_set_irq_type, 6101cd8e506SKumar Gala }; 6111cd8e506SKumar Gala 612b9f0f1bbSKim Phillips static int ipic_host_match(struct irq_host *h, struct device_node *node) 6131cd8e506SKumar Gala { 614b9f0f1bbSKim Phillips /* Exact match, unless ipic node is NULL */ 61552964f87SMichael Ellerman return h->of_node == NULL || h->of_node == node; 616b9f0f1bbSKim Phillips } 6171cd8e506SKumar Gala 618b9f0f1bbSKim Phillips static int ipic_host_map(struct irq_host *h, unsigned int virq, 619b9f0f1bbSKim Phillips irq_hw_number_t hw) 620b9f0f1bbSKim Phillips { 621b9f0f1bbSKim Phillips struct ipic *ipic = h->host_data; 622b9f0f1bbSKim Phillips 623b9f0f1bbSKim Phillips set_irq_chip_data(virq, ipic); 624*77d4309eSLi Yang set_irq_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq); 625b9f0f1bbSKim Phillips 626b9f0f1bbSKim Phillips /* Set default irq type */ 627b9f0f1bbSKim Phillips set_irq_type(virq, IRQ_TYPE_NONE); 628b9f0f1bbSKim Phillips 629b9f0f1bbSKim Phillips return 0; 630b9f0f1bbSKim Phillips } 631b9f0f1bbSKim Phillips 632b9f0f1bbSKim Phillips static int ipic_host_xlate(struct irq_host *h, struct device_node *ct, 633b9f0f1bbSKim Phillips u32 *intspec, unsigned int intsize, 634b9f0f1bbSKim Phillips irq_hw_number_t *out_hwirq, unsigned int *out_flags) 635b9f0f1bbSKim Phillips 636b9f0f1bbSKim Phillips { 637b9f0f1bbSKim Phillips /* interrupt sense values coming from the device tree equal either 638b9f0f1bbSKim Phillips * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change) 639b9f0f1bbSKim Phillips */ 640b9f0f1bbSKim Phillips *out_hwirq = intspec[0]; 641b9f0f1bbSKim Phillips if (intsize > 1) 642b9f0f1bbSKim Phillips *out_flags = intspec[1]; 643b9f0f1bbSKim Phillips else 644b9f0f1bbSKim Phillips *out_flags = IRQ_TYPE_NONE; 645b9f0f1bbSKim Phillips return 0; 646b9f0f1bbSKim Phillips } 647b9f0f1bbSKim Phillips 648b9f0f1bbSKim Phillips static struct irq_host_ops ipic_host_ops = { 649b9f0f1bbSKim Phillips .match = ipic_host_match, 650b9f0f1bbSKim Phillips .map = ipic_host_map, 651b9f0f1bbSKim Phillips .xlate = ipic_host_xlate, 652b9f0f1bbSKim Phillips }; 653b9f0f1bbSKim Phillips 654126186a0SKumar Gala struct ipic * __init ipic_init(struct device_node *node, unsigned int flags) 655b9f0f1bbSKim Phillips { 656b9f0f1bbSKim Phillips struct ipic *ipic; 657b9f0f1bbSKim Phillips struct resource res; 658b9f0f1bbSKim Phillips u32 temp = 0, ret; 659b9f0f1bbSKim Phillips 660b9f0f1bbSKim Phillips ipic = alloc_bootmem(sizeof(struct ipic)); 661b9f0f1bbSKim Phillips if (ipic == NULL) 662126186a0SKumar Gala return NULL; 663b9f0f1bbSKim Phillips 664b9f0f1bbSKim Phillips memset(ipic, 0, sizeof(struct ipic)); 665b9f0f1bbSKim Phillips 66652964f87SMichael Ellerman ipic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR, 667b9f0f1bbSKim Phillips NR_IPIC_INTS, 668b9f0f1bbSKim Phillips &ipic_host_ops, 0); 669b9f0f1bbSKim Phillips if (ipic->irqhost == NULL) { 670b9f0f1bbSKim Phillips of_node_put(node); 671126186a0SKumar Gala return NULL; 672b9f0f1bbSKim Phillips } 673b9f0f1bbSKim Phillips 674b9f0f1bbSKim Phillips ret = of_address_to_resource(node, 0, &res); 675126186a0SKumar Gala if (ret) { 676126186a0SKumar Gala of_node_put(node); 677126186a0SKumar Gala return NULL; 678126186a0SKumar Gala } 679b9f0f1bbSKim Phillips 680b9f0f1bbSKim Phillips ipic->regs = ioremap(res.start, res.end - res.start + 1); 681b9f0f1bbSKim Phillips 682b9f0f1bbSKim Phillips ipic->irqhost->host_data = ipic; 683b9f0f1bbSKim Phillips 684b9f0f1bbSKim Phillips /* init hw */ 685b9f0f1bbSKim Phillips ipic_write(ipic->regs, IPIC_SICNR, 0x0); 6861cd8e506SKumar Gala 6871cd8e506SKumar Gala /* default priority scheme is grouped. If spread mode is required 6881cd8e506SKumar Gala * configure SICFR accordingly */ 6891cd8e506SKumar Gala if (flags & IPIC_SPREADMODE_GRP_A) 6901cd8e506SKumar Gala temp |= SICFR_IPSA; 691f03ca957SLi Yang if (flags & IPIC_SPREADMODE_GRP_B) 692f03ca957SLi Yang temp |= SICFR_IPSB; 693f03ca957SLi Yang if (flags & IPIC_SPREADMODE_GRP_C) 694f03ca957SLi Yang temp |= SICFR_IPSC; 6951cd8e506SKumar Gala if (flags & IPIC_SPREADMODE_GRP_D) 6961cd8e506SKumar Gala temp |= SICFR_IPSD; 6971cd8e506SKumar Gala if (flags & IPIC_SPREADMODE_MIX_A) 6981cd8e506SKumar Gala temp |= SICFR_MPSA; 6991cd8e506SKumar Gala if (flags & IPIC_SPREADMODE_MIX_B) 7001cd8e506SKumar Gala temp |= SICFR_MPSB; 7011cd8e506SKumar Gala 702f03ca957SLi Yang ipic_write(ipic->regs, IPIC_SICFR, temp); 7031cd8e506SKumar Gala 7041cd8e506SKumar Gala /* handle MCP route */ 7051cd8e506SKumar Gala temp = 0; 7061cd8e506SKumar Gala if (flags & IPIC_DISABLE_MCP_OUT) 7071cd8e506SKumar Gala temp = SERCR_MCPR; 708b9f0f1bbSKim Phillips ipic_write(ipic->regs, IPIC_SERCR, temp); 7091cd8e506SKumar Gala 7101cd8e506SKumar Gala /* handle routing of IRQ0 to MCP */ 711b9f0f1bbSKim Phillips temp = ipic_read(ipic->regs, IPIC_SEMSR); 7121cd8e506SKumar Gala 7131cd8e506SKumar Gala if (flags & IPIC_IRQ0_MCP) 7141cd8e506SKumar Gala temp |= SEMSR_SIRQ0; 7151cd8e506SKumar Gala else 7161cd8e506SKumar Gala temp &= ~SEMSR_SIRQ0; 7171cd8e506SKumar Gala 718b9f0f1bbSKim Phillips ipic_write(ipic->regs, IPIC_SEMSR, temp); 7191cd8e506SKumar Gala 720b9f0f1bbSKim Phillips primary_ipic = ipic; 721b9f0f1bbSKim Phillips irq_set_default_host(primary_ipic->irqhost); 722b9f0f1bbSKim Phillips 723b9f0f1bbSKim Phillips printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS, 724b9f0f1bbSKim Phillips primary_ipic->regs); 725126186a0SKumar Gala 726126186a0SKumar Gala return ipic; 7271cd8e506SKumar Gala } 7281cd8e506SKumar Gala 729b9f0f1bbSKim Phillips int ipic_set_priority(unsigned int virq, unsigned int priority) 7301cd8e506SKumar Gala { 731b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 732b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 7331cd8e506SKumar Gala u32 temp; 7341cd8e506SKumar Gala 7351cd8e506SKumar Gala if (priority > 7) 7361cd8e506SKumar Gala return -EINVAL; 7371cd8e506SKumar Gala if (src > 127) 7381cd8e506SKumar Gala return -EINVAL; 7391cd8e506SKumar Gala if (ipic_info[src].prio == 0) 7401cd8e506SKumar Gala return -EINVAL; 7411cd8e506SKumar Gala 7421cd8e506SKumar Gala temp = ipic_read(ipic->regs, ipic_info[src].prio); 7431cd8e506SKumar Gala 7441cd8e506SKumar Gala if (priority < 4) { 7451cd8e506SKumar Gala temp &= ~(0x7 << (20 + (3 - priority) * 3)); 7461cd8e506SKumar Gala temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3); 7471cd8e506SKumar Gala } else { 7481cd8e506SKumar Gala temp &= ~(0x7 << (4 + (7 - priority) * 3)); 7491cd8e506SKumar Gala temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3); 7501cd8e506SKumar Gala } 7511cd8e506SKumar Gala 7521cd8e506SKumar Gala ipic_write(ipic->regs, ipic_info[src].prio, temp); 7531cd8e506SKumar Gala 7541cd8e506SKumar Gala return 0; 7551cd8e506SKumar Gala } 7561cd8e506SKumar Gala 757b9f0f1bbSKim Phillips void ipic_set_highest_priority(unsigned int virq) 7581cd8e506SKumar Gala { 759b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 760b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 7611cd8e506SKumar Gala u32 temp; 7621cd8e506SKumar Gala 7631cd8e506SKumar Gala temp = ipic_read(ipic->regs, IPIC_SICFR); 7641cd8e506SKumar Gala 7651cd8e506SKumar Gala /* clear and set HPI */ 7661cd8e506SKumar Gala temp &= 0x7f000000; 7671cd8e506SKumar Gala temp |= (src & 0x7f) << 24; 7681cd8e506SKumar Gala 7691cd8e506SKumar Gala ipic_write(ipic->regs, IPIC_SICFR, temp); 7701cd8e506SKumar Gala } 7711cd8e506SKumar Gala 7721cd8e506SKumar Gala void ipic_set_default_priority(void) 7731cd8e506SKumar Gala { 774f03ca957SLi Yang ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_PRIORITY_DEFAULT); 775f03ca957SLi Yang ipic_write(primary_ipic->regs, IPIC_SIPRR_B, IPIC_PRIORITY_DEFAULT); 776f03ca957SLi Yang ipic_write(primary_ipic->regs, IPIC_SIPRR_C, IPIC_PRIORITY_DEFAULT); 777f03ca957SLi Yang ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_PRIORITY_DEFAULT); 778f03ca957SLi Yang ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_PRIORITY_DEFAULT); 779f03ca957SLi Yang ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_PRIORITY_DEFAULT); 7801cd8e506SKumar Gala } 7811cd8e506SKumar Gala 7821cd8e506SKumar Gala void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq) 7831cd8e506SKumar Gala { 7841cd8e506SKumar Gala struct ipic *ipic = primary_ipic; 7851cd8e506SKumar Gala u32 temp; 7861cd8e506SKumar Gala 7871cd8e506SKumar Gala temp = ipic_read(ipic->regs, IPIC_SERMR); 7881cd8e506SKumar Gala temp |= (1 << (31 - mcp_irq)); 7891cd8e506SKumar Gala ipic_write(ipic->regs, IPIC_SERMR, temp); 7901cd8e506SKumar Gala } 7911cd8e506SKumar Gala 7921cd8e506SKumar Gala void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq) 7931cd8e506SKumar Gala { 7941cd8e506SKumar Gala struct ipic *ipic = primary_ipic; 7951cd8e506SKumar Gala u32 temp; 7961cd8e506SKumar Gala 7971cd8e506SKumar Gala temp = ipic_read(ipic->regs, IPIC_SERMR); 7981cd8e506SKumar Gala temp &= (1 << (31 - mcp_irq)); 7991cd8e506SKumar Gala ipic_write(ipic->regs, IPIC_SERMR, temp); 8001cd8e506SKumar Gala } 8011cd8e506SKumar Gala 8021cd8e506SKumar Gala u32 ipic_get_mcp_status(void) 8031cd8e506SKumar Gala { 8041cd8e506SKumar Gala return ipic_read(primary_ipic->regs, IPIC_SERMR); 8051cd8e506SKumar Gala } 8061cd8e506SKumar Gala 8071cd8e506SKumar Gala void ipic_clear_mcp_status(u32 mask) 8081cd8e506SKumar Gala { 8091cd8e506SKumar Gala ipic_write(primary_ipic->regs, IPIC_SERMR, mask); 8101cd8e506SKumar Gala } 8111cd8e506SKumar Gala 812b9f0f1bbSKim Phillips /* Return an interrupt vector or NO_IRQ if no interrupt is pending. */ 81335a84c2fSOlaf Hering unsigned int ipic_get_irq(void) 8141cd8e506SKumar Gala { 8151cd8e506SKumar Gala int irq; 8161cd8e506SKumar Gala 817b9f0f1bbSKim Phillips BUG_ON(primary_ipic == NULL); 818b9f0f1bbSKim Phillips 819b9f0f1bbSKim Phillips #define IPIC_SIVCR_VECTOR_MASK 0x7f 820b9f0f1bbSKim Phillips irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK; 8211cd8e506SKumar Gala 8221cd8e506SKumar Gala if (irq == 0) /* 0 --> no irq is pending */ 823b9f0f1bbSKim Phillips return NO_IRQ; 8241cd8e506SKumar Gala 825b9f0f1bbSKim Phillips return irq_linear_revmap(primary_ipic->irqhost, irq); 8261cd8e506SKumar Gala } 8271cd8e506SKumar Gala 8281cd8e506SKumar Gala static struct sysdev_class ipic_sysclass = { 8291cd8e506SKumar Gala set_kset_name("ipic"), 8301cd8e506SKumar Gala }; 8311cd8e506SKumar Gala 8321cd8e506SKumar Gala static struct sys_device device_ipic = { 8331cd8e506SKumar Gala .id = 0, 8341cd8e506SKumar Gala .cls = &ipic_sysclass, 8351cd8e506SKumar Gala }; 8361cd8e506SKumar Gala 8371cd8e506SKumar Gala static int __init init_ipic_sysfs(void) 8381cd8e506SKumar Gala { 8391cd8e506SKumar Gala int rc; 8401cd8e506SKumar Gala 8411cd8e506SKumar Gala if (!primary_ipic->regs) 8421cd8e506SKumar Gala return -ENODEV; 8431cd8e506SKumar Gala printk(KERN_DEBUG "Registering ipic with sysfs...\n"); 8441cd8e506SKumar Gala 8451cd8e506SKumar Gala rc = sysdev_class_register(&ipic_sysclass); 8461cd8e506SKumar Gala if (rc) { 8471cd8e506SKumar Gala printk(KERN_ERR "Failed registering ipic sys class\n"); 8481cd8e506SKumar Gala return -ENODEV; 8491cd8e506SKumar Gala } 8501cd8e506SKumar Gala rc = sysdev_register(&device_ipic); 8511cd8e506SKumar Gala if (rc) { 8521cd8e506SKumar Gala printk(KERN_ERR "Failed registering ipic sys device\n"); 8531cd8e506SKumar Gala return -ENODEV; 8541cd8e506SKumar Gala } 8551cd8e506SKumar Gala return 0; 8561cd8e506SKumar Gala } 8571cd8e506SKumar Gala 8581cd8e506SKumar Gala subsys_initcall(init_ipic_sysfs); 859