This adds support for interact with the UART controller on
NXP i.MX platforms.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Christopher Co <[email protected]>
Cc: Ard Biesheuvel <[email protected]>
Cc: Leif Lindholm <[email protected]>
Cc: Michael D Kinney <[email protected]>
---
 Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h                               | 
207 +++++++++++++++++
 Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c   | 
243 ++++++++++++++++++++
 Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf |  
41 ++++
 3 files changed, 491 insertions(+)

diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h 
b/Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h
new file mode 100644
index 000000000000..ddb61f59c656
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXUart.h
@@ -0,0 +1,207 @@
+/** @file
+*
+*  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD 
License
+*  which accompanies this distribution.  The full text of the license may be 
found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
+*
+**/
+
+#ifndef _IMXUART_H_
+#define _IMXUART_H_
+
+// UART Receiver Register bit definitions
+enum MX6UART_RXD {
+  MX6UART_RXD_RX_DATA_MASK =      (0xff << 0),
+  MX6UART_RXD_PRERR =             (1 << 10),
+  MX6UART_RXD_BRK =               (1 << 11),
+  MX6UART_RXD_FRMERR =            (1 << 12),
+  MX6UART_RXD_OVRRUN =            (1 << 13),
+  MX6UART_RXD_ERR =               (1 << 14),
+  MX6UART_RXD_CHARRDY =           (1 << 15),
+};
+
+// UART Control Register 1 bit definitions
+enum MX6UART_UCR1 {
+  MX6UART_UCR1_UARTEN =           (1 << 0),
+  MX6UART_UCR1_DOZE =             (1 << 1),
+  MX6UART_UCR1_ATDMAEN =          (1 << 2),
+  MX6UART_UCR1_TXDMAEN =          (1 << 3),
+  MX6UART_UCR1_SNDBRK =           (1 << 4),
+  MX6UART_UCR1_RTSDEN =           (1 << 5),
+  MX6UART_UCR1_TXMPTYEN =         (1 << 6),
+  MX6UART_UCR1_IREN =             (1 << 7),
+  MX6UART_UCR1_RXDMAEN =          (1 << 8),
+  MX6UART_UCR1_RRDYEN =           (1 << 9),
+  MX6UART_UCR1_ICD_MASK =         (3 << 10),
+  MX6UART_UCR1_ICD_4 =            (0 << 10),
+  MX6UART_UCR1_ICD_8 =            (1 << 10),
+  MX6UART_UCR1_ICD_16 =           (2 << 10),
+  MX6UART_UCR1_ICD_32 =           (3 << 10),
+  MX6UART_UCR1_IDEN =             (1 << 12),
+  MX6UART_UCR1_TRDYEN =           (1 << 13),
+  MX6UART_UCR1_ADBR =             (1 << 14),
+  MX6UART_UCR1_ADEN =             (1 << 15),
+};
+
+// UART Control Register 2 bit definitions
+enum MX6UART_UCR2 {
+  MX6UART_UCR2_SRST =             (1 << 0),
+  MX6UART_UCR2_RXEN =             (1 << 1),
+  MX6UART_UCR2_TXEN =             (1 << 2),
+  MX6UART_UCR2_ATEN =             (1 << 3),
+  MX6UART_UCR2_RTSEN =            (1 << 4),
+  MX6UART_UCR2_WS =               (1 << 5),
+  MX6UART_UCR2_STPB =             (1 << 6),
+  MX6UART_UCR2_PROE =             (1 << 7),
+  MX6UART_UCR2_PREN =             (1 << 8),
+  MX6UART_UCR2_RTEC_MASK =        (3 << 9),
+  MX6UART_UCR2_RTEC_RISING =      (0 << 9),
+  MX6UART_UCR2_RTEC_FALLING =     (1 << 9),
+  MX6UART_UCR2_RTEC_BOTH =        (2 << 9),
+  MX6UART_UCR2_ESCEN =            (1 << 11),
+  MX6UART_UCR2_CTS =              (1 << 12),
+  MX6UART_UCR2_CTSC =             (1 << 13),
+  MX6UART_UCR2_IRTS =             (1 << 14),
+  MX6UART_UCR2_ESCI =             (1 << 15),
+};
+
+// UART Control Register 3 bit definitions
+enum MX6UART_UCR3 {
+  MX6UART_UCR3_ACIEN =            (1 << 0),
+  MX6UART_UCR3_INVT =             (1 << 1),
+  MX6UART_UCR3_RXDMUXSEL =        (1 << 2),
+  MX6UART_UCR3_DTRDEN =           (1 << 3),
+  MX6UART_UCR3_AWAKEN =           (1 << 4),
+  MX6UART_UCR3_AIRINTEN =         (1 << 5),
+  MX6UART_UCR3_RXDSEN =           (1 << 6),
+  MX6UART_UCR3_ADNIMP =           (1 << 7),
+  MX6UART_UCR3_RI =               (1 << 8),
+  MX6UART_UCR3_DCD =              (1 << 9),
+  MX6UART_UCR3_DSR =              (1 << 10),
+  MX6UART_UCR3_FRAERREN =         (1 << 11),
+  MX6UART_UCR3_PARERREN =         (1 << 12),
+  MX6UART_UCR3_DTREN =            (1 << 13),
+  MX6UART_UCR3_DPEC_MASK =        (3 << 14),
+  MX6UART_UCR3_DPEC_RISING =      (0 << 14),
+  MX6UART_UCR3_DPEC_FALLING =     (1 << 14),
+  MX6UART_UCR3_DPEC_BOTH =        (2 << 14),
+};
+
+// UART Control Register 4 bit definitions
+enum MX6UART_UCR4 {
+  MX6UART_UCR4_DREN =             (1 << 0),
+  MX6UART_UCR4_OREN =             (1 << 1),
+  MX6UART_UCR4_BKEN =             (1 << 2),
+  MX6UART_UCR4_TCEN =             (1 << 3),
+  MX6UART_UCR4_LPBYP =            (1 << 4),
+  MX6UART_UCR4_IRSC =             (1 << 5),
+  MX6UART_UCR4_IDDMAEN =          (1 << 6),
+  MX6UART_UCR4_WKEN =             (1 << 7),
+  MX6UART_UCR4_ENIRI =            (1 << 8),
+  MX6UART_UCR4_INVR =             (1 << 9),
+  MX6UART_UCR4_CTSTL_MASK =       (0x3f << 10),
+  MX6UART_UCR4_CTSTL_SHIFT =      10,
+};
+
+// UART FIFO Control Register bit definitions
+enum MX6UART_UFCR {
+  MX6UART_UFCR_RXTL_MASK =        (0x3f << 0),
+  MX6UART_UFCR_RXTL_SHIFT =       0,
+  MX6UART_UFCR_DCEDTE =           (1 << 6),
+  MX6UART_UFCR_RFDIV_MASK =       (7 << 7),
+  MX6UART_UFCR_RFDIV_6 =          (0 << 7),
+  MX6UART_UFCR_RFDIV_5 =          (1 << 7),
+  MX6UART_UFCR_RFDIV_4 =          (2 << 7),
+  MX6UART_UFCR_RFDIV_3 =          (3 << 7),
+  MX6UART_UFCR_RFDIV_2 =          (4 << 7),
+  MX6UART_UFCR_RFDIV_1 =          (5 << 7),
+  MX6UART_UFCR_RFDIV_7 =          (6 << 7),
+  MX6UART_UFCR_TXTL_MASK =        (0x3f << 10),
+  MX6UART_UFCR_TXTL_SHIFT =       10,
+};
+
+// UART Status Register 1 bit definitions
+enum MX6UART_USR1 {
+  MX6UART_USR1_SAD =              (1 << 3),
+  MX6UART_USR1_AWAKE =            (1 << 4),
+  MX6UART_USR1_AIRINT =           (1 << 5),
+  MX6UART_USR1_RXDS =             (1 << 6),
+  MX6UART_USR1_DTRD =             (1 << 7),
+  MX6UART_USR1_AGTIM =            (1 << 8),
+  MX6UART_USR1_RRDY =             (1 << 9),
+  MX6UART_USR1_FRAMERR =          (1 << 10),
+  MX6UART_USR1_ESCF =             (1 << 11),
+  MX6UART_USR1_RTSD =             (1 << 12),
+  MX6UART_USR1_TRDY =             (1 << 13),
+  MX6UART_USR1_RTSS =             (1 << 14),
+  MX6UART_USR1_PARITYERR =        (1 << 15),
+};
+
+// UART Status Register 2 bit definitions
+enum MX6UART_USR2 {
+  MX6UART_USR2_RDR =              (1 << 0),
+  MX6UART_USR2_ORE =              (1 << 1),
+  MX6UART_USR2_BRCD =             (1 << 2),
+  MX6UART_USR2_TXDC =             (1 << 3),
+  MX6UART_USR2_RTSF =             (1 << 4),
+  MX6UART_USR2_DCDIN =            (1 << 5),
+  MX6UART_USR2_DCDDELT =          (1 << 6),
+  MX6UART_USR2_WAKE =             (1 << 7),
+  MX6UART_USR2_IRINT =            (1 << 8),
+  MX6UART_USR2_RIIN =             (1 << 9),
+  MX6UART_USR2_RIDLET =           (1 << 10),
+  MX6UART_USR2_ACST =             (1 << 11),
+  MX6UART_USR2_IDLE =             (1 << 12),
+  MX6UART_USR2_DTRF =             (1 << 13),
+  MX6UART_USR2_TXFE =             (1 << 14),
+  MX6UART_USR2_ADET =             (1 << 15),
+};
+
+// UART Test Register bit definitions
+enum MX6UART_UTS {
+  MX6UART_UTS_SOFTRST =           (1 << 0),
+  MX6UART_UTS_RXFULL =            (1 << 3),
+  MX6UART_UTS_TXFULL =            (1 << 4),
+  MX6UART_UTS_RXEMPTY =           (1 << 5),
+  MX6UART_UTS_TXEMPTY =           (1 << 6),
+  MX6UART_UTS_RXDBG =             (1 << 9),
+  MX6UART_UTS_LOOPIR =            (1 << 10),
+  MX6UART_UTS_DBGEN =             (1 << 11),
+  MX6UART_UTS_LOOP =              (1 << 12),
+  MX6UART_UTS_FRCPERR =           (1 << 13),
+};
+
+// Size of RX and TX FIFOs
+enum {
+  MX6UART_FIFO_COUNT = 32
+};
+
+typedef struct _MX6UART_REGISTERS {
+  UINT32 Rxd;                  // 0x00: UART Receiver Register
+  UINT32 reserved1[15];
+  UINT32 Txd;                  // 0x40: UART Transmitter Register
+  UINT32 reserved2[15];
+  UINT32 Ucr1;                 // 0x80: UART Control Register 1
+  UINT32 Ucr2;                 // 0x84: UART Control Register 2
+  UINT32 Ucr3;                 // 0x88: UART Control Register 3
+  UINT32 Ucr4;                 // 0x8C: UART Control Register 4
+  UINT32 Ufcr;                 // 0x90: UART FIFO Control Register
+  UINT32 Usr1;                 // 0x94: UART Status Register 1
+  UINT32 Usr2;                 // 0x98: UART Status Register 2
+  UINT32 Uesc;                 // 0x9C: UART Escape Character Register
+  UINT32 Utim;                 // 0xA0: UART Escape Timer Register
+  UINT32 Ubir;                 // 0xA4: UART BRM Incremental Register
+  UINT32 Ubmr;                 // 0xA8: UART BRM Modulator Register 
(UART1_UBMR)
+  UINT32 Ubrc;                 // 0xAC: UART Baud Rate Count Register
+  UINT32 Onems;                // 0xB0: UART One Millisecond Register
+  UINT32 Uts;                  // 0xB4: UART Test Register
+  UINT32 Umcr;                 // 0xB8: UART RS-485 Mode Control Register
+} MX6UART_REGISTERS;
+
+#endif // _IMXUART_H_
diff --git 
a/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c 
b/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c
new file mode 100644
index 000000000000..fbe24d98c6aa
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.c
@@ -0,0 +1,243 @@
+/** @file
+
+  Copyright (c) 2006 - 2008, Intel Corporation
+  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+
+  All rights reserved. This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/SerialPortLib.h>
+#include <iMXUart.h>
+
+
+/**
+  Initialize the serial device hardware.
+
+  If no initialization is required, then return RETURN_SUCCESS.
+  If the serial device was successfully initialized, then return 
RETURN_SUCCESS.
+  If the serial device could not be initialized, then return 
RETURN_DEVICE_ERROR.
+
+  @retval RETURN_SUCCESS        The serial device was initialized.
+  @retval RETURN_DEVICE_ERROR   The serial device could not be initialized.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortInitialize (
+  VOID
+  )
+{
+  MX6UART_REGISTERS   *UartBase;
+  UINT32              Ucr1;
+
+  UartBase = (MX6UART_REGISTERS*)FixedPcdGet32 (PcdSerialRegisterBase);
+
+  Ucr1 = MmioRead32 ((UINTN)&UartBase->Ucr1);
+  if ((Ucr1 & MX6UART_UCR1_UARTEN) == 0) {
+    // UART should have been initialized by previous boot stage
+    return RETURN_DEVICE_ERROR;
+  }
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  Write data from buffer to serial device.
+
+  Writes NumberOfBytes data bytes from Buffer to the serial device.
+  The number of bytes actually written to the serial device is returned.
+  If the return value is less than NumberOfBytes, then the write operation 
failed.
+  If Buffer is NULL, then ASSERT().
+  If NumberOfBytes is zero, then return 0.
+
+  @param  Buffer           Pointer to the data buffer to be written.
+  @param  NumberOfBytes    Number of bytes to written to the serial device.
+
+  @retval 0                NumberOfBytes is 0.
+  @retval >0               The number of bytes written to the serial device.
+                           If this value is less than NumberOfBytes, then the
+                           read operation failed.
+
+**/
+UINTN
+EFIAPI
+SerialPortWrite (
+  IN  UINT8   *Buffer,
+  IN  UINTN   NumberOfBytes
+  )
+{
+  MX6UART_REGISTERS   *UartBase;
+  UINTN               BytesSent;
+
+  UartBase = (MX6UART_REGISTERS*)FixedPcdGet32 (PcdSerialRegisterBase);
+  BytesSent = 0;
+  while (BytesSent < NumberOfBytes) {
+    // Check if FIFO is full and wait if it is.
+    while ((MmioRead32 ((UINTN)&UartBase->Uts) & MX6UART_UTS_TXFULL) != 0);
+    MmioWrite32 ((UINTN)&UartBase->Txd, Buffer[BytesSent]);
+    BytesSent++;
+  }
+
+  return BytesSent;
+}
+
+/**
+  Read data from serial device and save the datas in buffer.
+
+  Reads NumberOfBytes data bytes from a serial device into the buffer
+  specified by Buffer. The number of bytes actually read is returned.
+  If the return value is less than NumberOfBytes, then the rest operation 
failed.
+  If Buffer is NULL, then ASSERT().
+  If NumberOfBytes is zero, then return 0.
+
+  @param  Buffer            Pointer to the data buffer to store the data read
+                            from the serial device.
+  @param  NumberOfBytes     Number of bytes which will be read.
+
+  @retval 0                 Read data failed, No data is to be read.
+  @retval >0                Actual number of bytes read from serial device.
+
+**/
+UINTN
+EFIAPI
+SerialPortRead (
+  OUT UINT8   *Buffer,
+  IN  UINTN   NumberOfBytes
+  )
+{
+  MX6UART_REGISTERS   *UartBase;
+  UINTN               BytesRead;
+  UINT32              Rxd;
+
+  UartBase = (MX6UART_REGISTERS*)FixedPcdGet32 (PcdSerialRegisterBase);
+  BytesRead = 0;
+  while (BytesRead < NumberOfBytes) {
+    Rxd = MmioRead32 ((UINTN)&UartBase->Rxd);
+    if ((Rxd & MX6UART_RXD_CHARRDY) == 0) {
+      break;
+    }
+
+    Buffer[BytesRead] = (UINT8) (Rxd & MX6UART_RXD_RX_DATA_MASK);
+    BytesRead++;
+  }
+
+  return BytesRead;
+}
+
+/**
+  Polls a serial device to see if there is any data waiting to be read.
+
+  Polls a serial device to see if there is any data waiting to be read.
+  If there is data waiting to be read from the serial device, then TRUE is
+  returned.
+  If there is no data waiting to be read from the serial device, then FALSE is
+  returned.
+
+  @retval TRUE          Data is waiting to be read from the serial device.
+  @retval FALSE         There is no data waiting to be read from the serial 
device.
+
+**/
+BOOLEAN
+EFIAPI
+SerialPortPoll (
+  VOID
+  )
+{
+  MX6UART_REGISTERS *UartBase;
+  UINT32 Usr2;
+
+  UartBase = (MX6UART_REGISTERS*)FixedPcdGet32 (PcdSerialRegisterBase);
+  Usr2 = MmioRead32 ((UINTN)&UartBase->Usr2);
+  return (Usr2 & MX6UART_USR2_RDR) != 0;
+}
+
+/**
+  Sets the control bits on a serial device.
+
+  @param Control                Sets the bits of Control that are settable.
+
+  @retval RETURN_UNSUPPORTED    The serial device does not support this 
operation.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortSetControl (
+  IN UINT32   Control
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+/**
+  Retrieve the status of the control bits on a serial device.
+
+  @param Control                A pointer to return the current control signals
+                                from the serial device.
+
+  @retval RETURN_UNSUPPORTED    The serial device does not support this 
operation.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortGetControl (
+  OUT UINT32  *Control
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+/**
+  Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
+  data bits, and stop bits on a serial device.
+
+  @param BaudRate           The requested baud rate. A BaudRate value of 0 will
+                            use the device's default interface speed.
+                            On output, the value actually set.
+  @param ReveiveFifoDepth   The requested depth of the FIFO on the receive side
+                            of the serial interface. A ReceiveFifoDepth value
+                            of 0 will use the device's default FIFO depth.
+                            On output, the value actually set.
+  @param Timeout            The requested time out for a single character in
+                            microseconds. This timeout applies to both the
+                            transmit and receive side of the interface. A
+                            Timeout value of 0 will use the device's default
+                            timeout value.
+                            On output, the value actually set.
+  @param Parity             The type of parity to use on this serial device. A
+                            Parity value of DefaultParity will use the device's
+                            default parity value.
+                            On output, the value actually set.
+  @param DataBits           The number of data bits to use on the serial 
device.
+                            A DataBits value of 0 will use the device's default
+                            data bit setting.
+                            On output, the value actually set.
+  @param StopBits           The number of stop bits to use on this serial 
device.
+                            A StopBits value of DefaultStopBits will use the
+                            device's default number of stop bits.
+                            On output, the value actually set.
+
+  @retval RETURN_UNSUPPORTED        The serial device does not support this 
operation.
+
+**/
+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
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
diff --git 
a/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf 
b/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf
new file mode 100644
index 000000000000..9f381b199f38
--- /dev/null
+++ b/Silicon/NXP/iMXPlatformPkg/Library/UartSerialPortLib/UartSerialPortLib.inf
@@ -0,0 +1,41 @@
+## @file
+#
+#  Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD 
License
+#  which accompanies this distribution.  The full text of the license may be 
found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = SerialPortLib
+  FILE_GUID                      = C22D85E6-8B3E-4c05-AA5B-5732F3ACD055
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = SerialPortLib
+
+[Sources.common]
+  UartSerialPortLib.c
+
+[LibraryClasses]
+  ArmLib
+  BaseMemoryLib
+  CacheMaintenanceLib
+  IoLib
+  PcdLib
+  TimerLib
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec
+
+[FixedPcd]
+  giMXPlatformTokenSpaceGuid.PcdSerialRegisterBase
-- 
2.16.2.gvfs.1.33.gf5370f1

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to