1 #include "pxa260/pxa260_UART.h"
2 
3 
4 
5 //TODO: signal handler for Ctl+C and send break to fifo :)
6 //todo: recalc ints after eveyr write and every call to "process" from SoC
7 
8 
9 #define UART_IER_DMAE		0x80	//DMA enable
10 #define UART_IER_UUE		0x40	//Uart unit enable
11 #define UART_IER_NRZE		0x20	//NRZI enable
12 #define UART_IER_RTOIE		0x10	//transmit timeout interrupt enable
13 #define UART_IER_MIE		0x08	//modem interrupt enable
14 #define UART_IER_RLSE		0x04	//receiver line status interrupt enable
15 #define UART_IER_TIE		0x02	//transmit data request interrupt enable
16 #define UART_IER_RAVIE		0x01	//receiver data available interrupt enable
17 
18 #define UART_IIR_FIFOES		0xC0	//fifo enable status
19 #define UART_IIR_TOD		0x08	//character timout interrupt pending
20 #define UART_IIR_RECV_ERR	0x06	//receive error(overrun, parity, framing, break)
21 #define UART_IIR_RECV_DATA	0x04	//receive data available
22 #define UART_IIR_RCV_TIMEOUT	0x0C	//receive data in buffer and been a while since we've seen more
23 #define UART_IIR_SEND_DATA	0x02	//transmit fifo requests data
24 #define UART_IIR_MODEM_STAT	0x00	//modem lines changed state(CTS, DSR, DI, DCD)
25 #define UART_IIR_NOINT		0x01	//no interrupt pending
26 
27 
28 #define UART_FCR_ITL_MASK	0xC0	//mask for ITL part of FCR
29 #define UART_FCR_ITL_1		0x00	//interrupt when >=1 byte in recv fifo
30 #define UART_FCR_ITL_8		0x40	//interrupt when >=8 byte in recv fifo
31 #define UART_FCR_ITL_16		0x80	//interrupt when >=16 byte in recv fifo
32 #define UART_FCR_ITL_32		0xC0	//interrupt when >=32 byte in recv fifo
33 #define UART_FCR_RESETTF	0x04	//reset tranmitter fifo
34 #define UART_FCR_RESETRF	0x02	//reset receiver fifo
35 #define UART_FCR_TRFIFOE	0x01	//transmit and receive fifo enable
36 
37 #define UART_LCR_DLAB		0x80	//divisor latch access bit
38 #define UART_LCR_SB		0x40	//send break
39 #define UART_LCR_STKYP		0x20	//sticky parity (send parity bit but dont care what value)
40 #define UART_LCR_EPS		0x10	//even parity select
41 #define UART_LCR_PEN		0x08	//parity enable
42 #define UART_LCR_STB		0x04	//stop bits (1 = 2, 0 = 1)
43 #define UART_LCR_WLS_MASK	0x03	//mask for WLS values
44 #define UART_LCR_WLS_8		0x03	//8 bit words
45 #define UART_LCR_WLS_7		0x02	//7 bit words
46 #define UART_LCR_WLS_6		0x01	//6 bit words
47 #define UART_LCR_WLS_5		0x00	//5 bit words
48 
49 #define UART_LSR_FIFOE		0x80	//fifo contails an error (framing, parity, or break)
50 #define UART_LSR_TEMT		0x40	//tranmitter empty (shift reg is empty and no more byte sin fifo/no byte in holding reg)
51 #define UART_LSR_TDRQ		0x20	//transmitter data request (see docs)
52 #define UART_LSR_BI		0x10	//send when char at front of fifo (or in holding reg) was a break char (chr reads as zero by itself)
53 #define UART_LSR_FE		0x08	//same as above, but for framing errors
54 #define UART_LSR_PE		0x04	//dame as above, but for parity errors
55 #define UART_LSR_OE		0x02	//recv fifo overran
56 #define UART_LSR_DR		0x01	//byte received
57 
58 #define UART_MCR_LOOP		0x10	//loop modem control lines (not full loopback)
59 #define UART_MCR_OUT2		0x08	//when loop is 0 enables or disables UART interrupts
60 #define UART_MCR_OUT1		0x04	//force RI to 1
61 #define UART_MCR_RTS		0x02	//1 -> nRTS is 0
62 #define UART_MCR_DTR		0x01	//0 -> nDTR is 0
63 
64 #define UART_MSR_DCD		0x80
65 #define UART_MSR_RI		0x40
66 #define UART_MSR_DSR		0x20
67 #define UART_MSR_CTS		0x10
68 #define UART_MSR_DDCD		0x08	//dcd changed since last read
69 #define UART_MSR_TERI		0x04	//ri has changed from 0 to 1 since last read
70 #define UART_MSR_DDSR		0x02	//dsr changed since last read
71 #define UART_MSR_DCTS		0x01	//cts changed since last read
72 
73 
74 
75 static void pxa260uartPrvRecalc(Pxa260uart* uart);
76 
77 
pxa260uartPrvIrq(Pxa260uart * uart,Boolean raise)78 static void pxa260uartPrvIrq(Pxa260uart* uart, Boolean raise){
79 
80 	pxa260icInt(uart->ic, uart->irq, !(uart->MCR & UART_MCR_LOOP) && (uart->MCR & UART_MCR_OUT2) && raise/* only raise if ints are enabled */);
81 }
82 
pxa260uartPrvDefaultRead(_UNUSED_ void * userData)83 static UInt16 pxa260uartPrvDefaultRead(_UNUSED_ void* userData){			//these are special funcs since they always get their own userData - the uart pointer :)
84 
85 	return UART_CHAR_NONE;	//we read nothing..as always
86 }
87 
pxa260uartPrvDefaultWrite(_UNUSED_ UInt16 chr,_UNUSED_ void * userData)88 static void pxa260uartPrvDefaultWrite(_UNUSED_ UInt16 chr, _UNUSED_ void* userData){	//these are special funcs since they always get their own userData - the uart pointer :)
89 
90 	//nothing to do here
91 }
92 
pxa260uartPrvGetchar(Pxa260uart * uart)93 static UInt16 pxa260uartPrvGetchar(Pxa260uart* uart){
94 
95 	Pxa260UartReadF func = uart->readF;
96 	void* data = (func == pxa260uartPrvDefaultRead) ? uart : uart->accessFuncsData;
97 
98 	return func(data);
99 }
100 
pxa260uartPrvPutchar(Pxa260uart * uart,UInt16 chr)101 static void pxa260uartPrvPutchar(Pxa260uart* uart, UInt16 chr){
102 
103 	Pxa260UartWriteF func = uart->writeF;
104 	void* data = (func == pxa260uartPrvDefaultWrite) ? uart : uart->accessFuncsData;
105 
106 	func(chr, data);
107 }
108 
pxa260uartPrvFifoUsed(UartFifo * fifo)109 UInt8 pxa260uartPrvFifoUsed(UartFifo* fifo){	//return num spots used
110 
111 	UInt8 v;
112 
113 	if(fifo->read == UART_FIFO_EMPTY) return 0;
114 	v = fifo->write + UART_FIFO_DEPTH - fifo->read;
115 	if(v > UART_FIFO_DEPTH) v -=UART_FIFO_DEPTH;
116 
117 	return v;
118 }
119 
pxa260uartPrvFifoFlush(UartFifo * fifo)120 void pxa260uartPrvFifoFlush(UartFifo* fifo){
121 
122 	fifo->read = UART_FIFO_EMPTY;
123 	fifo->write = UART_FIFO_EMPTY;
124 }
125 
pxa260uartPrvFifoPut(UartFifo * fifo,UInt16 val)126 Boolean pxa260uartPrvFifoPut(UartFifo* fifo, UInt16 val){	//return success
127 
128 	if(fifo->read == UART_FIFO_EMPTY){
129 
130 		fifo->read = 0;
131 		fifo->write = 1;
132 		fifo->buf[0] = val;
133 	}
134 	else if(fifo->read != fifo->write){	//only if not full
135 
136 		fifo->buf[fifo->write++] = val;
137 		if(fifo->write == UART_FIFO_DEPTH) fifo->write = 0;
138 	}
139 	else return false;
140 
141 	return true;
142 }
143 
pxa260uartPrvFifoGet(UartFifo * fifo)144 UInt16 pxa260uartPrvFifoGet(UartFifo* fifo){
145 
146 	UInt16 ret;
147 
148 	if(fifo->read == UART_FIFO_EMPTY){
149 
150 		ret = 0xFFFF;	//why not?
151 	}
152 	else{
153 
154 		ret = fifo->buf[fifo->read++];
155 		if(fifo->read == UART_FIFO_DEPTH) fifo->read = 0;
156 
157 		if(fifo->read == fifo->write){	//it is now empty
158 
159 			fifo->read = UART_FIFO_EMPTY;
160 			fifo->write = UART_FIFO_EMPTY;
161 		}
162 	}
163 
164 	return ret;
165 }
166 
pxa260uartPrvFifoPeekNth(UartFifo * fifo,UInt8 n)167 UInt16 pxa260uartPrvFifoPeekNth(UartFifo* fifo, UInt8 n){
168 
169 	UInt16 ret;
170 
171 
172 	if(fifo->read == UART_FIFO_EMPTY){
173 
174 		ret = 0xFFFF;	//why not?
175 	}
176 	else{
177 
178 		n += fifo->read;
179 		if(n >= UART_FIFO_DEPTH) n-= UART_FIFO_DEPTH;
180 		ret = fifo->buf[n];
181 	}
182 
183 	return ret;
184 }
185 
pxa260uartPrvFifoPeek(UartFifo * fifo)186 UInt16 pxa260uartPrvFifoPeek(UartFifo* fifo){
187 
188 	return pxa260uartPrvFifoPeekNth(fifo, 0);
189 }
190 
191 
sendVal(Pxa260uart * uart,UInt16 v)192 static void sendVal(Pxa260uart* uart, UInt16 v){
193 
194 	if(uart->LSR & UART_LSR_TEMT){	//if transmit, put in shift register immediately if it's idle
195 
196 		uart->transmitShift = v;
197 		uart->LSR &=~ UART_LSR_TEMT;
198 	}
199 	else if(uart->FCR & UART_FCR_TRFIFOE){	//put in tx fifo if in fifo mode
200 
201 		pxa260uartPrvFifoPut(&uart->TX, v);
202 		if(pxa260uartPrvFifoUsed(&uart->TX) > UART_FIFO_DEPTH / 2){	//we go went below half-full buffer - set appropriate bit...
203 
204 			uart->LSR &=~ UART_LSR_TDRQ;
205 		}
206 	}
207 	else if(uart->LSR & UART_LSR_TDRQ){	//send without fifo if in polled mode
208 
209 		uart->transmitHolding = v;
210 		uart->LSR &=~ UART_LSR_TDRQ;
211 	}
212 	else{
213 
214 		//nothing to do - buffer is full so we ignore this request
215 	}
216 }
217 
pxa260uartPrvMemAccessF(void * userData,UInt32 pa,UInt8 size,Boolean write,void * buf)218 static Boolean pxa260uartPrvMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf){
219 
220 	Pxa260uart* uart = userData;
221 	Boolean DLAB = (uart->LCR & UART_LCR_DLAB) != 0;
222 	Boolean recalcValues = false;
223 	UInt8 t, val = 0;
224 
225 	if(size != 4 && size != 1) {
226 		err_str(__FILE__ ": Unexpected ");
227 	//	err_str(write ? "write" : "read");
228 	//	err_str(" of ");
229 	//	err_dec(size);
230 	//	err_str(" bytes to 0x");
231 	//	err_hex(pa);
232 	//	err_str("\r\n");
233 		return true;		//we do not support non-word accesses
234 	}
235 
236 	pa = (pa - uart->baseAddr) >> 2;
237 
238 	if(write){
239 		recalcValues = true;
240 		val = (size == 1) ? *(UInt8*)buf : *(UInt32*)buf;
241 
242 		switch(pa){
243 			case 0:
244 				if(DLAB){				//if DLAB - set "baudrate"...
245 					uart->DLL = val;
246 					recalcValues = false;
247 				}
248 				else{
249 
250 					sendVal(uart, val);
251 				}
252 				break;
253 
254 			case 1:
255 				if(DLAB){
256 
257 					uart->DLH = val;
258 					recalcValues = false;
259 				}
260 				else{
261 					t = uart->IER ^ val;
262 
263 					if(t & UART_IER_DMAE){
264 
265 						err_str("pxa260UART: DMA mode cannot be enabled");
266 						t &=~ UART_IER_DMAE;	//undo the change
267 					}
268 
269 					if(t & UART_IER_UUE){
270 
271 						if(val & UART_IER_UUE){
272 
273 							uart->LSR = UART_LSR_TEMT | UART_LSR_TDRQ;
274 							uart->MSR = UART_MSR_CTS;
275 						}
276 					}
277 
278 					uart->IER ^= t;
279 				}
280 				break;
281 
282 			case 2:
283 				t = uart->FCR ^ val;
284 				if(t & UART_FCR_TRFIFOE){
285 					if(val & UART_FCR_TRFIFOE){			//fifos are now on - perform other actions as requested
286 
287 						if(val & UART_FCR_RESETRF){
288 
289 							pxa260uartPrvFifoFlush(&uart->RX);	//clear the RX fifo now
290 						}
291 						if(val & UART_FCR_RESETTF){
292 
293 							pxa260uartPrvFifoFlush(&uart->TX);	//clear the TX fifo now
294 							uart->LSR = UART_LSR_TEMT | UART_LSR_TDRQ;
295 						}
296 						uart->IIR = UART_IIR_FIFOES  |UART_IIR_NOINT;
297 					}
298 					else{
299 						pxa260uartPrvFifoFlush(&uart->TX);
300 						pxa260uartPrvFifoFlush(&uart->RX);
301 						uart->LSR = UART_LSR_TEMT | UART_LSR_TDRQ;
302 						uart->IIR = UART_IIR_NOINT;
303 					}
304 				}
305 				uart->FCR = val;
306 				break;
307 
308 			case 3:
309 				t = uart->LCR ^ val;
310 				if(t & UART_LCR_SB){
311 					if(val & UART_LCR_SB){	//break set (tx line pulled low)
312 
313 
314 					}
315 					else{			//break cleared (tx line released)
316 
317 						sendVal(uart, UART_CHAR_BREAK);
318 					}
319 				}
320 				uart->LCR = val;
321 				break;
322 
323 			case 4:
324 				uart->MCR = val;
325 				break;
326 
327 			case 7:
328 				uart->SPR = val;
329 				break;
330 
331 			case 8:
332 				uart->ISR = val;
333 				if(val & 3){
334 					err_str("UART: IrDA mode set on UART\n");
335 				}
336 				break;
337 		}
338 	}
339 	else{
340 		switch(pa){
341 			case 0:
342 				if(DLAB) val = uart->DLL;
343 				else if(!(uart->LSR & UART_LSR_DR)){	//no data-> too bad
344 
345 					val = 0;
346 				}
347 				else if(uart->FCR & UART_FCR_TRFIFOE){	//fifo mode -> read fifo
348 
349 					val = pxa260uartPrvFifoGet(&uart->RX);
350 					if(!pxa260uartPrvFifoUsed(&uart->RX)) uart->LSR &=~ UART_LSR_DR;
351 					recalcValues = true;		//error bits might have changed
352 				}
353 				else{					//polled mode -> read rx polled reg
354 
355 					val = uart->receiveHolding;
356 					uart->LSR &=~ UART_LSR_DR;
357 				}
358 				break;
359 
360 			case 1:
361 				if(DLAB) val = uart->DLH;
362 				else val = uart->IER;
363 				break;
364 
365 			case 2:
366 				val = uart->IIR;
367 				break;
368 
369 			case 3:
370 				val = uart->LCR;
371 				break;
372 
373 			case 4:
374 				val = uart->MCR;
375 				break;
376 
377 			case 5:
378 				val = uart->LSR;
379 				break;
380 
381 			case 6:
382 				val = uart->MSR;
383 				break;
384 
385 			case 7:
386 				val = uart->SPR;
387 				break;
388 
389 			case 8:
390 				val = uart->ISR;
391 				break;
392 		}
393 		if(size == 1) *(UInt8*)buf = val;
394 		else *(UInt32*)buf = val;
395 	}
396 
397 	if(recalcValues) pxa260uartPrvRecalc(uart);
398 
399 	return true;
400 }
401 
pxa260uartSetFuncs(Pxa260uart * uart,Pxa260UartReadF readF,Pxa260UartWriteF writeF,void * userData)402 void pxa260uartSetFuncs(Pxa260uart* uart, Pxa260UartReadF readF, Pxa260UartWriteF writeF, void* userData){
403 
404 	if(!readF) readF = pxa260uartPrvDefaultRead;		//these are special funcs since they get their own private data - the uart :)
405 	if(!writeF) writeF = pxa260uartPrvDefaultWrite;
406 
407 	uart->readF = readF;
408 	uart->writeF = writeF;
409 	uart->accessFuncsData = userData;
410 }
411 
pxa260uartInit(Pxa260uart * uart,Pxa260ic * ic,UInt32 baseAddr,UInt8 irq)412 void pxa260uartInit(Pxa260uart* uart, Pxa260ic* ic, UInt32 baseAddr, UInt8 irq){
413 
414 	__mem_zero(uart, sizeof(Pxa260uart));
415 	uart->ic = ic;
416 	uart->irq = irq;
417 	uart->baseAddr = baseAddr;
418 	uart->IIR = UART_IIR_NOINT;
419 	uart->IER = UART_IER_UUE | UART_IER_NRZE; 		//uart on
420 	uart->LSR = UART_LSR_TEMT | UART_LSR_TDRQ;
421 	uart->MSR = UART_MSR_CTS;
422 	pxa260uartPrvFifoFlush(&uart->TX);
423 	pxa260uartPrvFifoFlush(&uart->RX);
424 
425 
426 	pxa260uartSetFuncs(uart, NULL, NULL, NULL);
427 
428    //return memRegionAdd(physMem, baseAddr, PXA260_UART_SIZE, pxa260uartPrvMemAccessF, uart);
429 }
430 
pxa260uartProcess(Pxa260uart * uart)431 void pxa260uartProcess(Pxa260uart* uart){		//send and rceive up to one character
432 
433 	UInt8 t;
434 	UInt16 v;
435 
436 	//first process sending (if any)
437 	if(!(uart->LSR & UART_LSR_TEMT)){
438 
439 		pxa260uartPrvPutchar(uart, uart->transmitShift);
440 
441 		if(uart->FCR & UART_FCR_TRFIFOE){	//fifo mode
442 
443 			t = pxa260uartPrvFifoUsed(&uart->TX);
444 
445 			if(t--){
446 
447 				uart->transmitShift = pxa260uartPrvFifoGet(&uart->TX);
448 				if(t <= UART_FIFO_DEPTH / 2) uart->LSR |= UART_LSR_TDRQ;	//above half full - clear TDRQ bit
449 			}
450 			else{
451 
452 				uart->LSR |= UART_LSR_TEMT;
453 			}
454 		}
455 		else if (uart->LSR & UART_LSR_TDRQ){
456 
457 			uart->LSR |= UART_LSR_TEMT;
458 		}
459 		else{
460 
461 			uart->transmitShift = uart->transmitHolding;
462 			uart->LSR |= UART_LSR_TDRQ;
463 		}
464 	}
465 
466 	//now process receiving
467 	v = pxa260uartPrvGetchar(uart);
468 	if(v != UART_CHAR_NONE){
469 
470 		uart->cyclesSinceRecv = 0;
471 		uart->LSR |= UART_LSR_DR;
472 
473 		if(uart->FCR & UART_FCR_TRFIFOE){	//fifo mode
474 
475 			if(!pxa260uartPrvFifoPut(&uart->RX, v)){
476 
477 				uart->LSR |= UART_LSR_OE;
478 			}
479 		}
480 		else{
481 
482 			if(uart->LSR & UART_LSR_DR) uart->LSR |= UART_LSR_OE;
483 			else uart->receiveHolding = v;
484 		}
485 	}
486 	else if(uart->cyclesSinceRecv <= 4){
487 		uart->cyclesSinceRecv++;
488 	}
489 
490 	pxa260uartPrvRecalc(uart);
491 }
492 
pxa260uartPrvRecalcCharBits(Pxa260uart * uart,UInt16 c)493 static void pxa260uartPrvRecalcCharBits(Pxa260uart* uart, UInt16 c){
494 
495 	if(c & UART_CHAR_BREAK) uart->LSR |= UART_LSR_BI;
496 	if(c & UART_CHAR_FRAME_ERR) uart->LSR |= UART_LSR_FE;
497 	if(c & UART_CHAR_PAR_ERR) uart->LSR |= UART_LSR_PE;
498 }
499 
pxa260uartPrvRecalc(Pxa260uart * uart)500 static void pxa260uartPrvRecalc(Pxa260uart* uart){
501 
502 	Boolean errorSet = false;
503 	UInt8 v;
504 
505 	uart->LSR &=~ UART_LSR_FIFOE;
506 	uart->IIR &= UART_IIR_FIFOES;	//clear all other bits...
507 	uart->LSR &=~ (UART_LSR_BI | UART_LSR_FE | UART_LSR_PE);
508 
509 	if(uart->FCR & UART_FCR_TRFIFOE){	//fifo mode
510 
511 
512 		//check rx fifo for errors
513 		for(v = 0; v < pxa260uartPrvFifoUsed(&uart->RX); v++){
514 
515 			if((pxa260uartPrvFifoPeekNth(&uart->RX, v) >> 8) && (uart->IER & UART_IER_RLSE)){
516 
517 				uart->LSR |= UART_LSR_FIFOE;
518 				uart->IIR |= UART_IIR_RECV_ERR;
519 				errorSet = true;
520 				break;
521 			}
522 		}
523 
524 		v = pxa260uartPrvFifoUsed(&uart->RX);
525 		if(v){
526 			pxa260uartPrvRecalcCharBits(uart, pxa260uartPrvFifoPeek(&uart->RX));
527 		}
528 
529 		switch(uart->FCR & UART_FCR_ITL_MASK){
530 
531 			case UART_FCR_ITL_1:
532 				v = v >= 1;
533 				break;
534 
535 			case UART_FCR_ITL_8:
536 				v = v >= 8;
537 				break;
538 
539 			case UART_FCR_ITL_16:
540 				v = v >= 16;
541 				break;
542 
543 			case UART_FCR_ITL_32:
544 				v = v >= 32;
545 				break;
546 		}
547 		if(v && (uart->IER & UART_IER_RAVIE) && !errorSet){
548 
549 			errorSet = true;
550 			uart->IIR |= UART_IIR_RECV_DATA;
551 		}
552 		if(pxa260uartPrvFifoUsed(&uart->RX) && uart->cyclesSinceRecv >= 4 && (uart->IER & UART_IER_RAVIE) && !errorSet){
553 
554 			errorSet = true;
555 			uart->IIR |= UART_IIR_RCV_TIMEOUT;
556 		}
557 	}
558 	else{		//polling mode
559 
560 		UInt16 c = uart->receiveHolding;
561 
562 		if(uart->LSR & UART_LSR_DR){
563 
564 			pxa260uartPrvRecalcCharBits(uart, c);
565 
566 			if((c >> 8) && !errorSet && (uart->IER & UART_IER_RLSE)){
567 
568 				uart->IIR |= UART_IIR_RECV_ERR;
569 				errorSet = true;
570 			}
571 			else if(!errorSet && (uart->IER & UART_IER_RAVIE)){
572 
573 				uart->IIR |= UART_IIR_RECV_DATA;
574 				errorSet = true;
575 			}
576 		}
577 	}
578 
579 	if(uart->LSR & UART_LSR_TDRQ && !errorSet && (uart->IER & UART_IER_TIE)){
580 
581 		errorSet = true;
582 		uart->IIR |= UART_IIR_SEND_DATA;
583 	}
584 
585 	if(!errorSet) uart->IIR |= UART_IIR_NOINT;
586 	pxa260uartPrvIrq(uart, errorSet);
587 }
588