at91_pio.c revision 259065
1/*- 2 * Copyright (c) 2006 M. Warner Losh. All rights reserved. 3 * Copyright (C) 2012 Ian Lepore. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: releng/10.0/sys/arm/at91/at91_pio.c 249232 2013-04-07 13:03:57Z hselasky $"); 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/bus.h> 33#include <sys/conf.h> 34#include <sys/kernel.h> 35#include <sys/lock.h> 36#include <sys/mbuf.h> 37#include <sys/malloc.h> 38#include <sys/module.h> 39#include <sys/poll.h> 40#include <sys/rman.h> 41#include <sys/selinfo.h> 42#include <sys/sx.h> 43#include <sys/uio.h> 44#include <machine/at91_gpio.h> 45#include <machine/bus.h> 46 47#include <arm/at91/at91reg.h> 48#include <arm/at91/at91_pioreg.h> 49#include <arm/at91/at91_piovar.h> 50 51#define MAX_CHANGE 64 52 53struct at91_pio_softc 54{ 55 device_t dev; /* Myself */ 56 void *intrhand; /* Interrupt handle */ 57 struct resource *irq_res; /* IRQ resource */ 58 struct resource *mem_res; /* Memory resource */ 59 struct sx sc_mtx; /* basically a perimeter lock */ 60 struct cdev *cdev; 61 struct selinfo selp; 62 int buflen; 63 uint8_t buf[MAX_CHANGE]; 64 int flags; 65#define OPENED 1 66}; 67 68static inline uint32_t 69RD4(struct at91_pio_softc *sc, bus_size_t off) 70{ 71 72 return (bus_read_4(sc->mem_res, off)); 73} 74 75static inline void 76WR4(struct at91_pio_softc *sc, bus_size_t off, uint32_t val) 77{ 78 79 bus_write_4(sc->mem_res, off, val); 80} 81 82#define AT91_PIO_LOCK(_sc) sx_xlock(&(_sc)->sc_mtx) 83#define AT91_PIO_UNLOCK(_sc) sx_xunlock(&(_sc)->sc_mtx) 84#define AT91_PIO_LOCK_INIT(_sc) \ 85 sx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev)) 86#define AT91_PIO_LOCK_DESTROY(_sc) sx_destroy(&_sc->sc_mtx); 87#define AT91_PIO_ASSERT_LOCKED(_sc) sx_assert(&_sc->sc_mtx, SA_XLOCKED); 88#define AT91_PIO_ASSERT_UNLOCKED(_sc) sx_assert(&_sc->sc_mtx, SA_UNLOCKED); 89#define CDEV2SOFTC(dev) ((dev)->si_drv1) 90 91static devclass_t at91_pio_devclass; 92 93/* bus entry points */ 94 95static int at91_pio_probe(device_t dev); 96static int at91_pio_attach(device_t dev); 97static int at91_pio_detach(device_t dev); 98static void at91_pio_intr(void *); 99 100/* helper routines */ 101static int at91_pio_activate(device_t dev); 102static void at91_pio_deactivate(device_t dev); 103 104/* cdev routines */ 105static d_open_t at91_pio_open; 106static d_close_t at91_pio_close; 107static d_read_t at91_pio_read; 108static d_poll_t at91_pio_poll; 109static d_ioctl_t at91_pio_ioctl; 110 111static struct cdevsw at91_pio_cdevsw = 112{ 113 .d_version = D_VERSION, 114 .d_open = at91_pio_open, 115 .d_close = at91_pio_close, 116 .d_read = at91_pio_read, 117 .d_poll = at91_pio_poll, 118 .d_ioctl = at91_pio_ioctl 119}; 120 121static int 122at91_pio_probe(device_t dev) 123{ 124 const char *name; 125 126 switch (device_get_unit(dev)) { 127 case 0: 128 name = "PIOA"; 129 break; 130 case 1: 131 name = "PIOB"; 132 break; 133 case 2: 134 name = "PIOC"; 135 break; 136 case 3: 137 name = "PIOD"; 138 break; 139 default: 140 name = "PIO"; 141 break; 142 } 143 device_set_desc(dev, name); 144 return (0); 145} 146 147static int 148at91_pio_attach(device_t dev) 149{ 150 struct at91_pio_softc *sc; 151 int err; 152 153 sc = device_get_softc(dev); 154 sc->dev = dev; 155 err = at91_pio_activate(dev); 156 if (err) 157 goto out; 158 159 if (bootverbose) 160 device_printf(dev, "ABSR: %#x OSR: %#x PSR:%#x ODSR: %#x\n", 161 RD4(sc, PIO_ABSR), RD4(sc, PIO_OSR), RD4(sc, PIO_PSR), 162 RD4(sc, PIO_ODSR)); 163 AT91_PIO_LOCK_INIT(sc); 164 165 /* 166 * Activate the interrupt, but disable all interrupts in the hardware. 167 */ 168 WR4(sc, PIO_IDR, 0xffffffff); 169 err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC, 170 NULL, at91_pio_intr, sc, &sc->intrhand); 171 if (err) { 172 AT91_PIO_LOCK_DESTROY(sc); 173 goto out; 174 } 175 sc->cdev = make_dev(&at91_pio_cdevsw, device_get_unit(dev), UID_ROOT, 176 GID_WHEEL, 0600, "pio%d", device_get_unit(dev)); 177 if (sc->cdev == NULL) { 178 err = ENOMEM; 179 goto out; 180 } 181 sc->cdev->si_drv1 = sc; 182out: 183 if (err) 184 at91_pio_deactivate(dev); 185 return (err); 186} 187 188static int 189at91_pio_detach(device_t dev) 190{ 191 192 return (EBUSY); /* XXX */ 193} 194 195static int 196at91_pio_activate(device_t dev) 197{ 198 struct at91_pio_softc *sc; 199 int rid; 200 201 sc = device_get_softc(dev); 202 rid = 0; 203 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 204 RF_ACTIVE); 205 if (sc->mem_res == NULL) 206 goto errout; 207 rid = 0; 208 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 209 RF_ACTIVE | RF_SHAREABLE); 210 if (sc->irq_res == NULL) 211 goto errout; 212 return (0); 213errout: 214 at91_pio_deactivate(dev); 215 return (ENOMEM); 216} 217 218static void 219at91_pio_deactivate(device_t dev) 220{ 221 struct at91_pio_softc *sc; 222 223 sc = device_get_softc(dev); 224 if (sc->intrhand) 225 bus_teardown_intr(dev, sc->irq_res, sc->intrhand); 226 sc->intrhand = 0; 227 bus_generic_detach(sc->dev); 228 if (sc->mem_res) 229 bus_release_resource(dev, SYS_RES_MEMORY, 230 rman_get_rid(sc->mem_res), sc->mem_res); 231 sc->mem_res = 0; 232 if (sc->irq_res) 233 bus_release_resource(dev, SYS_RES_IRQ, 234 rman_get_rid(sc->irq_res), sc->irq_res); 235 sc->irq_res = 0; 236} 237 238static void 239at91_pio_intr(void *xsc) 240{ 241 struct at91_pio_softc *sc = xsc; 242 uint32_t status; 243 int i; 244 245 /* Reading the status also clears the interrupt. */ 246 status = RD4(sc, PIO_ISR) & RD4(sc, PIO_IMR); 247 if (status != 0) { 248 AT91_PIO_LOCK(sc); 249 for (i = 0; status != 0 && sc->buflen < MAX_CHANGE; ++i) { 250 if (status & 1) 251 sc->buf[sc->buflen++] = (uint8_t)i; 252 status >>= 1; 253 } 254 AT91_PIO_UNLOCK(sc); 255 wakeup(sc); 256 selwakeup(&sc->selp); 257 } 258} 259 260static int 261at91_pio_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 262{ 263 struct at91_pio_softc *sc; 264 265 sc = CDEV2SOFTC(dev); 266 AT91_PIO_LOCK(sc); 267 if (!(sc->flags & OPENED)) { 268 sc->flags |= OPENED; 269 } 270 AT91_PIO_UNLOCK(sc); 271 return (0); 272} 273 274static int 275at91_pio_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 276{ 277 struct at91_pio_softc *sc; 278 279 sc = CDEV2SOFTC(dev); 280 AT91_PIO_LOCK(sc); 281 sc->flags &= ~OPENED; 282 AT91_PIO_UNLOCK(sc); 283 return (0); 284} 285 286static int 287at91_pio_poll(struct cdev *dev, int events, struct thread *td) 288{ 289 struct at91_pio_softc *sc; 290 int revents = 0; 291 292 sc = CDEV2SOFTC(dev); 293 AT91_PIO_LOCK(sc); 294 if (events & (POLLIN | POLLRDNORM)) { 295 if (sc->buflen != 0) 296 revents |= events & (POLLIN | POLLRDNORM); 297 else 298 selrecord(td, &sc->selp); 299 } 300 AT91_PIO_UNLOCK(sc); 301 302 return (revents); 303} 304 305static int 306at91_pio_read(struct cdev *dev, struct uio *uio, int flag) 307{ 308 struct at91_pio_softc *sc; 309 int err, ret, len; 310 311 sc = CDEV2SOFTC(dev); 312 AT91_PIO_LOCK(sc); 313 err = 0; 314 ret = 0; 315 while (uio->uio_resid) { 316 while (sc->buflen == 0 && err == 0) 317 err = msleep(sc, &sc->sc_mtx, PCATCH | PZERO, "prd", 0); 318 if (err != 0) 319 break; 320 len = MIN(sc->buflen, uio->uio_resid); 321 err = uiomove(sc->buf, len, uio); 322 if (err != 0) 323 break; 324 /* 325 * If we read the whole thing no datacopy is needed, 326 * otherwise we move the data down. 327 */ 328 ret += len; 329 if (sc->buflen == len) 330 sc->buflen = 0; 331 else { 332 bcopy(sc->buf + len, sc->buf, sc->buflen - len); 333 sc->buflen -= len; 334 } 335 /* If there's no data left, end the read. */ 336 if (sc->buflen == 0) 337 break; 338 } 339 AT91_PIO_UNLOCK(sc); 340 return (err); 341} 342 343static void 344at91_pio_bang32(struct at91_pio_softc *sc, uint32_t bits, uint32_t datapin, 345 uint32_t clockpin) 346{ 347 int i; 348 349 for (i = 0; i < 32; i++) { 350 if (bits & 0x80000000) 351 WR4(sc, PIO_SODR, datapin); 352 else 353 WR4(sc, PIO_CODR, datapin); 354 bits <<= 1; 355 WR4(sc, PIO_CODR, clockpin); 356 WR4(sc, PIO_SODR, clockpin); 357 } 358} 359 360static void 361at91_pio_bang(struct at91_pio_softc *sc, uint8_t bits, uint32_t bitcount, 362 uint32_t datapin, uint32_t clockpin) 363{ 364 int i; 365 366 for (i = 0; i < bitcount; i++) { 367 if (bits & 0x80) 368 WR4(sc, PIO_SODR, datapin); 369 else 370 WR4(sc, PIO_CODR, datapin); 371 bits <<= 1; 372 WR4(sc, PIO_CODR, clockpin); 373 WR4(sc, PIO_SODR, clockpin); 374 } 375} 376 377static int 378at91_pio_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 379 struct thread *td) 380{ 381 struct at91_pio_softc *sc; 382 struct at91_gpio_cfg *cfg; 383 struct at91_gpio_info *info; 384 struct at91_gpio_bang *bang; 385 struct at91_gpio_bang_many *bangmany; 386 uint32_t i, num; 387 uint8_t many[1024], *walker; 388 int err; 389 int bitcount; 390 391 sc = CDEV2SOFTC(dev); 392 switch(cmd) { 393 case AT91_GPIO_SET: /* turn bits on */ 394 WR4(sc, PIO_SODR, *(uint32_t *)data); 395 return (0); 396 case AT91_GPIO_CLR: /* turn bits off */ 397 WR4(sc, PIO_CODR, *(uint32_t *)data); 398 return (0); 399 case AT91_GPIO_READ: /* Get the status of input bits */ 400 *(uint32_t *)data = RD4(sc, PIO_PDSR); 401 return (0); 402 case AT91_GPIO_CFG: /* Configure AT91_GPIO pins */ 403 cfg = (struct at91_gpio_cfg *)data; 404 if (cfg->cfgmask & AT91_GPIO_CFG_INPUT) { 405 WR4(sc, PIO_OER, cfg->iomask & ~cfg->input); 406 WR4(sc, PIO_ODR, cfg->iomask & cfg->input); 407 } 408 if (cfg->cfgmask & AT91_GPIO_CFG_HI_Z) { 409 WR4(sc, PIO_MDDR, cfg->iomask & ~cfg->hi_z); 410 WR4(sc, PIO_MDER, cfg->iomask & cfg->hi_z); 411 } 412 if (cfg->cfgmask & AT91_GPIO_CFG_PULLUP) { 413 WR4(sc, PIO_PUDR, cfg->iomask & ~cfg->pullup); 414 WR4(sc, PIO_PUER, cfg->iomask & cfg->pullup); 415 } 416 if (cfg->cfgmask & AT91_GPIO_CFG_GLITCH) { 417 WR4(sc, PIO_IFDR, cfg->iomask & ~cfg->glitch); 418 WR4(sc, PIO_IFER, cfg->iomask & cfg->glitch); 419 } 420 if (cfg->cfgmask & AT91_GPIO_CFG_GPIO) { 421 WR4(sc, PIO_PDR, cfg->iomask & ~cfg->gpio); 422 WR4(sc, PIO_PER, cfg->iomask & cfg->gpio); 423 } 424 if (cfg->cfgmask & AT91_GPIO_CFG_PERIPH) { 425 WR4(sc, PIO_ASR, cfg->iomask & ~cfg->periph); 426 WR4(sc, PIO_BSR, cfg->iomask & cfg->periph); 427 } 428 if (cfg->cfgmask & AT91_GPIO_CFG_INTR) { 429 WR4(sc, PIO_IDR, cfg->iomask & ~cfg->intr); 430 WR4(sc, PIO_IER, cfg->iomask & cfg->intr); 431 } 432 return (0); 433 case AT91_GPIO_BANG: 434 bang = (struct at91_gpio_bang *)data; 435 at91_pio_bang32(sc, bang->bits, bang->datapin, bang->clockpin); 436 return (0); 437 case AT91_GPIO_BANG_MANY: 438 bangmany = (struct at91_gpio_bang_many *)data; 439 walker = (uint8_t *)bangmany->bits; 440 bitcount = bangmany->numbits; 441 while (bitcount > 0) { 442 num = MIN((bitcount + 7) / 8, sizeof(many)); 443 err = copyin(walker, many, num); 444 if (err) 445 return err; 446 for (i = 0; i < num && bitcount > 0; i++, bitcount -= 8) 447 if (bitcount >= 8) 448 at91_pio_bang(sc, many[i], 8, bangmany->datapin, bangmany->clockpin); 449 else 450 at91_pio_bang(sc, many[i], bitcount, bangmany->datapin, bangmany->clockpin); 451 walker += num; 452 } 453 return (0); 454 case AT91_GPIO_INFO: /* Learn about this device's AT91_GPIO bits */ 455 info = (struct at91_gpio_info *)data; 456 info->output_status = RD4(sc, PIO_ODSR); 457 info->input_status = RD4(sc, PIO_OSR); 458 info->highz_status = RD4(sc, PIO_MDSR); 459 info->pullup_status = RD4(sc, PIO_PUSR); 460 info->glitch_status = RD4(sc, PIO_IFSR); 461 info->enabled_status = RD4(sc, PIO_PSR); 462 info->periph_status = RD4(sc, PIO_ABSR); 463 info->intr_status = RD4(sc, PIO_IMR); 464 memset(info->extra_status, 0, sizeof(info->extra_status)); 465 return (0); 466 } 467 return (ENOTTY); 468} 469 470/* 471 * The following functions are called early in the boot process, so 472 * don't use bus_space, as that isn't yet available when we need to use 473 * them. 474 */ 475 476void 477at91_pio_use_periph_a(uint32_t pio, uint32_t periph_a_mask, int use_pullup) 478{ 479 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); 480 481 PIO[PIO_ASR / 4] = periph_a_mask; 482 PIO[PIO_PDR / 4] = periph_a_mask; 483 if (use_pullup) 484 PIO[PIO_PUER / 4] = periph_a_mask; 485 else 486 PIO[PIO_PUDR / 4] = periph_a_mask; 487} 488 489void 490at91_pio_use_periph_b(uint32_t pio, uint32_t periph_b_mask, int use_pullup) 491{ 492 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); 493 494 PIO[PIO_BSR / 4] = periph_b_mask; 495 PIO[PIO_PDR / 4] = periph_b_mask; 496 if (use_pullup) 497 PIO[PIO_PUER / 4] = periph_b_mask; 498 else 499 PIO[PIO_PUDR / 4] = periph_b_mask; 500} 501 502void 503at91_pio_use_gpio(uint32_t pio, uint32_t gpio_mask) 504{ 505 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); 506 507 PIO[PIO_PER / 4] = gpio_mask; 508} 509 510void 511at91_pio_gpio_input(uint32_t pio, uint32_t input_enable_mask) 512{ 513 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); 514 515 PIO[PIO_ODR / 4] = input_enable_mask; 516} 517 518void 519at91_pio_gpio_output(uint32_t pio, uint32_t output_enable_mask, int use_pullup) 520{ 521 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); 522 523 PIO[PIO_OER / 4] = output_enable_mask; 524 if (use_pullup) 525 PIO[PIO_PUER / 4] = output_enable_mask; 526 else 527 PIO[PIO_PUDR / 4] = output_enable_mask; 528} 529 530void 531at91_pio_gpio_high_z(uint32_t pio, uint32_t high_z_mask, int enable) 532{ 533 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); 534 535 if (enable) 536 PIO[PIO_MDER / 4] = high_z_mask; 537 else 538 PIO[PIO_MDDR / 4] = high_z_mask; 539} 540 541void 542at91_pio_gpio_set(uint32_t pio, uint32_t data_mask) 543{ 544 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); 545 546 PIO[PIO_SODR / 4] = data_mask; 547} 548 549void 550at91_pio_gpio_clear(uint32_t pio, uint32_t data_mask) 551{ 552 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); 553 554 PIO[PIO_CODR / 4] = data_mask; 555} 556 557uint32_t 558at91_pio_gpio_get(uint32_t pio, uint32_t data_mask) 559{ 560 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); 561 562 return (PIO[PIO_PDSR / 4] & data_mask); 563} 564 565void 566at91_pio_gpio_set_deglitch(uint32_t pio, uint32_t data_mask, int use_deglitch) 567{ 568 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); 569 570 if (use_deglitch) 571 PIO[PIO_IFER / 4] = data_mask; 572 else 573 PIO[PIO_IFDR / 4] = data_mask; 574} 575 576void 577at91_pio_gpio_set_interrupt(uint32_t pio, uint32_t data_mask, 578 int enable_interrupt) 579{ 580 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); 581 582 if (enable_interrupt) 583 PIO[PIO_IER / 4] = data_mask; 584 else 585 PIO[PIO_IDR / 4] = data_mask; 586} 587 588uint32_t 589at91_pio_gpio_clear_interrupt(uint32_t pio) 590{ 591 uint32_t *PIO = (uint32_t *)(AT91_BASE + pio); 592 593 /* Reading this register will clear the interrupts. */ 594 return (PIO[PIO_ISR / 4]); 595} 596 597static device_method_t at91_pio_methods[] = { 598 /* Device interface */ 599 DEVMETHOD(device_probe, at91_pio_probe), 600 DEVMETHOD(device_attach, at91_pio_attach), 601 DEVMETHOD(device_detach, at91_pio_detach), 602 603 DEVMETHOD_END 604}; 605 606static driver_t at91_pio_driver = { 607 "at91_pio", 608 at91_pio_methods, 609 sizeof(struct at91_pio_softc), 610}; 611 612DRIVER_MODULE(at91_pio, atmelarm, at91_pio_driver, at91_pio_devclass, NULL, 613 NULL); 614