pxa_icu.c revision 330897
1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2006 Benno Rice. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/11/sys/arm/xscale/pxa/pxa_icu.c 330897 2018-03-14 03:19:51Z eadler $"); 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/bus.h> 33#include <sys/kernel.h> 34#include <sys/module.h> 35#include <sys/malloc.h> 36#include <sys/rman.h> 37#include <sys/timetc.h> 38#include <machine/armreg.h> 39#include <machine/bus.h> 40#include <machine/intr.h> 41 42#include <arm/xscale/pxa/pxavar.h> 43#include <arm/xscale/pxa/pxareg.h> 44 45struct pxa_icu_softc { 46 struct resource * pi_res[1]; 47 bus_space_tag_t pi_bst; 48 bus_space_handle_t pi_bsh; 49}; 50 51static struct resource_spec pxa_icu_spec[] = { 52 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 53 { -1, 0 } 54}; 55 56static struct pxa_icu_softc *pxa_icu_softc = NULL; 57 58static int pxa_icu_probe(device_t); 59static int pxa_icu_attach(device_t); 60 61uint32_t pxa_icu_get_icip(void); 62void pxa_icu_clear_icip(int); 63uint32_t pxa_icu_get_icfp(void); 64void pxa_icu_clear_icfp(int); 65uint32_t pxa_icu_get_icmr(void); 66void pxa_icu_set_icmr(uint32_t); 67uint32_t pxa_icu_get_iclr(void); 68void pxa_icu_set_iclr(uint32_t); 69uint32_t pxa_icu_get_icpr(void); 70void pxa_icu_idle_enable(void); 71void pxa_icu_idle_disable(void); 72 73extern uint32_t pxa_gpio_intr_flags[]; 74 75static int 76pxa_icu_probe(device_t dev) 77{ 78 79 device_set_desc(dev, "Interrupt Controller"); 80 return (0); 81} 82 83static int 84pxa_icu_attach(device_t dev) 85{ 86 int error; 87 struct pxa_icu_softc *sc; 88 89 sc = (struct pxa_icu_softc *)device_get_softc(dev); 90 91 if (pxa_icu_softc != NULL) 92 return (ENXIO); 93 pxa_icu_softc = sc; 94 95 error = bus_alloc_resources(dev, pxa_icu_spec, sc->pi_res); 96 if (error) { 97 device_printf(dev, "could not allocate resources\n"); 98 return (ENXIO); 99 } 100 101 sc->pi_bst = rman_get_bustag(sc->pi_res[0]); 102 sc->pi_bsh = rman_get_bushandle(sc->pi_res[0]); 103 104 /* Disable all interrupts. */ 105 pxa_icu_set_icmr(0); 106 107 /* Route all interrupts to IRQ rather than FIQ. */ 108 pxa_icu_set_iclr(0); 109 110 /* XXX: This should move to configure_final or something. */ 111 enable_interrupts(PSR_I|PSR_F); 112 113 return (0); 114} 115 116static device_method_t pxa_icu_methods[] = { 117 DEVMETHOD(device_probe, pxa_icu_probe), 118 DEVMETHOD(device_attach, pxa_icu_attach), 119 120 {0, 0} 121}; 122 123static driver_t pxa_icu_driver = { 124 "icu", 125 pxa_icu_methods, 126 sizeof(struct pxa_icu_softc), 127}; 128 129static devclass_t pxa_icu_devclass; 130 131DRIVER_MODULE(pxaicu, pxa, pxa_icu_driver, pxa_icu_devclass, 0, 0); 132 133int 134arm_get_next_irq(int last __unused) 135{ 136 int irq; 137 138 if ((irq = pxa_icu_get_icip()) != 0) { 139 return (ffs(irq) - 1); 140 } 141 142 return (pxa_gpio_get_next_irq()); 143} 144 145void 146arm_mask_irq(uintptr_t nb) 147{ 148 uint32_t mr; 149 150 if (nb >= IRQ_GPIO0) { 151 pxa_gpio_mask_irq(nb); 152 return; 153 } 154 155 mr = pxa_icu_get_icmr(); 156 mr &= ~(1 << nb); 157 pxa_icu_set_icmr(mr); 158} 159 160void 161arm_unmask_irq(uintptr_t nb) 162{ 163 uint32_t mr; 164 165 if (nb >= IRQ_GPIO0) { 166 pxa_gpio_unmask_irq(nb); 167 return; 168 } 169 170 mr = pxa_icu_get_icmr(); 171 mr |= (1 << nb); 172 pxa_icu_set_icmr(mr); 173} 174 175uint32_t 176pxa_icu_get_icip(void) 177{ 178 179 return (bus_space_read_4(pxa_icu_softc->pi_bst, 180 pxa_icu_softc->pi_bsh, ICU_IP)); 181} 182 183void 184pxa_icu_clear_icip(int irq) 185{ 186 187 bus_space_write_4(pxa_icu_softc->pi_bst, 188 pxa_icu_softc->pi_bsh, ICU_IP, (1 << irq)); 189} 190 191uint32_t 192pxa_icu_get_icfp(void) 193{ 194 195 return (bus_space_read_4(pxa_icu_softc->pi_bst, 196 pxa_icu_softc->pi_bsh, ICU_FP)); 197} 198 199void 200pxa_icu_clear_icfp(int irq) 201{ 202 203 bus_space_write_4(pxa_icu_softc->pi_bst, 204 pxa_icu_softc->pi_bsh, ICU_FP, (1 << irq)); 205} 206 207uint32_t 208pxa_icu_get_icmr(void) 209{ 210 211 return (bus_space_read_4(pxa_icu_softc->pi_bst, 212 pxa_icu_softc->pi_bsh, ICU_MR)); 213} 214 215void 216pxa_icu_set_icmr(uint32_t val) 217{ 218 219 bus_space_write_4(pxa_icu_softc->pi_bst, 220 pxa_icu_softc->pi_bsh, ICU_MR, val); 221} 222 223uint32_t 224pxa_icu_get_iclr(void) 225{ 226 227 return (bus_space_read_4(pxa_icu_softc->pi_bst, 228 pxa_icu_softc->pi_bsh, ICU_LR)); 229} 230 231void 232pxa_icu_set_iclr(uint32_t val) 233{ 234 235 bus_space_write_4(pxa_icu_softc->pi_bst, 236 pxa_icu_softc->pi_bsh, ICU_LR, val); 237} 238 239uint32_t 240pxa_icu_get_icpr(void) 241{ 242 243 return (bus_space_read_4(pxa_icu_softc->pi_bst, 244 pxa_icu_softc->pi_bsh, ICU_PR)); 245} 246 247void 248pxa_icu_idle_enable(void) 249{ 250 251 bus_space_write_4(pxa_icu_softc->pi_bst, 252 pxa_icu_softc->pi_bsh, ICU_CR, 0x0); 253} 254 255void 256pxa_icu_idle_disable(void) 257{ 258 259 bus_space_write_4(pxa_icu_softc->pi_bst, 260 pxa_icu_softc->pi_bsh, ICU_CR, 0x1); 261} 262