TianoCore EDK2 master
Loading...
Searching...
No Matches
BaseSerialPortLibHob.c
Go to the documentation of this file.
1
8#include <PiDxe.h>
9#include <Base.h>
10#include <Library/PcdLib.h>
11#include <Library/IoLib.h>
12#include <Library/BaseLib.h>
13#include <Library/HobLib.h>
14#include <Library/TimerLib.h>
15#include <Library/DebugLib.h>
16#include <Protocol/SerialIo.h>
18
19//
20// 16550 UART register offsets and bitfields
21//
22#define R_UART_RXBUF 0 // LCR_DLAB = 0
23#define R_UART_TXBUF 0 // LCR_DLAB = 0
24#define R_UART_BAUD_LOW 0 // LCR_DLAB = 1
25#define R_UART_BAUD_HIGH 1 // LCR_DLAB = 1
26#define R_UART_IER 1 // LCR_DLAB = 0
27#define R_UART_FCR 2
28#define B_UART_FCR_FIFOE BIT0
29#define B_UART_FCR_FIFO64 BIT5
30#define R_UART_LCR 3
31#define B_UART_LCR_DLAB BIT7
32#define R_UART_MCR 4
33#define B_UART_MCR_DTRC BIT0
34#define B_UART_MCR_RTS BIT1
35#define R_UART_LSR 5
36#define B_UART_LSR_RXRDY BIT0
37#define B_UART_LSR_TXRDY BIT5
38#define B_UART_LSR_TEMT BIT6
39#define R_UART_MSR 6
40#define B_UART_MSR_CTS BIT4
41#define B_UART_MSR_DSR BIT5
42#define B_UART_MSR_RI BIT6
43#define B_UART_MSR_DCD BIT7
44
45#define MAX_SIZE 16
46
47typedef struct {
48 UINTN BaseAddress;
49 BOOLEAN UseMmio;
50 UINT32 BaudRate;
51 UINT8 RegisterStride;
52} UART_INFO;
53
54UART_INFO mUartInfo[MAX_SIZE];
55UINT8 mUartCount = 0;
56BOOLEAN mBaseSerialPortLibHobAtRuntime = FALSE;
57
71UINT8
73 UINTN Base,
74 UINTN Offset,
75 BOOLEAN UseMmio,
76 UINT8 RegisterStride
77 )
78{
79 if (UseMmio) {
80 return MmioRead8 (Base + Offset * RegisterStride);
81 } else {
82 return IoRead8 (Base + Offset * RegisterStride);
83 }
84}
85
100UINT8
102 UINTN Base,
103 UINTN Offset,
104 UINT8 Value,
105 BOOLEAN UseMmio,
106 UINT8 RegisterStride
107 )
108{
109 if (UseMmio) {
110 return MmioWrite8 (Base + Offset * RegisterStride, Value);
111 } else {
112 return IoWrite8 (Base + Offset * RegisterStride, Value);
113 }
114}
115
125RETURN_STATUS
126EFIAPI
128 VOID
129 )
130{
132 EFI_HOB_GUID_TYPE *GuidHob;
133 UINTN SerialRegisterBase;
134 UINT8 RegisterStride;
135 UINT32 Divisor;
136 UINT32 CurrentDivisor;
137 UINT32 BaudRate;
138 BOOLEAN Initialized;
139 BOOLEAN MmioEnable;
140 UINT8 Value;
141
142 if (mUartCount > 0) {
143 return RETURN_SUCCESS;
144 }
145
146 if (GetHobList () == NULL) {
147 mUartCount = 0;
148 SerialRegisterBase = PcdGet64 (PcdSerialRegisterBase);
149 MmioEnable = PcdGetBool (PcdSerialUseMmio);
150 BaudRate = PcdGet32 (PcdSerialBaudRate);
151 RegisterStride = (UINT8)PcdGet32 (PcdSerialRegisterStride);
152
153 mUartInfo[mUartCount].BaseAddress = SerialRegisterBase;
154 mUartInfo[mUartCount].UseMmio = MmioEnable;
155 mUartInfo[mUartCount].BaudRate = BaudRate;
156 mUartInfo[mUartCount].RegisterStride = RegisterStride;
157 mUartCount++;
158
159 Divisor = PcdGet32 (PcdSerialClockRate) / (BaudRate * 16);
160 if ((PcdGet32 (PcdSerialClockRate) % (BaudRate * 16)) >= BaudRate * 8) {
161 Divisor++;
162 }
163
164 //
165 // See if the serial port is already initialized
166 //
167 Initialized = TRUE;
168 if ((SerialPortReadRegister (SerialRegisterBase, R_UART_LCR, MmioEnable, RegisterStride) & 0x3F) != (PcdGet8 (PcdSerialLineControl) & 0x3F)) {
169 Initialized = FALSE;
170 }
171
172 Value = (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR, MmioEnable, RegisterStride) | B_UART_LCR_DLAB);
173 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, Value, MmioEnable, RegisterStride);
174 CurrentDivisor = SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_HIGH, MmioEnable, RegisterStride) << 8;
175 CurrentDivisor |= (UINT32)SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_LOW, MmioEnable, RegisterStride);
176 Value = (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR, MmioEnable, RegisterStride) & ~B_UART_LCR_DLAB);
177 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, Value, MmioEnable, RegisterStride);
178 if (CurrentDivisor != Divisor) {
179 Initialized = FALSE;
180 }
181
182 //
183 // Configure baud rate
184 //
185 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB, MmioEnable, RegisterStride);
186 SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8)(Divisor >> 8), MmioEnable, RegisterStride);
187 SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8)(Divisor & 0xff), MmioEnable, RegisterStride);
188
189 //
190 // Clear DLAB and configure Data Bits, Parity, and Stop Bits.
191 // Strip reserved bits from PcdSerialLineControl
192 //
193 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(PcdGet8 (PcdSerialLineControl) & 0x3F), MmioEnable, RegisterStride);
194
195 //
196 // Enable and reset FIFOs
197 // Strip reserved bits from PcdSerialFifoControl
198 //
199 SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, 0x00, MmioEnable, RegisterStride);
200 SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)), MmioEnable, RegisterStride);
201
202 //
203 // Set FIFO Polled Mode by clearing IER after setting FCR
204 //
205 SerialPortWriteRegister (SerialRegisterBase, R_UART_IER, 0x00, MmioEnable, RegisterStride);
206
207 //
208 // Put Modem Control Register(MCR) into its reset state of 0x00.
209 //
210 SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, 0x00, MmioEnable, RegisterStride);
211
212 return RETURN_SUCCESS;
213 }
214
215 GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid);
216 while (GuidHob != NULL) {
217 SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob);
218 SerialRegisterBase = SerialPortInfo->RegisterBase;
219 MmioEnable = SerialPortInfo->UseMmio;
220 BaudRate = SerialPortInfo->BaudRate;
221 RegisterStride = SerialPortInfo->RegisterStride;
222
223 if (SerialRegisterBase == 0) {
224 GuidHob = GET_NEXT_HOB (GuidHob);
225 GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob);
226 continue;
227 }
228
229 mUartInfo[mUartCount].BaseAddress = SerialRegisterBase;
230 mUartInfo[mUartCount].UseMmio = MmioEnable;
231 mUartInfo[mUartCount].BaudRate = BaudRate;
232 mUartInfo[mUartCount].RegisterStride = RegisterStride;
233 mUartCount++;
234
235 Divisor = PcdGet32 (PcdSerialClockRate) / (BaudRate * 16);
236 if ((PcdGet32 (PcdSerialClockRate) % (BaudRate * 16)) >= BaudRate * 8) {
237 Divisor++;
238 }
239
240 //
241 // See if the serial port is already initialized
242 //
243 Initialized = TRUE;
244 if ((SerialPortReadRegister (SerialRegisterBase, R_UART_LCR, MmioEnable, RegisterStride) & 0x3F) != (PcdGet8 (PcdSerialLineControl) & 0x3F)) {
245 Initialized = FALSE;
246 }
247
248 Value = (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR, MmioEnable, RegisterStride) | B_UART_LCR_DLAB);
249 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, Value, MmioEnable, RegisterStride);
250 CurrentDivisor = SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_HIGH, MmioEnable, RegisterStride) << 8;
251 CurrentDivisor |= (UINT32)SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_LOW, MmioEnable, RegisterStride);
252 Value = (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR, MmioEnable, RegisterStride) & ~B_UART_LCR_DLAB);
253 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, Value, MmioEnable, RegisterStride);
254 if (CurrentDivisor != Divisor) {
255 Initialized = FALSE;
256 }
257
258 if (Initialized) {
259 GuidHob = GET_NEXT_HOB (GuidHob);
260 GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob);
261 continue;
262 }
263
264 //
265 // Configure baud rate
266 //
267 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB, MmioEnable, RegisterStride);
268 SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8)(Divisor >> 8), MmioEnable, RegisterStride);
269 SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8)(Divisor & 0xff), MmioEnable, RegisterStride);
270
271 //
272 // Clear DLAB and configure Data Bits, Parity, and Stop Bits.
273 // Strip reserved bits from PcdSerialLineControl
274 //
275 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(PcdGet8 (PcdSerialLineControl) & 0x3F), MmioEnable, RegisterStride);
276
277 //
278 // Enable and reset FIFOs
279 // Strip reserved bits from PcdSerialFifoControl
280 //
281 SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, 0x00, MmioEnable, RegisterStride);
282 SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)), MmioEnable, RegisterStride);
283
284 //
285 // Set FIFO Polled Mode by clearing IER after setting FCR
286 //
287 SerialPortWriteRegister (SerialRegisterBase, R_UART_IER, 0x00, MmioEnable, RegisterStride);
288
289 //
290 // Put Modem Control Register(MCR) into its reset state of 0x00.
291 //
292 SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, 0x00, MmioEnable, RegisterStride);
293
294 GuidHob = GET_NEXT_HOB (GuidHob);
295 GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob);
296 }
297
298 return RETURN_SUCCESS;
299}
300
320UINTN
321EFIAPI
323 IN UINT8 *Buffer,
324 IN UINTN NumberOfBytes
325 )
326{
327 UINTN BaseAddress;
328 BOOLEAN UseMmio;
329 UINTN BytesLeft;
330 UINTN Index;
331 UINTN FifoSize;
332 UINT8 *DataBuffer;
333 UINT8 Count;
334 UINT8 Stride;
335
336 if ((Buffer == NULL) || (NumberOfBytes == 0) || (mUartCount == 0)) {
337 return 0;
338 }
339
340 //
341 // Compute the maximum size of the Tx FIFO
342 //
343 FifoSize = 1;
344 if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFOE) != 0) {
345 if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFO64) == 0) {
346 FifoSize = 16;
347 } else {
348 FifoSize = PcdGet32 (PcdSerialExtendedTxFifoSize);
349 }
350 }
351
352 Count = 0;
353 while (Count < mUartCount) {
354 BaseAddress = mUartInfo[Count].BaseAddress;
355 UseMmio = mUartInfo[Count].UseMmio;
356 Stride = mUartInfo[Count].RegisterStride;
357
358 if (UseMmio && mBaseSerialPortLibHobAtRuntime) {
359 Count++;
360 continue;
361 }
362
363 if (BaseAddress == 0) {
364 Count++;
365 continue;
366 }
367
368 DataBuffer = Buffer;
369 BytesLeft = NumberOfBytes;
370
371 while (BytesLeft != 0) {
372 //
373 // Wait for the serial port to be ready, to make sure both the transmit FIFO
374 // and shift register empty.
375 //
376 while ((SerialPortReadRegister (BaseAddress, R_UART_LSR, UseMmio, Stride) & B_UART_LSR_TXRDY) == 0) {
377 }
378
379 //
380 // Fill the entire Tx FIFO
381 //
382 for (Index = 0; Index < FifoSize && BytesLeft != 0; Index++, BytesLeft--, DataBuffer++) {
383 //
384 // Write byte to the transmit buffer.
385 //
386 SerialPortWriteRegister (BaseAddress, R_UART_TXBUF, *DataBuffer, UseMmio, Stride);
387 }
388
389 MicroSecondDelay (20);
390 }
391
392 Count++;
393 }
394
395 return NumberOfBytes;
396}
397
409UINTN
410EFIAPI
412 OUT UINT8 *Buffer,
413 IN UINTN NumberOfBytes
414 )
415{
416 UINTN BaseAddress;
417 BOOLEAN UseMmio;
418 BOOLEAN IsNextPort;
419 UINT8 *DataBuffer;
420 UINTN BytesLeft;
421 UINTN Result;
422 UINT8 Mcr;
423 UINT8 Count;
424 UINT8 Stride;
425
426 if (Buffer == NULL) {
427 return 0;
428 }
429
430 Count = 0;
431 while (Count < mUartCount) {
432 BaseAddress = mUartInfo[Count].BaseAddress;
433 UseMmio = mUartInfo[Count].UseMmio;
434 Stride = mUartInfo[Count].RegisterStride;
435
436 if (BaseAddress == 0) {
437 Count++;
438 continue;
439 }
440
441 DataBuffer = Buffer;
442 BytesLeft = NumberOfBytes;
443 IsNextPort = FALSE;
444
445 Mcr = (UINT8)(SerialPortReadRegister (BaseAddress, R_UART_MCR, UseMmio, Stride) & ~B_UART_MCR_RTS);
446
447 for (Result = 0; BytesLeft-- != 0; Result++, DataBuffer++) {
448 //
449 // Wait for the serial port to have some data.
450 //
451 while ((SerialPortReadRegister (BaseAddress, R_UART_LSR, UseMmio, Stride) & B_UART_LSR_RXRDY) == 0) {
452 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
453 //
454 // Set RTS to let the peer send some data
455 //
456 SerialPortWriteRegister (BaseAddress, R_UART_MCR, (UINT8)(Mcr | B_UART_MCR_RTS), UseMmio, Stride);
457 }
458
459 IsNextPort = TRUE;
460 break;
461 }
462
463 if (IsNextPort) {
464 break;
465 }
466
467 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
468 //
469 // Clear RTS to prevent peer from sending data
470 //
471 SerialPortWriteRegister (BaseAddress, R_UART_MCR, Mcr, UseMmio, Stride);
472 }
473
474 //
475 // Read byte from the receive buffer.
476 //
477 *DataBuffer = SerialPortReadRegister (BaseAddress, R_UART_RXBUF, UseMmio, Stride);
478 }
479
480 if ((!IsNextPort) && (*(--DataBuffer) != '\0')) {
481 return Result;
482 }
483
484 Count++;
485 }
486
487 return Result;
488}
489
501BOOLEAN
502EFIAPI
504 VOID
505 )
506{
507 UINTN BaseAddress;
508 BOOLEAN UseMmio;
509 UINT8 Stride;
510 UINT8 Count;
511 BOOLEAN IsDataReady;
512
513 Count = 0;
514 while (Count < mUartCount) {
515 BaseAddress = mUartInfo[Count].BaseAddress;
516 UseMmio = mUartInfo[Count].UseMmio;
517 Stride = mUartInfo[Count].RegisterStride;
518
519 if (BaseAddress == 0) {
520 Count++;
521 continue;
522 }
523
524 IsDataReady = FALSE;
525
526 //
527 // Read the serial port status
528 //
529 if ((SerialPortReadRegister (BaseAddress, R_UART_LSR, UseMmio, Stride) & B_UART_LSR_RXRDY) != 0) {
530 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
531 //
532 // Clear RTS to prevent peer from sending data
533 //
534 SerialPortWriteRegister (BaseAddress, R_UART_MCR, (UINT8)(SerialPortReadRegister (BaseAddress, R_UART_MCR, UseMmio, Stride) & ~B_UART_MCR_RTS), UseMmio, Stride);
535 }
536
537 IsDataReady = TRUE;
538 }
539
540 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
541 //
542 // Set RTS to let the peer send some data
543 //
544 SerialPortWriteRegister (BaseAddress, R_UART_MCR, (UINT8)(SerialPortReadRegister (BaseAddress, R_UART_MCR, UseMmio, Stride) | B_UART_MCR_RTS), UseMmio, Stride);
545 }
546
547 if (IsDataReady) {
548 return IsDataReady;
549 }
550
551 Count++;
552 }
553
554 return IsDataReady;
555}
556
565RETURN_STATUS
566EFIAPI
568 IN UINT32 Control
569 )
570{
571 UINTN BaseAddress;
572 BOOLEAN UseMmio;
573 UINT8 Mcr;
574 UINT8 Count;
575 UINT8 Stride;
576
577 Count = 0;
578 while (Count < mUartCount) {
579 BaseAddress = mUartInfo[Count].BaseAddress;
580 UseMmio = mUartInfo[Count].UseMmio;
581 Stride = mUartInfo[Count].RegisterStride;
582
583 if (BaseAddress == 0) {
584 Count++;
585 continue;
586 }
587
588 //
589 // First determine the parameter is invalid.
590 //
591 if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |
592 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0)
593 {
594 Count++;
595 continue;
596 }
597
598 //
599 // Read the Modem Control Register.
600 //
601 Mcr = SerialPortReadRegister (BaseAddress, R_UART_MCR, UseMmio, Stride);
602 Mcr &= (~(B_UART_MCR_DTRC | B_UART_MCR_RTS));
603
604 if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) {
605 Mcr |= B_UART_MCR_DTRC;
606 }
607
608 if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) {
609 Mcr |= B_UART_MCR_RTS;
610 }
611
612 //
613 // Write the Modem Control Register.
614 //
615 SerialPortWriteRegister (BaseAddress, R_UART_MCR, Mcr, UseMmio, Stride);
616 Count++;
617 }
618
619 return RETURN_SUCCESS;
620}
621
630RETURN_STATUS
631EFIAPI
633 OUT UINT32 *Control
634 )
635{
636 UINTN BaseAddress;
637 BOOLEAN UseMmio;
638 UINT8 Msr;
639 UINT8 Mcr;
640 UINT8 Lsr;
641 UINT8 Count;
642 UINT8 Stride;
643
644 Count = 0;
645 while (Count < mUartCount) {
646 BaseAddress = mUartInfo[Count].BaseAddress;
647 UseMmio = mUartInfo[Count].UseMmio;
648 Stride = mUartInfo[Count].RegisterStride;
649
650 if (BaseAddress == 0) {
651 Count++;
652 continue;
653 }
654
655 *Control = 0;
656
657 //
658 // Read the Modem Status Register.
659 //
660 Msr = SerialPortReadRegister (BaseAddress, R_UART_MSR, UseMmio, Stride);
661
662 if ((Msr & B_UART_MSR_CTS) == B_UART_MSR_CTS) {
663 *Control |= EFI_SERIAL_CLEAR_TO_SEND;
664 }
665
666 if ((Msr & B_UART_MSR_DSR) == B_UART_MSR_DSR) {
667 *Control |= EFI_SERIAL_DATA_SET_READY;
668 }
669
670 if ((Msr & B_UART_MSR_RI) == B_UART_MSR_RI) {
671 *Control |= EFI_SERIAL_RING_INDICATE;
672 }
673
674 if ((Msr & B_UART_MSR_DCD) == B_UART_MSR_DCD) {
675 *Control |= EFI_SERIAL_CARRIER_DETECT;
676 }
677
678 //
679 // Read the Modem Control Register.
680 //
681 Mcr = SerialPortReadRegister (BaseAddress, R_UART_MCR, UseMmio, Stride);
682
683 if ((Mcr & B_UART_MCR_DTRC) == B_UART_MCR_DTRC) {
684 *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
685 }
686
687 if ((Mcr & B_UART_MCR_RTS) == B_UART_MCR_RTS) {
688 *Control |= EFI_SERIAL_REQUEST_TO_SEND;
689 }
690
691 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
692 *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
693 }
694
695 //
696 // Read the Line Status Register.
697 //
698 Lsr = SerialPortReadRegister (BaseAddress, R_UART_LSR, UseMmio, Stride);
699
700 if ((Lsr & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) == (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) {
701 *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
702 }
703
704 if ((Lsr & B_UART_LSR_RXRDY) == 0) {
705 *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
706 }
707
708 if ((((*Control & EFI_SERIAL_OUTPUT_BUFFER_EMPTY) == EFI_SERIAL_OUTPUT_BUFFER_EMPTY) &&
709 ((*Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) != EFI_SERIAL_INPUT_BUFFER_EMPTY)) ||
710 ((*Control & (EFI_SERIAL_DATA_SET_READY | EFI_SERIAL_CLEAR_TO_SEND |
711 EFI_SERIAL_CARRIER_DETECT)) == (EFI_SERIAL_DATA_SET_READY | EFI_SERIAL_CLEAR_TO_SEND |
712 EFI_SERIAL_CARRIER_DETECT)))
713 {
714 return RETURN_SUCCESS;
715 }
716
717 Count++;
718 }
719
720 return RETURN_SUCCESS;
721}
722
753RETURN_STATUS
754EFIAPI
756 IN OUT UINT64 *BaudRate,
757 IN OUT UINT32 *ReceiveFifoDepth,
758 IN OUT UINT32 *Timeout,
759 IN OUT EFI_PARITY_TYPE *Parity,
760 IN OUT UINT8 *DataBits,
761 IN OUT EFI_STOP_BITS_TYPE *StopBits
762 )
763{
764 UINTN BaseAddress;
765 BOOLEAN UseMmio;
766 UINT32 SerialBaudRate;
767 UINTN Divisor;
768 UINT8 Lcr;
769 UINT8 LcrData;
770 UINT8 LcrParity;
771 UINT8 LcrStop;
772 UINT8 Count;
773 UINT8 Stride;
774
775 Count = 0;
776 while (Count < mUartCount) {
777 BaseAddress = mUartInfo[Count].BaseAddress;
778 UseMmio = mUartInfo[Count].UseMmio;
779 Stride = mUartInfo[Count].RegisterStride;
780
781 if (BaseAddress == 0) {
782 Count++;
783 continue;
784 }
785
786 //
787 // Check for default settings and fill in actual values.
788 //
789 if (*BaudRate == 0) {
790 *BaudRate = mUartInfo[Count].BaudRate;
791 }
792
793 SerialBaudRate = (UINT32)*BaudRate;
794
795 if (*DataBits == 0) {
796 LcrData = (UINT8)(PcdGet8 (PcdSerialLineControl) & 0x3);
797 *DataBits = LcrData + 5;
798 } else {
799 if ((*DataBits < 5) || (*DataBits > 8)) {
800 Count++;
801 continue;
802 }
803
804 //
805 // Map 5..8 to 0..3
806 //
807 LcrData = (UINT8)(*DataBits - (UINT8)5);
808 }
809
810 if (*Parity == DefaultParity) {
811 LcrParity = (UINT8)((PcdGet8 (PcdSerialLineControl) >> 3) & 0x7);
812 switch (LcrParity) {
813 case 0:
814 *Parity = NoParity;
815 break;
816
817 case 3:
818 *Parity = EvenParity;
819 break;
820
821 case 1:
822 *Parity = OddParity;
823 break;
824
825 case 7:
826 *Parity = SpaceParity;
827 break;
828
829 case 5:
830 *Parity = MarkParity;
831 break;
832
833 default:
834 break;
835 }
836 } else {
837 switch (*Parity) {
838 case NoParity:
839 LcrParity = 0;
840 break;
841
842 case EvenParity:
843 LcrParity = 3;
844 break;
845
846 case OddParity:
847 LcrParity = 1;
848 break;
849
850 case SpaceParity:
851 LcrParity = 7;
852 break;
853
854 case MarkParity:
855 LcrParity = 5;
856 break;
857
858 default:
859 Count++;
860 continue;
861 }
862 }
863
864 if (*StopBits == DefaultStopBits) {
865 LcrStop = (UINT8)((PcdGet8 (PcdSerialLineControl) >> 2) & 0x1);
866 switch (LcrStop) {
867 case 0:
868 *StopBits = OneStopBit;
869 break;
870
871 case 1:
872 if (*DataBits == 5) {
873 *StopBits = OneFiveStopBits;
874 } else {
875 *StopBits = TwoStopBits;
876 }
877
878 break;
879
880 default:
881 break;
882 }
883 } else {
884 switch (*StopBits) {
885 case OneStopBit:
886 LcrStop = 0;
887 break;
888
889 case OneFiveStopBits:
890 case TwoStopBits:
891 LcrStop = 1;
892 break;
893
894 default:
895 Count++;
896 continue;
897 }
898 }
899
900 //
901 // Calculate divisor for baud generator
902 // Ref_Clk_Rate / Baud_Rate / 16
903 //
904 Divisor = PcdGet32 (PcdSerialClockRate) / (SerialBaudRate * 16);
905 if ((PcdGet32 (PcdSerialClockRate) % (SerialBaudRate * 16)) >= SerialBaudRate * 8) {
906 Divisor++;
907 }
908
909 //
910 // Configure baud rate
911 //
912 SerialPortWriteRegister (BaseAddress, R_UART_LCR, B_UART_LCR_DLAB, UseMmio, Stride);
913 SerialPortWriteRegister (BaseAddress, R_UART_BAUD_HIGH, (UINT8)(Divisor >> 8), UseMmio, Stride);
914 SerialPortWriteRegister (BaseAddress, R_UART_BAUD_LOW, (UINT8)(Divisor & 0xff), UseMmio, Stride);
915
916 //
917 // Clear DLAB and configure Data Bits, Parity, and Stop Bits.
918 // Strip reserved bits from line control value
919 //
920 Lcr = (UINT8)((LcrParity << 3) | (LcrStop << 2) | LcrData);
921 SerialPortWriteRegister (BaseAddress, R_UART_LCR, (UINT8)(Lcr & 0x3F), UseMmio, Stride);
922 Count++;
923 }
924
925 return RETURN_SUCCESS;
926}
UINT64 UINTN
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
VOID *EFIAPI GetNextGuidHob(IN CONST EFI_GUID *Guid, IN CONST VOID *HobStart)
Definition: HobLib.c:176
VOID *EFIAPI GetHobList(VOID)
Definition: HobLib.c:76
UINT8 SerialPortReadRegister(UINTN Base, UINTN Offset, BOOLEAN UseMmio, UINT8 RegisterStride)
BOOLEAN EFIAPI SerialPortPoll(VOID)
RETURN_STATUS EFIAPI SerialPortSetAttributes(IN OUT UINT64 *BaudRate, IN OUT UINT32 *ReceiveFifoDepth, IN OUT UINT32 *Timeout, IN OUT EFI_PARITY_TYPE *Parity, IN OUT UINT8 *DataBits, IN OUT EFI_STOP_BITS_TYPE *StopBits)
UINTN EFIAPI SerialPortRead(OUT UINT8 *Buffer, IN UINTN NumberOfBytes)
RETURN_STATUS EFIAPI SerialPortInitialize(VOID)
RETURN_STATUS EFIAPI SerialPortSetControl(IN UINT32 Control)
UINT8 SerialPortWriteRegister(UINTN Base, UINTN Offset, UINT8 Value, BOOLEAN UseMmio, UINT8 RegisterStride)
RETURN_STATUS EFIAPI SerialPortGetControl(OUT UINT32 *Control)
UINTN EFIAPI SerialPortWrite(IN UINT8 *Buffer, IN UINTN NumberOfBytes)
UINT8 EFIAPI IoWrite8(IN UINTN Port, IN UINT8 Value)
Definition: IoLibArmVirt.c:200
UINT8 EFIAPI MmioRead8(IN UINTN Address)
Definition: IoLib.c:82
UINT8 EFIAPI MmioWrite8(IN UINTN Address, IN UINT8 Value)
Definition: IoLib.c:126
UINT8 EFIAPI IoRead8(IN UINTN Port)
Definition: IoLibArmVirt.c:175
#define NULL
Definition: Base.h:319
#define RETURN_SUCCESS
Definition: Base.h:1066
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
#define PcdGet8(TokenName)
Definition: PcdLib.h:336
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
EFI_STOP_BITS_TYPE
Definition: SerialIo.h:53
EFI_PARITY_TYPE
Definition: SerialIo.h:41