1/*- 2 * Copyright (c) 2006 M. Warner Losh. 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. --- 10 unchanged lines hidden (view full) --- 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> |
27__FBSDID("$FreeBSD: head/sys/arm/at91/at91_pio.c 234281 2012-04-14 11:29:32Z marius $"); |
28 29#include <sys/param.h> 30#include <sys/systm.h> 31#include <sys/bus.h> 32#include <sys/conf.h> 33#include <sys/kernel.h> 34#include <sys/lock.h> 35#include <sys/mbuf.h> --- 11 unchanged lines hidden (view full) --- 47{ 48 device_t dev; /* Myself */ 49 void *intrhand; /* Interrupt handle */ 50 struct resource *irq_res; /* IRQ resource */ 51 struct resource *mem_res; /* Memory resource */ 52 struct mtx sc_mtx; /* basically a perimeter lock */ 53 struct cdev *cdev; 54 int flags; |
55#define OPENED 1 |
56}; 57 58static inline uint32_t 59RD4(struct at91_pio_softc *sc, bus_size_t off) 60{ |
61 |
62 return (bus_read_4(sc->mem_res, off)); 63} 64 65static inline void 66WR4(struct at91_pio_softc *sc, bus_size_t off, uint32_t val) 67{ |
68 |
69 bus_write_4(sc->mem_res, off, val); 70} 71 |
72#define AT91_PIO_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx) |
73#define AT91_PIO_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->sc_mtx) |
74#define AT91_PIO_LOCK_INIT(_sc) \ |
75 mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \ 76 "pio", MTX_SPIN) |
77#define AT91_PIO_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); 78#define AT91_PIO_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); 79#define AT91_PIO_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); 80#define CDEV2SOFTC(dev) ((dev)->si_drv1) |
81 82static devclass_t at91_pio_devclass; 83 84/* bus entry points */ 85 86static int at91_pio_probe(device_t dev); 87static int at91_pio_attach(device_t dev); 88static int at91_pio_detach(device_t dev); --- 40 unchanged lines hidden (view full) --- 129 } 130 device_set_desc(dev, name); 131 return (0); 132} 133 134static int 135at91_pio_attach(device_t dev) 136{ |
137 struct at91_pio_softc *sc; |
138 int err; 139 |
140 sc = device_get_softc(dev); |
141 sc->dev = dev; 142 err = at91_pio_activate(dev); 143 if (err) 144 goto out; 145 146 device_printf(dev, "ABSR: %#x OSR: %#x PSR:%#x ODSR: %#x\n", 147 RD4(sc, PIO_ABSR), RD4(sc, PIO_OSR), RD4(sc, PIO_PSR), 148 RD4(sc, PIO_ODSR)); 149 AT91_PIO_LOCK_INIT(sc); 150 151 /* |
152 * Activate the interrupt, but disable all interrupts in the hardware. |
153 */ 154 WR4(sc, PIO_IDR, 0xffffffff); 155 err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC, 156 at91_pio_intr, NULL, sc, &sc->intrhand); 157 if (err) { 158 AT91_PIO_LOCK_DESTROY(sc); 159 goto out; 160 } --- 8 unchanged lines hidden (view full) --- 169 if (err) 170 at91_pio_deactivate(dev); 171 return (err); 172} 173 174static int 175at91_pio_detach(device_t dev) 176{ |
177 |
178 return (EBUSY); /* XXX */ 179} 180 181static int 182at91_pio_activate(device_t dev) 183{ 184 struct at91_pio_softc *sc; 185 int rid; --- 28 unchanged lines hidden (view full) --- 214 if (sc->mem_res) 215 bus_release_resource(dev, SYS_RES_IOPORT, 216 rman_get_rid(sc->mem_res), sc->mem_res); 217 sc->mem_res = 0; 218 if (sc->irq_res) 219 bus_release_resource(dev, SYS_RES_IRQ, 220 rman_get_rid(sc->irq_res), sc->irq_res); 221 sc->irq_res = 0; |
222} 223 224static int 225at91_pio_intr(void *xsc) 226{ 227 struct at91_pio_softc *sc = xsc; 228#if 0 229 uint32_t status; 230 |
231 /* Reading the status also clears the interrupt. */ |
232 status = RD4(sc, PIO_SR); 233 if (status == 0) 234 return; 235 AT91_PIO_LOCK(sc); 236 AT91_PIO_UNLOCK(sc); 237#endif 238 wakeup(sc); 239 return (FILTER_HANDLED); 240} 241 |
242static int |
243at91_pio_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 244{ 245 struct at91_pio_softc *sc; 246 247 sc = CDEV2SOFTC(dev); 248 AT91_PIO_LOCK(sc); 249 if (!(sc->flags & OPENED)) { 250 sc->flags |= OPENED; 251#if 0 |
252 /* Enable interrupts. */ |
253#endif 254 } 255 AT91_PIO_UNLOCK(sc); |
256 return (0); |
257} 258 259static int 260at91_pio_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 261{ 262 struct at91_pio_softc *sc; 263 264 sc = CDEV2SOFTC(dev); 265 AT91_PIO_LOCK(sc); 266 sc->flags &= ~OPENED; 267#if 0 |
268 /* Disable interrupts. */ |
269#endif 270 AT91_PIO_UNLOCK(sc); 271 return (0); 272} 273 274static int 275at91_pio_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 276 struct thread *td) 277{ |
278 |
279 return (ENXIO); 280} 281 282/* 283 * The following functions are called early in the boot process, so 284 * don't use bus_space, as that isn't yet available when we need to use 285 * them. 286 */ |
287 |
288void 289at91_pio_use_periph_a(uint32_t pio, uint32_t periph_a_mask, int use_pullup) 290{ 291 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); 292 293 PIO[PIO_ASR / 4] = periph_a_mask; 294 PIO[PIO_PDR / 4] = periph_a_mask; 295 if (use_pullup) --- 73 unchanged lines hidden (view full) --- 369at91_pio_gpio_set_deglitch(uint32_t pio, uint32_t data_mask, int use_deglitch) 370{ 371 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); 372 373 if (use_deglitch) 374 PIO[PIO_IFER / 4] = data_mask; 375 else 376 PIO[PIO_IFDR / 4] = data_mask; |
377} 378 379void |
380at91_pio_gpio_set_interrupt(uint32_t pio, uint32_t data_mask, |
381 int enable_interrupt) 382{ 383 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); 384 385 if (enable_interrupt) 386 PIO[PIO_IER / 4] = data_mask; 387 else 388 PIO[PIO_IDR / 4] = data_mask; |
389} 390 391uint32_t 392at91_pio_gpio_clear_interrupt(uint32_t pio) 393{ 394 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); |
395 396 /* Reading this register will clear the interrupts. */ |
397 return (PIO[PIO_ISR / 4]); 398} 399 400static device_method_t at91_pio_methods[] = { 401 /* Device interface */ 402 DEVMETHOD(device_probe, at91_pio_probe), 403 DEVMETHOD(device_attach, at91_pio_attach), 404 DEVMETHOD(device_detach, at91_pio_detach), 405 |
406 DEVMETHOD_END |
407}; 408 409static driver_t at91_pio_driver = { 410 "at91_pio", 411 at91_pio_methods, 412 sizeof(struct at91_pio_softc), 413}; 414 |
415DRIVER_MODULE(at91_pio, atmelarm, at91_pio_driver, at91_pio_devclass, NULL, 416 NULL); |