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