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