uartkw.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  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. typedef struct UartReg UartReg;
  54. struct UartReg
  55. {
  56. union {
  57. ulong thr;
  58. ulong dll;
  59. ulong rbr;
  60. };
  61. union {
  62. ulong ier;
  63. ulong dlh;
  64. };
  65. union {
  66. ulong iir;
  67. ulong fcr;
  68. };
  69. ulong lcr;
  70. ulong mcr;
  71. ulong lsr;
  72. ulong scr;
  73. };
  74. typedef struct Ctlr Ctlr;
  75. struct Ctlr {
  76. UartReg*regs;
  77. int irq;
  78. Lock;
  79. };
  80. static Ctlr kirkwoodctlr[] = {
  81. {
  82. .regs = nil, /* filled in below */
  83. .irq = IRQ1uart0, },
  84. };
  85. static Uart kirkwooduart[] = {
  86. {
  87. .regs = &kirkwoodctlr[0],
  88. .name = "eia0",
  89. .freq = UartFREQ,
  90. .phys = &kwphysuart,
  91. .special= 0,
  92. .console= 1,
  93. .next = nil, },
  94. };
  95. static void
  96. kw_read(Uart *uart)
  97. {
  98. Ctlr *ctlr = uart->regs;
  99. UartReg *regs = ctlr->regs;
  100. ulong lsr;
  101. char c;
  102. while ((lsr = regs->lsr) & LSRrx) {
  103. if(lsr&LSRrunerr)
  104. uart->oerr++;
  105. if(lsr&LSRparerr)
  106. uart->perr++;
  107. if(lsr&LSRframeerr)
  108. uart->ferr++;
  109. c = regs->rbr;
  110. if((lsr & (LSRbi|LSRframeerr|LSRparerr)) == 0)
  111. uartrecv(uart, c);
  112. }
  113. }
  114. static void
  115. kw_intr(Ureg*, void *arg)
  116. {
  117. Uart *uart = arg;
  118. Ctlr *ctlr = uart->regs;
  119. UartReg *regs = ctlr->regs;
  120. ulong v;
  121. if(regs == 0) {
  122. kirkwoodctlr[0].regs = (UartReg *)soc.uart[0];
  123. regs = (UartReg *)soc.uart[0]; /* caution */
  124. coherence();
  125. }
  126. v = regs->iir;
  127. if(v & IRRthrempty)
  128. uartkick(uart);
  129. if(v & IRRrxdata)
  130. kw_read(uart);
  131. intrclear(Irqhi, ctlr->irq);
  132. }
  133. static Uart*
  134. kw_pnp(void)
  135. {
  136. kirkwoodctlr[0].regs = (UartReg *)soc.uart[0];
  137. coherence();
  138. return kirkwooduart;
  139. }
  140. static void
  141. kw_enable(Uart* uart, int ie)
  142. {
  143. Ctlr *ctlr = uart->regs;
  144. UartReg *regs = ctlr->regs;
  145. if(regs == 0) {
  146. kirkwoodctlr[0].regs = (UartReg *)soc.uart[0];
  147. regs = (UartReg *)soc.uart[0]; /* caution */
  148. coherence();
  149. }
  150. USED(ie);
  151. regs->fcr = FCRenable|FCRrxtrigger4;
  152. regs->ier = IERrx|IERtx;
  153. intrenable(Irqhi, ctlr->irq, kw_intr, uart, uart->name);
  154. (*uart->phys->dtr)(uart, 1);
  155. (*uart->phys->rts)(uart, 1);
  156. }
  157. static void
  158. kw_disable(Uart* uart)
  159. {
  160. Ctlr *ctlr = uart->regs;
  161. (*uart->phys->dtr)(uart, 0);
  162. (*uart->phys->rts)(uart, 0);
  163. (*uart->phys->fifo)(uart, 0);
  164. intrdisable(Irqhi, ctlr->irq, kw_intr, uart, uart->name);
  165. }
  166. static void
  167. kw_kick(Uart* uart)
  168. {
  169. Ctlr *ctlr = uart->regs;
  170. UartReg *regs = ctlr->regs;
  171. int i;
  172. if(uart->cts == 0 || uart->blocked)
  173. return;
  174. for(i = 0; i < 16; i++) {
  175. if((regs->lsr & LSRthre) == 0 ||
  176. uart->op >= uart->oe && uartstageoutput(uart) == 0)
  177. break;
  178. regs->thr = *uart->op++;
  179. }
  180. }
  181. static void
  182. kw_break(Uart* uart, int ms)
  183. {
  184. USED(uart, ms);
  185. }
  186. static int
  187. kw_baud(Uart* uart, int baud)
  188. {
  189. USED(uart, baud);
  190. return 0;
  191. }
  192. static int
  193. kw_bits(Uart* uart, int bits)
  194. {
  195. USED(uart, bits);
  196. return 0;
  197. }
  198. static int
  199. kw_stop(Uart* uart, int stop)
  200. {
  201. USED(uart, stop);
  202. return 0;
  203. }
  204. static int
  205. kw_parity(Uart* uart, int parity)
  206. {
  207. USED(uart, parity);
  208. return 0;
  209. }
  210. static void
  211. kw_modemctl(Uart* uart, int on)
  212. {
  213. USED(uart, on);
  214. }
  215. static void
  216. kw_rts(Uart* uart, int on)
  217. {
  218. USED(uart, on);
  219. }
  220. static void
  221. kw_dtr(Uart* uart, int on)
  222. {
  223. USED(uart, on);
  224. }
  225. static long
  226. kw_status(Uart* uart, void* buf, long n, long offset)
  227. {
  228. USED(uart, buf, n, offset);
  229. return 0;
  230. }
  231. static void
  232. kw_fifo(Uart* uart, int level)
  233. {
  234. USED(uart, level);
  235. }
  236. static int
  237. kw_getc(Uart *uart)
  238. {
  239. Ctlr *ctlr = uart->regs;
  240. UartReg *regs = ctlr->regs;
  241. while((regs->lsr&LSRrx) == 0)
  242. ;
  243. return regs->rbr;
  244. }
  245. static void
  246. kw_putc(Uart *uart, int c)
  247. {
  248. Ctlr *ctlr = uart->regs;
  249. UartReg *regs = ctlr->regs;
  250. /* can be called from iprint, among many other places */
  251. if(regs == 0) {
  252. kirkwoodctlr[0].regs = (UartReg *)soc.uart[0];
  253. regs = (UartReg *)soc.uart[0]; /* caution */
  254. coherence();
  255. }
  256. while((regs->lsr&LSRthre) == 0)
  257. ;
  258. regs->thr = c;
  259. coherence();
  260. }
  261. PhysUart kwphysuart = {
  262. .name = "kirkwood",
  263. .pnp = kw_pnp,
  264. .enable = kw_enable,
  265. .disable = kw_disable,
  266. .kick = kw_kick,
  267. .dobreak = kw_break,
  268. .baud = kw_baud,
  269. .bits = kw_bits,
  270. .stop = kw_stop,
  271. .parity = kw_parity,
  272. .modemctl = kw_modemctl,
  273. .rts = kw_rts,
  274. .dtr = kw_dtr,
  275. .status = kw_status,
  276. .fifo = kw_fifo,
  277. .getc = kw_getc,
  278. .putc = kw_putc,
  279. };
  280. void
  281. uartkirkwoodconsole(void)
  282. {
  283. Uart *uart;
  284. uart = &kirkwooduart[0];
  285. (*uart->phys->enable)(uart, 0);
  286. uartctl(uart, "b115200 l8 pn s1 i1");
  287. uart->console = 1;
  288. consuart = uart;
  289. //serialputs("uart0 kirkwood\n", strlen("uart0 kirkwood\n"));
  290. }
  291. void
  292. serialputc(int c)
  293. {
  294. int cnt, s;
  295. UartReg *regs = (UartReg *)soc.uart[0];
  296. s = splhi();
  297. cnt = m->cpuhz;
  298. if (cnt <= 0) /* cpuhz not set yet? */
  299. cnt = 1000000;
  300. while((regs->lsr & LSRthre) == 0 && --cnt > 0)
  301. ;
  302. regs->thr = c;
  303. coherence();
  304. delay(1);
  305. splx(s);
  306. }
  307. void
  308. serialputs(char *p, int len)
  309. {
  310. while(--len >= 0) {
  311. if(*p == '\n')
  312. serialputc('\r');
  313. serialputc(*p++);
  314. }
  315. }