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: releng/10.2/sys/arm/xscale/pxa/pxa_icu.c 278613 2015-02-12 03:50:33Z ian $"); 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> 36278613Sian#include <machine/armreg.h> 37179595Sbenno#include <machine/bus.h> 38179595Sbenno#include <machine/intr.h> 39179595Sbenno 40179595Sbenno#include <arm/xscale/pxa/pxavar.h> 41179595Sbenno#include <arm/xscale/pxa/pxareg.h> 42179595Sbenno 43179595Sbennostruct pxa_icu_softc { 44179595Sbenno struct resource * pi_res[1]; 45179595Sbenno bus_space_tag_t pi_bst; 46179595Sbenno bus_space_handle_t pi_bsh; 47179595Sbenno}; 48179595Sbenno 49179595Sbennostatic struct resource_spec pxa_icu_spec[] = { 50179595Sbenno { SYS_RES_MEMORY, 0, RF_ACTIVE }, 51179595Sbenno { -1, 0 } 52179595Sbenno}; 53179595Sbenno 54179595Sbennostatic struct pxa_icu_softc *pxa_icu_softc = NULL; 55179595Sbenno 56179595Sbennostatic int pxa_icu_probe(device_t); 57179595Sbennostatic int pxa_icu_attach(device_t); 58179595Sbenno 59179595Sbennouint32_t pxa_icu_get_icip(void); 60179595Sbennovoid pxa_icu_clear_icip(int); 61179595Sbennouint32_t pxa_icu_get_icfp(void); 62179595Sbennovoid pxa_icu_clear_icfp(int); 63179595Sbennouint32_t pxa_icu_get_icmr(void); 64179595Sbennovoid pxa_icu_set_icmr(uint32_t); 65179595Sbennouint32_t pxa_icu_get_iclr(void); 66179595Sbennovoid pxa_icu_set_iclr(uint32_t); 67179595Sbennouint32_t pxa_icu_get_icpr(void); 68179595Sbennovoid pxa_icu_idle_enable(void); 69179595Sbennovoid pxa_icu_idle_disable(void); 70179595Sbenno 71179595Sbennoextern uint32_t pxa_gpio_intr_flags[]; 72179595Sbenno 73179595Sbennostatic int 74179595Sbennopxa_icu_probe(device_t dev) 75179595Sbenno{ 76179595Sbenno 77179595Sbenno device_set_desc(dev, "Interrupt Controller"); 78179595Sbenno return (0); 79179595Sbenno} 80179595Sbenno 81179595Sbennostatic int 82179595Sbennopxa_icu_attach(device_t dev) 83179595Sbenno{ 84179595Sbenno int error; 85179595Sbenno struct pxa_icu_softc *sc; 86179595Sbenno 87179595Sbenno sc = (struct pxa_icu_softc *)device_get_softc(dev); 88179595Sbenno 89179595Sbenno if (pxa_icu_softc != NULL) 90179595Sbenno return (ENXIO); 91179595Sbenno pxa_icu_softc = sc; 92179595Sbenno 93179595Sbenno error = bus_alloc_resources(dev, pxa_icu_spec, sc->pi_res); 94179595Sbenno if (error) { 95179595Sbenno device_printf(dev, "could not allocate resources\n"); 96179595Sbenno return (ENXIO); 97179595Sbenno } 98179595Sbenno 99179595Sbenno sc->pi_bst = rman_get_bustag(sc->pi_res[0]); 100179595Sbenno sc->pi_bsh = rman_get_bushandle(sc->pi_res[0]); 101179595Sbenno 102179595Sbenno /* Disable all interrupts. */ 103179595Sbenno pxa_icu_set_icmr(0); 104179595Sbenno 105179595Sbenno /* Route all interrupts to IRQ rather than FIQ. */ 106179595Sbenno pxa_icu_set_iclr(0); 107179595Sbenno 108179595Sbenno /* XXX: This should move to configure_final or something. */ 109278613Sian enable_interrupts(PSR_I|PSR_F); 110179595Sbenno 111179595Sbenno return (0); 112179595Sbenno} 113179595Sbenno 114179595Sbennostatic device_method_t pxa_icu_methods[] = { 115179595Sbenno DEVMETHOD(device_probe, pxa_icu_probe), 116179595Sbenno DEVMETHOD(device_attach, pxa_icu_attach), 117179595Sbenno 118179595Sbenno {0, 0} 119179595Sbenno}; 120179595Sbenno 121179595Sbennostatic driver_t pxa_icu_driver = { 122179595Sbenno "icu", 123179595Sbenno pxa_icu_methods, 124179595Sbenno sizeof(struct pxa_icu_softc), 125179595Sbenno}; 126179595Sbenno 127179595Sbennostatic devclass_t pxa_icu_devclass; 128179595Sbenno 129179595SbennoDRIVER_MODULE(pxaicu, pxa, pxa_icu_driver, pxa_icu_devclass, 0, 0); 130179595Sbenno 131179595Sbennoint 132193847Smarcelarm_get_next_irq(int last __unused) 133179595Sbenno{ 134179595Sbenno int irq; 135179595Sbenno 136179595Sbenno if ((irq = pxa_icu_get_icip()) != 0) { 137179595Sbenno return (ffs(irq) - 1); 138179595Sbenno } 139179595Sbenno 140179595Sbenno return (pxa_gpio_get_next_irq()); 141179595Sbenno} 142179595Sbenno 143179595Sbennovoid 144179595Sbennoarm_mask_irq(uintptr_t nb) 145179595Sbenno{ 146179595Sbenno uint32_t mr; 147179595Sbenno 148179595Sbenno if (nb >= IRQ_GPIO0) { 149179595Sbenno pxa_gpio_mask_irq(nb); 150179595Sbenno return; 151179595Sbenno } 152179595Sbenno 153179595Sbenno mr = pxa_icu_get_icmr(); 154179595Sbenno mr &= ~(1 << nb); 155179595Sbenno pxa_icu_set_icmr(mr); 156179595Sbenno} 157179595Sbenno 158179595Sbennovoid 159179595Sbennoarm_unmask_irq(uintptr_t nb) 160179595Sbenno{ 161179595Sbenno uint32_t mr; 162179595Sbenno 163179595Sbenno if (nb >= IRQ_GPIO0) { 164179595Sbenno pxa_gpio_unmask_irq(nb); 165179595Sbenno return; 166179595Sbenno } 167179595Sbenno 168179595Sbenno mr = pxa_icu_get_icmr(); 169179595Sbenno mr |= (1 << nb); 170179595Sbenno pxa_icu_set_icmr(mr); 171179595Sbenno} 172179595Sbenno 173179595Sbennouint32_t 174179595Sbennopxa_icu_get_icip() 175179595Sbenno{ 176179595Sbenno 177179595Sbenno return (bus_space_read_4(pxa_icu_softc->pi_bst, 178179595Sbenno pxa_icu_softc->pi_bsh, ICU_IP)); 179179595Sbenno} 180179595Sbenno 181179595Sbennovoid 182179595Sbennopxa_icu_clear_icip(int irq) 183179595Sbenno{ 184179595Sbenno 185179595Sbenno bus_space_write_4(pxa_icu_softc->pi_bst, 186179595Sbenno pxa_icu_softc->pi_bsh, ICU_IP, (1 << irq)); 187179595Sbenno} 188179595Sbenno 189179595Sbennouint32_t 190179595Sbennopxa_icu_get_icfp() 191179595Sbenno{ 192179595Sbenno 193179595Sbenno return (bus_space_read_4(pxa_icu_softc->pi_bst, 194179595Sbenno pxa_icu_softc->pi_bsh, ICU_FP)); 195179595Sbenno} 196179595Sbenno 197179595Sbennovoid 198179595Sbennopxa_icu_clear_icfp(int irq) 199179595Sbenno{ 200179595Sbenno 201179595Sbenno bus_space_write_4(pxa_icu_softc->pi_bst, 202179595Sbenno pxa_icu_softc->pi_bsh, ICU_FP, (1 << irq)); 203179595Sbenno} 204179595Sbenno 205179595Sbennouint32_t 206179595Sbennopxa_icu_get_icmr() 207179595Sbenno{ 208179595Sbenno 209179595Sbenno return (bus_space_read_4(pxa_icu_softc->pi_bst, 210179595Sbenno pxa_icu_softc->pi_bsh, ICU_MR)); 211179595Sbenno} 212179595Sbenno 213179595Sbennovoid 214179595Sbennopxa_icu_set_icmr(uint32_t val) 215179595Sbenno{ 216179595Sbenno 217179595Sbenno bus_space_write_4(pxa_icu_softc->pi_bst, 218179595Sbenno pxa_icu_softc->pi_bsh, ICU_MR, val); 219179595Sbenno} 220179595Sbenno 221179595Sbennouint32_t 222179595Sbennopxa_icu_get_iclr() 223179595Sbenno{ 224179595Sbenno 225179595Sbenno return (bus_space_read_4(pxa_icu_softc->pi_bst, 226179595Sbenno pxa_icu_softc->pi_bsh, ICU_LR)); 227179595Sbenno} 228179595Sbenno 229179595Sbennovoid 230179595Sbennopxa_icu_set_iclr(uint32_t val) 231179595Sbenno{ 232179595Sbenno 233179595Sbenno bus_space_write_4(pxa_icu_softc->pi_bst, 234179595Sbenno pxa_icu_softc->pi_bsh, ICU_LR, val); 235179595Sbenno} 236179595Sbenno 237179595Sbennouint32_t 238179595Sbennopxa_icu_get_icpr() 239179595Sbenno{ 240179595Sbenno 241179595Sbenno return (bus_space_read_4(pxa_icu_softc->pi_bst, 242179595Sbenno pxa_icu_softc->pi_bsh, ICU_PR)); 243179595Sbenno} 244179595Sbenno 245179595Sbennovoid 246179595Sbennopxa_icu_idle_enable() 247179595Sbenno{ 248179595Sbenno 249179595Sbenno bus_space_write_4(pxa_icu_softc->pi_bst, 250179595Sbenno pxa_icu_softc->pi_bsh, ICU_CR, 0x0); 251179595Sbenno} 252179595Sbenno 253179595Sbennovoid 254179595Sbennopxa_icu_idle_disable() 255179595Sbenno{ 256179595Sbenno 257179595Sbenno bus_space_write_4(pxa_icu_softc->pi_bst, 258179595Sbenno pxa_icu_softc->pi_bsh, ICU_CR, 0x1); 259179595Sbenno} 260