pxa_icu.c revision 193847
1179595Sbenno/*- 2179595Sbenno * Copyright (c) 2006 Benno Rice. All rights reserved. 3179595Sbenno * 4179595Sbenno * Redistribution and use in source and binary forms, with or without 5179595Sbenno * modification, are permitted provided that the following conditions 6179595Sbenno * are met: 7179595Sbenno * 1. Redistributions of source code must retain the above copyright 8179595Sbenno * notice, this list of conditions and the following disclaimer. 9179595Sbenno * 2. Redistributions in binary form must reproduce the above copyright 10179595Sbenno * notice, this list of conditions and the following disclaimer in the 11179595Sbenno * documentation and/or other materials provided with the distribution. 12179595Sbenno * 13179595Sbenno * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14179595Sbenno * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15179595Sbenno * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16179595Sbenno * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17179595Sbenno * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18179595Sbenno * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19179595Sbenno * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20179595Sbenno * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21179595Sbenno * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22179595Sbenno * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23179595Sbenno */ 24179595Sbenno 25179595Sbenno#include <sys/cdefs.h> 26179595Sbenno__FBSDID("$FreeBSD: head/sys/arm/xscale/pxa/pxa_icu.c 193847 2009-06-09 18:18:41Z marcel $"); 27179595Sbenno 28179595Sbenno#include <sys/param.h> 29179595Sbenno#include <sys/systm.h> 30179595Sbenno#include <sys/bus.h> 31179595Sbenno#include <sys/kernel.h> 32179595Sbenno#include <sys/module.h> 33179595Sbenno#include <sys/malloc.h> 34179595Sbenno#include <sys/rman.h> 35179595Sbenno#include <sys/timetc.h> 36179595Sbenno#include <machine/bus.h> 37179595Sbenno#include <machine/intr.h> 38179595Sbenno 39179595Sbenno#include <arm/xscale/pxa/pxavar.h> 40179595Sbenno#include <arm/xscale/pxa/pxareg.h> 41179595Sbenno 42179595Sbennostruct pxa_icu_softc { 43179595Sbenno struct resource * pi_res[1]; 44179595Sbenno bus_space_tag_t pi_bst; 45179595Sbenno bus_space_handle_t pi_bsh; 46179595Sbenno}; 47179595Sbenno 48179595Sbennostatic struct resource_spec pxa_icu_spec[] = { 49179595Sbenno { SYS_RES_MEMORY, 0, RF_ACTIVE }, 50179595Sbenno { -1, 0 } 51179595Sbenno}; 52179595Sbenno 53179595Sbennostatic struct pxa_icu_softc *pxa_icu_softc = NULL; 54179595Sbenno 55179595Sbennostatic int pxa_icu_probe(device_t); 56179595Sbennostatic int pxa_icu_attach(device_t); 57179595Sbenno 58179595Sbennouint32_t pxa_icu_get_icip(void); 59179595Sbennovoid pxa_icu_clear_icip(int); 60179595Sbennouint32_t pxa_icu_get_icfp(void); 61179595Sbennovoid pxa_icu_clear_icfp(int); 62179595Sbennouint32_t pxa_icu_get_icmr(void); 63179595Sbennovoid pxa_icu_set_icmr(uint32_t); 64179595Sbennouint32_t pxa_icu_get_iclr(void); 65179595Sbennovoid pxa_icu_set_iclr(uint32_t); 66179595Sbennouint32_t pxa_icu_get_icpr(void); 67179595Sbennovoid pxa_icu_idle_enable(void); 68179595Sbennovoid pxa_icu_idle_disable(void); 69179595Sbenno 70179595Sbennoextern uint32_t pxa_gpio_intr_flags[]; 71179595Sbenno 72179595Sbennostatic int 73179595Sbennopxa_icu_probe(device_t dev) 74179595Sbenno{ 75179595Sbenno 76179595Sbenno device_set_desc(dev, "Interrupt Controller"); 77179595Sbenno return (0); 78179595Sbenno} 79179595Sbenno 80179595Sbennostatic int 81179595Sbennopxa_icu_attach(device_t dev) 82179595Sbenno{ 83179595Sbenno int error; 84179595Sbenno struct pxa_icu_softc *sc; 85179595Sbenno 86179595Sbenno sc = (struct pxa_icu_softc *)device_get_softc(dev); 87179595Sbenno 88179595Sbenno if (pxa_icu_softc != NULL) 89179595Sbenno return (ENXIO); 90179595Sbenno pxa_icu_softc = sc; 91179595Sbenno 92179595Sbenno error = bus_alloc_resources(dev, pxa_icu_spec, sc->pi_res); 93179595Sbenno if (error) { 94179595Sbenno device_printf(dev, "could not allocate resources\n"); 95179595Sbenno return (ENXIO); 96179595Sbenno } 97179595Sbenno 98179595Sbenno sc->pi_bst = rman_get_bustag(sc->pi_res[0]); 99179595Sbenno sc->pi_bsh = rman_get_bushandle(sc->pi_res[0]); 100179595Sbenno 101179595Sbenno /* Disable all interrupts. */ 102179595Sbenno pxa_icu_set_icmr(0); 103179595Sbenno 104179595Sbenno /* Route all interrupts to IRQ rather than FIQ. */ 105179595Sbenno pxa_icu_set_iclr(0); 106179595Sbenno 107179595Sbenno /* XXX: This should move to configure_final or something. */ 108179595Sbenno enable_interrupts(I32_bit|F32_bit); 109179595Sbenno 110179595Sbenno return (0); 111179595Sbenno} 112179595Sbenno 113179595Sbennostatic device_method_t pxa_icu_methods[] = { 114179595Sbenno DEVMETHOD(device_probe, pxa_icu_probe), 115179595Sbenno DEVMETHOD(device_attach, pxa_icu_attach), 116179595Sbenno 117179595Sbenno {0, 0} 118179595Sbenno}; 119179595Sbenno 120179595Sbennostatic driver_t pxa_icu_driver = { 121179595Sbenno "icu", 122179595Sbenno pxa_icu_methods, 123179595Sbenno sizeof(struct pxa_icu_softc), 124179595Sbenno}; 125179595Sbenno 126179595Sbennostatic devclass_t pxa_icu_devclass; 127179595Sbenno 128179595SbennoDRIVER_MODULE(pxaicu, pxa, pxa_icu_driver, pxa_icu_devclass, 0, 0); 129179595Sbenno 130179595Sbennoint 131193847Smarcelarm_get_next_irq(int last __unused) 132179595Sbenno{ 133179595Sbenno int irq; 134179595Sbenno 135179595Sbenno if ((irq = pxa_icu_get_icip()) != 0) { 136179595Sbenno return (ffs(irq) - 1); 137179595Sbenno } 138179595Sbenno 139179595Sbenno return (pxa_gpio_get_next_irq()); 140179595Sbenno} 141179595Sbenno 142179595Sbennovoid 143179595Sbennoarm_mask_irq(uintptr_t nb) 144179595Sbenno{ 145179595Sbenno uint32_t mr; 146179595Sbenno 147179595Sbenno if (nb >= IRQ_GPIO0) { 148179595Sbenno pxa_gpio_mask_irq(nb); 149179595Sbenno return; 150179595Sbenno } 151179595Sbenno 152179595Sbenno mr = pxa_icu_get_icmr(); 153179595Sbenno mr &= ~(1 << nb); 154179595Sbenno pxa_icu_set_icmr(mr); 155179595Sbenno} 156179595Sbenno 157179595Sbennovoid 158179595Sbennoarm_unmask_irq(uintptr_t nb) 159179595Sbenno{ 160179595Sbenno uint32_t mr; 161179595Sbenno 162179595Sbenno if (nb >= IRQ_GPIO0) { 163179595Sbenno pxa_gpio_unmask_irq(nb); 164179595Sbenno return; 165179595Sbenno } 166179595Sbenno 167179595Sbenno mr = pxa_icu_get_icmr(); 168179595Sbenno mr |= (1 << nb); 169179595Sbenno pxa_icu_set_icmr(mr); 170179595Sbenno} 171179595Sbenno 172179595Sbennouint32_t 173179595Sbennopxa_icu_get_icip() 174179595Sbenno{ 175179595Sbenno 176179595Sbenno return (bus_space_read_4(pxa_icu_softc->pi_bst, 177179595Sbenno pxa_icu_softc->pi_bsh, ICU_IP)); 178179595Sbenno} 179179595Sbenno 180179595Sbennovoid 181179595Sbennopxa_icu_clear_icip(int irq) 182179595Sbenno{ 183179595Sbenno 184179595Sbenno bus_space_write_4(pxa_icu_softc->pi_bst, 185179595Sbenno pxa_icu_softc->pi_bsh, ICU_IP, (1 << irq)); 186179595Sbenno} 187179595Sbenno 188179595Sbennouint32_t 189179595Sbennopxa_icu_get_icfp() 190179595Sbenno{ 191179595Sbenno 192179595Sbenno return (bus_space_read_4(pxa_icu_softc->pi_bst, 193179595Sbenno pxa_icu_softc->pi_bsh, ICU_FP)); 194179595Sbenno} 195179595Sbenno 196179595Sbennovoid 197179595Sbennopxa_icu_clear_icfp(int irq) 198179595Sbenno{ 199179595Sbenno 200179595Sbenno bus_space_write_4(pxa_icu_softc->pi_bst, 201179595Sbenno pxa_icu_softc->pi_bsh, ICU_FP, (1 << irq)); 202179595Sbenno} 203179595Sbenno 204179595Sbennouint32_t 205179595Sbennopxa_icu_get_icmr() 206179595Sbenno{ 207179595Sbenno 208179595Sbenno return (bus_space_read_4(pxa_icu_softc->pi_bst, 209179595Sbenno pxa_icu_softc->pi_bsh, ICU_MR)); 210179595Sbenno} 211179595Sbenno 212179595Sbennovoid 213179595Sbennopxa_icu_set_icmr(uint32_t val) 214179595Sbenno{ 215179595Sbenno 216179595Sbenno bus_space_write_4(pxa_icu_softc->pi_bst, 217179595Sbenno pxa_icu_softc->pi_bsh, ICU_MR, val); 218179595Sbenno} 219179595Sbenno 220179595Sbennouint32_t 221179595Sbennopxa_icu_get_iclr() 222179595Sbenno{ 223179595Sbenno 224179595Sbenno return (bus_space_read_4(pxa_icu_softc->pi_bst, 225179595Sbenno pxa_icu_softc->pi_bsh, ICU_LR)); 226179595Sbenno} 227179595Sbenno 228179595Sbennovoid 229179595Sbennopxa_icu_set_iclr(uint32_t val) 230179595Sbenno{ 231179595Sbenno 232179595Sbenno bus_space_write_4(pxa_icu_softc->pi_bst, 233179595Sbenno pxa_icu_softc->pi_bsh, ICU_LR, val); 234179595Sbenno} 235179595Sbenno 236179595Sbennouint32_t 237179595Sbennopxa_icu_get_icpr() 238179595Sbenno{ 239179595Sbenno 240179595Sbenno return (bus_space_read_4(pxa_icu_softc->pi_bst, 241179595Sbenno pxa_icu_softc->pi_bsh, ICU_PR)); 242179595Sbenno} 243179595Sbenno 244179595Sbennovoid 245179595Sbennopxa_icu_idle_enable() 246179595Sbenno{ 247179595Sbenno 248179595Sbenno bus_space_write_4(pxa_icu_softc->pi_bst, 249179595Sbenno pxa_icu_softc->pi_bsh, ICU_CR, 0x0); 250179595Sbenno} 251179595Sbenno 252179595Sbennovoid 253179595Sbennopxa_icu_idle_disable() 254179595Sbenno{ 255179595Sbenno 256179595Sbenno bus_space_write_4(pxa_icu_softc->pi_bst, 257179595Sbenno pxa_icu_softc->pi_bsh, ICU_CR, 0x1); 258179595Sbenno} 259