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; 33b9f0f1bbSKim Phillips static DEFINE_SPINLOCK(ipic_lock); 341cd8e506SKumar Gala 351cd8e506SKumar Gala static struct ipic_info ipic_info[] = { 361cd8e506SKumar Gala [9] = { 371cd8e506SKumar Gala .pend = IPIC_SIPNR_H, 381cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 391cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 401cd8e506SKumar Gala .force = IPIC_SIFCR_H, 411cd8e506SKumar Gala .bit = 24, 421cd8e506SKumar Gala .prio_mask = 0, 431cd8e506SKumar Gala }, 441cd8e506SKumar Gala [10] = { 451cd8e506SKumar Gala .pend = IPIC_SIPNR_H, 461cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 471cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 481cd8e506SKumar Gala .force = IPIC_SIFCR_H, 491cd8e506SKumar Gala .bit = 25, 501cd8e506SKumar Gala .prio_mask = 1, 511cd8e506SKumar Gala }, 521cd8e506SKumar Gala [11] = { 531cd8e506SKumar Gala .pend = IPIC_SIPNR_H, 541cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 551cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 561cd8e506SKumar Gala .force = IPIC_SIFCR_H, 571cd8e506SKumar Gala .bit = 26, 581cd8e506SKumar Gala .prio_mask = 2, 591cd8e506SKumar Gala }, 601cd8e506SKumar Gala [14] = { 611cd8e506SKumar Gala .pend = IPIC_SIPNR_H, 621cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 631cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 641cd8e506SKumar Gala .force = IPIC_SIFCR_H, 651cd8e506SKumar Gala .bit = 29, 661cd8e506SKumar Gala .prio_mask = 5, 671cd8e506SKumar Gala }, 681cd8e506SKumar Gala [15] = { 691cd8e506SKumar Gala .pend = IPIC_SIPNR_H, 701cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 711cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 721cd8e506SKumar Gala .force = IPIC_SIFCR_H, 731cd8e506SKumar Gala .bit = 30, 741cd8e506SKumar Gala .prio_mask = 6, 751cd8e506SKumar Gala }, 761cd8e506SKumar Gala [16] = { 771cd8e506SKumar Gala .pend = IPIC_SIPNR_H, 781cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 791cd8e506SKumar Gala .prio = IPIC_SIPRR_D, 801cd8e506SKumar Gala .force = IPIC_SIFCR_H, 811cd8e506SKumar Gala .bit = 31, 821cd8e506SKumar Gala .prio_mask = 7, 831cd8e506SKumar Gala }, 841cd8e506SKumar Gala [17] = { 851cd8e506SKumar Gala .pend = IPIC_SEPNR, 861cd8e506SKumar Gala .mask = IPIC_SEMSR, 871cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 881cd8e506SKumar Gala .force = IPIC_SEFCR, 891cd8e506SKumar Gala .bit = 1, 901cd8e506SKumar Gala .prio_mask = 5, 911cd8e506SKumar Gala }, 921cd8e506SKumar Gala [18] = { 931cd8e506SKumar Gala .pend = IPIC_SEPNR, 941cd8e506SKumar Gala .mask = IPIC_SEMSR, 951cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 961cd8e506SKumar Gala .force = IPIC_SEFCR, 971cd8e506SKumar Gala .bit = 2, 981cd8e506SKumar Gala .prio_mask = 6, 991cd8e506SKumar Gala }, 1001cd8e506SKumar Gala [19] = { 1011cd8e506SKumar Gala .pend = IPIC_SEPNR, 1021cd8e506SKumar Gala .mask = IPIC_SEMSR, 1031cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 1041cd8e506SKumar Gala .force = IPIC_SEFCR, 1051cd8e506SKumar Gala .bit = 3, 1061cd8e506SKumar Gala .prio_mask = 7, 1071cd8e506SKumar Gala }, 1081cd8e506SKumar Gala [20] = { 1091cd8e506SKumar Gala .pend = IPIC_SEPNR, 1101cd8e506SKumar Gala .mask = IPIC_SEMSR, 1111cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 1121cd8e506SKumar Gala .force = IPIC_SEFCR, 1131cd8e506SKumar Gala .bit = 4, 1141cd8e506SKumar Gala .prio_mask = 4, 1151cd8e506SKumar Gala }, 1161cd8e506SKumar Gala [21] = { 1171cd8e506SKumar Gala .pend = IPIC_SEPNR, 1181cd8e506SKumar Gala .mask = IPIC_SEMSR, 1191cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 1201cd8e506SKumar Gala .force = IPIC_SEFCR, 1211cd8e506SKumar Gala .bit = 5, 1221cd8e506SKumar Gala .prio_mask = 5, 1231cd8e506SKumar Gala }, 1241cd8e506SKumar Gala [22] = { 1251cd8e506SKumar Gala .pend = IPIC_SEPNR, 1261cd8e506SKumar Gala .mask = IPIC_SEMSR, 1271cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 1281cd8e506SKumar Gala .force = IPIC_SEFCR, 1291cd8e506SKumar Gala .bit = 6, 1301cd8e506SKumar Gala .prio_mask = 6, 1311cd8e506SKumar Gala }, 1321cd8e506SKumar Gala [23] = { 1331cd8e506SKumar Gala .pend = IPIC_SEPNR, 1341cd8e506SKumar Gala .mask = IPIC_SEMSR, 1351cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 1361cd8e506SKumar Gala .force = IPIC_SEFCR, 1371cd8e506SKumar Gala .bit = 7, 1381cd8e506SKumar Gala .prio_mask = 7, 1391cd8e506SKumar Gala }, 1401cd8e506SKumar Gala [32] = { 1411cd8e506SKumar Gala .pend = IPIC_SIPNR_H, 1421cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1431cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 1441cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1451cd8e506SKumar Gala .bit = 0, 1461cd8e506SKumar Gala .prio_mask = 0, 1471cd8e506SKumar Gala }, 1481cd8e506SKumar Gala [33] = { 1491cd8e506SKumar Gala .pend = IPIC_SIPNR_H, 1501cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1511cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 1521cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1531cd8e506SKumar Gala .bit = 1, 1541cd8e506SKumar Gala .prio_mask = 1, 1551cd8e506SKumar Gala }, 1561cd8e506SKumar Gala [34] = { 1571cd8e506SKumar Gala .pend = IPIC_SIPNR_H, 1581cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1591cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 1601cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1611cd8e506SKumar Gala .bit = 2, 1621cd8e506SKumar Gala .prio_mask = 2, 1631cd8e506SKumar Gala }, 1641cd8e506SKumar Gala [35] = { 1651cd8e506SKumar Gala .pend = IPIC_SIPNR_H, 1661cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1671cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 1681cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1691cd8e506SKumar Gala .bit = 3, 1701cd8e506SKumar Gala .prio_mask = 3, 1711cd8e506SKumar Gala }, 1721cd8e506SKumar Gala [36] = { 1731cd8e506SKumar Gala .pend = IPIC_SIPNR_H, 1741cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1751cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 1761cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1771cd8e506SKumar Gala .bit = 4, 1781cd8e506SKumar Gala .prio_mask = 4, 1791cd8e506SKumar Gala }, 1801cd8e506SKumar Gala [37] = { 1811cd8e506SKumar Gala .pend = IPIC_SIPNR_H, 1821cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1831cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 1841cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1851cd8e506SKumar Gala .bit = 5, 1861cd8e506SKumar Gala .prio_mask = 5, 1871cd8e506SKumar Gala }, 1881cd8e506SKumar Gala [38] = { 1891cd8e506SKumar Gala .pend = IPIC_SIPNR_H, 1901cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1911cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 1921cd8e506SKumar Gala .force = IPIC_SIFCR_H, 1931cd8e506SKumar Gala .bit = 6, 1941cd8e506SKumar Gala .prio_mask = 6, 1951cd8e506SKumar Gala }, 1961cd8e506SKumar Gala [39] = { 1971cd8e506SKumar Gala .pend = IPIC_SIPNR_H, 1981cd8e506SKumar Gala .mask = IPIC_SIMSR_H, 1991cd8e506SKumar Gala .prio = IPIC_SIPRR_A, 2001cd8e506SKumar Gala .force = IPIC_SIFCR_H, 2011cd8e506SKumar Gala .bit = 7, 2021cd8e506SKumar Gala .prio_mask = 7, 2031cd8e506SKumar Gala }, 2041cd8e506SKumar Gala [48] = { 2051cd8e506SKumar Gala .pend = IPIC_SEPNR, 2061cd8e506SKumar Gala .mask = IPIC_SEMSR, 2071cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 2081cd8e506SKumar Gala .force = IPIC_SEFCR, 2091cd8e506SKumar Gala .bit = 0, 2101cd8e506SKumar Gala .prio_mask = 4, 2111cd8e506SKumar Gala }, 2121cd8e506SKumar Gala [64] = { 213ed709d13SScott Wood .pend = IPIC_SIPNR_L, 2141cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2151cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 2161cd8e506SKumar Gala .force = IPIC_SIFCR_L, 2171cd8e506SKumar Gala .bit = 0, 2181cd8e506SKumar Gala .prio_mask = 0, 2191cd8e506SKumar Gala }, 2201cd8e506SKumar Gala [65] = { 221ed709d13SScott Wood .pend = IPIC_SIPNR_L, 2221cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2231cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 2241cd8e506SKumar Gala .force = IPIC_SIFCR_L, 2251cd8e506SKumar Gala .bit = 1, 2261cd8e506SKumar Gala .prio_mask = 1, 2271cd8e506SKumar Gala }, 2281cd8e506SKumar Gala [66] = { 229ed709d13SScott Wood .pend = IPIC_SIPNR_L, 2301cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2311cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 2321cd8e506SKumar Gala .force = IPIC_SIFCR_L, 2331cd8e506SKumar Gala .bit = 2, 2341cd8e506SKumar Gala .prio_mask = 2, 2351cd8e506SKumar Gala }, 2361cd8e506SKumar Gala [67] = { 237ed709d13SScott Wood .pend = IPIC_SIPNR_L, 2381cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2391cd8e506SKumar Gala .prio = IPIC_SMPRR_A, 2401cd8e506SKumar Gala .force = IPIC_SIFCR_L, 2411cd8e506SKumar Gala .bit = 3, 2421cd8e506SKumar Gala .prio_mask = 3, 2431cd8e506SKumar Gala }, 2441cd8e506SKumar Gala [68] = { 245ed709d13SScott Wood .pend = IPIC_SIPNR_L, 2461cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2471cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 2481cd8e506SKumar Gala .force = IPIC_SIFCR_L, 2491cd8e506SKumar Gala .bit = 4, 2501cd8e506SKumar Gala .prio_mask = 0, 2511cd8e506SKumar Gala }, 2521cd8e506SKumar Gala [69] = { 253ed709d13SScott Wood .pend = IPIC_SIPNR_L, 2541cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2551cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 2561cd8e506SKumar Gala .force = IPIC_SIFCR_L, 2571cd8e506SKumar Gala .bit = 5, 2581cd8e506SKumar Gala .prio_mask = 1, 2591cd8e506SKumar Gala }, 2601cd8e506SKumar Gala [70] = { 261ed709d13SScott Wood .pend = IPIC_SIPNR_L, 2621cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2631cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 2641cd8e506SKumar Gala .force = IPIC_SIFCR_L, 2651cd8e506SKumar Gala .bit = 6, 2661cd8e506SKumar Gala .prio_mask = 2, 2671cd8e506SKumar Gala }, 2681cd8e506SKumar Gala [71] = { 269ed709d13SScott Wood .pend = IPIC_SIPNR_L, 2701cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2711cd8e506SKumar Gala .prio = IPIC_SMPRR_B, 2721cd8e506SKumar Gala .force = IPIC_SIFCR_L, 2731cd8e506SKumar Gala .bit = 7, 2741cd8e506SKumar Gala .prio_mask = 3, 2751cd8e506SKumar Gala }, 2761cd8e506SKumar Gala [72] = { 277ed709d13SScott Wood .pend = IPIC_SIPNR_L, 2781cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2791cd8e506SKumar Gala .prio = 0, 2801cd8e506SKumar Gala .force = IPIC_SIFCR_L, 2811cd8e506SKumar Gala .bit = 8, 2821cd8e506SKumar Gala }, 2831cd8e506SKumar Gala [73] = { 284ed709d13SScott Wood .pend = IPIC_SIPNR_L, 2851cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2861cd8e506SKumar Gala .prio = 0, 2871cd8e506SKumar Gala .force = IPIC_SIFCR_L, 2881cd8e506SKumar Gala .bit = 9, 2891cd8e506SKumar Gala }, 2901cd8e506SKumar Gala [74] = { 291ed709d13SScott Wood .pend = IPIC_SIPNR_L, 2921cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 2931cd8e506SKumar Gala .prio = 0, 2941cd8e506SKumar Gala .force = IPIC_SIFCR_L, 2951cd8e506SKumar Gala .bit = 10, 2961cd8e506SKumar Gala }, 2971cd8e506SKumar Gala [75] = { 298ed709d13SScott Wood .pend = IPIC_SIPNR_L, 2991cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3001cd8e506SKumar Gala .prio = 0, 3011cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3021cd8e506SKumar Gala .bit = 11, 3031cd8e506SKumar Gala }, 3041cd8e506SKumar Gala [76] = { 305ed709d13SScott Wood .pend = IPIC_SIPNR_L, 3061cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3071cd8e506SKumar Gala .prio = 0, 3081cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3091cd8e506SKumar Gala .bit = 12, 3101cd8e506SKumar Gala }, 3111cd8e506SKumar Gala [77] = { 312ed709d13SScott Wood .pend = IPIC_SIPNR_L, 3131cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3141cd8e506SKumar Gala .prio = 0, 3151cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3161cd8e506SKumar Gala .bit = 13, 3171cd8e506SKumar Gala }, 3181cd8e506SKumar Gala [78] = { 319ed709d13SScott Wood .pend = IPIC_SIPNR_L, 3201cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3211cd8e506SKumar Gala .prio = 0, 3221cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3231cd8e506SKumar Gala .bit = 14, 3241cd8e506SKumar Gala }, 3251cd8e506SKumar Gala [79] = { 326ed709d13SScott Wood .pend = IPIC_SIPNR_L, 3271cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3281cd8e506SKumar Gala .prio = 0, 3291cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3301cd8e506SKumar Gala .bit = 15, 3311cd8e506SKumar Gala }, 3321cd8e506SKumar Gala [80] = { 333ed709d13SScott Wood .pend = IPIC_SIPNR_L, 3341cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3351cd8e506SKumar Gala .prio = 0, 3361cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3371cd8e506SKumar Gala .bit = 16, 3381cd8e506SKumar Gala }, 3391cd8e506SKumar Gala [84] = { 340ed709d13SScott Wood .pend = IPIC_SIPNR_L, 3411cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3421cd8e506SKumar Gala .prio = 0, 3431cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3441cd8e506SKumar Gala .bit = 20, 3451cd8e506SKumar Gala }, 3461cd8e506SKumar Gala [85] = { 347ed709d13SScott Wood .pend = IPIC_SIPNR_L, 3481cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3491cd8e506SKumar Gala .prio = 0, 3501cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3511cd8e506SKumar Gala .bit = 21, 3521cd8e506SKumar Gala }, 3531cd8e506SKumar Gala [90] = { 354ed709d13SScott Wood .pend = IPIC_SIPNR_L, 3551cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3561cd8e506SKumar Gala .prio = 0, 3571cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3581cd8e506SKumar Gala .bit = 26, 3591cd8e506SKumar Gala }, 3601cd8e506SKumar Gala [91] = { 361ed709d13SScott Wood .pend = IPIC_SIPNR_L, 3621cd8e506SKumar Gala .mask = IPIC_SIMSR_L, 3631cd8e506SKumar Gala .prio = 0, 3641cd8e506SKumar Gala .force = IPIC_SIFCR_L, 3651cd8e506SKumar Gala .bit = 27, 3661cd8e506SKumar Gala }, 3671cd8e506SKumar Gala }; 3681cd8e506SKumar Gala 3691cd8e506SKumar Gala static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg) 3701cd8e506SKumar Gala { 3711cd8e506SKumar Gala return in_be32(base + (reg >> 2)); 3721cd8e506SKumar Gala } 3731cd8e506SKumar Gala 3741cd8e506SKumar Gala static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value) 3751cd8e506SKumar Gala { 3761cd8e506SKumar Gala out_be32(base + (reg >> 2), value); 3771cd8e506SKumar Gala } 3781cd8e506SKumar Gala 379b9f0f1bbSKim Phillips static inline struct ipic * ipic_from_irq(unsigned int virq) 3801cd8e506SKumar Gala { 3811cd8e506SKumar Gala return primary_ipic; 3821cd8e506SKumar Gala } 3831cd8e506SKumar Gala 384b9f0f1bbSKim Phillips #define ipic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) 385b9f0f1bbSKim Phillips 386b9f0f1bbSKim Phillips static void ipic_unmask_irq(unsigned int virq) 3871cd8e506SKumar Gala { 388b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 389b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 390b9f0f1bbSKim Phillips unsigned long flags; 3911cd8e506SKumar Gala u32 temp; 3921cd8e506SKumar Gala 393b9f0f1bbSKim Phillips spin_lock_irqsave(&ipic_lock, flags); 394b9f0f1bbSKim Phillips 3951cd8e506SKumar Gala temp = ipic_read(ipic->regs, ipic_info[src].mask); 3961cd8e506SKumar Gala temp |= (1 << (31 - ipic_info[src].bit)); 3971cd8e506SKumar Gala ipic_write(ipic->regs, ipic_info[src].mask, temp); 398b9f0f1bbSKim Phillips 399b9f0f1bbSKim Phillips spin_unlock_irqrestore(&ipic_lock, flags); 4001cd8e506SKumar Gala } 4011cd8e506SKumar Gala 402b9f0f1bbSKim Phillips static void ipic_mask_irq(unsigned int virq) 4031cd8e506SKumar Gala { 404b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 405b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 406b9f0f1bbSKim Phillips unsigned long flags; 4071cd8e506SKumar Gala u32 temp; 4081cd8e506SKumar Gala 409b9f0f1bbSKim Phillips spin_lock_irqsave(&ipic_lock, flags); 410b9f0f1bbSKim Phillips 4111cd8e506SKumar Gala temp = ipic_read(ipic->regs, ipic_info[src].mask); 4121cd8e506SKumar Gala temp &= ~(1 << (31 - ipic_info[src].bit)); 4131cd8e506SKumar Gala ipic_write(ipic->regs, ipic_info[src].mask, temp); 414b9f0f1bbSKim Phillips 415b9f0f1bbSKim Phillips spin_unlock_irqrestore(&ipic_lock, flags); 4161cd8e506SKumar Gala } 4171cd8e506SKumar Gala 418b9f0f1bbSKim Phillips static void ipic_ack_irq(unsigned int virq) 4191cd8e506SKumar Gala { 420b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 421b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 422b9f0f1bbSKim Phillips unsigned long flags; 4231cd8e506SKumar Gala u32 temp; 4241cd8e506SKumar Gala 425b9f0f1bbSKim Phillips spin_lock_irqsave(&ipic_lock, flags); 4261cd8e506SKumar Gala 4271cd8e506SKumar Gala temp = ipic_read(ipic->regs, ipic_info[src].pend); 4281cd8e506SKumar Gala temp |= (1 << (31 - ipic_info[src].bit)); 4291cd8e506SKumar Gala ipic_write(ipic->regs, ipic_info[src].pend, temp); 430b9f0f1bbSKim Phillips 431b9f0f1bbSKim Phillips spin_unlock_irqrestore(&ipic_lock, flags); 4321cd8e506SKumar Gala } 4331cd8e506SKumar Gala 434b9f0f1bbSKim Phillips static void ipic_mask_irq_and_ack(unsigned int virq) 4351cd8e506SKumar Gala { 436b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 437b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 438b9f0f1bbSKim Phillips unsigned long flags; 439b9f0f1bbSKim Phillips u32 temp; 440b9f0f1bbSKim Phillips 441b9f0f1bbSKim Phillips spin_lock_irqsave(&ipic_lock, flags); 442b9f0f1bbSKim Phillips 443b9f0f1bbSKim Phillips temp = ipic_read(ipic->regs, ipic_info[src].mask); 444b9f0f1bbSKim Phillips temp &= ~(1 << (31 - ipic_info[src].bit)); 445b9f0f1bbSKim Phillips ipic_write(ipic->regs, ipic_info[src].mask, temp); 446b9f0f1bbSKim Phillips 447b9f0f1bbSKim Phillips temp = ipic_read(ipic->regs, ipic_info[src].pend); 448b9f0f1bbSKim Phillips temp |= (1 << (31 - ipic_info[src].bit)); 449b9f0f1bbSKim Phillips ipic_write(ipic->regs, ipic_info[src].pend, temp); 450b9f0f1bbSKim Phillips 451b9f0f1bbSKim Phillips spin_unlock_irqrestore(&ipic_lock, flags); 4521cd8e506SKumar Gala } 4531cd8e506SKumar Gala 454b9f0f1bbSKim Phillips static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) 455b9f0f1bbSKim Phillips { 456b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 457b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 458b9f0f1bbSKim Phillips struct irq_desc *desc = get_irq_desc(virq); 459b9f0f1bbSKim Phillips unsigned int vold, vnew, edibit; 460b9f0f1bbSKim Phillips 461b9f0f1bbSKim Phillips if (flow_type == IRQ_TYPE_NONE) 462b9f0f1bbSKim Phillips flow_type = IRQ_TYPE_LEVEL_LOW; 463b9f0f1bbSKim Phillips 464b9f0f1bbSKim Phillips /* ipic supports only low assertion and high-to-low change senses 465b9f0f1bbSKim Phillips */ 466b9f0f1bbSKim Phillips if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) { 467b9f0f1bbSKim Phillips printk(KERN_ERR "ipic: sense type 0x%x not supported\n", 468b9f0f1bbSKim Phillips flow_type); 469b9f0f1bbSKim Phillips return -EINVAL; 470b9f0f1bbSKim Phillips } 471b9f0f1bbSKim Phillips 472b9f0f1bbSKim Phillips desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); 473b9f0f1bbSKim Phillips desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; 474b9f0f1bbSKim Phillips if (flow_type & IRQ_TYPE_LEVEL_LOW) { 475b9f0f1bbSKim Phillips desc->status |= IRQ_LEVEL; 476f49196a5SScott Wood desc->handle_irq = handle_level_irq; 477b9f0f1bbSKim Phillips } else { 478f49196a5SScott Wood desc->handle_irq = handle_edge_irq; 479b9f0f1bbSKim Phillips } 480b9f0f1bbSKim Phillips 481b9f0f1bbSKim Phillips /* only EXT IRQ senses are programmable on ipic 482b9f0f1bbSKim Phillips * internal IRQ senses are LEVEL_LOW 483b9f0f1bbSKim Phillips */ 484b9f0f1bbSKim Phillips if (src == IPIC_IRQ_EXT0) 485b9f0f1bbSKim Phillips edibit = 15; 486b9f0f1bbSKim Phillips else 487b9f0f1bbSKim Phillips if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7) 488b9f0f1bbSKim Phillips edibit = (14 - (src - IPIC_IRQ_EXT1)); 489b9f0f1bbSKim Phillips else 490b9f0f1bbSKim Phillips return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL; 491b9f0f1bbSKim Phillips 492b9f0f1bbSKim Phillips vold = ipic_read(ipic->regs, IPIC_SECNR); 493b9f0f1bbSKim Phillips if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) { 494b9f0f1bbSKim Phillips vnew = vold | (1 << edibit); 495b9f0f1bbSKim Phillips } else { 496b9f0f1bbSKim Phillips vnew = vold & ~(1 << edibit); 497b9f0f1bbSKim Phillips } 498b9f0f1bbSKim Phillips if (vold != vnew) 499b9f0f1bbSKim Phillips ipic_write(ipic->regs, IPIC_SECNR, vnew); 500b9f0f1bbSKim Phillips return 0; 501b9f0f1bbSKim Phillips } 502b9f0f1bbSKim Phillips 503b9f0f1bbSKim Phillips static struct irq_chip ipic_irq_chip = { 5041cd8e506SKumar Gala .typename = " IPIC ", 505b9f0f1bbSKim Phillips .unmask = ipic_unmask_irq, 506b9f0f1bbSKim Phillips .mask = ipic_mask_irq, 507b9f0f1bbSKim Phillips .mask_ack = ipic_mask_irq_and_ack, 508b9f0f1bbSKim Phillips .ack = ipic_ack_irq, 509b9f0f1bbSKim Phillips .set_type = ipic_set_irq_type, 5101cd8e506SKumar Gala }; 5111cd8e506SKumar Gala 512b9f0f1bbSKim Phillips static int ipic_host_match(struct irq_host *h, struct device_node *node) 5131cd8e506SKumar Gala { 514b9f0f1bbSKim Phillips struct ipic *ipic = h->host_data; 5151cd8e506SKumar Gala 516b9f0f1bbSKim Phillips /* Exact match, unless ipic node is NULL */ 517b9f0f1bbSKim Phillips return ipic->of_node == NULL || ipic->of_node == node; 518b9f0f1bbSKim Phillips } 5191cd8e506SKumar Gala 520b9f0f1bbSKim Phillips static int ipic_host_map(struct irq_host *h, unsigned int virq, 521b9f0f1bbSKim Phillips irq_hw_number_t hw) 522b9f0f1bbSKim Phillips { 523b9f0f1bbSKim Phillips struct ipic *ipic = h->host_data; 524b9f0f1bbSKim Phillips struct irq_chip *chip; 5251cd8e506SKumar Gala 526b9f0f1bbSKim Phillips /* Default chip */ 527b9f0f1bbSKim Phillips chip = &ipic->hc_irq; 528b9f0f1bbSKim Phillips 529b9f0f1bbSKim Phillips set_irq_chip_data(virq, ipic); 530b9f0f1bbSKim Phillips set_irq_chip_and_handler(virq, chip, handle_level_irq); 531b9f0f1bbSKim Phillips 532b9f0f1bbSKim Phillips /* Set default irq type */ 533b9f0f1bbSKim Phillips set_irq_type(virq, IRQ_TYPE_NONE); 534b9f0f1bbSKim Phillips 535b9f0f1bbSKim Phillips return 0; 536b9f0f1bbSKim Phillips } 537b9f0f1bbSKim Phillips 538b9f0f1bbSKim Phillips static int ipic_host_xlate(struct irq_host *h, struct device_node *ct, 539b9f0f1bbSKim Phillips u32 *intspec, unsigned int intsize, 540b9f0f1bbSKim Phillips irq_hw_number_t *out_hwirq, unsigned int *out_flags) 541b9f0f1bbSKim Phillips 542b9f0f1bbSKim Phillips { 543b9f0f1bbSKim Phillips /* interrupt sense values coming from the device tree equal either 544b9f0f1bbSKim Phillips * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change) 545b9f0f1bbSKim Phillips */ 546b9f0f1bbSKim Phillips *out_hwirq = intspec[0]; 547b9f0f1bbSKim Phillips if (intsize > 1) 548b9f0f1bbSKim Phillips *out_flags = intspec[1]; 549b9f0f1bbSKim Phillips else 550b9f0f1bbSKim Phillips *out_flags = IRQ_TYPE_NONE; 551b9f0f1bbSKim Phillips return 0; 552b9f0f1bbSKim Phillips } 553b9f0f1bbSKim Phillips 554b9f0f1bbSKim Phillips static struct irq_host_ops ipic_host_ops = { 555b9f0f1bbSKim Phillips .match = ipic_host_match, 556b9f0f1bbSKim Phillips .map = ipic_host_map, 557b9f0f1bbSKim Phillips .xlate = ipic_host_xlate, 558b9f0f1bbSKim Phillips }; 559b9f0f1bbSKim Phillips 560*126186a0SKumar Gala struct ipic * __init ipic_init(struct device_node *node, unsigned int flags) 561b9f0f1bbSKim Phillips { 562b9f0f1bbSKim Phillips struct ipic *ipic; 563b9f0f1bbSKim Phillips struct resource res; 564b9f0f1bbSKim Phillips u32 temp = 0, ret; 565b9f0f1bbSKim Phillips 566b9f0f1bbSKim Phillips ipic = alloc_bootmem(sizeof(struct ipic)); 567b9f0f1bbSKim Phillips if (ipic == NULL) 568*126186a0SKumar Gala return NULL; 569b9f0f1bbSKim Phillips 570b9f0f1bbSKim Phillips memset(ipic, 0, sizeof(struct ipic)); 571af337c09SMariusz Kozlowski ipic->of_node = of_node_get(node); 572b9f0f1bbSKim Phillips 573b9f0f1bbSKim Phillips ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 574b9f0f1bbSKim Phillips NR_IPIC_INTS, 575b9f0f1bbSKim Phillips &ipic_host_ops, 0); 576b9f0f1bbSKim Phillips if (ipic->irqhost == NULL) { 577b9f0f1bbSKim Phillips of_node_put(node); 578*126186a0SKumar Gala return NULL; 579b9f0f1bbSKim Phillips } 580b9f0f1bbSKim Phillips 581b9f0f1bbSKim Phillips ret = of_address_to_resource(node, 0, &res); 582*126186a0SKumar Gala if (ret) { 583*126186a0SKumar Gala of_node_put(node); 584*126186a0SKumar Gala return NULL; 585*126186a0SKumar Gala } 586b9f0f1bbSKim Phillips 587b9f0f1bbSKim Phillips ipic->regs = ioremap(res.start, res.end - res.start + 1); 588b9f0f1bbSKim Phillips 589b9f0f1bbSKim Phillips ipic->irqhost->host_data = ipic; 590b9f0f1bbSKim Phillips ipic->hc_irq = ipic_irq_chip; 591b9f0f1bbSKim Phillips 592b9f0f1bbSKim Phillips /* init hw */ 593b9f0f1bbSKim Phillips ipic_write(ipic->regs, IPIC_SICNR, 0x0); 5941cd8e506SKumar Gala 5951cd8e506SKumar Gala /* default priority scheme is grouped. If spread mode is required 5961cd8e506SKumar Gala * configure SICFR accordingly */ 5971cd8e506SKumar Gala if (flags & IPIC_SPREADMODE_GRP_A) 5981cd8e506SKumar Gala temp |= SICFR_IPSA; 5991cd8e506SKumar Gala if (flags & IPIC_SPREADMODE_GRP_D) 6001cd8e506SKumar Gala temp |= SICFR_IPSD; 6011cd8e506SKumar Gala if (flags & IPIC_SPREADMODE_MIX_A) 6021cd8e506SKumar Gala temp |= SICFR_MPSA; 6031cd8e506SKumar Gala if (flags & IPIC_SPREADMODE_MIX_B) 6041cd8e506SKumar Gala temp |= SICFR_MPSB; 6051cd8e506SKumar Gala 606b9f0f1bbSKim Phillips ipic_write(ipic->regs, IPIC_SICNR, temp); 6071cd8e506SKumar Gala 6081cd8e506SKumar Gala /* handle MCP route */ 6091cd8e506SKumar Gala temp = 0; 6101cd8e506SKumar Gala if (flags & IPIC_DISABLE_MCP_OUT) 6111cd8e506SKumar Gala temp = SERCR_MCPR; 612b9f0f1bbSKim Phillips ipic_write(ipic->regs, IPIC_SERCR, temp); 6131cd8e506SKumar Gala 6141cd8e506SKumar Gala /* handle routing of IRQ0 to MCP */ 615b9f0f1bbSKim Phillips temp = ipic_read(ipic->regs, IPIC_SEMSR); 6161cd8e506SKumar Gala 6171cd8e506SKumar Gala if (flags & IPIC_IRQ0_MCP) 6181cd8e506SKumar Gala temp |= SEMSR_SIRQ0; 6191cd8e506SKumar Gala else 6201cd8e506SKumar Gala temp &= ~SEMSR_SIRQ0; 6211cd8e506SKumar Gala 622b9f0f1bbSKim Phillips ipic_write(ipic->regs, IPIC_SEMSR, temp); 6231cd8e506SKumar Gala 624b9f0f1bbSKim Phillips primary_ipic = ipic; 625b9f0f1bbSKim Phillips irq_set_default_host(primary_ipic->irqhost); 626b9f0f1bbSKim Phillips 627b9f0f1bbSKim Phillips printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS, 628b9f0f1bbSKim Phillips primary_ipic->regs); 629*126186a0SKumar Gala 630*126186a0SKumar Gala return ipic; 6311cd8e506SKumar Gala } 6321cd8e506SKumar Gala 633b9f0f1bbSKim Phillips int ipic_set_priority(unsigned int virq, unsigned int priority) 6341cd8e506SKumar Gala { 635b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 636b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 6371cd8e506SKumar Gala u32 temp; 6381cd8e506SKumar Gala 6391cd8e506SKumar Gala if (priority > 7) 6401cd8e506SKumar Gala return -EINVAL; 6411cd8e506SKumar Gala if (src > 127) 6421cd8e506SKumar Gala return -EINVAL; 6431cd8e506SKumar Gala if (ipic_info[src].prio == 0) 6441cd8e506SKumar Gala return -EINVAL; 6451cd8e506SKumar Gala 6461cd8e506SKumar Gala temp = ipic_read(ipic->regs, ipic_info[src].prio); 6471cd8e506SKumar Gala 6481cd8e506SKumar Gala if (priority < 4) { 6491cd8e506SKumar Gala temp &= ~(0x7 << (20 + (3 - priority) * 3)); 6501cd8e506SKumar Gala temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3); 6511cd8e506SKumar Gala } else { 6521cd8e506SKumar Gala temp &= ~(0x7 << (4 + (7 - priority) * 3)); 6531cd8e506SKumar Gala temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3); 6541cd8e506SKumar Gala } 6551cd8e506SKumar Gala 6561cd8e506SKumar Gala ipic_write(ipic->regs, ipic_info[src].prio, temp); 6571cd8e506SKumar Gala 6581cd8e506SKumar Gala return 0; 6591cd8e506SKumar Gala } 6601cd8e506SKumar Gala 661b9f0f1bbSKim Phillips void ipic_set_highest_priority(unsigned int virq) 6621cd8e506SKumar Gala { 663b9f0f1bbSKim Phillips struct ipic *ipic = ipic_from_irq(virq); 664b9f0f1bbSKim Phillips unsigned int src = ipic_irq_to_hw(virq); 6651cd8e506SKumar Gala u32 temp; 6661cd8e506SKumar Gala 6671cd8e506SKumar Gala temp = ipic_read(ipic->regs, IPIC_SICFR); 6681cd8e506SKumar Gala 6691cd8e506SKumar Gala /* clear and set HPI */ 6701cd8e506SKumar Gala temp &= 0x7f000000; 6711cd8e506SKumar Gala temp |= (src & 0x7f) << 24; 6721cd8e506SKumar Gala 6731cd8e506SKumar Gala ipic_write(ipic->regs, IPIC_SICFR, temp); 6741cd8e506SKumar Gala } 6751cd8e506SKumar Gala 6761cd8e506SKumar Gala void ipic_set_default_priority(void) 6771cd8e506SKumar Gala { 678b9f0f1bbSKim Phillips ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_SIPRR_A_DEFAULT); 679b9f0f1bbSKim Phillips ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_SIPRR_D_DEFAULT); 680b9f0f1bbSKim Phillips ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_SMPRR_A_DEFAULT); 681b9f0f1bbSKim Phillips ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_SMPRR_B_DEFAULT); 6821cd8e506SKumar Gala } 6831cd8e506SKumar Gala 6841cd8e506SKumar Gala void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq) 6851cd8e506SKumar Gala { 6861cd8e506SKumar Gala struct ipic *ipic = primary_ipic; 6871cd8e506SKumar Gala u32 temp; 6881cd8e506SKumar Gala 6891cd8e506SKumar Gala temp = ipic_read(ipic->regs, IPIC_SERMR); 6901cd8e506SKumar Gala temp |= (1 << (31 - mcp_irq)); 6911cd8e506SKumar Gala ipic_write(ipic->regs, IPIC_SERMR, temp); 6921cd8e506SKumar Gala } 6931cd8e506SKumar Gala 6941cd8e506SKumar Gala void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq) 6951cd8e506SKumar Gala { 6961cd8e506SKumar Gala struct ipic *ipic = primary_ipic; 6971cd8e506SKumar Gala u32 temp; 6981cd8e506SKumar Gala 6991cd8e506SKumar Gala temp = ipic_read(ipic->regs, IPIC_SERMR); 7001cd8e506SKumar Gala temp &= (1 << (31 - mcp_irq)); 7011cd8e506SKumar Gala ipic_write(ipic->regs, IPIC_SERMR, temp); 7021cd8e506SKumar Gala } 7031cd8e506SKumar Gala 7041cd8e506SKumar Gala u32 ipic_get_mcp_status(void) 7051cd8e506SKumar Gala { 7061cd8e506SKumar Gala return ipic_read(primary_ipic->regs, IPIC_SERMR); 7071cd8e506SKumar Gala } 7081cd8e506SKumar Gala 7091cd8e506SKumar Gala void ipic_clear_mcp_status(u32 mask) 7101cd8e506SKumar Gala { 7111cd8e506SKumar Gala ipic_write(primary_ipic->regs, IPIC_SERMR, mask); 7121cd8e506SKumar Gala } 7131cd8e506SKumar Gala 714b9f0f1bbSKim Phillips /* Return an interrupt vector or NO_IRQ if no interrupt is pending. */ 71535a84c2fSOlaf Hering unsigned int ipic_get_irq(void) 7161cd8e506SKumar Gala { 7171cd8e506SKumar Gala int irq; 7181cd8e506SKumar Gala 719b9f0f1bbSKim Phillips BUG_ON(primary_ipic == NULL); 720b9f0f1bbSKim Phillips 721b9f0f1bbSKim Phillips #define IPIC_SIVCR_VECTOR_MASK 0x7f 722b9f0f1bbSKim Phillips irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK; 7231cd8e506SKumar Gala 7241cd8e506SKumar Gala if (irq == 0) /* 0 --> no irq is pending */ 725b9f0f1bbSKim Phillips return NO_IRQ; 7261cd8e506SKumar Gala 727b9f0f1bbSKim Phillips return irq_linear_revmap(primary_ipic->irqhost, irq); 7281cd8e506SKumar Gala } 7291cd8e506SKumar Gala 7301cd8e506SKumar Gala static struct sysdev_class ipic_sysclass = { 7311cd8e506SKumar Gala set_kset_name("ipic"), 7321cd8e506SKumar Gala }; 7331cd8e506SKumar Gala 7341cd8e506SKumar Gala static struct sys_device device_ipic = { 7351cd8e506SKumar Gala .id = 0, 7361cd8e506SKumar Gala .cls = &ipic_sysclass, 7371cd8e506SKumar Gala }; 7381cd8e506SKumar Gala 7391cd8e506SKumar Gala static int __init init_ipic_sysfs(void) 7401cd8e506SKumar Gala { 7411cd8e506SKumar Gala int rc; 7421cd8e506SKumar Gala 7431cd8e506SKumar Gala if (!primary_ipic->regs) 7441cd8e506SKumar Gala return -ENODEV; 7451cd8e506SKumar Gala printk(KERN_DEBUG "Registering ipic with sysfs...\n"); 7461cd8e506SKumar Gala 7471cd8e506SKumar Gala rc = sysdev_class_register(&ipic_sysclass); 7481cd8e506SKumar Gala if (rc) { 7491cd8e506SKumar Gala printk(KERN_ERR "Failed registering ipic sys class\n"); 7501cd8e506SKumar Gala return -ENODEV; 7511cd8e506SKumar Gala } 7521cd8e506SKumar Gala rc = sysdev_register(&device_ipic); 7531cd8e506SKumar Gala if (rc) { 7541cd8e506SKumar Gala printk(KERN_ERR "Failed registering ipic sys device\n"); 7551cd8e506SKumar Gala return -ENODEV; 7561cd8e506SKumar Gala } 7571cd8e506SKumar Gala return 0; 7581cd8e506SKumar Gala } 7591cd8e506SKumar Gala 7601cd8e506SKumar Gala subsys_initcall(init_ipic_sysfs); 761