Hi Ard,
Thanks for the review comments.
From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org] Sent: Tuesday, October 18, 2016 3:05 PM
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
Ok.
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
- */
+#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.
Ok, I will add 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.
Ok.
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)
Ok, I will change this as per the latest PL011 implementation.
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
Ok.
- MODULE_TYPE = BASE
- VERSION_STRING = 1.0
- LIBRARY_CLASS = SerialPortLib
+[Sources.common]
- DUartPortLib.c
+[LibraryClasses]
- ArmLib
- PcdLib
SocLib
Indentation
Ok.
+[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
Regards, Bhupesh