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