xref: /plan9/sys/src/9/pc/uartox.c (revision 6bbfed0d85c6d7248503ef0614d0f1e40438b735)
1 /*
2  * Oxford Semiconductor OXPCIe95x UART driver
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 
12 extern PhysUart oxphysuart;
13 
14 enum {
15 	Ccr		= 0x0000/4,	/* Class Code and Revision ID */
16 	Nuart		= 0x0004/4,	/* Decimal Number of UARTs */
17 	Gis		= 0x0008/4,	/* Global UART IRQ Status */
18 	Gie		= 0x000C/4,	/* Global UART IRQ Enable */
19 	Gid		= 0x0010/4,	/* Global UART IRQ Disable */
20 	Gwe		= 0x0014/4,	/* Global UART Wake Enable */
21 	Gwd		= 0x0018/4,	/* Global UART Wake Disable */
22 };
23 
24 enum {
25 	Thr		= 0x00,		/* Transmitter Holding */
26 	Rhr		= 0x00,		/* Receiver Holding */
27 	Ier		= 0x01,		/* Interrupt Enable */
28 	Fcr		= 0x02,		/* FIFO Control */
29 	Isr		= 0x02,		/* Interrupt Status */
30 	Lcr		= 0x03,		/* Line Control */
31 	Mcr		= 0x04,		/* Modem Control */
32 	Lsr		= 0x05,		/* Line Status */
33 	Msr		= 0x06,		/* Modem Status */
34 	Spr		= 0x07,		/* Scratch Pad */
35 	Dll		= 0x00,		/* Divisor Latch LSB */
36 	Dlm		= 0x01,		/* Divisor Latch MSB */
37 	Efr		= 0x02,		/* Enhanced Feature */
38 };
39 
40 typedef struct Port Port;
41 typedef struct Ctlr Ctlr;
42 
43 struct Port {
44 	Uart;
45 	Ctlr	*ctlr;
46 	u8int	*mem;
47 
48 	int	level;
49 	int	dtr, rts;
50 	int	ri;
51 };
52 
53 struct Ctlr {
54 	Lock;
55 	char	*name;
56 	Pcidev	*pcidev;
57 	u32int	*mem;
58 
59 	u32int	im;
60 
61 	Port	port[0x10];
62 	int	nport;
63 };
64 
65 static Uart *
oxpnp(void)66 oxpnp(void)
67 {
68 	Pcidev *p;
69 	Ctlr *ctlr;
70 	Port *port;
71 	int i;
72 	char *model;
73 	char name[12+1];
74 	Uart *head, *tail;
75 	static int ctlrno;
76 
77 	p = nil;
78 	head = tail = nil;
79 	while(p = pcimatch(p, 0x1415, 0)){
80 		switch(p->did){
81 		case 0xc101:
82 		case 0xc105:
83 		case 0xc11b:
84 		case 0xc11f:
85 		case 0xc120:
86 		case 0xc124:
87 		case 0xc138:
88 		case 0xc13d:
89 		case 0xc140:
90 		case 0xc141:
91 		case 0xc144:
92 		case 0xc145:
93 		case 0xc158:
94 		case 0xc15d:
95 			model = "OXPCIe952";
96 			break;
97 		case 0xc208:
98 		case 0xc20d:
99 			model = "OXPCIe954";
100 			break;
101 		case 0xc308:
102 		case 0xc30d:
103 			model = "OXPCIe958";
104 			break;
105 		default:
106 			continue;
107 		}
108 		ctlr = malloc(sizeof *ctlr);
109 		if(ctlr == nil){
110 			print("oxpnp: out of memory\n");
111 			continue;
112 		}
113 		ctlr->pcidev = p;
114 		ctlr->mem = vmap(p->mem[0].bar & ~0xf, p->mem[0].size);
115 		if(ctlr->mem == nil){
116 			print("oxpnp: vmap failed\n");
117 			free(ctlr);
118 			continue;
119 		}
120 		snprint(name, sizeof name, "uartox%d", ctlrno);
121 		kstrdup(&ctlr->name, name);
122 		ctlr->nport = ctlr->mem[Nuart] & 0x1f;
123 		for(i = 0; i < ctlr->nport; ++i){
124 			port = &ctlr->port[i];
125 			port->ctlr = ctlr;
126 			port->mem = (u8int *)ctlr->mem + 0x1000 + 0x200*i;
127 			port->regs = port;
128 			snprint(name, sizeof name, "%s.%d", ctlr->name, i);
129 			kstrdup(&port->name, name);
130 			port->phys = &oxphysuart;
131 			if(head == nil)
132 				head = port;
133 			else
134 				tail->next = port;
135 			tail = port;
136 		}
137 		print("%s: %s: %d ports irq %d\n",
138 		    ctlr->name, model, ctlr->nport, p->intl);
139 		ctlrno++;
140 	}
141 	return head;
142 }
143 
144 static void
oxinterrupt(Ureg *,void * arg)145 oxinterrupt(Ureg *, void *arg)
146 {
147 	Ctlr *ctlr;
148 	Port *port;
149 	Uart *uart;
150 	int i, old;
151 	u8int val;
152 	char ch;
153 
154 	ctlr = arg;
155 
156 	ilock(ctlr);
157 	if(!(ctlr->im & ctlr->mem[Gis])){
158 		iunlock(ctlr);
159 		return;
160 	}
161 	for(i = 0; i < ctlr->nport; ++i){
162 		if(!(ctlr->im & 1<<i))
163 			continue;
164 		port = &ctlr->port[i];
165 		uart = port;	/* "Come Clarity" */
166 		switch(port->mem[Isr] & 0x3f){
167 		case 0x06:	/* Receiver status error */
168 		case 0x04:	/* Receiver data available */
169 		case 0x0c:	/* Receiver time-out */
170 			for(;;){
171 				val = port->mem[Lsr];
172 				if(!(val & 1<<0))	/* RxRDY */
173 					break;
174 				if(val & 1<<1)		/* Overrun Error */
175 					uart->oerr++;
176 				if(val & 1<<2)		/* Parity Error */
177 					uart->perr++;
178 				if(val & 1<<3)		/* Framing Error */
179 					uart->ferr++;
180 				ch = port->mem[Rhr];
181 				if(!(val & 1<<7))	/* Data Error */
182 					uartrecv(uart, ch);
183 			}
184 			break;
185 		case 0x02:	/* Transmitter THR empty */
186 			uartkick(uart);
187 			break;
188 		case 0x00:	/* Modem status change */
189 			val = port->mem[Msr];
190 			if(val & 1<<0){			/* Delta nCTS */
191 				ilock(&uart->tlock);
192 				old = uart->cts;
193 				uart->cts = val & 1<<4;	/* CTS */
194 				if(!old && uart->cts)
195 					uart->ctsbackoff = 2;
196 				iunlock(&uart->tlock);
197 			}
198 			if(val & 1<<1){			/* Delta nDSR */
199 				old = val & 1<<5;	/* DSR */
200 				if(!old && uart->dsr && uart->hup_dsr)
201 					uart->dohup = 1;
202 				uart->dsr = old;
203 			}
204 			port->ri = val & 1<<6;		/* RI */
205 			if(val & 1<<3){			/* Delta nDCD */
206 				old = val & 1<<7;	/* DCD */
207 				if(!old && uart->dcd && uart->hup_dcd)
208 					uart->dohup = 1;
209 				uart->dcd = old;
210 			}
211 			break;
212 		}
213 	}
214 	iunlock(ctlr);
215 }
216 
217 #define MASK(p)	(1UL<<((p)-(p)->ctlr->port))
218 
219 static void
oxenable(Uart * uart,int)220 oxenable(Uart *uart, int)
221 {
222 	Ctlr *ctlr;
223 	Port *port;
224 
225 	port = uart->regs;
226 	ctlr = port->ctlr;
227 
228 	ilock(ctlr);
229 	if(ctlr->im == 0)
230 		intrenable(ctlr->pcidev->intl, oxinterrupt, ctlr,
231 		    ctlr->pcidev->tbdf, ctlr->name);
232 	ctlr->im |= MASK(port);
233 	iunlock(ctlr);
234 
235 	/* Enable 950 Mode */
236 	port->mem[Lcr] |= 1<<7;			/* Divisor latch access */
237 	port->mem[Efr] = 1<<4;			/* Enhanced mode */
238 	port->mem[Lcr] &= ~(1<<7);
239 
240 	port->mem[Ier] = 1<<2|1<<1|1<<0;	/* Rx Stat, THRE, RxRDY */
241 
242 	(*uart->phys->dtr)(uart, 1);
243 	(*uart->phys->rts)(uart, 1);
244 
245 	/* Enable FIFO */
246 	(*uart->phys->fifo)(uart, ~0);
247 }
248 
249 static void
oxdisable(Uart * uart)250 oxdisable(Uart *uart)
251 {
252 	Ctlr *ctlr;
253 	Port *port;
254 
255 	port = uart->regs;
256 	ctlr = port->ctlr;
257 
258 	(*uart->phys->dtr)(uart, 0);
259 	(*uart->phys->rts)(uart, 0);
260 	(*uart->phys->fifo)(uart, 0);
261 
262 	port->mem[Ier] = 0;
263 
264 	ilock(ctlr);
265 	ctlr->im &= ~MASK(port);
266 	if(ctlr->im == 0)
267 		intrdisable(ctlr->pcidev->intl, oxinterrupt, ctlr,
268 		    ctlr->pcidev->tbdf, ctlr->name);
269 	iunlock(ctlr);
270 }
271 
272 static void
oxkick(Uart * uart)273 oxkick(Uart *uart)
274 {
275 	Port *port;
276 
277 	if(uart->cts == 0 || uart->blocked)
278 		return;
279 
280 	port = uart->regs;
281 
282 	for(;;){
283 		if(!(port->mem[Lsr] & 1<<5))	/* THR Empty */
284 			break;
285 		if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
286 			break;
287 		port->mem[Thr] = *(uart->op++);
288 	}
289 }
290 
291 static void
oxdobreak(Uart * uart,int ms)292 oxdobreak(Uart *uart, int ms)
293 {
294 	Port *port;
295 
296 	if(ms <= 0)
297 		ms = 200;
298 
299 	port = uart->regs;
300 
301 	port->mem[Lcr] |= 1<<6;			/* Transmission break */
302 	if(!waserror()){
303 		tsleep(&up->sleep, return0, nil, ms);
304 		poperror();
305 	}
306 	port->mem[Lcr] &= ~(1<<6);
307 }
308 
309 static int
oxbaud(Uart * uart,int baud)310 oxbaud(Uart *uart, int baud)
311 {
312 	Port *port;
313 	u16int val;
314 
315 	if(baud <= 0)
316 		return -1;
317 
318 	port = uart->regs;
319 
320 	/*
321 	 * We aren't terribly interested in non-standard baud rates.
322 	 * Rather than mess about with generator constants, we instead
323 	 * program DLM and DLL according to Table 37 in the datasheet.
324 	 */
325 	switch(baud){
326 	case 1200:
327 		val = 0x0cb6;
328 		break;
329 	case 2400:
330 		val = 0x065b;
331 		break;
332 	case 4800:
333 		val = 0x032d;
334 		break;
335 	case 9600:
336 		val = 0x0196;
337 		break;
338 	case 19200:
339 		val = 0x00cb;
340 		break;
341 	case 38400:
342 		val = 0x0066;
343 		break;
344 	case 57600:
345 		val = 0x0044;
346 		break;
347 	case 115200:
348 		val = 0x0022;
349 		break;
350 	default:
351 		return -1;
352 	}
353 	port->mem[Lcr] |= 1<<7;			/* Divisor latch access */
354 	port->mem[Dlm] = val>>8;
355 	port->mem[Dll] = val;
356 	port->mem[Lcr] &= ~(1<<7);
357 	uart->baud = baud;
358 	return 0;
359 }
360 
361 static int
oxbits(Uart * uart,int bits)362 oxbits(Uart *uart, int bits)
363 {
364 	Port *port;
365 	u8int val;
366 
367 	port = uart->regs;
368 
369 	val = port->mem[Lcr] & 0x7c;
370 	switch(bits){
371 	case 8:
372 		val |= 0x3;			/* Data length */
373 		break;
374 	case 7:
375 		val |= 0x2;
376 		break;
377 	case 6:
378 		val |= 0x1;
379 		break;
380 	case 5:
381 		break;
382 	default:
383 		return -1;
384 	}
385 	port->mem[Lcr] = val;
386 	uart->bits = bits;
387 	return 0;
388 }
389 
390 static int
oxstop(Uart * uart,int stop)391 oxstop(Uart *uart, int stop)
392 {
393 	Port *port;
394 	u8int val;
395 
396 	port = uart->regs;
397 
398 	val = port->mem[Lcr] & 0x7b;
399 	switch(stop){
400 	case 2:
401 		val |= 1<<2;			/* Number of Stop Bits */
402 		break;
403 	case 1:
404 		break;
405 	default:
406 		return -1;
407 	}
408 	port->mem[Lcr] = val;
409 	uart->stop = stop;
410 	return 0;
411 }
412 
413 static int
oxparity(Uart * uart,int parity)414 oxparity(Uart *uart, int parity)
415 {
416 	Port *port;
417 	u8int val;
418 
419 	port = uart->regs;
420 
421 	val = port->mem[Lcr] & 0x67;
422 	switch(parity){
423 	case 'e':
424 		val |= 1<<4;			/* Even/Odd Parity */
425 	case 'o':
426 		val |= 1<<3;			/* Parity Enable */
427 		break;
428 	case 'n':
429 		break;
430 	default:
431 		return -1;
432 	}
433 	port->mem[Lcr] = val;
434 	uart->parity = parity;
435 	return 0;
436 }
437 
438 static void
oxmodemctl(Uart * uart,int on)439 oxmodemctl(Uart *uart, int on)
440 {
441 	Ctlr *ctlr;
442 	Port *port;
443 
444 	port = uart->regs;
445 	ctlr = port->ctlr;
446 
447 	ilock(ctlr);
448 	ilock(&uart->tlock);
449 	if(on){
450 		port->mem[Ier] |= 1<<3;			/* Modem */
451 		uart->cts = port->mem[Msr] & 1<<4;	/* CTS */
452 	}else{
453 		port->mem[Ier] &= ~(1<<3);
454 		uart->cts = 1;
455 	}
456 	uart->modem = on;
457 	iunlock(&uart->tlock);
458 	iunlock(ctlr);
459 }
460 
461 static void
oxrts(Uart * uart,int on)462 oxrts(Uart *uart, int on)
463 {
464 	Port *port;
465 
466 	port = uart->regs;
467 
468 	if(on)
469 		port->mem[Mcr] |= 1<<1;		/* RTS */
470 	else
471 		port->mem[Mcr] &= ~(1<<1);
472 	port->rts = on;
473 }
474 
475 static void
oxdtr(Uart * uart,int on)476 oxdtr(Uart *uart, int on)
477 {
478 	Port *port;
479 
480 	port = uart->regs;
481 
482 	if(on)
483 		port->mem[Mcr] |= 1<<0;		/* DTR */
484 	else
485 		port->mem[Mcr] &= ~(1<<0);
486 	port->dtr = on;
487 }
488 
489 static long
oxstatus(Uart * uart,void * buf,long n,long offset)490 oxstatus(Uart *uart, void *buf, long n, long offset)
491 {
492 	Port *port;
493 
494 	if(offset > 0)
495 		return 0;
496 
497 	port = uart->regs;
498 
499 	return snprint(buf, n,
500 	    "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
501 	    "dev(%d) type(%d) framing(%d) overruns(%d) "
502 	    "berr(%d) serr(%d)%s%s%s%s\n",
503 
504 	    uart->baud,
505 	    uart->hup_dcd,
506 	    port->dtr,
507 	    uart->hup_dsr,
508 	    uart->bits,
509 	    uart->modem,
510 	    uart->parity,
511 	    port->rts,
512 	    uart->stop,
513 	    port->level,
514 
515 	    uart->dev,
516 	    uart->type,
517 	    uart->ferr,
518 	    uart->oerr,
519 	    uart->berr,
520 	    uart->serr,
521 	    uart->cts ? " cts": "",
522 	    uart->dsr ? " dsr": "",
523 	    port->ri ? " ring": "",
524 	    uart->dcd ? " dcd": ""
525 	);
526 }
527 
528 static void
oxfifo(Uart * uart,int level)529 oxfifo(Uart *uart, int level)
530 {
531 	Ctlr *ctlr;
532 	Port *port;
533 
534 	port = uart->regs;
535 	ctlr = port->ctlr;
536 
537 	/*
538 	 * 950 Mode FIFOs have a depth of 128 bytes; devuart only
539 	 * cares about setting RHR trigger levels.  THR trigger
540 	 * levels are not supported.
541 	 */
542 	ilock(ctlr);
543 	if(level == 0)
544 		port->mem[Fcr] = 0;		/* Disable FIFO */
545 	else{
546 		port->mem[Fcr] = 1<<0;		/* Enable FIFO */
547 		switch(level){
548 		default:
549 			level = 112;
550 		case 112:
551 			port->mem[Fcr] = 0x03<<6|1<<0;	/* RHR Trigger Level */
552 			break;
553 		case 64:
554 			port->mem[Fcr] = 0x02<<6|1<<0;
555 			break;
556 		case 32:
557 			port->mem[Fcr] = 0x01<<6|1<<0;
558 			break;
559 		case 16:
560 			break;
561 		}
562 	}
563 	port->level = level;
564 	iunlock(ctlr);
565 }
566 
567 PhysUart oxphysuart = {
568 	.name		= "OXPCIe95x",
569 	.pnp		= oxpnp,
570 	.enable		= oxenable,
571 	.disable	= oxdisable,
572 	.kick		= oxkick,
573 	.dobreak	= oxdobreak,
574 	.baud		= oxbaud,
575 	.bits		= oxbits,
576 	.stop		= oxstop,
577 	.parity		= oxparity,
578 	.modemctl	= oxmodemctl,
579 	.rts		= oxrts,
580 	.dtr		= oxdtr,
581 	.status		= oxstatus,
582 	.fifo		= oxfifo,
583 };
584