Annotation of src/sys/arch/arm/imx/imxuart.c, Revision 1.1.24.1
1.1.24.1! yamt 1: /* $Id$ */
! 2: #include <sys/types.h>
! 3: #include <sys/systm.h>
! 4: #include <sys/device.h>
! 5: #include <sys/conf.h>
! 6:
! 7: #include <arm/armreg.h>
! 8:
! 9: #include <sys/tty.h>
! 10: #include <sys/termios.h>
! 11: #include <dev/cons.h>
! 12:
! 13: #include <machine/bus.h>
! 14: #include <arm/imx/imx31var.h>
! 15: #include <arm/imx/imxuartreg.h>
! 16: #include <arm/imx/imxuartvar.h>
! 17: #include <evbarm/imx31/imx31lk_reg.h>
! 18:
! 19: #define IMXUART_UNIT_MASK 0x7ffff
! 20: #define IMXUART_DIALOUT_MASK 0x80000
! 21:
! 22: #define IMXUART_UNIT(dev) (minor(dev) & IMXUART_UNIT_MASK)
! 23: #define IMXUART_DIALOUT(dev) (minor(dev) & IMXUART_DIALOUT_MASK)
! 24:
! 25:
! 26:
! 27: #define __TRACE imxuart_puts(&imxuart_softc, __FUNCTION__ )
! 28:
! 29: extern struct bus_space imx31_bs_tag;
! 30:
! 31: imxuart_softc_t imxuart_softc = { { 0, }, };
! 32:
! 33: uint32_t imxuart_snapshot_data[32];
! 34: const char *imxuart_test_string =
! 35: "0123456789012345678901234567890123456789\r\n";
! 36:
! 37:
! 38: cons_decl(imxuart);
! 39: static struct consdev imxuartcntab = cons_init(imxuart);
! 40:
! 41: #ifdef NOTYET
! 42: dev_type_open(imxuartopen);
! 43: dev_type_close(imxuartclose);
! 44: dev_type_read(imxuartread);
! 45: dev_type_write(imxuartwrite);
! 46: dev_type_ioctl(imxuartioctl);
! 47: dev_type_stop(imxuartstop);
! 48: dev_type_tty(imxuarttty);
! 49: dev_type_poll(imxuartpoll);
! 50: const struct cdevsw imxuart_cdevsw = {
! 51: imxuartopen, imxuartclose, imxuartread, imxuartwrite,
! 52: imxuartioctl, imxuartstop, imxuarttty, imxuartpoll,
! 53: nommap, ttykqfilter, D_TTY
! 54: };
! 55: #else
! 56: const struct cdevsw imxuart_cdevsw = {
! 57: nullopen, nullclose, nullread, nullwrite,
! 58: nullioctl, nullstop, notty, nullpoll,
! 59: nommap, nullkqfilter, D_TTY
! 60: };
! 61: #endif
! 62:
! 63:
! 64: int imxuart_cnattach(bus_space_tag_t, bus_addr_t, int, int, int, tcflag_t);
! 65: int imxuart_puts(imxuart_softc_t *, const char *);
! 66: int imxuart_putchar(imxuart_softc_t *, int);
! 67: int imxuart_getchar(imxuart_softc_t *);
! 68:
! 69: static int imxuart_urxd_brk(void);
! 70: static void imxuart_urxd_err(imxuart_softc_t *, uint32_t);
! 71:
! 72: static int imxuart_match(struct device *, struct cfdata *, void *);
! 73: static void imxuart_attach(struct device *, struct device *, void *);
! 74:
! 75: static void imxuart_start(struct tty *);
! 76: static int imxuart_param(struct tty *, struct termios *);
! 77: static void imxuart_shutdownhook(void *arg);
! 78:
! 79: CFATTACH_DECL(imxuart, sizeof(struct imxuart_softc),
! 80: imxuart_match, imxuart_attach, NULL, NULL);
! 81:
! 82:
! 83: /*
! 84: * disable the specified IMX UART interrupt in softc
! 85: * return -1 on error
! 86: * else return previous enabled state
! 87: */
! 88: static __inline int
! 89: imxuart_intrspec_dis(imxuart_softc_t *sc, imxuart_intrix_t ix)
! 90: {
! 91: const imxuart_intrspec_t *spec = &imxuart_intrspec_tab[ix];
! 92: uint32_t v;
! 93: uint32_t b;
! 94: const uint32_t syncbit = 1 << 31;
! 95: uint n;
! 96:
! 97: if (ix >= IMXUART_INTRSPEC_TAB_SZ)
! 98: return -1;
! 99:
! 100: v = (1 << ix);
! 101: if ((sc->sc_intrspec_enb & v) == 0)
! 102: return 0;
! 103: sc->sc_intrspec_enb &= ~v;
! 104:
! 105: n = spec->enb_reg;
! 106: b = spec->enb_bit;
! 107: v = sc->sc_ucr[n];
! 108: v &= ~b;
! 109: v |= syncbit;
! 110: sc->sc_ucr[n] = v;
! 111:
! 112: n = spec->flg_reg;
! 113: b = spec->flg_bit;
! 114: v = sc->sc_usr[n];
! 115: v &= ~b;
! 116: v |= syncbit;
! 117: sc->sc_usr[n] = v;
! 118:
! 119: return 1;
! 120: }
! 121:
! 122: /*
! 123: * enable the specified IMX UART interrupt in softc
! 124: * return -1 on error
! 125: * else return previous enabled state
! 126: */
! 127: static __inline int
! 128: imxuart_intrspec_enb(imxuart_softc_t *sc, imxuart_intrix_t ix)
! 129: {
! 130: const imxuart_intrspec_t *spec = &imxuart_intrspec_tab[ix];
! 131: uint32_t v;
! 132: uint n;
! 133: const uint32_t syncbit = 1 << 31;
! 134:
! 135: if (ix >= IMXUART_INTRSPEC_TAB_SZ)
! 136: return -1;
! 137:
! 138: v = (1 << ix);
! 139: if ((sc->sc_intrspec_enb & v) != 0)
! 140: return 1;
! 141: sc->sc_intrspec_enb |= v;
! 142:
! 143:
! 144: n = spec->enb_reg;
! 145: v = spec->enb_bit;
! 146: v |= syncbit;
! 147: sc->sc_ucr[n] |= v;
! 148:
! 149: n = spec->flg_reg;
! 150: v = spec->flg_bit;
! 151: v |= syncbit;
! 152: sc->sc_usr[n] |= v;
! 153:
! 154: return 0;
! 155: }
! 156:
! 157: /*
! 158: * sync softc interrupt spec to UART Control regs
! 159: */
! 160: static __inline void
! 161: imxuart_intrspec_sync(imxuart_softc_t *sc)
! 162: {
! 163: int i;
! 164: uint32_t r;
! 165: uint32_t v;
! 166: const uint32_t syncbit = 1 << 31;
! 167: const uint32_t mask[4] = {
! 168: IMXUART_INTRS_UCR1,
! 169: IMXUART_INTRS_UCR2,
! 170: IMXUART_INTRS_UCR3,
! 171: IMXUART_INTRS_UCR4
! 172: };
! 173:
! 174: for (i=0; i < 4; i++) {
! 175: v = sc->sc_ucr[i];
! 176: if (v & syncbit) {
! 177: v &= ~syncbit;
! 178: sc->sc_ucr[i] = v;
! 179: r = bus_space_read_4(sc->sc_bt, sc->sc_bh, IMX_UCRn(i));
! 180: r &= ~mask[i];
! 181: r |= v;
! 182: bus_space_write_4(sc->sc_bt, sc->sc_bh, IMX_UCRn(i), r);
! 183: }
! 184: }
! 185: }
! 186:
! 187:
! 188: int
! 189: imxuart_init(imxuart_softc_t *sc, uint bh)
! 190: {
! 191: if (sc == 0)
! 192: sc = &imxuart_softc;
! 193: sc->sc_init_cnt++;
! 194: cn_tab = &imxuartcntab;
! 195: sc->sc_bt = &imx31_bs_tag;
! 196: sc->sc_bh = bh;
! 197:
! 198: memset(&sc->sc_errors, 0, sizeof(sc->sc_errors));
! 199:
! 200: return 0;
! 201: }
! 202:
! 203: int
! 204: imxuart_puts(imxuart_softc_t *sc, const char *s)
! 205: {
! 206: char c;
! 207: int err = -2;
! 208:
! 209: for(;;) {
! 210: c = *s++;
! 211: if (c == '\0')
! 212: break;
! 213: err = imxuart_putchar(sc, c);
! 214: }
! 215: return err;
! 216: }
! 217:
! 218: int
! 219: imxuart_putchar(imxuart_softc_t *sc, int c)
! 220: {
! 221: uint32_t r;
! 222:
! 223: for (;;) {
! 224: r = bus_space_read_4(sc->sc_bt, sc->sc_bh, IMX_UTS);
! 225: if ((r & IMX_UTS_TXFUL) == 0)
! 226: break;
! 227: }
! 228:
! 229: r = (uint32_t)c & IMX_UTXD_TX_DATA;
! 230: bus_space_write_4(sc->sc_bt, sc->sc_bh, IMX_UTXD, r);
! 231:
! 232: return 0;
! 233: }
! 234:
! 235: int
! 236: imxuart_getchar(imxuart_softc_t *sc)
! 237: {
! 238: uint32_t r;
! 239: int c;
! 240:
! 241: for(;;) {
! 242: r = bus_space_read_4(sc->sc_bt, sc->sc_bh, IMX_URXD);
! 243: if (r & IMX_URXD_ERR) {
! 244: imxuart_urxd_err(sc, r);
! 245: continue;
! 246: }
! 247: if (r & IMX_URXD_CHARDY) {
! 248: c = (int)(r & IMX_URXD_RX_DATA);
! 249: break;
! 250: }
! 251: }
! 252:
! 253: return c;
! 254: }
! 255:
! 256: static int
! 257: imxuart_urxd_brk(void)
! 258: {
! 259: #ifdef DDB
! 260: if (cn_tab == &imxuartcntab) {
! 261: Debugger();
! 262: return 0;
! 263: }
! 264: #endif
! 265: return 1;
! 266: }
! 267:
! 268: static void
! 269: imxuart_urxd_err(imxuart_softc_t *sc, uint32_t r)
! 270: {
! 271: if (r & IMX_URXD_BRK)
! 272: if (imxuart_urxd_brk() == 0)
! 273: return;
! 274:
! 275: sc->sc_errors.err++;
! 276: if (r & IMX_URXD_BRK)
! 277: sc->sc_errors.brk++;
! 278: if (r & IMX_URXD_PRERR)
! 279: sc->sc_errors.prerr++;
! 280: if (r & IMX_URXD_FRMERR)
! 281: sc->sc_errors.frmerr++;
! 282: if (r & IMX_URXD_OVRRUN)
! 283: sc->sc_errors.ovrrun++;
! 284: }
! 285:
! 286: static int
! 287: imxuart_snapshot(imxuart_softc_t *sc, uint32_t *p)
! 288: {
! 289: int i;
! 290: const uint r[] = { IMX_URXD, IMX_UTXD, IMX_UCR1, IMX_UCR2,
! 291: IMX_UCR3, IMX_UCR4, IMX_UFCR, IMX_USR1,
! 292: IMX_USR2, IMX_UESC, IMX_UTIM, IMX_UBIR,
! 293: IMX_UBMR, IMX_UBRC, IMX_ONEMS, IMX_UTS };
! 294:
! 295: for (i=0; i < ((sizeof(r)/sizeof(r[0]))); i++) {
! 296: *p++ = sc->sc_bh + r[i];
! 297: *p++ = bus_space_read_4(sc->sc_bt, sc->sc_bh, r[i]);
! 298: }
! 299: return 0;
! 300: }
! 301:
! 302: int
! 303: imxuart_test(void)
! 304: {
! 305: imxuart_softc_t *sc = &imxuart_softc;
! 306: int n;
! 307: int err;
! 308:
! 309: err = imxuart_init(sc, 1);
! 310: if (err != 0)
! 311: return err;
! 312:
! 313: if (0) {
! 314: extern u_int cpufunc_id(void);
! 315: err = cpufunc_id();
! 316: return err;
! 317: }
! 318:
! 319: #if 0
! 320: err = imxuart_snapshot(sc, imxuart_snapshot_data);
! 321: if (err != 0)
! 322: return err;
! 323: #endif
! 324:
! 325:
! 326: err = imxuart_putchar(sc, 'x');
! 327: if (err != 0)
! 328: return err;
! 329:
! 330: for (n=100; n--; ) {
! 331: err = imxuart_puts(sc, imxuart_test_string);
! 332: if (err != 0)
! 333: break;
! 334: }
! 335:
! 336: err = imxuart_snapshot(sc, imxuart_snapshot_data);
! 337: if (err != 0)
! 338: return err;
! 339:
! 340: return err;
! 341: }
! 342:
! 343: static int
! 344: imxuart_match(struct device *parent, struct cfdata *cf, void *aux)
! 345: {
! 346: struct aips_attach_args * const aipsa = aux;
! 347:
! 348: switch (aipsa->aipsa_addr) {
! 349: case IMX_UART1_BASE:
! 350: case IMX_UART2_BASE:
! 351: case IMX_UART3_BASE:
! 352: case IMX_UART4_BASE:
! 353: case IMX_UART5_BASE:
! 354: return 1;
! 355: default:
! 356: return 0;
! 357: }
! 358: }
! 359:
! 360: static void
! 361: imxuart_attach(struct device *parent, struct device *self, void *aux)
! 362: {
! 363: imxuart_softc_t *sc = (void *)self;
! 364: struct aips_attach_args * const aipsa = aux;
! 365: struct tty *tp;
! 366:
! 367: sc->sc_bt = aipsa->aipsa_memt;
! 368: sc->sc_addr = aipsa->aipsa_addr;
! 369: sc->sc_size = aipsa->aipsa_size;
! 370: sc->sc_intr = aipsa->aipsa_intr;
! 371:
! 372: sc->sc_tty = tp = ttymalloc();
! 373: tp->t_oproc = imxuart_start;
! 374: tp->t_param = imxuart_param;
! 375: tty_attach(tp);
! 376:
! 377: shutdownhook_establish(imxuart_shutdownhook, sc);
! 378:
! 379: printf("\n");
! 380: }
! 381:
! 382: void
! 383: imxuartcnprobe(struct consdev *cp)
! 384: {
! 385: int major;
! 386:
! 387: __TRACE;
! 388: major = cdevsw_lookup_major(&imxuart_cdevsw);
! 389: cp->cn_dev = makedev(major, 0); /* XXX unit 0 */
! 390: cp->cn_pri = CN_REMOTE;
! 391: }
! 392:
! 393: static void
! 394: imxuart_start(struct tty *tp)
! 395: {
! 396: __TRACE;
! 397: }
! 398:
! 399: static int
! 400: imxuart_param(struct tty *tp, struct termios *termios)
! 401: {
! 402: __TRACE;
! 403: return 0;
! 404: }
! 405:
! 406: static void
! 407: imxuart_shutdownhook(void *arg)
! 408: {
! 409: __TRACE;
! 410: }
! 411:
! 412: void
! 413: imxuartcninit(struct consdev *cp)
! 414: {
! 415: __TRACE;
! 416: }
! 417:
! 418: int
! 419: imxuartcngetc(dev_t dev)
! 420: {
! 421: struct imxuart_softc *sc;
! 422: uint unit;
! 423: int c;
! 424:
! 425: unit = IMXUART_UNIT(dev);
! 426: if (unit != 0)
! 427: return 0;
! 428: sc = &imxuart_softc;
! 429: c = imxuart_getchar(sc);
! 430: return c;
! 431: }
! 432:
! 433: void
! 434: imxuartcnputc(dev_t dev, int c)
! 435: {
! 436: (void)imxuart_putchar(&imxuart_softc, c);
! 437: }
! 438:
! 439: void
! 440: imxuartcnpollc(dev_t dev, int mode)
! 441: {
! 442: /* always polled for now */
! 443: }
! 444: int
! 445: imxuart_cnattach(bus_space_tag_t iot, bus_addr_t iobase,
! 446: int rate, int frequency, int type, tcflag_t cflag)
! 447: {
! 448: cn_tab = &imxuartcntab;
! 449: return 0;
! 450: }
! 451:
CVSweb <webmaster@jp.NetBSD.org>