123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- /*
- * marvell kirkwood uart (supposed to be a 16550)
- */
- #include "u.h"
- #include "../port/lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "io.h"
- #include "../port/error.h"
- // #include "../port/uart.h"
- enum {
- UartFREQ = 0, // xxx
- IERrx = 1<<0,
- IERtx = 1<<1,
- IRRintrmask = (1<<4)-1,
- IRRnointr = 1,
- IRRthrempty = 2,
- IRRrxdata = 4,
- IRRrxstatus = 6,
- IRRtimeout = 12,
- IRRfifomask = 3<<6,
- IRRfifoenable = 3<<6,
- FCRenable = 1<<0,
- FCRrxreset = 1<<1,
- FCRtxreset = 1<<2,
- /* reserved */
- FCRrxtriggermask = 3<<6,
- FCRrxtrigger1 = 0<<6,
- FCRrxtrigger4 = 1<<6,
- FCRrxtrigger8 = 2<<6,
- FCRrxtrigger14 = 3<<6,
- LCRbpcmask = 3<<0,
- LCRbpc5 = 0<<0,
- LCRbpc6 = 1<<0,
- LCRbpc7 = 2<<0,
- LCRbpc8 = 3<<0,
- LCRstop2b = 1<<2,
- LCRparity = 1<<3,
- LCRparityeven = 1<<4,
- LCRbreak = 1<<6,
- LCRdivlatch = 1<<7,
- LSRrx = 1<<0,
- LSRrunerr = 1<<1,
- LSRparerr = 1<<2,
- LSRframeerr = 1<<3,
- LSRbi = 1<<4,
- LSRthre = 1<<5,
- LSRtxempty = 1<<6,
- LSRfifoerr = 1<<7,
- };
- extern PhysUart kwphysuart;
- #define UART0REG ((UartReg*)AddrUart0)
- typedef struct UartReg UartReg;
- struct UartReg
- {
- union {
- ulong thr;
- ulong dll;
- ulong rbr;
- };
- union {
- ulong ier;
- ulong dlh;
- };
- union {
- ulong iir;
- ulong fcr;
- };
- ulong lcr;
- ulong mcr;
- ulong lsr;
- ulong scr;
- };
- typedef struct Ctlr Ctlr;
- struct Ctlr {
- UartReg*regs;
- int irq;
- Lock;
- };
- static Ctlr kirkwoodctlr[] = {
- {
- .regs = UART0REG,
- .irq = IRQ1uart0, },
- };
- static Uart kirkwooduart[] = {
- {
- .regs = &kirkwoodctlr[0],
- .name = "eia0",
- .freq = UartFREQ,
- .phys = &kwphysuart,
- .special= 0,
- .console= 1,
- .next = nil, },
- };
- static void
- kw_read(Uart *uart)
- {
- Ctlr *ctlr = uart->regs;
- UartReg *regs = ctlr->regs;
- ulong lsr;
- char c;
- while ((lsr = regs->lsr) & LSRrx) {
- if(lsr&LSRrunerr)
- uart->oerr++;
- if(lsr&LSRparerr)
- uart->perr++;
- if(lsr&LSRframeerr)
- uart->ferr++;
- c = regs->rbr;
- if((lsr & (LSRbi|LSRframeerr|LSRparerr)) == 0)
- uartrecv(uart, c);
- }
- }
- static void
- kw_intr(Ureg*, void *arg)
- {
- Uart *uart = arg;
- Ctlr *ctlr = uart->regs;
- UartReg *regs = ctlr->regs;
- ulong v;
- v = regs->iir;
- if(v & IRRthrempty)
- uartkick(uart);
- if(v & IRRrxdata)
- kw_read(uart);
- intrclear(Irqhi, ctlr->irq);
- }
- static Uart*
- kw_pnp(void)
- {
- return kirkwooduart;
- }
- static void
- kw_enable(Uart* uart, int ie)
- {
- Ctlr *ctlr = uart->regs;
- UartReg *regs = ctlr->regs;
- USED(ie);
- regs->fcr = FCRenable|FCRrxtrigger4;
- regs->ier = IERrx|IERtx;
- intrenable(Irqhi, ctlr->irq, kw_intr, uart, uart->name);
- (*uart->phys->dtr)(uart, 1);
- (*uart->phys->rts)(uart, 1);
- }
- static void
- kw_disable(Uart* uart)
- {
- Ctlr *ctlr = uart->regs;
- (*uart->phys->dtr)(uart, 0);
- (*uart->phys->rts)(uart, 0);
- (*uart->phys->fifo)(uart, 0);
- intrdisable(Irqhi, ctlr->irq, kw_intr, uart, uart->name);
- }
- static void
- kw_kick(Uart* uart)
- {
- Ctlr *ctlr = uart->regs;
- UartReg *regs = ctlr->regs;
- int i;
- if(uart->cts == 0 || uart->blocked)
- return;
- for(i = 0; i < 16; i++) {
- if((regs->lsr & LSRthre) == 0 ||
- uart->op >= uart->oe && uartstageoutput(uart) == 0)
- break;
- regs->thr = *uart->op++;
- }
- }
- static void
- kw_break(Uart* uart, int ms)
- {
- USED(uart, ms);
- }
- static int
- kw_baud(Uart* uart, int baud)
- {
- USED(uart, baud);
- return 0;
- }
- static int
- kw_bits(Uart* uart, int bits)
- {
- USED(uart, bits);
- return 0;
- }
- static int
- kw_stop(Uart* uart, int stop)
- {
- USED(uart, stop);
- return 0;
- }
- static int
- kw_parity(Uart* uart, int parity)
- {
- USED(uart, parity);
- return 0;
- }
- static void
- kw_modemctl(Uart* uart, int on)
- {
- USED(uart, on);
- }
- static void
- kw_rts(Uart* uart, int on)
- {
- USED(uart, on);
- }
- static void
- kw_dtr(Uart* uart, int on)
- {
- USED(uart, on);
- }
- static long
- kw_status(Uart* uart, void* buf, long n, long offset)
- {
- USED(uart, buf, n, offset);
- return 0;
- }
- static void
- kw_fifo(Uart* uart, int level)
- {
- USED(uart, level);
- }
- static int
- kw_getc(Uart *uart)
- {
- Ctlr *ctlr = uart->regs;
- UartReg *regs = ctlr->regs;
- while((regs->lsr&LSRrx) == 0)
- ;
- return regs->rbr;
- }
- static void
- kw_putc(Uart *uart, int c)
- {
- Ctlr *ctlr = uart->regs;
- UartReg *regs = ctlr->regs;
- while((regs->lsr&LSRthre) == 0)
- ;
- regs->thr = c;
- }
- PhysUart kwphysuart = {
- .name = "kirkwood",
- .pnp = kw_pnp,
- .enable = kw_enable,
- .disable = kw_disable,
- .kick = kw_kick,
- .dobreak = kw_break,
- .baud = kw_baud,
- .bits = kw_bits,
- .stop = kw_stop,
- .parity = kw_parity,
- .modemctl = kw_modemctl,
- .rts = kw_rts,
- .dtr = kw_dtr,
- .status = kw_status,
- .fifo = kw_fifo,
- .getc = kw_getc,
- .putc = kw_putc,
- };
- void
- uartkirkwoodconsole(void)
- {
- Uart *uart;
- uart = &kirkwooduart[0];
- (*uart->phys->enable)(uart, 0);
- uartctl(uart, "b115200 l8 pn s1 i1");
- uart->console = 1;
- consuart = uart;
- //serialputs("uart0 kirkwood\n", strlen("uart0 kirkwood\n"));
- }
- void
- serialputc(int c)
- {
- int cnt, s;
- s = splhi();
- cnt = m->cpuhz;
- if (cnt <= 0) /* cpuhz not set yet? */
- cnt = 1000000;
- while((UART0REG->lsr & LSRthre) == 0 && --cnt > 0)
- ;
- UART0REG->thr = c;
- delay(1);
- splx(s);
- }
- void
- serialputs(char *p, int len)
- {
- while(--len >= 0) {
- if(*p == '\n')
- serialputc('\r');
- serialputc(*p++);
- }
- }
|