pxa_icu.c revision 256281
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: stable/10/sys/arm/xscale/pxa/pxa_icu.c 193847 2009-06-09 18:18:41Z marcel $"); 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/bus.h> 37#include <machine/intr.h> 38 39#include <arm/xscale/pxa/pxavar.h> 40#include <arm/xscale/pxa/pxareg.h> 41 42struct pxa_icu_softc { 43 struct resource * pi_res[1]; 44 bus_space_tag_t pi_bst; 45 bus_space_handle_t pi_bsh; 46}; 47 48static struct resource_spec pxa_icu_spec[] = { 49 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 50 { -1, 0 } 51}; 52 53static struct pxa_icu_softc *pxa_icu_softc = NULL; 54 55static int pxa_icu_probe(device_t); 56static int pxa_icu_attach(device_t); 57 58uint32_t pxa_icu_get_icip(void); 59void pxa_icu_clear_icip(int); 60uint32_t pxa_icu_get_icfp(void); 61void pxa_icu_clear_icfp(int); 62uint32_t pxa_icu_get_icmr(void); 63void pxa_icu_set_icmr(uint32_t); 64uint32_t pxa_icu_get_iclr(void); 65void pxa_icu_set_iclr(uint32_t); 66uint32_t pxa_icu_get_icpr(void); 67void pxa_icu_idle_enable(void); 68void pxa_icu_idle_disable(void); 69 70extern uint32_t pxa_gpio_intr_flags[]; 71 72static int 73pxa_icu_probe(device_t dev) 74{ 75 76 device_set_desc(dev, "Interrupt Controller"); 77 return (0); 78} 79 80static int 81pxa_icu_attach(device_t dev) 82{ 83 int error; 84 struct pxa_icu_softc *sc; 85 86 sc = (struct pxa_icu_softc *)device_get_softc(dev); 87 88 if (pxa_icu_softc != NULL) 89 return (ENXIO); 90 pxa_icu_softc = sc; 91 92 error = bus_alloc_resources(dev, pxa_icu_spec, sc->pi_res); 93 if (error) { 94 device_printf(dev, "could not allocate resources\n"); 95 return (ENXIO); 96 } 97 98 sc->pi_bst = rman_get_bustag(sc->pi_res[0]); 99 sc->pi_bsh = rman_get_bushandle(sc->pi_res[0]); 100 101 /* Disable all interrupts. */ 102 pxa_icu_set_icmr(0); 103 104 /* Route all interrupts to IRQ rather than FIQ. */ 105 pxa_icu_set_iclr(0); 106 107 /* XXX: This should move to configure_final or something. */ 108 enable_interrupts(I32_bit|F32_bit); 109 110 return (0); 111} 112 113static device_method_t pxa_icu_methods[] = { 114 DEVMETHOD(device_probe, pxa_icu_probe), 115 DEVMETHOD(device_attach, pxa_icu_attach), 116 117 {0, 0} 118}; 119 120static driver_t pxa_icu_driver = { 121 "icu", 122 pxa_icu_methods, 123 sizeof(struct pxa_icu_softc), 124}; 125 126static devclass_t pxa_icu_devclass; 127 128DRIVER_MODULE(pxaicu, pxa, pxa_icu_driver, pxa_icu_devclass, 0, 0); 129 130int 131arm_get_next_irq(int last __unused) 132{ 133 int irq; 134 135 if ((irq = pxa_icu_get_icip()) != 0) { 136 return (ffs(irq) - 1); 137 } 138 139 return (pxa_gpio_get_next_irq()); 140} 141 142void 143arm_mask_irq(uintptr_t nb) 144{ 145 uint32_t mr; 146 147 if (nb >= IRQ_GPIO0) { 148 pxa_gpio_mask_irq(nb); 149 return; 150 } 151 152 mr = pxa_icu_get_icmr(); 153 mr &= ~(1 << nb); 154 pxa_icu_set_icmr(mr); 155} 156 157void 158arm_unmask_irq(uintptr_t nb) 159{ 160 uint32_t mr; 161 162 if (nb >= IRQ_GPIO0) { 163 pxa_gpio_unmask_irq(nb); 164 return; 165 } 166 167 mr = pxa_icu_get_icmr(); 168 mr |= (1 << nb); 169 pxa_icu_set_icmr(mr); 170} 171 172uint32_t 173pxa_icu_get_icip() 174{ 175 176 return (bus_space_read_4(pxa_icu_softc->pi_bst, 177 pxa_icu_softc->pi_bsh, ICU_IP)); 178} 179 180void 181pxa_icu_clear_icip(int irq) 182{ 183 184 bus_space_write_4(pxa_icu_softc->pi_bst, 185 pxa_icu_softc->pi_bsh, ICU_IP, (1 << irq)); 186} 187 188uint32_t 189pxa_icu_get_icfp() 190{ 191 192 return (bus_space_read_4(pxa_icu_softc->pi_bst, 193 pxa_icu_softc->pi_bsh, ICU_FP)); 194} 195 196void 197pxa_icu_clear_icfp(int irq) 198{ 199 200 bus_space_write_4(pxa_icu_softc->pi_bst, 201 pxa_icu_softc->pi_bsh, ICU_FP, (1 << irq)); 202} 203 204uint32_t 205pxa_icu_get_icmr() 206{ 207 208 return (bus_space_read_4(pxa_icu_softc->pi_bst, 209 pxa_icu_softc->pi_bsh, ICU_MR)); 210} 211 212void 213pxa_icu_set_icmr(uint32_t val) 214{ 215 216 bus_space_write_4(pxa_icu_softc->pi_bst, 217 pxa_icu_softc->pi_bsh, ICU_MR, val); 218} 219 220uint32_t 221pxa_icu_get_iclr() 222{ 223 224 return (bus_space_read_4(pxa_icu_softc->pi_bst, 225 pxa_icu_softc->pi_bsh, ICU_LR)); 226} 227 228void 229pxa_icu_set_iclr(uint32_t val) 230{ 231 232 bus_space_write_4(pxa_icu_softc->pi_bst, 233 pxa_icu_softc->pi_bsh, ICU_LR, val); 234} 235 236uint32_t 237pxa_icu_get_icpr() 238{ 239 240 return (bus_space_read_4(pxa_icu_softc->pi_bst, 241 pxa_icu_softc->pi_bsh, ICU_PR)); 242} 243 244void 245pxa_icu_idle_enable() 246{ 247 248 bus_space_write_4(pxa_icu_softc->pi_bst, 249 pxa_icu_softc->pi_bsh, ICU_CR, 0x0); 250} 251 252void 253pxa_icu_idle_disable() 254{ 255 256 bus_space_write_4(pxa_icu_softc->pi_bst, 257 pxa_icu_softc->pi_bsh, ICU_CR, 0x1); 258} 259