1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "imm.h"
8 #include "../port/error.h"
9 #include "../ppc/uartsmc.h"
10
11 /*
12 * PowerPC 8260 SMC UART
13 */
14
15 enum {
16 /* SMC Mode Registers */
17 Clen = 0x7800, /* Character length */
18 Sl = 0x0400, /* Stop length, 0: one stop bit, 1: two */
19 Pen = 0x0200, /* Parity enable */
20 Pm = 0x0100, /* Parity mode, 0 is odd */
21 Sm = 0x0030, /* SMC mode, two bits */
22 SMUart = 0x0020, /* SMC mode, 0b10 is uart */
23 Dm = 0x000c, /* Diagnostic mode, 00 is normal */
24 Ten = 0x0002, /* Transmit enable, 1 is enabled */
25 Ren = 0x0001, /* Receive enable, 1 is enabled */
26
27 /* SMC Event/Mask Registers */
28 ce_Brke = 0x0040, /* Break end */
29 ce_Br = 0x0020, /* Break character received */
30 ce_Bsy = 0x0004, /* Busy condition */
31 ce_Txb = 0x0002, /* Tx buffer */
32 ce_Rxb = 0x0001, /* Rx buffer */
33
34 /* Receive/Transmit Buffer Descriptor Control bits */
35 BDContin= 1<<9,
36 BDIdle= 1<<8,
37 BDPreamble= 1<<8,
38 BDBreak= 1<<5,
39 BDFrame= 1<<4,
40 BDParity= 1<<3,
41 BDOverrun= 1<<1,
42
43 /* Tx and Rx buffer sizes (32 bytes) */
44 Rxsize= CACHELINESZ,
45 Txsize= CACHELINESZ,
46 };
47
48 extern PhysUart smcphysuart;
49
50 Uart smcuart[Nuart] = {
51 {
52 .name = "SMC1",
53 .baud = 115200,
54 .bits = 8,
55 .stop = 1,
56 .parity = 'n',
57 .phys = &smcphysuart,
58 .special = 0,
59 },
60 /* Only configure SMC1 for now
61 {
62 .name = "SMC2",
63 .baud = 115200,
64 .bits = 8,
65 .stop = 1,
66 .parity = 'n',
67 .phys = &smcphysuart,
68 .special = 0,
69 },
70 */
71 };
72
73 int uartinited = 0;
74
75 static void smcinterrupt(Ureg*, void*);
76 static void smcputc(Uart *uart, int c);
77
78 int
baudgen(int baud)79 baudgen(int baud)
80 {
81 int d;
82
83 d = ((m->brghz+(baud>>1))/baud)>>4;
84 if(d >= (1<<12))
85 return ((d+15)>>3)|1;
86 return d<<1;
87 }
88
89 static Uart*
smcpnp(void)90 smcpnp(void)
91 {
92 int i;
93
94 for (i = 0; i < nelem(smcuart) - 1; i++)
95 smcuart[i].next = smcuart + i + 1;
96 return smcuart;
97 }
98
99 void
smcsetup(Uart * uart)100 smcsetup(Uart *uart)
101 {
102 Uartsmc *p;
103 SMC *smc;
104 UartData *ud;
105
106 ud = uart->regs;
107
108 /* magic addresses */
109
110 p = &m->immr->uartsmc[ud->smcno];
111 smc = imm->smc + ud->smcno; /* SMC1 */
112 ud->smc = smc;
113 ud->usmc = p;
114
115 /* step 0: disable rx/tx */
116 smc->smcmr &= ~3;
117
118 ioplock();
119
120 /* step 1, Using Port D */
121 if (ud->smcno != 0)
122 panic("Don't know how to set Port D bits");
123 imm->port[SMC1PORT].ppar |= SMRXD1|SMTXD1;
124 imm->port[SMC1PORT].pdir |= SMTXD1;
125 imm->port[SMC1PORT].pdir &= ~SMRXD1;
126 imm->port[SMC1PORT].psor &= ~(SMRXD1|SMTXD1);
127
128 /* step 2: set up brgc1 */
129 imm->brgc[ud->smcno] = baudgen(uart->baud) | 0x10000;
130
131 /* step 3: route clock to SMC1 */
132 imm->cmxsmr &= (ud->smcno == 0) ? ~0xb0 : ~0xb; /* clear smcx and smcxcs */
133
134 iopunlock();
135
136 /* step 4: assign a pointer to the SMCparameter RAM */
137 m->immr->param[ud->smcno].smcbase = (ulong)p - IMMR;
138
139 /* step 6: issue command to CP */
140 if (ud->smcno == 0)
141 cpmop(InitRxTx, SMC1ID, 0);
142 else
143 cpmop(InitRxTx, SMC2ID, 0);
144
145 /* step 7: protocol parameters */
146 p->rfcr = 0x30;
147 p->tfcr = 0x30;
148 }
149
150 void
smcinit(Uart * uart)151 smcinit(Uart *uart)
152 {
153 Uartsmc *p;
154 SMC *smc;
155 UartData *ud;
156 ulong lcr;
157 int bits;
158
159 ud = uart->regs;
160
161 if (ud->initialized)
162 return;
163
164 smcsetup(uart); /* Steps 1 through 4, PPC-dependent */
165 p = ud->usmc;
166 smc = ud->smc;
167
168 /* step 5: set up buffer descriptors */
169 /* setup my uart structure */
170 if (ud->rxb == nil)
171 ud->rxb = bdalloc(1);
172 if (ud->txb == nil)
173 ud->txb = bdalloc(1);
174
175 p->rbase = ((ulong)ud->rxb) - (ulong)IMMR;
176 p->tbase = ((ulong)ud->txb) - (ulong)IMMR;
177
178 /* step 8: receive buffer size */
179 p->mrblr = Rxsize;
180
181 /* step 9: */
182 p->maxidl = 15;
183
184 /* step 10: */
185 p->brkln = 0;
186 p->brkec = 0;
187
188 /* step 11: */
189 p->brkcr = 0;
190
191 /* step 12: setup receive buffer */
192 ud->rxb->status = BDEmpty|BDWrap|BDInt;
193 ud->rxb->length = 0;
194 ud->rxbuf = xspanalloc(Rxsize, 0, CACHELINESZ);
195 ud->rxb->addr = PADDR(ud->rxbuf);
196
197 /* step 13: step transmit buffer */
198 ud->txb->status = BDWrap|BDInt;
199 ud->txb->length = 0;
200 ud->txbuf = xspanalloc(Txsize, 0, CACHELINESZ);
201 ud->txb->addr = PADDR(ud->txbuf);
202
203 /* step 14: clear events */
204 smc->smce = ce_Brke | ce_Br | ce_Bsy | ce_Txb | ce_Rxb;
205
206 /*
207 * step 15: enable interrupts (done later)
208 * smc->smcm = ce_Brke | ce_Br | ce_Bsy | ce_Txb | ce_Rxb;
209 */
210
211 /* step 17: set parity, no of bits, UART mode, ... */
212 lcr = SMUart;
213 bits = uart->bits + 1;
214
215 switch(uart->parity){
216 case 'e':
217 lcr |= (Pen|Pm);
218 bits +=1;
219 break;
220 case 'o':
221 lcr |= Pen;
222 bits +=1;
223 break;
224 case 'n':
225 default:
226 break;
227 }
228
229 if(uart->stop == 2){
230 lcr |= Sl;
231 bits += 1;
232 }
233
234 /* Set new value and reenable if device was previously enabled */
235 smc->smcmr = lcr | bits <<11 | 0x3;
236
237 ud->initialized = 1;
238 }
239
240 static void
smcenable(Uart * uart,int intenb)241 smcenable(Uart *uart, int intenb)
242 {
243 UartData *ud;
244 SMC *smc;
245 int nr;
246
247 nr = uart - smcuart;
248 if (nr < 0 || nr > Nuart)
249 panic("No SMC %d", nr);
250 ud = uartdata + nr;
251 ud->smcno = nr;
252 uart->regs = ud;
253 if (ud->initialized == 0)
254 smcinit(uart);
255 if (ud->enabled || intenb == 0)
256 return;
257 smc = ud->smc;
258 /* clear events */
259 smc->smce = ce_Brke | ce_Br | ce_Bsy | ce_Txb | ce_Rxb;
260 /* enable interrupts */
261 smc->smcm = ce_Brke | ce_Br | ce_Bsy | ce_Txb | ce_Rxb;
262 intrenable(VecSMC1 + ud->smcno, smcinterrupt, uart, uart->name);
263 ud->enabled = 1;
264 }
265
266 static long
smcstatus(Uart * uart,void * buf,long n,long offset)267 smcstatus(Uart* uart, void* buf, long n, long offset)
268 {
269 SMC *sp;
270 char p[128];
271
272 sp = ((UartData*)uart->regs)->smc;
273 snprint(p, sizeof p, "b%d c%d e%d l%d m0 p%c s%d i1\n"
274 "dev(%d) type(%d) framing(%d) overruns(%d)\n",
275
276 uart->baud,
277 uart->hup_dcd,
278 uart->hup_dsr,
279 ((sp->smcmr & Clen) >>11) - ((sp->smcmr&Pen) ? 1 : 0) - ((sp->smcmr&Sl) ? 2 : 1),
280 (sp->smcmr & Pen) ? ((sp->smcmr & Pm) ? 'e': 'o'): 'n',
281 (sp->smcmr & Sl) ? 2: 1,
282
283 uart->dev,
284 uart->type,
285 uart->ferr,
286 uart->oerr
287 );
288 n = readstr(offset, buf, n, p);
289 free(p);
290
291 return n;
292 }
293
294 static void
smcfifo(Uart *,int)295 smcfifo(Uart*, int)
296 {
297 /*
298 * Toggle FIFOs:
299 * if none, do nothing;
300 * reset the Rx and Tx FIFOs;
301 * empty the Rx buffer and clear any interrupt conditions;
302 * if enabling, try to turn them on.
303 */
304 return;
305 }
306
307 static void
smcdtr(Uart *,int)308 smcdtr(Uart*, int)
309 {
310 }
311
312 static void
smcrts(Uart *,int)313 smcrts(Uart*, int)
314 {
315 }
316
317 static void
smcmodemctl(Uart *,int)318 smcmodemctl(Uart*, int)
319 {
320 }
321
322 static int
smcparity(Uart * uart,int parity)323 smcparity(Uart* uart, int parity)
324 {
325 int lcr;
326 SMC *sp;
327
328 sp = ((UartData*)uart->regs)->smc;
329
330 lcr = sp->smcmr & ~(Pen|Pm);
331
332 /* Disable transmitter/receiver. */
333 sp->smcmr &= ~(Ren | Ten);
334
335 switch(parity){
336 case 'e':
337 lcr |= (Pen|Pm);
338 break;
339 case 'o':
340 lcr |= Pen;
341 break;
342 case 'n':
343 default:
344 break;
345 }
346 /* Set new value and reenable if device was previously enabled */
347 sp->smcmr = lcr;
348
349 uart->parity = parity;
350
351 return 0;
352 }
353
354 static int
smcstop(Uart * uart,int stop)355 smcstop(Uart* uart, int stop)
356 {
357 int lcr, bits;
358 SMC *sp;
359
360 sp = ((UartData*)uart->regs)->smc;
361 lcr = sp->smcmr & ~(Sl | Clen);
362
363 /* Disable transmitter/receiver. */
364 sp->smcmr &= ~(Ren | Ten);
365
366 switch(stop){
367 case 1:
368 break;
369 case 2:
370 lcr |= Sl;
371 break;
372 default:
373 return -1;
374 }
375
376 bits = uart->bits + ((lcr & Pen) ? 1 : 0) + ((lcr & Sl) ? 2 : 1);
377 lcr |= bits<<11;
378
379 /* Set new value and reenable if device was previously enabled */
380 sp->smcmr = lcr;
381
382 uart->stop = stop;
383
384 return 0;
385 }
386
387 static int
smcbits(Uart * uart,int bits)388 smcbits(Uart* uart, int bits)
389 {
390 int lcr, b;
391 SMC *sp;
392
393 if (bits < 5 || bits > 14)
394 return -1;
395
396 sp = ((UartData*)uart->regs)->smc;
397 lcr = sp->smcmr & ~Clen;
398
399 b = bits + ((sp->smcmr & Pen) ? 1 : 0) + ((sp->smcmr & Sl) ? 2 : 1);
400
401 if (b > 15)
402 return -1;
403
404 /* Disable transmitter/receiver */
405 sp->smcmr &= ~(Ren | Ten);
406
407 /* Set new value and reenable if device was previously enabled */
408 sp->smcmr = lcr | b<<11;
409
410 uart->bits = bits;
411
412 return 0;
413 }
414
415 static int
smcbaud(Uart * uart,int baud)416 smcbaud(Uart* uart, int baud)
417 {
418 int i;
419 SMC *sp;
420
421 if (uart->enabled){
422 sp = ((UartData*)uart->regs)->smc;
423
424 if(uart->freq == 0 || baud <= 0)
425 return -1;
426
427 i = sp - imm->smc;
428 imm->brgc[i] = (((m->brghz >> 4) / baud) << 1) | 0x00010000;
429 }
430 uart->baud = baud;
431
432 return 0;
433 }
434
435 static void
smcbreak(Uart *,int)436 smcbreak(Uart*, int)
437 {
438 }
439
440 static void
smckick(Uart * uart)441 smckick(Uart *uart)
442 {
443 BD *txb;
444 UartData *ud;
445 int i;
446
447 if(uart->blocked)
448 return;
449
450 ud = uart->regs;
451 txb = ud->txb;
452
453 if (txb->status & BDReady)
454 return; /* Still busy */
455
456 for(i = 0; i < Txsize; i++){
457 if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
458 break;
459 ud->txbuf[i] = *(uart->op++);
460 }
461 if (i == 0)
462 return;
463 dcflush(ud->txbuf, Txsize);
464 txb->length = i;
465 sync();
466 txb->status |= BDReady|BDInt;
467 }
468
469 static void
smcinterrupt(Ureg *,void * u)470 smcinterrupt(Ureg*, void* u)
471 {
472 int i, nc;
473 char *buf;
474 BD *rxb;
475 UartData *ud;
476 Uart *uart;
477 uchar events;
478
479 uart = u;
480 if (uart == nil)
481 panic("uart is nil");
482 ud = uart->regs;
483 if (ud == nil)
484 panic("ud is nil");
485
486 events = ud->smc->smce;
487 ud->smc->smce = events; /* Clear events */
488
489 if (events & 0x10)
490 iprint("smc%d: break\n", ud->smcno);
491 if (events & 0x4)
492 uart->oerr++;
493 if (events & 0x1){
494 /* Receive characters
495 */
496 rxb = ud->rxb;
497 buf = ud->rxbuf;
498 dczap(buf, Rxsize); /* invalidate data cache before copying */
499 if ((rxb->status & BDEmpty) == 0){
500 nc = rxb->length;
501 for (i=0; i<nc; i++)
502 uartrecv(uart, *buf++);
503 sync();
504 rxb->status |= BDEmpty;
505 }else{
506 iprint("uartsmc: unexpected receive event\n");
507 }
508 }
509 if (events & 0x2){
510 if ((ud->txb->status & BDReady) == 0)
511 uartkick(uart);
512 }
513 }
514
515 static void
smcdisable(Uart * uart)516 smcdisable(Uart* uart)
517 {
518 SMC *sp;
519
520 sp = ((UartData*)uart->regs)->smc;
521 sp->smcmr &= ~(Ren | Ten);
522 }
523
524 static int
getchars(Uart * uart,uchar * cbuf)525 getchars(Uart *uart, uchar *cbuf)
526 {
527 int i, nc;
528 char *buf;
529 BD *rxb;
530 UartData *ud;
531
532 ud = uart->regs;
533 rxb = ud->rxb;
534
535 /* Wait for character to show up.
536 */
537 buf = ud->rxbuf;
538 while (rxb->status & BDEmpty)
539 ;
540 nc = rxb->length;
541 for (i=0; i<nc; i++)
542 *cbuf++ = *buf++;
543 sync();
544 rxb->status |= BDEmpty;
545
546 return(nc);
547 }
548
549 static int
smcgetc(Uart * uart)550 smcgetc(Uart *uart)
551 {
552 static uchar buf[128], *p;
553 static int cnt;
554 char c;
555
556 if (cnt <= 0) {
557 cnt = getchars(uart, buf);
558 p = buf;
559 }
560 c = *p++;
561 cnt--;
562
563 return(c);
564 }
565
566 static void
smcputc(Uart * uart,int c)567 smcputc(Uart *uart, int c)
568 {
569 BD *txb;
570 UartData *ud;
571 SMC *smc;
572
573 ud = uart->regs;
574 txb = ud->txb;
575 smc = ud->smc;
576 smc->smcm = 0;
577
578 /* Wait for last character to go.
579 */
580 while (txb->status & BDReady)
581 ;
582
583 ud->txbuf[0] = c;
584 dcflush(ud->txbuf, 1);
585 txb->length = 1;
586 sync();
587 txb->status |= BDReady;
588
589 while (txb->status & BDReady)
590 ;
591 }
592
593 PhysUart smcphysuart = {
594 .name = "smc",
595 .pnp = smcpnp,
596 .enable = smcenable,
597 .disable = smcdisable,
598 .kick = smckick,
599 .dobreak = smcbreak,
600 .baud = smcbaud,
601 .bits = smcbits,
602 .stop = smcstop,
603 .parity = smcparity,
604 .modemctl = smcmodemctl,
605 .rts = smcrts,
606 .dtr = smcdtr,
607 .status = smcstatus,
608 .fifo = smcfifo,
609 .getc = smcgetc,
610 .putc = smcputc,
611 };
612
613 void
console(void)614 console(void)
615 {
616 Uart *uart;
617 int n;
618 char *cmd, *p;
619
620 if((p = getconf("console")) == nil)
621 return;
622 n = strtoul(p, &cmd, 0);
623 if(p == cmd)
624 return;
625 if(n < 0 || n >= nelem(smcuart))
626 return;
627 uart = smcuart + n;
628
629 /* uartctl(uart, "b115200 l8 pn s1"); */
630 if(*cmd != '\0')
631 uartctl(uart, cmd);
632 (*uart->phys->enable)(uart, 0);
633
634 consuart = uart;
635 uart->console = 1;
636 }
637