uartkw.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. /*
  2. * marvell kirkwood uart (supposed to be a 16550)
  3. */
  4. #include "u.h"
  5. #include "../port/lib.h"
  6. #include "mem.h"
  7. #include "dat.h"
  8. #include "fns.h"
  9. #include "io.h"
  10. #include "../port/error.h"
  11. // #include "../port/uart.h"
  12. enum {
  13. UartFREQ = 0, // xxx
  14. IERrx = 1<<0,
  15. IERtx = 1<<1,
  16. IRRintrmask = (1<<4)-1,
  17. IRRnointr = 1,
  18. IRRthrempty = 2,
  19. IRRrxdata = 4,
  20. IRRrxstatus = 6,
  21. IRRtimeout = 12,
  22. IRRfifomask = 3<<6,
  23. IRRfifoenable = 3<<6,
  24. FCRenable = 1<<0,
  25. FCRrxreset = 1<<1,
  26. FCRtxreset = 1<<2,
  27. /* reserved */
  28. FCRrxtriggermask = 3<<6,
  29. FCRrxtrigger1 = 0<<6,
  30. FCRrxtrigger4 = 1<<6,
  31. FCRrxtrigger8 = 2<<6,
  32. FCRrxtrigger14 = 3<<6,
  33. LCRbpcmask = 3<<0,
  34. LCRbpc5 = 0<<0,
  35. LCRbpc6 = 1<<0,
  36. LCRbpc7 = 2<<0,
  37. LCRbpc8 = 3<<0,
  38. LCRstop2b = 1<<2,
  39. LCRparity = 1<<3,
  40. LCRparityeven = 1<<4,
  41. LCRbreak = 1<<6,
  42. LCRdivlatch = 1<<7,
  43. LSRrx = 1<<0,
  44. LSRrunerr = 1<<1,
  45. LSRparerr = 1<<2,
  46. LSRframeerr = 1<<3,
  47. LSRbi = 1<<4,
  48. LSRthre = 1<<5,
  49. LSRtxempty = 1<<6,
  50. LSRfifoerr = 1<<7,
  51. };
  52. extern PhysUart kwphysuart;
  53. #define UART0REG ((UartReg*)AddrUart0)
  54. typedef struct UartReg UartReg;
  55. struct UartReg
  56. {
  57. union {
  58. ulong thr;
  59. ulong dll;
  60. ulong rbr;
  61. };
  62. union {
  63. ulong ier;
  64. ulong dlh;
  65. };
  66. union {
  67. ulong iir;
  68. ulong fcr;
  69. };
  70. ulong lcr;
  71. ulong mcr;
  72. ulong lsr;
  73. ulong scr;
  74. };
  75. typedef struct Ctlr Ctlr;
  76. struct Ctlr {
  77. UartReg*regs;
  78. int irq;
  79. Lock;
  80. };
  81. static Ctlr kirkwoodctlr[] = {
  82. {
  83. .regs = UART0REG,
  84. .irq = IRQ1uart0, },
  85. };
  86. static Uart kirkwooduart[] = {
  87. {
  88. .regs = &kirkwoodctlr[0],
  89. .name = "eia0",
  90. .freq = UartFREQ,
  91. .phys = &kwphysuart,
  92. .special= 0,
  93. .console= 1,
  94. .next = nil, },
  95. };
  96. static void
  97. kw_read(Uart *uart)
  98. {
  99. Ctlr *ctlr = uart->regs;
  100. UartReg *regs = ctlr->regs;
  101. ulong lsr;
  102. char c;
  103. while ((lsr = regs->lsr) & LSRrx) {
  104. if(lsr&LSRrunerr)
  105. uart->oerr++;
  106. if(lsr&LSRparerr)
  107. uart->perr++;
  108. if(lsr&LSRframeerr)
  109. uart->ferr++;
  110. c = regs->rbr;
  111. if((lsr & (LSRbi|LSRframeerr|LSRparerr)) == 0)
  112. uartrecv(uart, c);
  113. }
  114. }
  115. static void
  116. kw_intr(Ureg*, void *arg)
  117. {
  118. Uart *uart = arg;
  119. Ctlr *ctlr = uart->regs;
  120. UartReg *regs = ctlr->regs;
  121. ulong v;
  122. v = regs->iir;
  123. if(v & IRRthrempty)
  124. uartkick(uart);
  125. if(v & IRRrxdata)
  126. kw_read(uart);
  127. intrclear(Irqhi, ctlr->irq);
  128. }
  129. static Uart*
  130. kw_pnp(void)
  131. {
  132. return kirkwooduart;
  133. }
  134. static void
  135. kw_enable(Uart* uart, int ie)
  136. {
  137. Ctlr *ctlr = uart->regs;
  138. UartReg *regs = ctlr->regs;
  139. USED(ie);
  140. regs->fcr = FCRenable|FCRrxtrigger4;
  141. regs->ier = IERrx|IERtx;
  142. intrenable(Irqhi, ctlr->irq, kw_intr, uart, uart->name);
  143. (*uart->phys->dtr)(uart, 1);
  144. (*uart->phys->rts)(uart, 1);
  145. }
  146. static void
  147. kw_disable(Uart* uart)
  148. {
  149. Ctlr *ctlr = uart->regs;
  150. (*uart->phys->dtr)(uart, 0);
  151. (*uart->phys->rts)(uart, 0);
  152. (*uart->phys->fifo)(uart, 0);
  153. intrdisable(Irqhi, ctlr->irq, kw_intr, uart, uart->name);
  154. }
  155. static void
  156. kw_kick(Uart* uart)
  157. {
  158. Ctlr *ctlr = uart->regs;
  159. UartReg *regs = ctlr->regs;
  160. int i;
  161. if(uart->cts == 0 || uart->blocked)
  162. return;
  163. for(i = 0; i < 16; i++) {
  164. if((regs->lsr & LSRthre) == 0 ||
  165. uart->op >= uart->oe && uartstageoutput(uart) == 0)
  166. break;
  167. regs->thr = *uart->op++;
  168. }
  169. }
  170. static void
  171. kw_break(Uart* uart, int ms)
  172. {
  173. USED(uart, ms);
  174. }
  175. static int
  176. kw_baud(Uart* uart, int baud)
  177. {
  178. USED(uart, baud);
  179. return 0;
  180. }
  181. static int
  182. kw_bits(Uart* uart, int bits)
  183. {
  184. USED(uart, bits);
  185. return 0;
  186. }
  187. static int
  188. kw_stop(Uart* uart, int stop)
  189. {
  190. USED(uart, stop);
  191. return 0;
  192. }
  193. static int
  194. kw_parity(Uart* uart, int parity)
  195. {
  196. USED(uart, parity);
  197. return 0;
  198. }
  199. static void
  200. kw_modemctl(Uart* uart, int on)
  201. {
  202. USED(uart, on);
  203. }
  204. static void
  205. kw_rts(Uart* uart, int on)
  206. {
  207. USED(uart, on);
  208. }
  209. static void
  210. kw_dtr(Uart* uart, int on)
  211. {
  212. USED(uart, on);
  213. }
  214. static long
  215. kw_status(Uart* uart, void* buf, long n, long offset)
  216. {
  217. USED(uart, buf, n, offset);
  218. return 0;
  219. }
  220. static void
  221. kw_fifo(Uart* uart, int level)
  222. {
  223. USED(uart, level);
  224. }
  225. static int
  226. kw_getc(Uart *uart)
  227. {
  228. Ctlr *ctlr = uart->regs;
  229. UartReg *regs = ctlr->regs;
  230. while((regs->lsr&LSRrx) == 0)
  231. ;
  232. return regs->rbr;
  233. }
  234. static void
  235. kw_putc(Uart *uart, int c)
  236. {
  237. Ctlr *ctlr = uart->regs;
  238. UartReg *regs = ctlr->regs;
  239. while((regs->lsr&LSRthre) == 0)
  240. ;
  241. regs->thr = c;
  242. }
  243. PhysUart kwphysuart = {
  244. .name = "kirkwood",
  245. .pnp = kw_pnp,
  246. .enable = kw_enable,
  247. .disable = kw_disable,
  248. .kick = kw_kick,
  249. .dobreak = kw_break,
  250. .baud = kw_baud,
  251. .bits = kw_bits,
  252. .stop = kw_stop,
  253. .parity = kw_parity,
  254. .modemctl = kw_modemctl,
  255. .rts = kw_rts,
  256. .dtr = kw_dtr,
  257. .status = kw_status,
  258. .fifo = kw_fifo,
  259. .getc = kw_getc,
  260. .putc = kw_putc,
  261. };
  262. void
  263. uartkirkwoodconsole(void)
  264. {
  265. Uart *uart;
  266. uart = &kirkwooduart[0];
  267. (*uart->phys->enable)(uart, 0);
  268. uartctl(uart, "b115200 l8 pn s1 i1");
  269. uart->console = 1;
  270. consuart = uart;
  271. //serialputs("uart0 kirkwood\n", strlen("uart0 kirkwood\n"));
  272. }
  273. void
  274. serialputc(int c)
  275. {
  276. int cnt, s;
  277. s = splhi();
  278. cnt = m->cpuhz;
  279. if (cnt <= 0) /* cpuhz not set yet? */
  280. cnt = 1000000;
  281. while((UART0REG->lsr & LSRthre) == 0 && --cnt > 0)
  282. ;
  283. UART0REG->thr = c;
  284. delay(1);
  285. splx(s);
  286. }
  287. void
  288. serialputs(char *p, int len)
  289. {
  290. while(--len >= 0) {
  291. if(*p == '\n')
  292. serialputc('\r');
  293. serialputc(*p++);
  294. }
  295. }