On 17 October 2016 at 21:04, Bhupesh Sharma bhupesh.sharma@freescale.com wrote:
From: Sakar Arora sakar.arora@nxp.com
LS1043A SoC houses a DUART (Dual UART) IP which has two UART ports. One of these UART ports is connected to the A53 CPUs and is used for console in and out functionality.
This patch adds the support of the DUART IP as a PEI library.
Signed-off-by: Sakar Arora sakar.arora@nxp.com Signed-off-by: Bhupesh Sharma bhupesh.sharma@nxp.com
Chips/Nxp/QoriqLs/Include/Library/DUart.h | 133 +++++++++ .../QoriqLs/Library/DUartPortLib/DUartPortLib.c | 321 +++++++++++++++++++++ .../QoriqLs/Library/DUartPortLib/DUartPortLib.inf | 43 +++ 3 files changed, 497 insertions(+) create mode 100644 Chips/Nxp/QoriqLs/Include/Library/DUart.h create mode 100644 Chips/Nxp/QoriqLs/Library/DUartPortLib/DUartPortLib.c create mode 100644 Chips/Nxp/QoriqLs/Library/DUartPortLib/DUartPortLib.inf
diff --git a/Chips/Nxp/QoriqLs/Include/Library/DUart.h b/Chips/Nxp/QoriqLs/Include/Library/DUart.h
If this is an internal header, keep it with the .c file
new file mode 100644 index 0000000..479f533 --- /dev/null +++ b/Chips/Nxp/QoriqLs/Include/Library/DUart.h @@ -0,0 +1,133 @@ +/** DUart.h +* Header defining the DUART constants (Base addresses, sizes, flags) +* +* Based on Serial I/O Port library headers available in PL011Uart.h +* +* Copyright (c) 2011-2012, ARM Limited. All rights reserved. +* Copyright (c) 2016, Freescale Semiconductor, Inc. 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 __DUART_H__ +#define __DUART_H__
+#include <Uefi.h> +#include <Protocol/SerialIo.h>
+/* Register Definitions */
+// FIFO Control Register +#define DUART_FCR_FIFO_EN 0x01 /* Fifo enable */ +#define DUART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ +#define DUART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */ +#define DUART_FCR_DMA_SELECT 0x08 /* For DMA applications */ +#define DUART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */ +#define DUART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */ +#define DUART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */ +#define DUART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */ +#define DUART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */
+#define DUART_FCR_RXSR 0x02 /* Receiver soft reset */ +#define DUART_FCR_TXSR 0x04 /* Transmitter soft reset */
+// Modem Control Register +#define DUART_MCR_DTR 0x01 /* Reserved */ +#define DUART_MCR_RTS 0x02 /* RTS */ +#define DUART_MCR_OUT1 0x04 /* Reserved */ +#define DUART_MCR_OUT2 0x08 /* Reserved */ +#define DUART_MCR_LOOP 0x10 /* Enable loopback test mode */ +#define DUART_MCR_AFE 0x20 /* AFE (Auto Flow Control) */
+#define DUART_MCR_DMA_EN 0x04 +#define DUART_MCR_TX_DFR 0x08
+// Line Control Register +/* +* Note: if the word length is 5 bits (DUART_LCR_WLEN5), then setting +* DUART_LCR_STOP will select 1.5 stop bits, not 2 stop bits. +*/ +#define DUART_LCR_WLS_MSK 0x03 /* character length select mask */ +#define DUART_LCR_WLS_5 0x00 /* 5 bit character length */ +#define DUART_LCR_WLS_6 0x01 /* 6 bit character length */ +#define DUART_LCR_WLS_7 0x02 /* 7 bit character length */ +#define DUART_LCR_WLS_8 0x03 /* 8 bit character length */ +#define DUART_LCR_STB 0x04 /* # stop Bits, off=1, on=1.5 or 2) */ +#define DUART_LCR_PEN 0x08 /* Parity eneble */ +#define DUART_LCR_EPS 0x10 /* Even Parity Select */ +#define DUART_LCR_STKP 0x20 /* Stick Parity */ +#define DUART_LCR_SBRK 0x40 /* Set Break */ +#define DUART_LCR_BKSE 0x80 /* Bank select enable */ +#define DUART_LCR_DLAB 0x80 /* Divisor latch access bit */
+// Line Status Register +#define DUART_LSR_DR 0x01 /* Data ready */ +#define DUART_LSR_OE 0x02 /* Overrun */ +#define DUART_LSR_PE 0x04 /* Parity error */ +#define DUART_LSR_FE 0x08 /* Framing error */ +#define DUART_LSR_BI 0x10 /* Break */ +#define DUART_LSR_THRE 0x20 /* Xmit holding register empty */ +#define DUART_LSR_TEMT 0x40 /* Xmitter empty */ +#define DUART_LSR_ERR 0x80 /* Error */
+// Modem Status Register +#define DUART_MSR_DCTS 0x01 /* Delta CTS */ +#define DUART_MSR_DDSR 0x02 /* Reserved */ +#define DUART_MSR_TERI 0x04 /* Reserved */ +#define DUART_MSR_DDCD 0x08 /* Reserved */ +#define DUART_MSR_CTS 0x10 /* Clear to Send */ +#define DUART_MSR_DSR 0x20 /* Reserved */ +#define DUART_MSR_RI 0x40 /* Reserved */ +#define DUART_MSR_DCD 0x80 /* Reserved */
+// Interrupt Identification Register +#define DUART_IIR_NO_INT 0x01 /* No interrupts pending */ +#define DUART_IIR_ID 0x06 /* Mask for the interrupt ID */
+#define DUART_IIR_MSI 0x00 /* Modem status interrupt */ +#define DUART_IIR_THRI 0x02 /* Transmitter holding register empty */ +#define DUART_IIR_RDI 0x04 /* Receiver data interrupt */ +#define DUART_IIR_RLSI 0x06 /* Receiver line status interrupt */
+// Interrupt Enable Register +#define DUART_IER_MSI 0x08 /* Enable Modem status interrupt */ +#define DUART_IER_RLSI 0x04 /* Enable receiver line status interrupt */ +#define DUART_IER_THRI 0x02 /* Enable Transmitter holding register int. */ +#define DUART_IER_RDI 0x01 /* Enable receiver data interrupt */
+// LCR defaults +#define DUART_LCR_8N1 0x03
+#define DUART_LCRVAL DUART_LCR_8N1 /* 8 data, 1 stop, no parity */ +#define DUART_MCRVAL (DUART_MCR_DTR | \
DUART_MCR_RTS) /* RTS/DTR */
+#define DUART_FCRVAL (DUART_FCR_FIFO_EN | \
DUART_FCR_RXSR | \
DUART_FCR_TXSR) /* Clear & enable FIFOs */
+#define URBR 0x0 +#define UTHR 0x0 +#define UDLB 0x0 +#define UDMB 0x1 +#define UIER 0x1 +#define UIIR 0x2 +#define UFCR 0x2 +#define UAFR 0x2 +#define ULCR 0x3 +#define UMCR 0x4 +#define ULSR 0x5 +#define UMSR 0x6 +#define USCR 0x7 +#define UDSR 0x10
+#endif /* __DUART_H__ */ diff --git a/Chips/Nxp/QoriqLs/Library/DUartPortLib/DUartPortLib.c b/Chips/Nxp/QoriqLs/Library/DUartPortLib/DUartPortLib.c new file mode 100644 index 0000000..8e999b4 --- /dev/null +++ b/Chips/Nxp/QoriqLs/Library/DUartPortLib/DUartPortLib.c @@ -0,0 +1,321 @@ +/** DuartPortLib.c
- DUART (NS16550) library functions
- Based on Serial I/O Port library functions available in PL011SerialPortLib.c
- Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
- Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.<BR>
- Copyright (c) 2016, Freescale Semiconductor, Inc. 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 <Base.h>
+#include <Library/IoLib.h> +#include <Library/PcdLib.h> +#include <Library/SerialPortLib.h> +#include <Library/DUart.h>
+extern UINT32 CalculateBaudDivisor(UINT64 *BaudRate);
Where is this function defined? If it is in a separate library, include the appropriate header.
+STATIC CONST UINT32 mInvalidControlBits = (EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | \
EFI_SERIAL_DATA_TERMINAL_READY);
+/**
- Assert or deassert the control signals on a serial port.
- The following control signals are set according their bit settings :
- . Request to Send
- . Data Terminal Ready
- @param[in] Control The following bits are taken into account :
. EFI_SERIAL_REQUEST_TO_SEND : assert/deassert the
"Request To Send" control signal if this bit is
equal to one/zero.
. EFI_SERIAL_DATA_TERMINAL_READY : assert/deassert
the "Data Terminal Ready" control signal if this
bit is equal to one/zero.
. EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : enable/disable
the hardware loopback if this bit is equal to
one/zero.
. EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : not supported.
. EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : enable/
disable the hardware flow control based on CTS (Clear
To Send) and RTS (Ready To Send) control signals.
- @retval RETURN_SUCCESS The new control bits were set on the device.
- @retval RETURN_UNSUPPORTED The device does not support this operation.
+**/ +RETURN_STATUS +EFIAPI +SerialPortSetControl (
- IN UINT32 Control
- )
+{
- UINT32 McrBits;
- UINTN UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
- if (Control & (mInvalidControlBits)) {
- return RETURN_UNSUPPORTED;
- }
- McrBits = MmioRead8 (UartBase + UMCR);
- if (Control & EFI_SERIAL_REQUEST_TO_SEND) {
- McrBits |= DUART_MCR_RTS;
- } else {
- McrBits &= ~DUART_MCR_RTS;
- }
- if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
- McrBits |= DUART_MCR_LOOP;
- } else {
- McrBits &= ~DUART_MCR_LOOP;
- }
- if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
- McrBits |= DUART_MCR_AFE;
- } else {
- McrBits &= ~DUART_MCR_AFE;
- }
- MmioWrite32 (UartBase + UMCR, McrBits);
- return RETURN_SUCCESS;
+}
+/**
- Retrieve the status of the control bits on a serial device.
- @param[out] Control Status of the control bits on a serial device :
. EFI_SERIAL_DATA_CLEAR_TO_SEND,
EFI_SERIAL_DATA_SET_READY,
EFI_SERIAL_RING_INDICATE,
EFI_SERIAL_CARRIER_DETECT,
EFI_SERIAL_REQUEST_TO_SEND,
EFI_SERIAL_DATA_TERMINAL_READY
are all related to the DTE (Data Terminal Equipment)
and DCE (Data Communication Equipment) modes of
operation of the serial device.
. EFI_SERIAL_INPUT_BUFFER_EMPTY : equal to one if the
receive buffer is empty, 0 otherwise.
. EFI_SERIAL_OUTPUT_BUFFER_EMPTY : equal to one if the
transmit buffer is empty, 0 otherwise.
. EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : equal to one if
the hardware loopback is enabled (the ouput feeds the
receive buffer), 0 otherwise.
. EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : equal to one if
a loopback is accomplished by software, 0 otherwise.
. EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : equal to
one if the hardware flow control based on CTS (Clear
To Send) and RTS (Ready To Send) control signals is
enabled, 0 otherwise.
- @retval RETURN_SUCCESS The control bits were read from the serial device.
+**/ +RETURN_STATUS +EFIAPI +SerialPortGetControl (
- OUT UINT32 *Control
- )
+{
- UINT32 MsrRegister;
- UINT32 McrRegister;
- UINT32 LsrRegister;
- UINTN UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
- MsrRegister = MmioRead8 (UartBase + UMSR);
- McrRegister = MmioRead8 (UartBase + UMCR);
- LsrRegister = MmioRead8 (UartBase + ULSR);
- *Control = 0;
- if ((MsrRegister & DUART_MSR_CTS) == DUART_MSR_CTS) {
- *Control |= EFI_SERIAL_CLEAR_TO_SEND;
- }
- if ((McrRegister & DUART_MCR_RTS) == DUART_MCR_RTS) {
- *Control |= EFI_SERIAL_REQUEST_TO_SEND;
- }
- if ((LsrRegister & DUART_LSR_TEMT) == DUART_LSR_TEMT) {
- *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
- }
- if ((McrRegister & DUART_MCR_AFE) == DUART_MCR_AFE) {
- *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
- }
- if ((McrRegister & DUART_MCR_LOOP) == DUART_MCR_LOOP) {
- *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
- }
- return RETURN_SUCCESS;
+}
+/**
- Programmed hardware of Serial port.
- @return Always return RETURN_UNSUPPORTED.
+**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize (
- VOID
- )
+{
- UINT64 BaudRate;
UINT32 BaudDivisor;
UINTN UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
- BaudRate = (UINTN)PcdGet64 (PcdUartDefaultBaudRate);
BaudDivisor = CalculateBaudDivisor(&BaudRate);
while (!(MmioRead8(UartBase + ULSR) & DUART_LSR_TEMT))
;
MmioWrite8(UartBase + UIER, 0x1);
MmioWrite8(UartBase + ULCR, DUART_LCR_BKSE | DUART_LCRVAL);
MmioWrite8(UartBase + UDLB, 0);
MmioWrite8(UartBase + UDMB, 0);
MmioWrite8(UartBase + ULCR, DUART_LCRVAL);
MmioWrite8(UartBase + UMCR, DUART_MCRVAL);
MmioWrite8(UartBase + UFCR, DUART_FCRVAL);
MmioWrite8(UartBase + ULCR, DUART_LCR_BKSE | DUART_LCRVAL);
MmioWrite8(UartBase + UDLB, BaudDivisor & 0xff);
MmioWrite8(UartBase + UDMB, (BaudDivisor >> 8) & 0xff);
MmioWrite8(UartBase + ULCR, DUART_LCRVAL);
return RETURN_SUCCESS;
+}
+/**
- Write data to serial device.
- @param Buffer Point of data buffer which need to be written.
- @param NumberOfBytes Number of output bytes which are cached in Buffer.
- @retval 0 Write data failed.
- @retval !0 Actual number of bytes written to serial device.
+**/ +UINTN +EFIAPI +SerialPortWrite (
- IN UINT8 *Buffer,
- IN UINTN NumberOfBytes
- )
+{
UINT8* CONST Final = &Buffer[NumberOfBytes];
What is the point of this const? A constant value on the stack? Or did you mean 'UINT8 CONST *Final'? In either case, you can drop the const.
UINTN UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
while (Buffer < Final) {
while ((MmioRead8(UartBase + ULSR) & DUART_LSR_THRE) == 0)
;
MmioWrite8(UartBase + UTHR, *Buffer++);
}
return NumberOfBytes;
+}
+/**
- Read data from serial device and save the data in buffer.
- @param Buffer Point of data buffer which need to be written.
- @param NumberOfBytes Number of output bytes which are cached in Buffer.
- @retval 0 Read data failed.
- @retval !0 Actual number of bytes read from serial device.
+**/ +UINTN +EFIAPI +SerialPortRead (
- OUT UINT8 *Buffer,
- IN UINTN NumberOfBytes
+) +{
UINTN Count;
UINTN UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
for (Count = 0; Count < NumberOfBytes; Count++, Buffer++) {
/*
* Loop while waiting for a new char(s) to arrive in the
* RxFIFO
*/
while ((MmioRead8(UartBase + ULSR) & DUART_LSR_DR) == 0);
*Buffer = MmioRead8(UartBase + URBR);
}
return NumberOfBytes;
+}
+/**
- Check to see if any data is available to be read from the debug device.
- @retval EFI_SUCCESS At least one byte of data is available to be read
- @retval EFI_NOT_READY No data is available to be read
- @retval EFI_DEVICE_ERROR The serial device is not functioning properly
+**/ +BOOLEAN +EFIAPI +SerialPortPoll (
- VOID
- )
+{
UINTN UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
return ((MmioRead8 (UartBase + ULSR) & DUART_LSR_DR) != 0);
+}
+/**
- Set new attributes to LS1043a.
- @param BaudRate The baud rate of the serial device. If the baud rate is not supported,
the speed will be reduced down to the nearest supported one and the
variable's value will be updated accordingly.
- @param ReceiveFifoDepth The number of characters the device will buffer on input. If the specified
value is not supported, the variable's value will be reduced down to the
nearest supported one.
- @param Timeout If applicable, the number of microseconds the device will wait
before timing out a Read or a Write operation.
- @param Parity If applicable, this is the EFI_PARITY_TYPE that is computed or checked
as each character is transmitted or received. If the device does not
support parity, the value is the default parity value.
- @param DataBits The number of data bits in each character
- @param StopBits If applicable, the EFI_STOP_BITS_TYPE number of stop bits per character.
If the device does not support stop bits, the value is the default stop
bit value.
- @retval EFI_SUCCESS All attributes were set correctly on the serial device.
- @retval EFI_INVALID_PARAMETERS One or more of the attributes has an unsupported value.
+**/ +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 SerialPortInitialize ();
+}
This looks wrong. Please explain in a comment why this makes sense (if it does)
diff --git a/Chips/Nxp/QoriqLs/Library/DUartPortLib/DUartPortLib.inf b/Chips/Nxp/QoriqLs/Library/DUartPortLib/DUartPortLib.inf new file mode 100644 index 0000000..e19ab62 --- /dev/null +++ b/Chips/Nxp/QoriqLs/Library/DUartPortLib/DUartPortLib.inf @@ -0,0 +1,43 @@ +#/** DUartPortLib.inf +# +# Component description file for DUartPortLib module +# +# Copyright (c) 2013, Freescale Ltd. All rights reserved. +# Author: Bhupesh Sharma bhupesh.sharma@nxp.com +# +# 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 = 0x00010005
- BASE_NAME = DUartPortLib
- FILE_GUID = 8ecefc8f-a2c4-4091-b80f-20f7aeb0567f
Use a fresh GUID
- MODULE_TYPE = BASE
- VERSION_STRING = 1.0
- LIBRARY_CLASS = SerialPortLib
+[Sources.common]
- DUartPortLib.c
+[LibraryClasses]
- ArmLib
- PcdLib
SocLib
Indentation
+[Packages]
- EmbeddedPkg/EmbeddedPkg.dec
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
- ArmPlatformPkg/ArmPlatformPkg.dec
- OpenPlatformPkg/Chips/Nxp/QoriqLs/NxpQoriqLs.dec
+[Pcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase
- gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
-- 1.9.1