+++ /dev/null
-/** @file\r
- SerialPortLib instance for UART device upon coreboot\r
-\r
- Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include <Uefi/UefiBaseType.h>\r
-#include <Library/SerialPortLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/CbParseLib.h>\r
-\r
-//\r
-// 16550 UART register offsets and bitfields\r
-//\r
-#define R_UART_RXBUF 0\r
-#define R_UART_TXBUF 0\r
-#define R_UART_BAUD_LOW 0\r
-#define R_UART_BAUD_HIGH 1\r
-#define R_UART_FCR 2\r
-#define B_UART_FCR_FIFOE BIT0\r
-#define B_UART_FCR_FIFO64 BIT5\r
-#define R_UART_LCR 3\r
-#define B_UART_LCR_DLAB BIT7\r
-#define R_UART_MCR 4\r
-#define B_UART_MCR_RTS BIT1\r
-#define R_UART_LSR 5\r
-#define B_UART_LSR_RXRDY BIT0\r
-#define B_UART_LSR_TXRDY BIT5\r
-#define B_UART_LSR_TEMT BIT6\r
-#define R_UART_MSR 6\r
-#define B_UART_MSR_CTS BIT4\r
-#define B_UART_MSR_DSR BIT5\r
-\r
-UINT32 mSerialRegBase = 0;\r
-UINT32 mSerialRegAccessType = 0;\r
-\r
-/**\r
- Read an 8-bit 16550 register. If PcdSerialUseMmio is TRUE, then the value is read from \r
- MMIO space. If PcdSerialUseMmio is FALSE, then the value is read from I/O space. The\r
- parameter Offset is added to the base address of the 16550 registers that is specified \r
- by PcdSerialRegisterBase. \r
- \r
- @param Offset The offset of the 16550 register to read.\r
-\r
- @return The value read from the 16550 register.\r
-\r
-**/\r
-UINT8\r
-SerialPortReadRegister (\r
- UINTN Offset\r
- )\r
-{\r
- if (mSerialRegAccessType == 2) { //MMIO\r
- return MmioRead8 (mSerialRegBase + Offset);\r
- } else { //IO\r
- return IoRead8 ((UINT16)mSerialRegBase + Offset);\r
- }\r
-}\r
-\r
-/**\r
- Write an 8-bit 16550 register. If PcdSerialUseMmio is TRUE, then the value is written to\r
- MMIO space. If PcdSerialUseMmio is FALSE, then the value is written to I/O space. The\r
- parameter Offset is added to the base address of the 16550 registers that is specified \r
- by PcdSerialRegisterBase. \r
- \r
- @param Offset The offset of the 16550 register to write.\r
- @param Value The value to write to the 16550 register specified by Offset.\r
-\r
- @return The value written to the 16550 register.\r
-\r
-**/\r
-UINT8\r
-SerialPortWriteRegister (\r
- UINTN Offset,\r
- UINT8 Value\r
- )\r
-{\r
- if (mSerialRegAccessType == 2) { //MMIO\r
- return MmioWrite8 (mSerialRegBase + Offset, Value);\r
- } else {// IO\r
- return IoWrite8 ((UINT16)mSerialRegBase + Offset, Value);\r
- }\r
-}\r
-\r
-/**\r
- Initialize the serial device hardware.\r
- \r
- If no initialization is required, then return RETURN_SUCCESS.\r
- If the serial device was successfully initialized, then return RETURN_SUCCESS.\r
- If the serial device could not be initialized, then return RETURN_DEVICE_ERROR.\r
- \r
- @retval RETURN_SUCCESS The serial device was initialized.\r
- @retval RETURN_DEVICE_ERROR The serial device could not be initialized.\r
-\r
-**/\r
-RETURN_STATUS\r
-EFIAPI\r
-SerialPortInitialize (\r
- VOID\r
- )\r
-{\r
- RETURN_STATUS Status;\r
- UINTN Divisor;\r
- BOOLEAN Initialized;\r
- \r
- Status = CbParseSerialInfo (&mSerialRegBase, &mSerialRegAccessType, NULL);\r
- if (RETURN_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // See if the serial port is already initialized\r
- //\r
- Initialized = TRUE;\r
- if ((SerialPortReadRegister (R_UART_FCR) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)) !=\r
- (PcdGet8 (PcdSerialFifoControl) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)) ) {\r
- Initialized = FALSE;\r
- }\r
-\r
- if ((SerialPortReadRegister (R_UART_LCR) & 0x3F) != (PcdGet8 (PcdSerialLineControl) & 0x3F)) {\r
- Initialized = FALSE;\r
- }\r
- SerialPortWriteRegister (R_UART_LCR, (UINT8)(SerialPortReadRegister (R_UART_LCR) | B_UART_LCR_DLAB));\r
- Divisor = SerialPortReadRegister (R_UART_BAUD_HIGH) << 8;\r
- Divisor |= SerialPortReadRegister (R_UART_BAUD_LOW);\r
- SerialPortWriteRegister (R_UART_LCR, (UINT8)(SerialPortReadRegister (R_UART_LCR) & ~B_UART_LCR_DLAB));\r
- if (Divisor != 115200 / PcdGet32 (PcdSerialBaudRate)) {\r
- Initialized = FALSE;\r
- }\r
- if (Initialized) {\r
- return RETURN_SUCCESS;\r
- }\r
- \r
- //\r
- // Configure baud rate\r
- //\r
- Divisor = 115200 / PcdGet32 (PcdSerialBaudRate);\r
- SerialPortWriteRegister (R_UART_LCR, B_UART_LCR_DLAB);\r
- SerialPortWriteRegister (R_UART_BAUD_HIGH, (UINT8) (Divisor >> 8));\r
- SerialPortWriteRegister (R_UART_BAUD_LOW, (UINT8) (Divisor & 0xff));\r
-\r
- //\r
- // Clear DLAB and configure Data Bits, Parity, and Stop Bits.\r
- // Strip reserved bits from PcdSerialLineControl\r
- //\r
- SerialPortWriteRegister (R_UART_LCR, (UINT8)(PcdGet8 (PcdSerialLineControl) & 0x3F));\r
-\r
- //\r
- // Enable and reset FIFOs\r
- // Strip reserved bits from PcdSerialFifoControl\r
- //\r
- SerialPortWriteRegister (R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & 0x27));\r
-\r
- //\r
- // Put Modem Control Register(MCR) into its reset state of 0x00.\r
- // \r
- SerialPortWriteRegister (R_UART_MCR, 0x00);\r
- \r
- return RETURN_SUCCESS;\r
-}\r
-\r
-/**\r
- Write data from buffer to serial device. \r
- \r
- Writes NumberOfBytes data bytes from Buffer to the serial device. \r
- The number of bytes actually written to the serial device is returned.\r
- If the return value is less than NumberOfBytes, then the write operation failed.\r
-\r
- If Buffer is NULL, then ASSERT(). \r
-\r
- If NumberOfBytes is zero, then return 0.\r
-\r
- @param Buffer Pointer to the data buffer to be written.\r
- @param NumberOfBytes Number of bytes to written to the serial device.\r
-\r
- @retval 0 NumberOfBytes is 0.\r
- @retval >0 The number of bytes written to the serial device. \r
- If this value is less than NumberOfBytes, then the read operation failed.\r
-\r
-**/\r
-UINTN\r
-EFIAPI\r
-SerialPortWrite (\r
- IN UINT8 *Buffer,\r
- IN UINTN NumberOfBytes\r
-)\r
-{\r
- UINTN Result;\r
- UINTN Index;\r
- UINTN FifoSize;\r
-\r
- if (Buffer == NULL) {\r
- return 0;\r
- }\r
-\r
- if (NumberOfBytes == 0) {\r
- //\r
- // Flush the hardware\r
- //\r
-\r
- //\r
- // Wait for both the transmit FIFO and shift register empty.\r
- //\r
- while ((SerialPortReadRegister (R_UART_LSR) & B_UART_LSR_TEMT) == 0);\r
-\r
- return 0;\r
- }\r
-\r
- //\r
- // Compute the maximum size of the Tx FIFO\r
- //\r
- FifoSize = 1;\r
- if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFOE) != 0) {\r
- if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFO64) == 0) {\r
- FifoSize = 16;\r
- } else {\r
- FifoSize = 64;\r
- }\r
- }\r
-\r
- Result = NumberOfBytes;\r
- while (NumberOfBytes != 0) {\r
- //\r
- // Wait for the serial port to be ready, to make sure both the transmit FIFO\r
- // and shift register empty.\r
- //\r
- while ((SerialPortReadRegister (R_UART_LSR) & B_UART_LSR_TEMT) == 0);\r
-\r
- //\r
- // Fill then entire Tx FIFO\r
- //\r
- for (Index = 0; Index < FifoSize && NumberOfBytes != 0; Index++, NumberOfBytes--, Buffer++) {\r
-\r
- //\r
- // Write byte to the transmit buffer.\r
- //\r
- SerialPortWriteRegister (R_UART_TXBUF, *Buffer);\r
- }\r
- }\r
- return Result;\r
-}\r
-\r
-/**\r
- Reads data from a serial device into a buffer.\r
-\r
- @param Buffer Pointer to the data buffer to store the data read from the serial device.\r
- @param NumberOfBytes Number of bytes to read from the serial device.\r
-\r
- @retval 0 NumberOfBytes is 0.\r
- @retval >0 The number of bytes read from the serial device. \r
- If this value is less than NumberOfBytes, then the read operation failed.\r
-\r
-**/\r
-UINTN\r
-EFIAPI\r
-SerialPortRead (\r
- OUT UINT8 *Buffer,\r
- IN UINTN NumberOfBytes\r
-)\r
-{\r
- UINTN Result;\r
-\r
- if (NULL == Buffer) {\r
- return 0;\r
- }\r
- \r
- for (Result = 0; NumberOfBytes-- != 0; Result++, Buffer++) {\r
- //\r
- // Wait for the serial port to have some data.\r
- //\r
- while ((SerialPortReadRegister (R_UART_LSR) & B_UART_LSR_RXRDY) == 0);\r
- \r
- //\r
- // Read byte from the receive buffer.\r
- //\r
- *Buffer = SerialPortReadRegister (R_UART_RXBUF);\r
- }\r
- \r
- return Result;\r
-}\r
-\r
-/**\r
- Polls a serial device to see if there is any data waiting to be read.\r
-\r
- Polls aserial device to see if there is any data waiting to be read.\r
- If there is data waiting to be read from the serial device, then TRUE is returned.\r
- If there is no data waiting to be read from the serial device, then FALSE is returned.\r
-\r
- @retval TRUE Data is waiting to be read from the serial device.\r
- @retval FALSE There is no data waiting to be read from the serial device.\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-SerialPortPoll (\r
- VOID\r
- )\r
-{\r
- //\r
- // Read the serial port status\r
- //\r
- if ((SerialPortReadRegister (R_UART_LSR) & B_UART_LSR_RXRDY) != 0) {\r
- return TRUE;\r
- } \r
- \r
- return FALSE;\r
-}\r