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> 25d49747bdSScott Wood #include <linux/fsl_devices.h> 261cd8e506SKumar Gala #include <asm/irq.h> 271cd8e506SKumar Gala #include <asm/io.h> 28b9f0f1bbSKim Phillips #include <asm/prom.h> 291cd8e506SKumar Gala #include <asm/ipic.h> 301cd8e506SKumar Gala 311cd8e506SKumar Gala #include "ipic.h" 321cd8e506SKumar Gala 331cd8e506SKumar Gala static struct ipic * primary_ipic; 3477d4309eSLi Yang static struct irq_chip ipic_level_irq_chip, ipic_edge_irq_chip; 35b9f0f1bbSKim Phillips static DEFINE_SPINLOCK(ipic_lock); 361cd8e506SKumar Gala 371cd8e506SKumar Gala static struct ipic_info ipic_info[] = { 38f03ca957SLi Yang [1] = { 39f03ca957SLi Yang .mask = IPIC_SIMSR_H, 40f03ca957SLi Yang .prio = IPIC_SIPRR_C, 41f03ca957SLi Yang .force = IPIC_SIFCR_H, 42f03ca957SLi Yang .bit = 16, 43f03ca957SLi Yang .prio_mask = 0, 44f03ca957SLi Yang }, 45f03ca957SLi Yang [2] = { 46f03ca957SLi Yang .mask = IPIC_SIMSR_H, 47f03ca957SLi Yang .prio = IPIC_SIPRR_C, 48f03ca957SLi Yang .force = IPIC_SIFCR_H, 49f03ca957SLi Yang .bit = 17, 50f03ca957SLi Yang .prio_mask = 1, 51f03ca957SLi Yang }, 52a7267d67SJohn Rigby [3] = { 53a7267d67SJohn Rigby .mask = IPIC_SIMSR_H, 54a7267d67SJohn Rigby .prio = IPIC_SIPRR_C, 55a7267d67SJohn Rigby .force = IPIC_SIFCR_H, 56a7267d67SJohn Rigby .bit = 18, 57a7267d67SJohn Rigby .prio_mask = 2, 58a7267d67SJohn Rigby }, 59f03ca957SLi Yang [4] = { 60f03ca957SLi Yang .mask = IPIC_SIMSR_H, 61f03ca957SLi Yang .prio = IPIC_SIPRR_C, 62f03ca957SLi Yang .force = IPIC_SIFCR_H, 63f03ca957SLi Yang .bit = 19, 64f03ca957SLi Yang .prio_mask = 3, 65f03ca957SLi Yang }, 66a7267d67SJohn Rigby [5] = { 67a7267d67SJohn Rigby .mask = IPIC_SIMSR_H, 68a7267d67SJohn Rigby .prio = IPIC_SIPRR_C, 69a7267d67SJohn Rigby .force = IPIC_SIFCR_H, 70a7267d67SJohn Rigby .bit = 20, 71a7267d67SJohn Rigby .prio_mask = 4, 72a7267d67SJohn Rigby }, 73a7267d67SJohn Rigby [6] = { 74a7267d67SJohn Rigby .mask = IPIC_SIMSR_H, 75a7267d67SJohn Rigby .prio = IPIC_SIPRR_C, 76a7267d67SJohn Rigby .force = IPIC_SIFCR_H, 77a7267d67SJohn Rigby .bit = 21, 78a7267d67SJohn Rigby .prio_mask = 5, 79a7267d67SJohn Rigby }, 80a7267d67SJohn Rigby [7] = { 81a7267d67SJohn Rigby .mask = IPIC_SIMSR_H, 82a7267d67SJohn Rigby .prio = IPIC_SIPRR_C, 83a7267d67SJohn Rigby .force = IPIC_SIFCR_H, 84a7267d67SJohn Rigby .bit = 22, 85a7267d67SJohn Rigby .prio_mask = 6, 86a7267d67SJohn Rigby }, 87a7267d67SJohn Rigby [8] = { 88a7267d67SJohn Rigby .mask = IPIC_SIMSR_H, 89a7267d67SJohn Rigby .prio = IPIC_SIPRR_C, 90a7267d67SJohn Rigby .force = IPIC_SIFCR_H, 91a7267d67SJohn Rigby .bit = 23, 92a7267d67SJohn Rigby .prio_mask = 7, 93a7267d67SJohn Rigby }, 941cd8e506SKumar Gala [9] = { 951cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 961cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 971cd8e506SKumar Gala .force = IPIC_SIFCR_H, 981cd8e506SKumar Gala .bit = 24, 991cd8e506SKumar Gala .prio_mask = 0, 1001cd8e506SKumar Gala }, 1011cd8e506SKumar Gala [10] = { 1021cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1031cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 1041cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1051cd8e506SKumar Gala .bit = 25, 1061cd8e506SKumar Gala .prio_mask = 1, 1071cd8e506SKumar Gala }, 1081cd8e506SKumar Gala [11] = { 1091cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1101cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 1111cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1121cd8e506SKumar Gala .bit = 26, 1131cd8e506SKumar Gala .prio_mask = 2, 1141cd8e506SKumar Gala }, 115f03ca957SLi Yang [12] = { 116f03ca957SLi Yang .mask = IPIC_SIMSR_H, 117f03ca957SLi Yang .prio = IPIC_SIPRR_D, 118f03ca957SLi Yang .force = IPIC_SIFCR_H, 119f03ca957SLi Yang .bit = 27, 120f03ca957SLi Yang .prio_mask = 3, 121f03ca957SLi Yang }, 122f03ca957SLi Yang [13] = { 123f03ca957SLi Yang .mask = IPIC_SIMSR_H, 124f03ca957SLi Yang .prio = IPIC_SIPRR_D, 125f03ca957SLi Yang .force = IPIC_SIFCR_H, 126f03ca957SLi Yang .bit = 28, 127f03ca957SLi Yang .prio_mask = 4, 128f03ca957SLi Yang }, 1291cd8e506SKumar Gala [14] = { 1301cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1311cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 1321cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1331cd8e506SKumar Gala .bit = 29, 1341cd8e506SKumar Gala .prio_mask = 5, 1351cd8e506SKumar Gala }, 1361cd8e506SKumar Gala [15] = { 1371cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1381cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 1391cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1401cd8e506SKumar Gala .bit = 30, 1411cd8e506SKumar Gala .prio_mask = 6, 1421cd8e506SKumar Gala }, 1431cd8e506SKumar Gala [16] = { 1441cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1451cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 1461cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1471cd8e506SKumar Gala .bit = 31, 1481cd8e506SKumar Gala .prio_mask = 7, 1491cd8e506SKumar Gala }, 1501cd8e506SKumar Gala [17] = { 15177d4309eSLi Yang .ack = IPIC_SEPNR, 1521cd8e506SKumar Gala .mask = IPIC_SEMSR, 1531cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 1541cd8e506SKumar Gala .force = IPIC_SEFCR, 1551cd8e506SKumar Gala .bit = 1, 1561cd8e506SKumar Gala .prio_mask = 5, 1571cd8e506SKumar Gala }, 1581cd8e506SKumar Gala [18] = { 15977d4309eSLi Yang .ack = IPIC_SEPNR, 1601cd8e506SKumar Gala .mask = IPIC_SEMSR, 1611cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 1621cd8e506SKumar Gala .force = IPIC_SEFCR, 1631cd8e506SKumar Gala .bit = 2, 1641cd8e506SKumar Gala .prio_mask = 6, 1651cd8e506SKumar Gala }, 1661cd8e506SKumar Gala [19] = { 16777d4309eSLi Yang .ack = IPIC_SEPNR, 1681cd8e506SKumar Gala .mask = IPIC_SEMSR, 1691cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 1701cd8e506SKumar Gala .force = IPIC_SEFCR, 1711cd8e506SKumar Gala .bit = 3, 1721cd8e506SKumar Gala .prio_mask = 7, 1731cd8e506SKumar Gala }, 1741cd8e506SKumar Gala [20] = { 17577d4309eSLi Yang .ack = IPIC_SEPNR, 1761cd8e506SKumar Gala .mask = IPIC_SEMSR, 1771cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 1781cd8e506SKumar Gala .force = IPIC_SEFCR, 1791cd8e506SKumar Gala .bit = 4, 1801cd8e506SKumar Gala .prio_mask = 4, 1811cd8e506SKumar Gala }, 1821cd8e506SKumar Gala [21] = { 18377d4309eSLi Yang .ack = IPIC_SEPNR, 1841cd8e506SKumar Gala .mask = IPIC_SEMSR, 1851cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 1861cd8e506SKumar Gala .force = IPIC_SEFCR, 1871cd8e506SKumar Gala .bit = 5, 1881cd8e506SKumar Gala .prio_mask = 5, 1891cd8e506SKumar Gala }, 1901cd8e506SKumar Gala [22] = { 19177d4309eSLi Yang .ack = IPIC_SEPNR, 1921cd8e506SKumar Gala .mask = IPIC_SEMSR, 1931cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 1941cd8e506SKumar Gala .force = IPIC_SEFCR, 1951cd8e506SKumar Gala .bit = 6, 1961cd8e506SKumar Gala .prio_mask = 6, 1971cd8e506SKumar Gala }, 1981cd8e506SKumar Gala [23] = { 19977d4309eSLi Yang .ack = IPIC_SEPNR, 2001cd8e506SKumar Gala .mask = IPIC_SEMSR, 2011cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 2021cd8e506SKumar Gala .force = IPIC_SEFCR, 2031cd8e506SKumar Gala .bit = 7, 2041cd8e506SKumar Gala .prio_mask = 7, 2051cd8e506SKumar Gala }, 2061cd8e506SKumar Gala [32] = { 2071cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 2081cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 2091cd8e506SKumar Gala .force = IPIC_SIFCR_H, 2101cd8e506SKumar Gala .bit = 0, 2111cd8e506SKumar Gala .prio_mask = 0, 2121cd8e506SKumar Gala }, 2131cd8e506SKumar Gala [33] = { 2141cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 2151cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 2161cd8e506SKumar Gala .force = IPIC_SIFCR_H, 2171cd8e506SKumar Gala .bit = 1, 2181cd8e506SKumar Gala .prio_mask = 1, 2191cd8e506SKumar Gala }, 2201cd8e506SKumar Gala [34] = { 2211cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 2221cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 2231cd8e506SKumar Gala .force = IPIC_SIFCR_H, 2241cd8e506SKumar Gala .bit = 2, 2251cd8e506SKumar Gala .prio_mask = 2, 2261cd8e506SKumar Gala }, 2271cd8e506SKumar Gala [35] = { 2281cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 2291cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 2301cd8e506SKumar Gala .force = IPIC_SIFCR_H, 2311cd8e506SKumar Gala .bit = 3, 2321cd8e506SKumar Gala .prio_mask = 3, 2331cd8e506SKumar Gala }, 2341cd8e506SKumar Gala [36] = { 2351cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 2361cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 2371cd8e506SKumar Gala .force = IPIC_SIFCR_H, 2381cd8e506SKumar Gala .bit = 4, 2391cd8e506SKumar Gala .prio_mask = 4, 2401cd8e506SKumar Gala }, 2411cd8e506SKumar Gala [37] = { 2421cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 2431cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 2441cd8e506SKumar Gala .force = IPIC_SIFCR_H, 2451cd8e506SKumar Gala .bit = 5, 2461cd8e506SKumar Gala .prio_mask = 5, 2471cd8e506SKumar Gala }, 2481cd8e506SKumar Gala [38] = { 2491cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 2501cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 2511cd8e506SKumar Gala .force = IPIC_SIFCR_H, 2521cd8e506SKumar Gala .bit = 6, 2531cd8e506SKumar Gala .prio_mask = 6, 2541cd8e506SKumar Gala }, 2551cd8e506SKumar Gala [39] = { 2561cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 2571cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 2581cd8e506SKumar Gala .force = IPIC_SIFCR_H, 2591cd8e506SKumar Gala .bit = 7, 2601cd8e506SKumar Gala .prio_mask = 7, 2611cd8e506SKumar Gala }, 262a7267d67SJohn Rigby [40] = { 263a7267d67SJohn Rigby .mask = IPIC_SIMSR_H, 264a7267d67SJohn Rigby .prio = IPIC_SIPRR_B, 265a7267d67SJohn Rigby .force = IPIC_SIFCR_H, 266a7267d67SJohn Rigby .bit = 8, 267a7267d67SJohn Rigby .prio_mask = 0, 268a7267d67SJohn Rigby }, 269a7267d67SJohn Rigby [41] = { 270a7267d67SJohn Rigby .mask = IPIC_SIMSR_H, 271a7267d67SJohn Rigby .prio = IPIC_SIPRR_B, 272a7267d67SJohn Rigby .force = IPIC_SIFCR_H, 273a7267d67SJohn Rigby .bit = 9, 274a7267d67SJohn Rigby .prio_mask = 1, 275a7267d67SJohn Rigby }, 276f03ca957SLi Yang [42] = { 277f03ca957SLi Yang .mask = IPIC_SIMSR_H, 278f03ca957SLi Yang .prio = IPIC_SIPRR_B, 279f03ca957SLi Yang .force = IPIC_SIFCR_H, 280f03ca957SLi Yang .bit = 10, 281f03ca957SLi Yang .prio_mask = 2, 282f03ca957SLi Yang }, 283a7267d67SJohn Rigby [43] = { 284a7267d67SJohn Rigby .mask = IPIC_SIMSR_H, 285a7267d67SJohn Rigby .prio = IPIC_SIPRR_B, 286a7267d67SJohn Rigby .force = IPIC_SIFCR_H, 287a7267d67SJohn Rigby .bit = 11, 288a7267d67SJohn Rigby .prio_mask = 3, 289a7267d67SJohn Rigby }, 290f03ca957SLi Yang [44] = { 291f03ca957SLi Yang .mask = IPIC_SIMSR_H, 292f03ca957SLi Yang .prio = IPIC_SIPRR_B, 293f03ca957SLi Yang .force = IPIC_SIFCR_H, 294f03ca957SLi Yang .bit = 12, 295f03ca957SLi Yang .prio_mask = 4, 296f03ca957SLi Yang }, 297f03ca957SLi Yang [45] = { 298f03ca957SLi Yang .mask = IPIC_SIMSR_H, 299f03ca957SLi Yang .prio = IPIC_SIPRR_B, 300f03ca957SLi Yang .force = IPIC_SIFCR_H, 301f03ca957SLi Yang .bit = 13, 302f03ca957SLi Yang .prio_mask = 5, 303f03ca957SLi Yang }, 304f03ca957SLi Yang [46] = { 305f03ca957SLi Yang .mask = IPIC_SIMSR_H, 306f03ca957SLi Yang .prio = IPIC_SIPRR_B, 307f03ca957SLi Yang .force = IPIC_SIFCR_H, 308f03ca957SLi Yang .bit = 14, 309f03ca957SLi Yang .prio_mask = 6, 310f03ca957SLi Yang }, 311f03ca957SLi Yang [47] = { 312f03ca957SLi Yang .mask = IPIC_SIMSR_H, 313f03ca957SLi Yang .prio = IPIC_SIPRR_B, 314f03ca957SLi Yang .force = IPIC_SIFCR_H, 315f03ca957SLi Yang .bit = 15, 316f03ca957SLi Yang .prio_mask = 7, 317f03ca957SLi Yang }, 3181cd8e506SKumar Gala [48] = { 3191cd8e506SKumar Gala .mask = IPIC_SEMSR, 3201cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 3211cd8e506SKumar Gala .force = IPIC_SEFCR, 3221cd8e506SKumar Gala .bit = 0, 3231cd8e506SKumar Gala .prio_mask = 4, 3241cd8e506SKumar Gala }, 3251cd8e506SKumar Gala [64] = { 3261cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3271cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 3281cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3291cd8e506SKumar Gala .bit = 0, 3301cd8e506SKumar Gala .prio_mask = 0, 3311cd8e506SKumar Gala }, 3321cd8e506SKumar Gala [65] = { 3331cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3341cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 3351cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3361cd8e506SKumar Gala .bit = 1, 3371cd8e506SKumar Gala .prio_mask = 1, 3381cd8e506SKumar Gala }, 3391cd8e506SKumar Gala [66] = { 3401cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3411cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 3421cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3431cd8e506SKumar Gala .bit = 2, 3441cd8e506SKumar Gala .prio_mask = 2, 3451cd8e506SKumar Gala }, 3461cd8e506SKumar Gala [67] = { 3471cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3481cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 3491cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3501cd8e506SKumar Gala .bit = 3, 3511cd8e506SKumar Gala .prio_mask = 3, 3521cd8e506SKumar Gala }, 3531cd8e506SKumar Gala [68] = { 3541cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3551cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 3561cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3571cd8e506SKumar Gala .bit = 4, 3581cd8e506SKumar Gala .prio_mask = 0, 3591cd8e506SKumar Gala }, 3601cd8e506SKumar Gala [69] = { 3611cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3621cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 3631cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3641cd8e506SKumar Gala .bit = 5, 3651cd8e506SKumar Gala .prio_mask = 1, 3661cd8e506SKumar Gala }, 3671cd8e506SKumar Gala [70] = { 3681cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3691cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 3701cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3711cd8e506SKumar Gala .bit = 6, 3721cd8e506SKumar Gala .prio_mask = 2, 3731cd8e506SKumar Gala }, 3741cd8e506SKumar Gala [71] = { 3751cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3761cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 3771cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3781cd8e506SKumar Gala .bit = 7, 3791cd8e506SKumar Gala .prio_mask = 3, 3801cd8e506SKumar Gala }, 3811cd8e506SKumar Gala [72] = { 3821cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3831cd8e506SKumar Gala .prio = 0, 3841cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3851cd8e506SKumar Gala .bit = 8, 3861cd8e506SKumar Gala }, 3871cd8e506SKumar Gala [73] = { 3881cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3891cd8e506SKumar Gala .prio = 0, 3901cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3911cd8e506SKumar Gala .bit = 9, 3921cd8e506SKumar Gala }, 3931cd8e506SKumar Gala [74] = { 3941cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3951cd8e506SKumar Gala .prio = 0, 3961cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3971cd8e506SKumar Gala .bit = 10, 3981cd8e506SKumar Gala }, 3991cd8e506SKumar Gala [75] = { 4001cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 4011cd8e506SKumar Gala .prio = 0, 4021cd8e506SKumar Gala .force = IPIC_SIFCR_L, 4031cd8e506SKumar Gala .bit = 11, 4041cd8e506SKumar Gala }, 4051cd8e506SKumar Gala [76] = { 4061cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 4071cd8e506SKumar Gala .prio = 0, 4081cd8e506SKumar Gala .force = IPIC_SIFCR_L, 4091cd8e506SKumar Gala .bit = 12, 4101cd8e506SKumar Gala }, 4111cd8e506SKumar Gala [77] = { 4121cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 4131cd8e506SKumar Gala .prio = 0, 4141cd8e506SKumar Gala .force = IPIC_SIFCR_L, 4151cd8e506SKumar Gala .bit = 13, 4161cd8e506SKumar Gala }, 4171cd8e506SKumar Gala [78] = { 4181cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 4191cd8e506SKumar Gala .prio = 0, 4201cd8e506SKumar Gala .force = IPIC_SIFCR_L, 4211cd8e506SKumar Gala .bit = 14, 4221cd8e506SKumar Gala }, 4231cd8e506SKumar Gala [79] = { 4241cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 4251cd8e506SKumar Gala .prio = 0, 4261cd8e506SKumar Gala .force = IPIC_SIFCR_L, 4271cd8e506SKumar Gala .bit = 15, 4281cd8e506SKumar Gala }, 4291cd8e506SKumar Gala [80] = { 4301cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 4311cd8e506SKumar Gala .prio = 0, 4321cd8e506SKumar Gala .force = IPIC_SIFCR_L, 4331cd8e506SKumar Gala .bit = 16, 4341cd8e506SKumar Gala }, 435f03ca957SLi Yang [81] = { 436f03ca957SLi Yang .mask = IPIC_SIMSR_L, 437f03ca957SLi Yang .prio = 0, 438f03ca957SLi Yang .force = IPIC_SIFCR_L, 439f03ca957SLi Yang .bit = 17, 440f03ca957SLi Yang }, 441f03ca957SLi Yang [82] = { 442f03ca957SLi Yang .mask = IPIC_SIMSR_L, 443f03ca957SLi Yang .prio = 0, 444f03ca957SLi Yang .force = IPIC_SIFCR_L, 445f03ca957SLi Yang .bit = 18, 446f03ca957SLi Yang }, 447a7267d67SJohn Rigby [83] = { 448a7267d67SJohn Rigby .mask = IPIC_SIMSR_L, 449a7267d67SJohn Rigby .prio = 0, 450a7267d67SJohn Rigby .force = IPIC_SIFCR_L, 451a7267d67SJohn Rigby .bit = 19, 452a7267d67SJohn Rigby }, 4531cd8e506SKumar Gala [84] = { 4541cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 4551cd8e506SKumar Gala .prio = 0, 4561cd8e506SKumar Gala .force = IPIC_SIFCR_L, 4571cd8e506SKumar Gala .bit = 20, 4581cd8e506SKumar Gala }, 4591cd8e506SKumar Gala [85] = { 4601cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 4611cd8e506SKumar Gala .prio = 0, 4621cd8e506SKumar Gala .force = IPIC_SIFCR_L, 4631cd8e506SKumar Gala .bit = 21, 4641cd8e506SKumar Gala }, 465f03ca957SLi Yang [86] = { 466f03ca957SLi Yang .mask = IPIC_SIMSR_L, 467f03ca957SLi Yang .prio = 0, 468f03ca957SLi Yang .force = IPIC_SIFCR_L, 469f03ca957SLi Yang .bit = 22, 470f03ca957SLi Yang }, 471f03ca957SLi Yang [87] = { 472f03ca957SLi Yang .mask = IPIC_SIMSR_L, 473f03ca957SLi Yang .prio = 0, 474f03ca957SLi Yang .force = IPIC_SIFCR_L, 475f03ca957SLi Yang .bit = 23, 476f03ca957SLi Yang }, 477f03ca957SLi Yang [88] = { 478f03ca957SLi Yang .mask = IPIC_SIMSR_L, 479f03ca957SLi Yang .prio = 0, 480f03ca957SLi Yang .force = IPIC_SIFCR_L, 481f03ca957SLi Yang .bit = 24, 482f03ca957SLi Yang }, 483f03ca957SLi Yang [89] = { 484f03ca957SLi Yang .mask = IPIC_SIMSR_L, 485f03ca957SLi Yang .prio = 0, 486f03ca957SLi Yang .force = IPIC_SIFCR_L, 487f03ca957SLi Yang .bit = 25, 488f03ca957SLi Yang }, 4891cd8e506SKumar Gala [90] = { 4901cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 4911cd8e506SKumar Gala .prio = 0, 4921cd8e506SKumar Gala .force = IPIC_SIFCR_L, 4931cd8e506SKumar Gala .bit = 26, 4941cd8e506SKumar Gala }, 4951cd8e506SKumar Gala [91] = { 4961cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 4971cd8e506SKumar Gala .prio = 0, 4981cd8e506SKumar Gala .force = IPIC_SIFCR_L, 4991cd8e506SKumar Gala .bit = 27, 5001cd8e506SKumar Gala }, 5018cf6b195SKim Phillips [94] = { 5028cf6b195SKim Phillips .mask = IPIC_SIMSR_L, 5038cf6b195SKim Phillips .prio = 0, 5048cf6b195SKim Phillips .force = IPIC_SIFCR_L, 5058cf6b195SKim Phillips .bit = 30, 5068cf6b195SKim Phillips }, 5071cd8e506SKumar Gala }; 5081cd8e506SKumar Gala 5091cd8e506SKumar Gala static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg) 5101cd8e506SKumar Gala { 5111cd8e506SKumar Gala return in_be32(base + (reg >> 2)); 5121cd8e506SKumar Gala } 5131cd8e506SKumar Gala 5141cd8e506SKumar Gala static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value) 5151cd8e506SKumar Gala { 5161cd8e506SKumar Gala out_be32(base + (reg >> 2), value); 5171cd8e506SKumar Gala } 5181cd8e506SKumar Gala 519b9f0f1bbSKim Phillips static inline struct ipic * ipic_from_irq(unsigned int virq) 5201cd8e506SKumar Gala { 5211cd8e506SKumar Gala return primary_ipic; 5221cd8e506SKumar Gala } 5231cd8e506SKumar Gala 524b9f0f1bbSKim Phillips #define ipic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) 525b9f0f1bbSKim Phillips 526b9f0f1bbSKim Phillips static void ipic_unmask_irq(unsigned int virq) 5271cd8e506SKumar Gala { 528b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 529b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 530b9f0f1bbSKim Phillips unsigned long flags; 5311cd8e506SKumar Gala u32 temp; 5321cd8e506SKumar Gala 533b9f0f1bbSKim Phillips spin_lock_irqsave(&ipic_lock, flags); 534b9f0f1bbSKim Phillips 5351cd8e506SKumar Gala temp = ipic_read(ipic->regs, ipic_info[src].mask); 5361cd8e506SKumar Gala temp |= (1 << (31 - ipic_info[src].bit)); 5371cd8e506SKumar Gala ipic_write(ipic->regs, ipic_info[src].mask, temp); 538b9f0f1bbSKim Phillips 539b9f0f1bbSKim Phillips spin_unlock_irqrestore(&ipic_lock, flags); 5401cd8e506SKumar Gala } 5411cd8e506SKumar Gala 542b9f0f1bbSKim Phillips static void ipic_mask_irq(unsigned int virq) 5431cd8e506SKumar Gala { 544b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 545b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 546b9f0f1bbSKim Phillips unsigned long flags; 5471cd8e506SKumar Gala u32 temp; 5481cd8e506SKumar Gala 549b9f0f1bbSKim Phillips spin_lock_irqsave(&ipic_lock, flags); 550b9f0f1bbSKim Phillips 5511cd8e506SKumar Gala temp = ipic_read(ipic->regs, ipic_info[src].mask); 5521cd8e506SKumar Gala temp &= ~(1 << (31 - ipic_info[src].bit)); 5531cd8e506SKumar Gala ipic_write(ipic->regs, ipic_info[src].mask, temp); 554b9f0f1bbSKim Phillips 55577d4309eSLi Yang /* mb() can't guarantee that masking is finished. But it does finish 55677d4309eSLi Yang * for nearly all cases. */ 55777d4309eSLi Yang mb(); 55877d4309eSLi Yang 559b9f0f1bbSKim Phillips spin_unlock_irqrestore(&ipic_lock, flags); 5601cd8e506SKumar Gala } 5611cd8e506SKumar Gala 562b9f0f1bbSKim Phillips static void ipic_ack_irq(unsigned int virq) 5631cd8e506SKumar Gala { 564b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 565b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 566b9f0f1bbSKim Phillips unsigned long flags; 5671cd8e506SKumar Gala u32 temp; 5681cd8e506SKumar Gala 569b9f0f1bbSKim Phillips spin_lock_irqsave(&ipic_lock, flags); 5701cd8e506SKumar Gala 571*30c40469Sdayu@datangmobile.cn temp = 1 << (31 - ipic_info[src].bit); 57277d4309eSLi Yang ipic_write(ipic->regs, ipic_info[src].ack, temp); 57377d4309eSLi Yang 57477d4309eSLi Yang /* mb() can't guarantee that ack is finished. But it does finish 57577d4309eSLi Yang * for nearly all cases. */ 57677d4309eSLi Yang mb(); 577b9f0f1bbSKim Phillips 578b9f0f1bbSKim Phillips spin_unlock_irqrestore(&ipic_lock, flags); 5791cd8e506SKumar Gala } 5801cd8e506SKumar Gala 581b9f0f1bbSKim Phillips static void ipic_mask_irq_and_ack(unsigned int virq) 5821cd8e506SKumar Gala { 583b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 584b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 585b9f0f1bbSKim Phillips unsigned long flags; 586b9f0f1bbSKim Phillips u32 temp; 587b9f0f1bbSKim Phillips 588b9f0f1bbSKim Phillips spin_lock_irqsave(&ipic_lock, flags); 589b9f0f1bbSKim Phillips 590b9f0f1bbSKim Phillips temp = ipic_read(ipic->regs, ipic_info[src].mask); 591b9f0f1bbSKim Phillips temp &= ~(1 << (31 - ipic_info[src].bit)); 592b9f0f1bbSKim Phillips ipic_write(ipic->regs, ipic_info[src].mask, temp); 593b9f0f1bbSKim Phillips 594*30c40469Sdayu@datangmobile.cn temp = 1 << (31 - ipic_info[src].bit); 59577d4309eSLi Yang ipic_write(ipic->regs, ipic_info[src].ack, temp); 59677d4309eSLi Yang 59777d4309eSLi Yang /* mb() can't guarantee that ack is finished. But it does finish 59877d4309eSLi Yang * for nearly all cases. */ 59977d4309eSLi Yang mb(); 600b9f0f1bbSKim Phillips 601b9f0f1bbSKim Phillips spin_unlock_irqrestore(&ipic_lock, flags); 6021cd8e506SKumar Gala } 6031cd8e506SKumar Gala 604b9f0f1bbSKim Phillips static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) 605b9f0f1bbSKim Phillips { 606b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 607b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 608b9f0f1bbSKim Phillips struct irq_desc *desc = get_irq_desc(virq); 609b9f0f1bbSKim Phillips unsigned int vold, vnew, edibit; 610b9f0f1bbSKim Phillips 611b9f0f1bbSKim Phillips if (flow_type == IRQ_TYPE_NONE) 612b9f0f1bbSKim Phillips flow_type = IRQ_TYPE_LEVEL_LOW; 613b9f0f1bbSKim Phillips 614b9f0f1bbSKim Phillips /* ipic supports only low assertion and high-to-low change senses 615b9f0f1bbSKim Phillips */ 616b9f0f1bbSKim Phillips if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) { 617b9f0f1bbSKim Phillips printk(KERN_ERR "ipic: sense type 0x%x not supported\n", 618b9f0f1bbSKim Phillips flow_type); 619b9f0f1bbSKim Phillips return -EINVAL; 620b9f0f1bbSKim Phillips } 62177d4309eSLi Yang /* ipic supports only edge mode on external interrupts */ 62277d4309eSLi Yang if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !ipic_info[src].ack) { 62377d4309eSLi Yang printk(KERN_ERR "ipic: edge sense not supported on internal " 62477d4309eSLi Yang "interrupts\n"); 62577d4309eSLi Yang return -EINVAL; 62677d4309eSLi Yang } 627b9f0f1bbSKim Phillips 628b9f0f1bbSKim Phillips desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); 629b9f0f1bbSKim Phillips desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; 630b9f0f1bbSKim Phillips if (flow_type & IRQ_TYPE_LEVEL_LOW) { 631b9f0f1bbSKim Phillips desc->status |= IRQ_LEVEL; 632f49196a5SScott Wood desc->handle_irq = handle_level_irq; 63377d4309eSLi Yang desc->chip = &ipic_level_irq_chip; 634b9f0f1bbSKim Phillips } else { 635f49196a5SScott Wood desc->handle_irq = handle_edge_irq; 63677d4309eSLi Yang desc->chip = &ipic_edge_irq_chip; 637b9f0f1bbSKim Phillips } 638b9f0f1bbSKim Phillips 639b9f0f1bbSKim Phillips /* only EXT IRQ senses are programmable on ipic 640b9f0f1bbSKim Phillips * internal IRQ senses are LEVEL_LOW 641b9f0f1bbSKim Phillips */ 642b9f0f1bbSKim Phillips if (src == IPIC_IRQ_EXT0) 643b9f0f1bbSKim Phillips edibit = 15; 644b9f0f1bbSKim Phillips else 645b9f0f1bbSKim Phillips if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7) 646b9f0f1bbSKim Phillips edibit = (14 - (src - IPIC_IRQ_EXT1)); 647b9f0f1bbSKim Phillips else 648b9f0f1bbSKim Phillips return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL; 649b9f0f1bbSKim Phillips 650b9f0f1bbSKim Phillips vold = ipic_read(ipic->regs, IPIC_SECNR); 651b9f0f1bbSKim Phillips if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) { 652b9f0f1bbSKim Phillips vnew = vold | (1 << edibit); 653b9f0f1bbSKim Phillips } else { 654b9f0f1bbSKim Phillips vnew = vold & ~(1 << edibit); 655b9f0f1bbSKim Phillips } 656b9f0f1bbSKim Phillips if (vold != vnew) 657b9f0f1bbSKim Phillips ipic_write(ipic->regs, IPIC_SECNR, vnew); 658b9f0f1bbSKim Phillips return 0; 659b9f0f1bbSKim Phillips } 660b9f0f1bbSKim Phillips 66177d4309eSLi Yang /* level interrupts and edge interrupts have different ack operations */ 66277d4309eSLi Yang static struct irq_chip ipic_level_irq_chip = { 66377d4309eSLi Yang .typename = " IPIC ", 66477d4309eSLi Yang .unmask = ipic_unmask_irq, 66577d4309eSLi Yang .mask = ipic_mask_irq, 66677d4309eSLi Yang .mask_ack = ipic_mask_irq, 66777d4309eSLi Yang .set_type = ipic_set_irq_type, 66877d4309eSLi Yang }; 66977d4309eSLi Yang 67077d4309eSLi Yang static struct irq_chip ipic_edge_irq_chip = { 6711cd8e506SKumar Gala .typename = " IPIC ", 672b9f0f1bbSKim Phillips .unmask = ipic_unmask_irq, 673b9f0f1bbSKim Phillips .mask = ipic_mask_irq, 674b9f0f1bbSKim Phillips .mask_ack = ipic_mask_irq_and_ack, 675b9f0f1bbSKim Phillips .ack = ipic_ack_irq, 676b9f0f1bbSKim Phillips .set_type = ipic_set_irq_type, 6771cd8e506SKumar Gala }; 6781cd8e506SKumar Gala 679b9f0f1bbSKim Phillips static int ipic_host_match(struct irq_host *h, struct device_node *node) 6801cd8e506SKumar Gala { 681b9f0f1bbSKim Phillips /* Exact match, unless ipic node is NULL */ 68252964f87SMichael Ellerman return h->of_node == NULL || h->of_node == node; 683b9f0f1bbSKim Phillips } 6841cd8e506SKumar Gala 685b9f0f1bbSKim Phillips static int ipic_host_map(struct irq_host *h, unsigned int virq, 686b9f0f1bbSKim Phillips irq_hw_number_t hw) 687b9f0f1bbSKim Phillips { 688b9f0f1bbSKim Phillips struct ipic *ipic = h->host_data; 689b9f0f1bbSKim Phillips 690b9f0f1bbSKim Phillips set_irq_chip_data(virq, ipic); 69177d4309eSLi Yang set_irq_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq); 692b9f0f1bbSKim Phillips 693b9f0f1bbSKim Phillips /* Set default irq type */ 694b9f0f1bbSKim Phillips set_irq_type(virq, IRQ_TYPE_NONE); 695b9f0f1bbSKim Phillips 696b9f0f1bbSKim Phillips return 0; 697b9f0f1bbSKim Phillips } 698b9f0f1bbSKim Phillips 699b9f0f1bbSKim Phillips static int ipic_host_xlate(struct irq_host *h, struct device_node *ct, 700b9f0f1bbSKim Phillips u32 *intspec, unsigned int intsize, 701b9f0f1bbSKim Phillips irq_hw_number_t *out_hwirq, unsigned int *out_flags) 702b9f0f1bbSKim Phillips 703b9f0f1bbSKim Phillips { 704b9f0f1bbSKim Phillips /* interrupt sense values coming from the device tree equal either 705b9f0f1bbSKim Phillips * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change) 706b9f0f1bbSKim Phillips */ 707b9f0f1bbSKim Phillips *out_hwirq = intspec[0]; 708b9f0f1bbSKim Phillips if (intsize > 1) 709b9f0f1bbSKim Phillips *out_flags = intspec[1]; 710b9f0f1bbSKim Phillips else 711b9f0f1bbSKim Phillips *out_flags = IRQ_TYPE_NONE; 712b9f0f1bbSKim Phillips return 0; 713b9f0f1bbSKim Phillips } 714b9f0f1bbSKim Phillips 715b9f0f1bbSKim Phillips static struct irq_host_ops ipic_host_ops = { 716b9f0f1bbSKim Phillips .match = ipic_host_match, 717b9f0f1bbSKim Phillips .map = ipic_host_map, 718b9f0f1bbSKim Phillips .xlate = ipic_host_xlate, 719b9f0f1bbSKim Phillips }; 720b9f0f1bbSKim Phillips 721126186a0SKumar Gala struct ipic * __init ipic_init(struct device_node *node, unsigned int flags) 722b9f0f1bbSKim Phillips { 723b9f0f1bbSKim Phillips struct ipic *ipic; 724b9f0f1bbSKim Phillips struct resource res; 725b9f0f1bbSKim Phillips u32 temp = 0, ret; 726b9f0f1bbSKim Phillips 72784f1c1e0SMichael Ellerman ret = of_address_to_resource(node, 0, &res); 72884f1c1e0SMichael Ellerman if (ret) 72984f1c1e0SMichael Ellerman return NULL; 73084f1c1e0SMichael Ellerman 731b9f0f1bbSKim Phillips ipic = alloc_bootmem(sizeof(struct ipic)); 732b9f0f1bbSKim Phillips if (ipic == NULL) 733126186a0SKumar Gala return NULL; 734b9f0f1bbSKim Phillips 735b9f0f1bbSKim Phillips memset(ipic, 0, sizeof(struct ipic)); 736b9f0f1bbSKim Phillips 73719fc65b5SMichael Ellerman ipic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, 738b9f0f1bbSKim Phillips NR_IPIC_INTS, 739b9f0f1bbSKim Phillips &ipic_host_ops, 0); 74019fc65b5SMichael Ellerman if (ipic->irqhost == NULL) 741126186a0SKumar Gala return NULL; 742b9f0f1bbSKim Phillips 743b9f0f1bbSKim Phillips ipic->regs = ioremap(res.start, res.end - res.start + 1); 744b9f0f1bbSKim Phillips 745b9f0f1bbSKim Phillips ipic->irqhost->host_data = ipic; 746b9f0f1bbSKim Phillips 747b9f0f1bbSKim Phillips /* init hw */ 748b9f0f1bbSKim Phillips ipic_write(ipic->regs, IPIC_SICNR, 0x0); 7491cd8e506SKumar Gala 7501cd8e506SKumar Gala /* default priority scheme is grouped. If spread mode is required 7511cd8e506SKumar Gala * configure SICFR accordingly */ 7521cd8e506SKumar Gala if (flags & IPIC_SPREADMODE_GRP_A) 7531cd8e506SKumar Gala temp |= SICFR_IPSA; 754f03ca957SLi Yang if (flags & IPIC_SPREADMODE_GRP_B) 755f03ca957SLi Yang temp |= SICFR_IPSB; 756f03ca957SLi Yang if (flags & IPIC_SPREADMODE_GRP_C) 757f03ca957SLi Yang temp |= SICFR_IPSC; 7581cd8e506SKumar Gala if (flags & IPIC_SPREADMODE_GRP_D) 7591cd8e506SKumar Gala temp |= SICFR_IPSD; 7601cd8e506SKumar Gala if (flags & IPIC_SPREADMODE_MIX_A) 7611cd8e506SKumar Gala temp |= SICFR_MPSA; 7621cd8e506SKumar Gala if (flags & IPIC_SPREADMODE_MIX_B) 7631cd8e506SKumar Gala temp |= SICFR_MPSB; 7641cd8e506SKumar Gala 765f03ca957SLi Yang ipic_write(ipic->regs, IPIC_SICFR, temp); 7661cd8e506SKumar Gala 7671cd8e506SKumar Gala /* handle MCP route */ 7681cd8e506SKumar Gala temp = 0; 7691cd8e506SKumar Gala if (flags & IPIC_DISABLE_MCP_OUT) 7701cd8e506SKumar Gala temp = SERCR_MCPR; 771b9f0f1bbSKim Phillips ipic_write(ipic->regs, IPIC_SERCR, temp); 7721cd8e506SKumar Gala 7731cd8e506SKumar Gala /* handle routing of IRQ0 to MCP */ 774b9f0f1bbSKim Phillips temp = ipic_read(ipic->regs, IPIC_SEMSR); 7751cd8e506SKumar Gala 7761cd8e506SKumar Gala if (flags & IPIC_IRQ0_MCP) 7771cd8e506SKumar Gala temp |= SEMSR_SIRQ0; 7781cd8e506SKumar Gala else 7791cd8e506SKumar Gala temp &= ~SEMSR_SIRQ0; 7801cd8e506SKumar Gala 781b9f0f1bbSKim Phillips ipic_write(ipic->regs, IPIC_SEMSR, temp); 7821cd8e506SKumar Gala 783b9f0f1bbSKim Phillips primary_ipic = ipic; 784b9f0f1bbSKim Phillips irq_set_default_host(primary_ipic->irqhost); 785b9f0f1bbSKim Phillips 786b9f0f1bbSKim Phillips printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS, 787b9f0f1bbSKim Phillips primary_ipic->regs); 788126186a0SKumar Gala 789126186a0SKumar Gala return ipic; 7901cd8e506SKumar Gala } 7911cd8e506SKumar Gala 792b9f0f1bbSKim Phillips int ipic_set_priority(unsigned int virq, unsigned int priority) 7931cd8e506SKumar Gala { 794b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 795b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 7961cd8e506SKumar Gala u32 temp; 7971cd8e506SKumar Gala 7981cd8e506SKumar Gala if (priority > 7) 7991cd8e506SKumar Gala return -EINVAL; 8001cd8e506SKumar Gala if (src > 127) 8011cd8e506SKumar Gala return -EINVAL; 8021cd8e506SKumar Gala if (ipic_info[src].prio == 0) 8031cd8e506SKumar Gala return -EINVAL; 8041cd8e506SKumar Gala 8051cd8e506SKumar Gala temp = ipic_read(ipic->regs, ipic_info[src].prio); 8061cd8e506SKumar Gala 8071cd8e506SKumar Gala if (priority < 4) { 8081cd8e506SKumar Gala temp &= ~(0x7 << (20 + (3 - priority) * 3)); 8091cd8e506SKumar Gala temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3); 8101cd8e506SKumar Gala } else { 8111cd8e506SKumar Gala temp &= ~(0x7 << (4 + (7 - priority) * 3)); 8121cd8e506SKumar Gala temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3); 8131cd8e506SKumar Gala } 8141cd8e506SKumar Gala 8151cd8e506SKumar Gala ipic_write(ipic->regs, ipic_info[src].prio, temp); 8161cd8e506SKumar Gala 8171cd8e506SKumar Gala return 0; 8181cd8e506SKumar Gala } 8191cd8e506SKumar Gala 820b9f0f1bbSKim Phillips void ipic_set_highest_priority(unsigned int virq) 8211cd8e506SKumar Gala { 822b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 823b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 8241cd8e506SKumar Gala u32 temp; 8251cd8e506SKumar Gala 8261cd8e506SKumar Gala temp = ipic_read(ipic->regs, IPIC_SICFR); 8271cd8e506SKumar Gala 8281cd8e506SKumar Gala /* clear and set HPI */ 8291cd8e506SKumar Gala temp &= 0x7f000000; 8301cd8e506SKumar Gala temp |= (src & 0x7f) << 24; 8311cd8e506SKumar Gala 8321cd8e506SKumar Gala ipic_write(ipic->regs, IPIC_SICFR, temp); 8331cd8e506SKumar Gala } 8341cd8e506SKumar Gala 8351cd8e506SKumar Gala void ipic_set_default_priority(void) 8361cd8e506SKumar Gala { 837f03ca957SLi Yang ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_PRIORITY_DEFAULT); 838f03ca957SLi Yang ipic_write(primary_ipic->regs, IPIC_SIPRR_B, IPIC_PRIORITY_DEFAULT); 839f03ca957SLi Yang ipic_write(primary_ipic->regs, IPIC_SIPRR_C, IPIC_PRIORITY_DEFAULT); 840f03ca957SLi Yang ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_PRIORITY_DEFAULT); 841f03ca957SLi Yang ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_PRIORITY_DEFAULT); 842f03ca957SLi Yang ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_PRIORITY_DEFAULT); 8431cd8e506SKumar Gala } 8441cd8e506SKumar Gala 8451cd8e506SKumar Gala void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq) 8461cd8e506SKumar Gala { 8471cd8e506SKumar Gala struct ipic *ipic = primary_ipic; 8481cd8e506SKumar Gala u32 temp; 8491cd8e506SKumar Gala 8501cd8e506SKumar Gala temp = ipic_read(ipic->regs, IPIC_SERMR); 8511cd8e506SKumar Gala temp |= (1 << (31 - mcp_irq)); 8521cd8e506SKumar Gala ipic_write(ipic->regs, IPIC_SERMR, temp); 8531cd8e506SKumar Gala } 8541cd8e506SKumar Gala 8551cd8e506SKumar Gala void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq) 8561cd8e506SKumar Gala { 8571cd8e506SKumar Gala struct ipic *ipic = primary_ipic; 8581cd8e506SKumar Gala u32 temp; 8591cd8e506SKumar Gala 8601cd8e506SKumar Gala temp = ipic_read(ipic->regs, IPIC_SERMR); 8611cd8e506SKumar Gala temp &= (1 << (31 - mcp_irq)); 8621cd8e506SKumar Gala ipic_write(ipic->regs, IPIC_SERMR, temp); 8631cd8e506SKumar Gala } 8641cd8e506SKumar Gala 8651cd8e506SKumar Gala u32 ipic_get_mcp_status(void) 8661cd8e506SKumar Gala { 8671cd8e506SKumar Gala return ipic_read(primary_ipic->regs, IPIC_SERMR); 8681cd8e506SKumar Gala } 8691cd8e506SKumar Gala 8701cd8e506SKumar Gala void ipic_clear_mcp_status(u32 mask) 8711cd8e506SKumar Gala { 8721cd8e506SKumar Gala ipic_write(primary_ipic->regs, IPIC_SERMR, mask); 8731cd8e506SKumar Gala } 8741cd8e506SKumar Gala 875b9f0f1bbSKim Phillips /* Return an interrupt vector or NO_IRQ if no interrupt is pending. */ 87635a84c2fSOlaf Hering unsigned int ipic_get_irq(void) 8771cd8e506SKumar Gala { 8781cd8e506SKumar Gala int irq; 8791cd8e506SKumar Gala 880b9f0f1bbSKim Phillips BUG_ON(primary_ipic == NULL); 881b9f0f1bbSKim Phillips 882b9f0f1bbSKim Phillips #define IPIC_SIVCR_VECTOR_MASK 0x7f 883b9f0f1bbSKim Phillips irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK; 8841cd8e506SKumar Gala 8851cd8e506SKumar Gala if (irq == 0) /* 0 --> no irq is pending */ 886b9f0f1bbSKim Phillips return NO_IRQ; 8871cd8e506SKumar Gala 888b9f0f1bbSKim Phillips return irq_linear_revmap(primary_ipic->irqhost, irq); 8891cd8e506SKumar Gala } 8901cd8e506SKumar Gala 891e2a02ba6SMichael Neuling #ifdef CONFIG_SUSPEND 892d49747bdSScott Wood static struct { 893d49747bdSScott Wood u32 sicfr; 894d49747bdSScott Wood u32 siprr[2]; 895d49747bdSScott Wood u32 simsr[2]; 896d49747bdSScott Wood u32 sicnr; 897d49747bdSScott Wood u32 smprr[2]; 898d49747bdSScott Wood u32 semsr; 899d49747bdSScott Wood u32 secnr; 900d49747bdSScott Wood u32 sermr; 901d49747bdSScott Wood u32 sercr; 902d49747bdSScott Wood } ipic_saved_state; 903d49747bdSScott Wood 904d49747bdSScott Wood static int ipic_suspend(struct sys_device *sdev, pm_message_t state) 905d49747bdSScott Wood { 906d49747bdSScott Wood struct ipic *ipic = primary_ipic; 907d49747bdSScott Wood 908d49747bdSScott Wood ipic_saved_state.sicfr = ipic_read(ipic->regs, IPIC_SICFR); 909d49747bdSScott Wood ipic_saved_state.siprr[0] = ipic_read(ipic->regs, IPIC_SIPRR_A); 910d49747bdSScott Wood ipic_saved_state.siprr[1] = ipic_read(ipic->regs, IPIC_SIPRR_D); 911d49747bdSScott Wood ipic_saved_state.simsr[0] = ipic_read(ipic->regs, IPIC_SIMSR_H); 912d49747bdSScott Wood ipic_saved_state.simsr[1] = ipic_read(ipic->regs, IPIC_SIMSR_L); 913d49747bdSScott Wood ipic_saved_state.sicnr = ipic_read(ipic->regs, IPIC_SICNR); 914d49747bdSScott Wood ipic_saved_state.smprr[0] = ipic_read(ipic->regs, IPIC_SMPRR_A); 915d49747bdSScott Wood ipic_saved_state.smprr[1] = ipic_read(ipic->regs, IPIC_SMPRR_B); 916d49747bdSScott Wood ipic_saved_state.semsr = ipic_read(ipic->regs, IPIC_SEMSR); 917d49747bdSScott Wood ipic_saved_state.secnr = ipic_read(ipic->regs, IPIC_SECNR); 918d49747bdSScott Wood ipic_saved_state.sermr = ipic_read(ipic->regs, IPIC_SERMR); 919d49747bdSScott Wood ipic_saved_state.sercr = ipic_read(ipic->regs, IPIC_SERCR); 920d49747bdSScott Wood 921d49747bdSScott Wood if (fsl_deep_sleep()) { 922d49747bdSScott Wood /* In deep sleep, make sure there can be no 923d49747bdSScott Wood * pending interrupts, as this can cause 924d49747bdSScott Wood * problems on 831x. 925d49747bdSScott Wood */ 926d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SIMSR_H, 0); 927d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SIMSR_L, 0); 928d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SEMSR, 0); 929d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SERMR, 0); 930d49747bdSScott Wood } 931d49747bdSScott Wood 932d49747bdSScott Wood return 0; 933d49747bdSScott Wood } 934d49747bdSScott Wood 935d49747bdSScott Wood static int ipic_resume(struct sys_device *sdev) 936d49747bdSScott Wood { 937d49747bdSScott Wood struct ipic *ipic = primary_ipic; 938d49747bdSScott Wood 939d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SICFR, ipic_saved_state.sicfr); 940d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SIPRR_A, ipic_saved_state.siprr[0]); 941d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SIPRR_D, ipic_saved_state.siprr[1]); 942d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SIMSR_H, ipic_saved_state.simsr[0]); 943d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SIMSR_L, ipic_saved_state.simsr[1]); 944d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SICNR, ipic_saved_state.sicnr); 945d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SMPRR_A, ipic_saved_state.smprr[0]); 946d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SMPRR_B, ipic_saved_state.smprr[1]); 947d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SEMSR, ipic_saved_state.semsr); 948d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SECNR, ipic_saved_state.secnr); 949d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SERMR, ipic_saved_state.sermr); 950d49747bdSScott Wood ipic_write(ipic->regs, IPIC_SERCR, ipic_saved_state.sercr); 951d49747bdSScott Wood 952d49747bdSScott Wood return 0; 953d49747bdSScott Wood } 954d49747bdSScott Wood #else 955d49747bdSScott Wood #define ipic_suspend NULL 956d49747bdSScott Wood #define ipic_resume NULL 957d49747bdSScott Wood #endif 958d49747bdSScott Wood 9591cd8e506SKumar Gala static struct sysdev_class ipic_sysclass = { 960af5ca3f4SKay Sievers .name = "ipic", 961d49747bdSScott Wood .suspend = ipic_suspend, 962d49747bdSScott Wood .resume = ipic_resume, 9631cd8e506SKumar Gala }; 9641cd8e506SKumar Gala 9651cd8e506SKumar Gala static struct sys_device device_ipic = { 9661cd8e506SKumar Gala .id = 0, 9671cd8e506SKumar Gala .cls = &ipic_sysclass, 9681cd8e506SKumar Gala }; 9691cd8e506SKumar Gala 9701cd8e506SKumar Gala static int __init init_ipic_sysfs(void) 9711cd8e506SKumar Gala { 9721cd8e506SKumar Gala int rc; 9731cd8e506SKumar Gala 9741428a9faSOlaf Hering if (!primary_ipic || !primary_ipic->regs) 9751cd8e506SKumar Gala return -ENODEV; 9761cd8e506SKumar Gala printk(KERN_DEBUG "Registering ipic with sysfs...\n"); 9771cd8e506SKumar Gala 9781cd8e506SKumar Gala rc = sysdev_class_register(&ipic_sysclass); 9791cd8e506SKumar Gala if (rc) { 9801cd8e506SKumar Gala printk(KERN_ERR "Failed registering ipic sys class\n"); 9811cd8e506SKumar Gala return -ENODEV; 9821cd8e506SKumar Gala } 9831cd8e506SKumar Gala rc = sysdev_register(&device_ipic); 9841cd8e506SKumar Gala if (rc) { 9851cd8e506SKumar Gala printk(KERN_ERR "Failed registering ipic sys device\n"); 9861cd8e506SKumar Gala return -ENODEV; 9871cd8e506SKumar Gala } 9881cd8e506SKumar Gala return 0; 9891cd8e506SKumar Gala } 9901cd8e506SKumar Gala 9911cd8e506SKumar Gala subsys_initcall(init_ipic_sysfs); 992