1*d974db0aSgarbled /* $NetBSD: pic_discovery.c,v 1.2 2007/10/17 19:56:42 garbled Exp $ */ 2*d974db0aSgarbled 3*d974db0aSgarbled /* 4*d974db0aSgarbled * Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc. 5*d974db0aSgarbled * All rights reserved. 6*d974db0aSgarbled * 7*d974db0aSgarbled * Redistribution and use in source and binary forms, with or without 8*d974db0aSgarbled * modification, are permitted provided that the following conditions 9*d974db0aSgarbled * are met: 10*d974db0aSgarbled * 1. Redistributions of source code must retain the above copyright 11*d974db0aSgarbled * notice, this list of conditions and the following disclaimer. 12*d974db0aSgarbled * 2. Redistributions in binary form must reproduce the above copyright 13*d974db0aSgarbled * notice, this list of conditions and the following disclaimer in the 14*d974db0aSgarbled * documentation and/or other materials provided with the distribution. 15*d974db0aSgarbled * 3. All advertising materials mentioning features or use of this software 16*d974db0aSgarbled * must display the following acknowledgement: 17*d974db0aSgarbled * This product includes software developed for the NetBSD Project by 18*d974db0aSgarbled * Allegro Networks, Inc., and Wasabi Systems, Inc. 19*d974db0aSgarbled * 4. The name of Allegro Networks, Inc. may not be used to endorse 20*d974db0aSgarbled * or promote products derived from this software without specific prior 21*d974db0aSgarbled * written permission. 22*d974db0aSgarbled * 5. The name of Wasabi Systems, Inc. may not be used to endorse 23*d974db0aSgarbled * or promote products derived from this software without specific prior 24*d974db0aSgarbled * written permission. 25*d974db0aSgarbled * 26*d974db0aSgarbled * THIS SOFTWARE IS PROVIDED BY ALLEGRO NETWORKS, INC. AND 27*d974db0aSgarbled * WASABI SYSTEMS, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 28*d974db0aSgarbled * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 29*d974db0aSgarbled * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 30*d974db0aSgarbled * IN NO EVENT SHALL EITHER ALLEGRO NETWORKS, INC. OR WASABI SYSTEMS, INC. 31*d974db0aSgarbled * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32*d974db0aSgarbled * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33*d974db0aSgarbled * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34*d974db0aSgarbled * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35*d974db0aSgarbled * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36*d974db0aSgarbled * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37*d974db0aSgarbled * POSSIBILITY OF SUCH DAMAGE. 38*d974db0aSgarbled */ 39*d974db0aSgarbled 40*d974db0aSgarbled /* 41*d974db0aSgarbled * extintr.c - external interrupt management for discovery 42*d974db0aSgarbled * 43*d974db0aSgarbled * Interrupts are software-prioritized and preempting, 44*d974db0aSgarbled * they are only actually masked when pending. 45*d974db0aSgarbled * this allows avoiding slow, off-CPU mask reprogramming for spl/splx. 46*d974db0aSgarbled * When a lower priority interrupt preempts a high one, 47*d974db0aSgarbled * it is pended and masked. Masks are re-enabled after service. 48*d974db0aSgarbled * 49*d974db0aSgarbled * `ci->ci_cpl' is a "priority level" not a bitmask. 50*d974db0aSgarbled * `irq' is a bit number in the 128 bit imask_t which reflects 51*d974db0aSgarbled * the GT-64260 Main Cause register pair (64 bits), and 52*d974db0aSgarbled * GPP Cause register (32 bits) interrupts. 53*d974db0aSgarbled * 54*d974db0aSgarbled * Intra IPL dispatch order is defined in cause_irq() 55*d974db0aSgarbled * 56*d974db0aSgarbled * Summary bits in cause registers are not valid IRQs 57*d974db0aSgarbled * 58*d974db0aSgarbled * Within a cause register bit vector ISRs are called in 59*d974db0aSgarbled * order of IRQ (descending). 60*d974db0aSgarbled * 61*d974db0aSgarbled * When IRQs are shared, ISRs are called in order on the queue 62*d974db0aSgarbled * (which is arbitrarily first-established-first-served). 63*d974db0aSgarbled * 64*d974db0aSgarbled * GT64260 GPP setup is for edge-triggered interrupts. 65*d974db0aSgarbled * We maintain a mask of level-triggered type IRQs 66*d974db0aSgarbled * and gather unlatched level from the GPP Value register. 67*d974db0aSgarbled * 68*d974db0aSgarbled * Software interrupts are just like regular IRQs, 69*d974db0aSgarbled * they are established, pended, and dispatched exactly the 70*d974db0aSgarbled * same as HW interrupts. 71*d974db0aSgarbled * 72*d974db0aSgarbled * 128 bit imask_t operations could be implemented with Altivec 73*d974db0aSgarbled * ("vand", "vor", etc however no "vcntlzw" or "vffs"....) 74*d974db0aSgarbled * 75*d974db0aSgarbled * creation Tue Feb 6 17:27:18 PST 2001 cliff 76*d974db0aSgarbled */ 77*d974db0aSgarbled 78*d974db0aSgarbled #include <sys/cdefs.h> 79*d974db0aSgarbled __KERNEL_RCSID(0, "$NetBSD: pic_discovery.c,v 1.2 2007/10/17 19:56:42 garbled Exp $"); 80*d974db0aSgarbled 81*d974db0aSgarbled #include "opt_marvell.h" 82*d974db0aSgarbled #include "opt_kgdb.h" 83*d974db0aSgarbled 84*d974db0aSgarbled #include <sys/param.h> 85*d974db0aSgarbled #include <sys/systm.h> 86*d974db0aSgarbled #include <sys/types.h> 87*d974db0aSgarbled #include <sys/malloc.h> 88*d974db0aSgarbled #include <sys/kernel.h> 89*d974db0aSgarbled 90*d974db0aSgarbled #include <machine/psl.h> 91*d974db0aSgarbled #include <machine/bus.h> 92*d974db0aSgarbled #include <machine/cpu.h> 93*d974db0aSgarbled #include <machine/intr.h> 94*d974db0aSgarbled #include <powerpc/pic/picvar.h> 95*d974db0aSgarbled #ifdef KGDB 96*d974db0aSgarbled #include <machine/db_machdep.h> 97*d974db0aSgarbled #endif 98*d974db0aSgarbled #include <dev/marvell/gtreg.h> 99*d974db0aSgarbled #include <dev/marvell/gtvar.h> 100*d974db0aSgarbled #include <dev/marvell/gtintrreg.h> 101*d974db0aSgarbled 102*d974db0aSgarbled #include <uvm/uvm_extern.h> 103*d974db0aSgarbled 104*d974db0aSgarbled #if defined(DEBUG) && defined(DDB) 105*d974db0aSgarbled #endif 106*d974db0aSgarbled 107*d974db0aSgarbled #ifdef DEBUG 108*d974db0aSgarbled # define STATIC 109*d974db0aSgarbled int intrdebug = 0; 110*d974db0aSgarbled # define DPRINTF(x) do { if (intrdebug) printf x ; } while (0) 111*d974db0aSgarbled # define DPRINTFN(n, x) do { if (intrdebug > (n)) printf x ; } while (0) 112*d974db0aSgarbled #else 113*d974db0aSgarbled # define STATIC static 114*d974db0aSgarbled # define DPRINTF(x) 115*d974db0aSgarbled # define DPRINTFN(n, x) 116*d974db0aSgarbled #endif 117*d974db0aSgarbled 118*d974db0aSgarbled #ifdef DIAGNOSTIC 119*d974db0aSgarbled # define DIAGPRF(x) printf x 120*d974db0aSgarbled #else 121*d974db0aSgarbled # define DIAGPRF(x) 122*d974db0aSgarbled #endif 123*d974db0aSgarbled 124*d974db0aSgarbled #define ILLEGAL_IRQ(x) (((x) < 0) || ((x) >= NIRQ) || \ 125*d974db0aSgarbled ((1<<((x)&IMASK_BITMASK)) & imres.bits[(x)>>IMASK_WORDSHIFT])) 126*d974db0aSgarbled 127*d974db0aSgarbled extern struct powerpc_bus_space gt_mem_bs_tag; 128*d974db0aSgarbled extern bus_space_handle_t gt_memh; 129*d974db0aSgarbled 130*d974db0aSgarbled static const char intr_source_strings[NIRQ][16] = { 131*d974db0aSgarbled "unknown 0", "dev", "dma", "cpu", 132*d974db0aSgarbled "idma 01", "idma 23", "idma 45", "idma 67", 133*d974db0aSgarbled "timer 01", "timer 23", "timer 45", "timer 67", 134*d974db0aSgarbled "pci0-0", "pci0-1", "pci0-2", "pci0-3", 135*d974db0aSgarbled /*16*/ "pci1-0", "ecc", "pci1-1", "pci1-2", 136*d974db0aSgarbled "pci1-3", "pci0-outl", "pci0-outh", "pci1-outl", 137*d974db0aSgarbled "pci1-outh", "unknown 25", "pci0-inl", "pci0-inh", 138*d974db0aSgarbled "pci1-inl", "pci1-inh", "unknown 30", "unknown 31", 139*d974db0aSgarbled /*32*/ "ether 0", "ether 1", "ether 2", "unknown 35", 140*d974db0aSgarbled "sdma", "iic", "unknown 38", "brg", 141*d974db0aSgarbled "mpsc 0", "unknown 41", "mpsc 1", "comm", 142*d974db0aSgarbled "unknown 44", "unknown 45", "unknown 46", "unknown 47", 143*d974db0aSgarbled /*48*/ "unknown 48", "unknown 49", "unknown 50", "unknown 51", 144*d974db0aSgarbled "unknown 52", "unknown 53", "unknown 54", "unknown 55", 145*d974db0aSgarbled "gppsum 0", "gppsum 1", "gppsum 2", "gppsum 3", 146*d974db0aSgarbled "unknown 60", "unknown 61", "unknown 62", "unknown 63", 147*d974db0aSgarbled }; 148*d974db0aSgarbled 149*d974db0aSgarbled struct discovery_pic_ops { 150*d974db0aSgarbled struct pic_ops dsc_pic; 151*d974db0aSgarbled bus_space_tag_t dsc_memt; 152*d974db0aSgarbled bus_space_tag_t dsc_memh; 153*d974db0aSgarbled uint32_t dsc_interrupt_mask[2]; 154*d974db0aSgarbled uint8_t dsc_priority[64]; 155*d974db0aSgarbled uint8_t dsc_maxpriority[64]; 156*d974db0aSgarbled }; 157*d974db0aSgarbled 158*d974db0aSgarbled struct gpp_pic_ops { 159*d974db0aSgarbled struct pic_ops gpp_pic; 160*d974db0aSgarbled bus_space_tag_t gpp_memt; 161*d974db0aSgarbled bus_space_handle_t gpp_memh; 162*d974db0aSgarbled uint32_t gpp_interrupt_mask; 163*d974db0aSgarbled uint8_t gpp_priority[32]; 164*d974db0aSgarbled uint8_t gpp_maxpriority[32]; 165*d974db0aSgarbled }; 166*d974db0aSgarbled 167*d974db0aSgarbled static void 168*d974db0aSgarbled gpp_source_name(struct pic_ops *pic, int irq, char *name, size_t len) 169*d974db0aSgarbled { 170*d974db0aSgarbled snprintf(name, len, "gpp %d", irq); 171*d974db0aSgarbled } 172*d974db0aSgarbled 173*d974db0aSgarbled #define GPP_RES ~GT_MPP_INTERRUPTS /* from config */ 174*d974db0aSgarbled 175*d974db0aSgarbled static int 176*d974db0aSgarbled gpp_get_irq(struct pic_ops *pic) 177*d974db0aSgarbled { 178*d974db0aSgarbled struct gpppic_ops * const gpp = (void *)pic; 179*d974db0aSgarbled uint32_t mask; 180*d974db0aSgarbled int maybe_irq = -1; 181*d974db0aSgarbled int maybe_priority = IPL_NONE; 182*d974db0aSgarbled 183*d974db0aSgarbled #ifdef GPP_EDGE 184*d974db0aSgarbled mask = bus_space_read_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Interrupt_Cause); 185*d974db0aSgarbled #else 186*d974db0aSgarbled mask = bus_space_read_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Value); 187*d974db0aSgarbled #endif 188*d974db0aSgarbled mask &= gpp->gpp_interrupt_mask; 189*d974db0aSgarbled if (mask == 0) 190*d974db0aSgarbled return NO_IRQ; 191*d974db0aSgarbled 192*d974db0aSgarbled while (mask != 0) { 193*d974db0aSgarbled int irq = 32 - __builtin_clz(mask); 194*d974db0aSgarbled if (gpp->gpp_priority[irq] > maybe_irq) { 195*d974db0aSgarbled maybe_irq = irq; 196*d974db0aSgarbled maybe_priority = gpp->gpp_priority[irq]; 197*d974db0aSgarbled if (maybe_priority > gpp->gpp_maxpriority[irq]) 198*d974db0aSgarbled break; 199*d974db0aSgarbled } 200*d974db0aSgarbled mask &= ~(1 << irq); 201*d974db0aSgarbled } 202*d974db0aSgarbled /* 203*d974db0aSgarbled * We now have the highest priority IRQ. 204*d974db0aSgarbled */ 205*d974db0aSgarbled KASSERT(maybe_irq >= 0); 206*d974db0aSgarbled #ifdef GPP_EDGE 207*d974db0aSgarbled mask = 1 << maybe_irq; 208*d974db0aSgarbled bus_space_write_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Interrupt_Cause, mask); 209*d974db0aSgarbled #endif 210*d974db0aSgarbled 211*d974db0aSgarbled return maybe_irq; 212*d974db0aSgarbled } 213*d974db0aSgarbled 214*d974db0aSgarbled static void 215*d974db0aSgarbled gpp_establish_irq(struct pic_ops *pic, int irq, int type, int pri) 216*d974db0aSgarbled { 217*d974db0aSgarbled struct gpppic_ops * const gpp = (void *)pic; 218*d974db0aSgarbled const uint32_t mask = 1 << irq; 219*d974db0aSgarbled 220*d974db0aSgarbled KASSERT((unsigned) irq < 32); 221*d974db0aSgarbled #ifdef GPP_EDGE 222*d974db0aSgarbled KASSERT(type == IST_EDGE); 223*d974db0aSgarbled #else 224*d974db0aSgarbled KASSERT(type == IST_LEVEL); 225*d974db0aSgarbled #endif 226*d974db0aSgarbled 227*d974db0aSgarbled /* 228*d974db0aSgarbled * Set pin to input and active low. 229*d974db0aSgarbled */ 230*d974db0aSgarbled val = bus_space_read_4(gpp->gpp_memt, gpp->gpp_memh, GT_GPP_IO_Control); 231*d974db0aSgarbled val &= ~mask; 232*d974db0aSgarbled bus_space_write_4(gpp->gpp_memt, gpp->gpp_memh, GT_GPP_IO_Control, val); 233*d974db0aSgarbled 234*d974db0aSgarbled val = bus_space_read_4(gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Level_Control); 235*d974db0aSgarbled val |= mask; 236*d974db0aSgarbled bus_space_write_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Level_Control, val); 237*d974db0aSgarbled 238*d974db0aSgarbled gpp->gpp_priority[irq] = pri; 239*d974db0aSgarbled 240*d974db0aSgarbled /* 241*d974db0aSgarbled * recalculate the maxpriority of an interrupt. This is highest 242*d974db0aSgarbled * priority interrupt from itself to gpp0. 243*d974db0aSgarbled */ 244*d974db0aSgarbled pri = IPL_NONE; 245*d974db0aSgarbled for (i = 0; i < __arraycount(gpp->gpp_priority); i++) { 246*d974db0aSgarbled if (gpp->gpp_priority[i] > pri) 247*d974db0aSgarbled pri = gpp->gpp_priority[i]; 248*d974db0aSgarbled gpp->gpp_maxpriority[i] = pri; 249*d974db0aSgarbled } 250*d974db0aSgarbled } 251*d974db0aSgarbled 252*d974db0aSgarbled static void 253*d974db0aSgarbled gpp_enable_irq(struct pic_ops *pic, int irq, int type) 254*d974db0aSgarbled { 255*d974db0aSgarbled struct gpppic_ops * const gpp = (void *)pic; 256*d974db0aSgarbled const uint32_t mask = 1 << irq; 257*d974db0aSgarbled 258*d974db0aSgarbled KASSERT(type == IST_LEVEL); 259*d974db0aSgarbled KASSERT(gpp->gpp_priority[irq] != IPL_NONE); 260*d974db0aSgarbled gpp->gpp_interrupt_mask |= mask; 261*d974db0aSgarbled bus_space_write_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Interrupt_Mask, 262*d974db0aSgarbled gpp->gpp_interrupt_mask); 263*d974db0aSgarbled } 264*d974db0aSgarbled 265*d974db0aSgarbled static void 266*d974db0aSgarbled gpp_disable_irq(struct pic_ops *pic, int irq) 267*d974db0aSgarbled { 268*d974db0aSgarbled struct gpppic_ops * const gpp = (void *)pic; 269*d974db0aSgarbled const uint32_t mask = 1 << irq; 270*d974db0aSgarbled 271*d974db0aSgarbled gpp->gpp_interrupt_mask &= ~mask; 272*d974db0aSgarbled bus_space_write_4(&gpp->gpp_memt, gpp->gpp_memh, GT_GPP_Interrupt_Mask, 273*d974db0aSgarbled gpp->gpp_interrupt_mask); 274*d974db0aSgarbled } 275*d974db0aSgarbled 276*d974db0aSgarbled static void 277*d974db0aSgarbled gpp_ack_irq(struct pic_ops *pic, int irq) 278*d974db0aSgarbled { 279*d974db0aSgarbled } 280*d974db0aSgarbled 281*d974db0aSgarbled static struct pic_ops * 282*d974db0aSgarbled gpp_pic_setup(bus_space_tag_t memt, bus_space_handle_t memh) 283*d974db0aSgarbled { 284*d974db0aSgarbled struct gpppic_ops * gpp; 285*d974db0aSgarbled uint32_t val; 286*d974db0aSgarbled 287*d974db0aSgarbled gpp = malloc(sizeof(*gpp), M_DEVBUF, M_NOWAIT|M_ZERO); 288*d974db0aSgarbled if (!gpp) 289*d974db0aSgarbled panic("gpp_pic_setup: malloc(%zu) failed", sizeof(*gpp)); 290*d974db0aSgarbled 291*d974db0aSgarbled gpp->gpp_memt = memt; 292*d974db0aSgarbled gpp->gpp_memh = memh; 293*d974db0aSgarbled gpp->gpp_pic.pic_get_irq = gpp_get_irq; 294*d974db0aSgarbled gpp->gpp_pic.pic_enable_irq = gpp_enable_irq; 295*d974db0aSgarbled gpp->gpp_pic.pic_reenable_irq = gpp_enable_irq; 296*d974db0aSgarbled gpp->gpp_pic.pic_disable_irq = gpp_disable_irq; 297*d974db0aSgarbled gpp->gpp_pic.pic_ack_irq = gpp_ack_irq; 298*d974db0aSgarbled gpp->gpp_pic.pic_establish_irq = gpp_establish_irq; 299*d974db0aSgarbled gpp->gpp_pic.pic_source_name = gpp_source_name; 300*d974db0aSgarbled 301*d974db0aSgarbled /* 302*d974db0aSgarbled * Force GPP interrupts to be level sensitive. 303*d974db0aSgarbled */ 304*d974db0aSgarbled val = bus_space_read_4(&gpp->gpp_memt, gpp->gpp_memh, 0xf300); 305*d974db0aSgarbled bus_space_write_4(&gpp->gpp_memt, gpp->gpp_memh, 0xf300, val | 0x400); 306*d974db0aSgarbled 307*d974db0aSgarbled pic_add(&gpp->gpp_pic); 308*d974db0aSgarbled 309*d974db0aSgarbled return &gpp->gpp_pic; 310*d974db0aSgarbled } 311*d974db0aSgarbled 312*d974db0aSgarbled static void 313*d974db0aSgarbled discovery_source_name(struct pic_ops *pic, int irq, char *name, size_t len) 314*d974db0aSgarbled { 315*d974db0aSgarbled strlcpy(name, discovery_intr_source_strings[irq], len); 316*d974db0aSgarbled } 317*d974db0aSgarbled 318*d974db0aSgarbled static int 319*d974db0aSgarbled discovery_get_irq(struct pic_ops *pic) 320*d974db0aSgarbled { 321*d974db0aSgarbled struct discoverypic_ops * const dsc = (void *)pic; 322*d974db0aSgarbled uint32_t mask; 323*d974db0aSgarbled int irq_base = 0; 324*d974db0aSgarbled int maybe_irq = -1; 325*d974db0aSgarbled int maybe_priority = IPL_NONE; 326*d974db0aSgarbled 327*d974db0aSgarbled mask = bus_space_read_4(&dsc->dsc_memt, dsc->dsc_memh, ICR_CSC); 328*d974db0aSgarbled if (!(mask & CSC_STAT)) 329*d974db0aSgarbled return NO_IRQ; 330*d974db0aSgarbled irq_base = (mask & CSC_SEL) ? 32 : 0; 331*d974db0aSgarbled mask &= dsc->dsc_interrupt_mask[(mask & CSC_SEL) ? 1 : 0]; 332*d974db0aSgarbled while (mask != 0) { 333*d974db0aSgarbled int irq = 32 - __builtin_clz(mask); 334*d974db0aSgarbled if (dsc->dsc_priority[irq_base + irq] > maybe_irq) { 335*d974db0aSgarbled maybe_irq = irq_base + irq; 336*d974db0aSgarbled maybe_priority = dsc->dsc_priority[irq_base + irq]; 337*d974db0aSgarbled if (maybe_priority > dsc->dsc_maxpriority[irq_base + irq]) 338*d974db0aSgarbled break; 339*d974db0aSgarbled } 340*d974db0aSgarbled mask &= ~(1 << irq); 341*d974db0aSgarbled } 342*d974db0aSgarbled /* 343*d974db0aSgarbled * We now have the highest priority IRQ (except it's cascaded). 344*d974db0aSgarbled */ 345*d974db0aSgarbled KASSERT(maybe_irq >= 0); 346*d974db0aSgarbled return maybe_irq; 347*d974db0aSgarbled } 348*d974db0aSgarbled 349*d974db0aSgarbled static void 350*d974db0aSgarbled discovery_establish_irq(struct pic_ops *pic, int irq, int type, int pri) 351*d974db0aSgarbled { 352*d974db0aSgarbled struct discoverypic_ops * const dsc = (void *)pic; 353*d974db0aSgarbled 354*d974db0aSgarbled KASSERT((unsigned) irq < 32); 355*d974db0aSgarbled #ifdef GPP_EDGE 356*d974db0aSgarbled KASSERT(type == IST_EDGE); 357*d974db0aSgarbled #else 358*d974db0aSgarbled KASSERT(type == IST_LEVEL); 359*d974db0aSgarbled #endif 360*d974db0aSgarbled 361*d974db0aSgarbled dsc->dsc_priority[irq] = pri; 362*d974db0aSgarbled 363*d974db0aSgarbled /* 364*d974db0aSgarbled * recalculate the maxpriority of an interrupt. This is highest 365*d974db0aSgarbled * priority interrupt from itself to irq 0. 366*d974db0aSgarbled */ 367*d974db0aSgarbled pri = IPL_NONE; 368*d974db0aSgarbled for (i = 0; i < __arraycount(dsc->dsc_priority); i++) { 369*d974db0aSgarbled if (dsc->dsc_priority[i] > pri) 370*d974db0aSgarbled pri = dsc->dsc_priority[i]; 371*d974db0aSgarbled dsc->dsc_maxpriority[i] = pri; 372*d974db0aSgarbled } 373*d974db0aSgarbled } 374*d974db0aSgarbled 375*d974db0aSgarbled static void 376*d974db0aSgarbled discovery_enable_irq(struct pic_ops *pic, int irq, int type) 377*d974db0aSgarbled { 378*d974db0aSgarbled struct discoverypic_ops * const dsc = (void *)pic; 379*d974db0aSgarbled const uint32_t mask = 1 << (irq & 31); 380*d974db0aSgarbled 381*d974db0aSgarbled KASSERT(type == IST_LEVEL); 382*d974db0aSgarbled KASSERT(dsc->dsc_priority[irq] != IPL_NONE); 383*d974db0aSgarbled if (irq < 32) { 384*d974db0aSgarbled dsc->dsc_interrupt_mask[0] |= mask; 385*d974db0aSgarbled bus_space_write_4(&dsc->dsc_memt, dsc->dsc_memh, 386*d974db0aSgarbled ICR_MIC_LO, dsc->dsc_interrupt_mask[0]); 387*d974db0aSgarbled } else { 388*d974db0aSgarbled dsc->dsc_interrupt_mask[1] |= mask; 389*d974db0aSgarbled bus_space_write_4(&dsc->dsc_memt, dsc->dsc_memh, 390*d974db0aSgarbled ICR_MIC_HI, dsc->dsc_interrupt_mask[1]); 391*d974db0aSgarbled } 392*d974db0aSgarbled } 393*d974db0aSgarbled 394*d974db0aSgarbled static void 395*d974db0aSgarbled discovery_disable_irq(struct pic_ops *pic, int irq) 396*d974db0aSgarbled { 397*d974db0aSgarbled struct discoverypic_ops * const dsc = (void *)pic; 398*d974db0aSgarbled const uint32_t mask = 1 << (irq & 31); 399*d974db0aSgarbled 400*d974db0aSgarbled if (irq < 32) { 401*d974db0aSgarbled dsc->dsc_interrupt_mask[0] &= ~mask; 402*d974db0aSgarbled bus_space_write_4(&dsc->dsc_memt, dsc->dsc_memh, 403*d974db0aSgarbled ICR_MIC_LO, dsc->dsc_interrupt_mask[0]); 404*d974db0aSgarbled } else { 405*d974db0aSgarbled dsc->dsc_interrupt_mask[1] &= ~mask; 406*d974db0aSgarbled bus_space_write_4(&dsc->dsc_memt, dsc->dsc_memh, 407*d974db0aSgarbled ICR_MIC_HI, dsc->dsc_interrupt_mask[1]); 408*d974db0aSgarbled } 409*d974db0aSgarbled } 410*d974db0aSgarbled 411*d974db0aSgarbled static void 412*d974db0aSgarbled discovery_ack_irq(struct pic_ops *pic, int irq) 413*d974db0aSgarbled { 414*d974db0aSgarbled } 415*d974db0aSgarbled 416*d974db0aSgarbled void 417*d974db0aSgarbled discoverypic_setup(bus_space_tag_t memt, bus_space_handle_t memh) 418*d974db0aSgarbled { 419*d974db0aSgarbled struct discoverypic_ops *dsc; 420*d974db0aSgarbled uint32_t val; 421*d974db0aSgarbled 422*d974db0aSgarbled dsc = malloc(sizeof(*dsc), M_DEVBUF, M_NOWAIT|M_ZERO); 423*d974db0aSgarbled if (!dsc) 424*d974db0aSgarbled panic("dsc_pic_setup: malloc(%zu) failed", sizeof(*dsc)); 425*d974db0aSgarbled 426*d974db0aSgarbled dsc->dsc_memt = memt; 427*d974db0aSgarbled dsc->dsc_memh = memh; 428*d974db0aSgarbled dsc->dsc_pic.pic_get_irq = dsc_get_irq; 429*d974db0aSgarbled dsc->dsc_pic.pic_enable_irq = dsc_enable_irq; 430*d974db0aSgarbled dsc->dsc_pic.pic_reenable_irq = dsc_enable_irq; 431*d974db0aSgarbled dsc->dsc_pic.pic_disable_irq = dsc_disable_irq; 432*d974db0aSgarbled dsc->dsc_pic.pic_ack_irq = dsc_ack_irq; 433*d974db0aSgarbled dsc->dsc_pic.pic_establish_irq = dsc_establish_irq; 434*d974db0aSgarbled dsc->dsc_pic.pic_source_name = dsc_source_name; 435*d974db0aSgarbled 436*d974db0aSgarbled pic_add(&dsc->dsc_pic); 437*d974db0aSgarbled KASSERT(dsc->dsc_pic.pic_intrbase == 0); 438*d974db0aSgarbled 439*d974db0aSgarbled pic = dscpic_setup(memt, memh); 440*d974db0aSgarbled intr_establish(dsc->dsc_pic.pic_intrbase + IRQ_GPP7_0, 441*d974db0aSgarbled IST_LEVEL, IPL_NONE, pic_handle_intr, pic); 442*d974db0aSgarbled intr_establish(dsc->dsc_pic.pic_intrbase + IRQ_GPP15_8, 443*d974db0aSgarbled IST_LEVEL, IPL_NONE, pic_handle_intr, pic); 444*d974db0aSgarbled intr_establish(dsc->dsc_pic.pic_intrbase + IRQ_GPP23_16, 445*d974db0aSgarbled IST_LEVEL, IPL_NONE, pic_handle_intr, pic); 446*d974db0aSgarbled intr_establish(dsc->dsc_pic.pic_intrbase + IRQ_GPP31_24, 447*d974db0aSgarbled IST_LEVEL, IPL_NONE, pic_handle_intr, pic); 448*d974db0aSgarbled } 449