uartmini.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /*
  2. * bcm2835 mini uart (UART1)
  3. */
  4. #include "u.h"
  5. #include "../port/lib.h"
  6. #include "../port/error.h"
  7. #include "mem.h"
  8. #include "dat.h"
  9. #include "fns.h"
  10. #include "io.h"
  11. #define GPIOREGS (VIRTIO+0x200000)
  12. #define AUXREGS (VIRTIO+0x215000)
  13. #define OkLed 16
  14. #define TxPin 14
  15. #define RxPin 15
  16. /* GPIO regs */
  17. enum {
  18. Fsel0 = 0x00>>2,
  19. FuncMask= 0x7,
  20. Input = 0x0,
  21. Output = 0x1,
  22. Alt0 = 0x4,
  23. Alt1 = 0x5,
  24. Alt2 = 0x6,
  25. Alt3 = 0x7,
  26. Alt4 = 0x3,
  27. Alt5 = 0x2,
  28. Set0 = 0x1c>>2,
  29. Clr0 = 0x28>>2,
  30. Lev0 = 0x34>>2,
  31. PUD = 0x94>>2,
  32. Off = 0x0,
  33. Pulldown= 0x1,
  34. Pullup = 0x2,
  35. PUDclk0 = 0x98>>2,
  36. PUDclk1 = 0x9c>>2,
  37. };
  38. /* AUX regs */
  39. enum {
  40. Irq = 0x00>>2,
  41. UartIrq = 1<<0,
  42. Enables = 0x04>>2,
  43. UartEn = 1<<0,
  44. MuIo = 0x40>>2,
  45. MuIer = 0x44>>2,
  46. RxIen = 1<<0,
  47. TxIen = 1<<1,
  48. MuIir = 0x48>>2,
  49. MuLcr = 0x4c>>2,
  50. Bitsmask= 3<<0,
  51. Bits7 = 2<<0,
  52. Bits8 = 3<<0,
  53. MuMcr = 0x50>>2,
  54. RtsN = 1<<1,
  55. MuLsr = 0x54>>2,
  56. TxDone = 1<<6,
  57. TxRdy = 1<<5,
  58. RxRdy = 1<<0,
  59. MuCntl = 0x60>>2,
  60. CtsFlow = 1<<3,
  61. TxEn = 1<<1,
  62. RxEn = 1<<0,
  63. MuBaud = 0x68>>2,
  64. };
  65. extern PhysUart miniphysuart;
  66. static Uart miniuart = {
  67. .regs = (u32int*)AUXREGS,
  68. .name = "uart0",
  69. .freq = 250000000,
  70. .phys = &miniphysuart,
  71. };
  72. void
  73. gpiosel(uint pin, int func)
  74. {
  75. u32int *gp, *fsel;
  76. int off;
  77. gp = (u32int*)GPIOREGS;
  78. fsel = &gp[Fsel0 + pin/10];
  79. off = (pin % 10) * 3;
  80. *fsel = (*fsel & ~(FuncMask<<off)) | func<<off;
  81. }
  82. void
  83. gpiopulloff(uint pin)
  84. {
  85. u32int *gp, *reg;
  86. u32int mask;
  87. gp = (u32int*)GPIOREGS;
  88. reg = &gp[PUDclk0 + pin/32];
  89. mask = 1 << (pin % 32);
  90. gp[PUD] = Off;
  91. microdelay(1);
  92. *reg = mask;
  93. microdelay(1);
  94. *reg = 0;
  95. }
  96. void
  97. gpioout(uint pin, int set)
  98. {
  99. u32int *gp;
  100. int v;
  101. gp = (u32int*)GPIOREGS;
  102. v = set? Set0 : Clr0;
  103. gp[v + pin/32] = 1 << (pin % 32);
  104. }
  105. int
  106. gpioin(uint pin)
  107. {
  108. u32int *gp;
  109. gp = (u32int*)GPIOREGS;
  110. return (gp[Lev0 + pin/32] & (1 << (pin % 32))) != 0;
  111. }
  112. static void
  113. interrupt(Ureg*, void *arg)
  114. {
  115. Uart *uart;
  116. u32int *ap;
  117. uart = arg;
  118. ap = (u32int*)uart->regs;
  119. coherence();
  120. if(0 && (ap[Irq] & UartIrq) == 0)
  121. return;
  122. if(ap[MuLsr] & TxRdy)
  123. uartkick(uart);
  124. if(ap[MuLsr] & RxRdy){
  125. if(uart->console){
  126. if(uart->opens == 1)
  127. uart->putc = kbdcr2nl;
  128. else
  129. uart->putc = nil;
  130. }
  131. do{
  132. uartrecv(uart, ap[MuIo] & 0xFF);
  133. }while(ap[MuLsr] & RxRdy);
  134. }
  135. coherence();
  136. }
  137. static Uart*
  138. pnp(void)
  139. {
  140. Uart *uart;
  141. uart = &miniuart;
  142. if(uart->console == 0)
  143. kbdq = qopen(8*1024, 0, nil, nil);
  144. return uart;
  145. }
  146. static void
  147. enable(Uart *uart, int ie)
  148. {
  149. u32int *ap;
  150. ap = (u32int*)uart->regs;
  151. delay(10);
  152. gpiosel(TxPin, Alt5);
  153. gpiosel(RxPin, Alt5);
  154. gpiopulloff(TxPin);
  155. gpiopulloff(RxPin);
  156. ap[Enables] |= UartEn;
  157. ap[MuIir] = 6;
  158. ap[MuLcr] = Bits8;
  159. ap[MuCntl] = TxEn|RxEn;
  160. ap[MuBaud] = 250000000/(115200*8) - 1;
  161. if(ie){
  162. intrenable(IRQaux, interrupt, uart, 0, "uart");
  163. ap[MuIer] = RxIen|TxIen;
  164. }else
  165. ap[MuIer] = 0;
  166. }
  167. static void
  168. disable(Uart *uart)
  169. {
  170. u32int *ap;
  171. ap = (u32int*)uart->regs;
  172. ap[MuCntl] = 0;
  173. ap[MuIer] = 0;
  174. }
  175. static void
  176. kick(Uart *uart)
  177. {
  178. u32int *ap;
  179. ap = (u32int*)uart->regs;
  180. if(uart->blocked)
  181. return;
  182. coherence();
  183. while(ap[MuLsr] & TxRdy){
  184. if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
  185. break;
  186. ap[MuIo] = *(uart->op++);
  187. }
  188. if(ap[MuLsr] & TxDone)
  189. ap[MuIer] &= ~TxIen;
  190. else
  191. ap[MuIer] |= TxIen;
  192. coherence();
  193. }
  194. /* TODO */
  195. static void
  196. dobreak(Uart *uart, int ms)
  197. {
  198. USED(uart, ms);
  199. }
  200. static int
  201. baud(Uart *uart, int n)
  202. {
  203. u32int *ap;
  204. ap = (u32int*)uart->regs;
  205. if(uart->freq == 0 || n <= 0)
  206. return -1;
  207. ap[MuBaud] = (uart->freq + 4*n - 1) / (8 * n) - 1;
  208. uart->baud = n;
  209. return 0;
  210. }
  211. static int
  212. bits(Uart *uart, int n)
  213. {
  214. u32int *ap;
  215. int set;
  216. ap = (u32int*)uart->regs;
  217. switch(n){
  218. case 7:
  219. set = Bits7;
  220. break;
  221. case 8:
  222. set = Bits8;
  223. break;
  224. default:
  225. return -1;
  226. }
  227. ap[MuLcr] = (ap[MuLcr] & ~Bitsmask) | set;
  228. uart->bits = n;
  229. return 0;
  230. }
  231. static int
  232. stop(Uart *uart, int n)
  233. {
  234. if(n != 1)
  235. return -1;
  236. uart->stop = n;
  237. return 0;
  238. }
  239. static int
  240. parity(Uart *uart, int n)
  241. {
  242. if(n != 'n')
  243. return -1;
  244. uart->parity = n;
  245. return 0;
  246. }
  247. /*
  248. * cts/rts flow control
  249. * need to bring signals to gpio pins before enabling this
  250. */
  251. static void
  252. modemctl(Uart *uart, int on)
  253. {
  254. u32int *ap;
  255. ap = (u32int*)uart->regs;
  256. if(on)
  257. ap[MuCntl] |= CtsFlow;
  258. else
  259. ap[MuCntl] &= ~CtsFlow;
  260. uart->modem = on;
  261. }
  262. static void
  263. rts(Uart *uart, int on)
  264. {
  265. u32int *ap;
  266. ap = (u32int*)uart->regs;
  267. if(on)
  268. ap[MuMcr] &= ~RtsN;
  269. else
  270. ap[MuMcr] |= RtsN;
  271. }
  272. static long
  273. status(Uart *uart, void *buf, long n, long offset)
  274. {
  275. char *p;
  276. p = malloc(READSTR);
  277. if(p == nil)
  278. error(Enomem);
  279. snprint(p, READSTR,
  280. "b%d\n"
  281. "dev(%d) type(%d) framing(%d) overruns(%d) "
  282. "berr(%d) serr(%d)\n",
  283. uart->baud,
  284. uart->dev,
  285. uart->type,
  286. uart->ferr,
  287. uart->oerr,
  288. uart->berr,
  289. uart->serr
  290. );
  291. n = readstr(offset, buf, n, p);
  292. free(p);
  293. return n;
  294. }
  295. static void
  296. donothing(Uart*, int)
  297. {
  298. }
  299. void
  300. putc(Uart*, int c)
  301. {
  302. u32int *ap;
  303. ap = (u32int*)AUXREGS;
  304. while((ap[MuLsr] & TxRdy) == 0)
  305. ;
  306. ap[MuIo] = c;
  307. while((ap[MuLsr] & TxRdy) == 0)
  308. ;
  309. }
  310. int
  311. getc(Uart*)
  312. {
  313. u32int *ap;
  314. ap = (u32int*)AUXREGS;
  315. while((ap[MuLsr] & RxRdy) == 0)
  316. ;
  317. return ap[MuIo] & 0xFF;
  318. }
  319. void
  320. uartconsinit(void)
  321. {
  322. Uart *uart;
  323. int n;
  324. char *p, *cmd;
  325. if((p = getconf("console")) == nil)
  326. return;
  327. n = strtoul(p, &cmd, 0);
  328. if(p == cmd)
  329. return;
  330. switch(n){
  331. default:
  332. return;
  333. case 0:
  334. uart = &miniuart;
  335. break;
  336. }
  337. if(!uart->enabled)
  338. (*uart->phys->enable)(uart, 0);
  339. uartctl(uart, "b9600 l8 pn s1");
  340. if(*cmd != '\0')
  341. uartctl(uart, cmd);
  342. consuart = uart;
  343. uart->console = 1;
  344. }
  345. PhysUart miniphysuart = {
  346. .name = "miniuart",
  347. .pnp = pnp,
  348. .enable = enable,
  349. .disable = disable,
  350. .kick = kick,
  351. .dobreak = dobreak,
  352. .baud = baud,
  353. .bits = bits,
  354. .stop = stop,
  355. .parity = parity,
  356. .modemctl = donothing,
  357. .rts = rts,
  358. .dtr = donothing,
  359. .status = status,
  360. .fifo = donothing,
  361. .getc = getc,
  362. .putc = putc,
  363. };
  364. void
  365. okay(int on)
  366. {
  367. static int first;
  368. if(!first++)
  369. gpiosel(OkLed, Output);
  370. gpioout(OkLed, !on);
  371. }