Serial Port library for LoongarchQemuPkg
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4054
Cc: Bibo Mao <maobibo@loongson.cn>
Cc: Chao Li <lichao@loongson.cn>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Signed-off-by: xianglai li <lixianglai@loongson.cn>
---
.../LoongArchQemuPkg/Include/Library/Cpu.h | 237 +++++++
.../Include/LoongArchQemuPlatform.h | 95 +++
.../Library/SerialPortLib/SerialPortLib.c | 593 ++++++++++++++++++
.../Library/SerialPortLib/SerialPortLib.inf | 39 ++
4 files changed, 964 insertions(+)
create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/Cpu.h
create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.h
create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.c
create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.inf
diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/Library/Cpu.h b/Platform/Loongson/LoongArchQemuPkg/Include/Library/Cpu.h
new file mode 100644
index 0000000000..c6599c6ed7
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/Cpu.h
@@ -0,0 +1,237 @@
+/** @file
+
+ Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - EXC - Exception
+ - INT - Interrupt
+ - FPU - Floating Point Unit
+ - CSR - CPU Status Register
+ - READQ - Read Quad Word
+**/
+#ifndef LOONGARCH_CPU_H_
+#define LOONGARCH_CPU_H_
+
+/* Exception types decoded by machdep exception decoder */
+#define EXC_INT 0 /* HW interrupt */
+#define EXC_TLBL 1 /* TLB miss on a load */
+#define EXC_TLBS 2 /* TLB miss on a store */
+#define EXC_TLBI 3 /* TLB miss on a ifetch */
+#define EXC_TLBM 4 /* TLB modified fault */
+#define EXC_TLBRI 5 /* TLB Read-Inhibit exception */
+#define EXC_TLBXI 6 /* TLB Execution-Inhibit exception */
+#define EXC_TLBPE 7 /* TLB Privilege Error */
+#define EXC_ADE 8 /* Address Error */
+#define EXC_ALE 9 /* Unalign Access */
+#define EXC_OOB 10 /* Out of bounds */
+#define EXC_SYS 11 /* System call */
+#define EXC_BP 12 /* Breakpoint */
+#define EXC_INE 13 /* Inst. Not Exist */
+#define EXC_IPE 14 /* Inst. Privileged Error */
+#define EXC_FPDIS 15 /* FPU Disabled */
+#define EXC_LSXDIS 16 /* LSX Disabled */
+#define EXC_LASXDIS 17 /* LASX Disabled */
+#define EXC_FPE 18 /* Floating Point Exception */
+#define EXC_WATCH 19 /* Watch address reference */
+#define EXC_BAD 255 /* Undecodeable */
+
+#define COPY_SIGCODE // copy sigcode above user stack in exec
+#define ZERO $r0 /* wired zero */
+#define RA $r1 /* return address */
+#define GP $r2 /* global pointer - caller saved for PIC */
+#define SP $r3 /* stack pointer */
+#define V0 $r4 /* return value - caller saved */
+#define V1 $r5
+#define A0 $r4 /* argument registers */
+#define A1 $r5
+#define A2 $r6
+#define A3 $r7
+#define A4 $r8 /* arg reg 64 bit; caller saved in 32 bit */
+#define A5 $r9
+#define A6 $r10
+#define A7 $r11
+#define T0 $r12 /* caller saved */
+#define T1 $r13
+#define T2 $r14
+#define T3 $r15
+#define T4 $r16 /* callee saved */
+#define T5 $r17
+#define T6 $r18
+#define T7 $r19
+#define T8 $r20 /* caller saved */
+#define TP $r21 /* TLS */
+#define FP $r22 /* frame pointer */
+#define S0 $r23 /* callee saved */
+#define S1 $r24
+#define S2 $r25
+#define S3 $r26
+#define S4 $r27
+#define S5 $r28
+#define S6 $r29
+#define S7 $r30
+#define S8 $r31 /* callee saved */
+
+#define FCSR0 $r0
+
+//
+// Location of the saved registers relative to ZERO.
+// Usage is p->p_regs[XX].
+//
+#define RA_NUM 1
+#define GP_NUM 2
+#define SP_NUM 3
+#define A0_NUM 4
+#define A1_NUM 5
+#define A2_NUM 6
+#define A3_NUM 7
+#define A4_NUM 8
+#define A5_NUM 9
+#define A6_NUM 10
+#define A7_NUM 11
+#define T0_NUM 12
+#define T1_NUM 13
+#define T2_NUM 14
+#define T3_NUM 15
+#define T4_NUM 16
+#define T5_NUM 17
+#define T6_NUM 18
+#define T7_NUM 19
+#define T8_NUM 20
+#define TP_NUM 21
+#define FP_NUM 22
+#define S0_NUM 23
+#define S1_NUM 24
+#define S2_NUM 25
+#define S3_NUM 26
+#define S4_NUM 27
+#define S5_NUM 28
+#define S6_NUM 29
+#define S7_NUM 30
+#define S8_NUM 31
+
+#define FP0_NUM 0
+#define FP1_NUM 1
+#define FP2_NUM 2
+#define FP3_NUM 3
+#define FP4_NUM 4
+#define FP5_NUM 5
+#define FP6_NUM 6
+#define FP7_NUM 7
+#define FP8_NUM 8
+#define FP9_NUM 9
+#define FP10_NUM 10
+#define FP11_NUM 11
+#define FP12_NUM 12
+#define FP13_NUM 13
+#define FP14_NUM 14
+#define FP15_NUM 15
+#define FP16_NUM 16
+#define FP17_NUM 17
+#define FP18_NUM 18
+#define FP19_NUM 19
+#define FP20_NUM 20
+#define FP21_NUM 21
+#define FP22_NUM 22
+#define FP23_NUM 23
+#define FP24_NUM 24
+#define FP25_NUM 25
+#define FP26_NUM 26
+#define FP27_NUM 27
+#define FP28_NUM 28
+#define FP29_NUM 29
+#define FP30_NUM 30
+#define FP31_NUM 31
+#define FCSR_NUM 32
+#define FCC_NUM 33
+
+#ifdef __ASSEMBLY__
+#define _ULCAST_
+#define _U64CAST_
+#else
+#define _ULCAST_ (unsigned long)
+#define _U64CAST_ (u64)
+#endif
+
+#define LOONGARCH_CSR_CRMD 0
+#define LOONGARCH_CSR_PRMD 1
+#define LOONGARCH_CSR_EUEN 2
+#define CSR_EUEN_LBTEN_SHIFT 3
+#define CSR_EUEN_LBTEN (_ULCAST_(0x1) << CSR_EUEN_LBTEN_SHIFT)
+#define CSR_EUEN_LASXEN_SHIFT 2
+#define CSR_EUEN_LASXEN (_ULCAST_(0x1) << CSR_EUEN_LASXEN_SHIFT)
+#define CSR_EUEN_LSXEN_SHIFT 1
+#define CSR_EUEN_LSXEN (_ULCAST_(0x1) << CSR_EUEN_LSXEN_SHIFT)
+#define CSR_EUEN_FPEN_SHIFT 0
+#define CSR_EUEN_FPEN (_ULCAST_(0x1) << CSR_EUEN_FPEN_SHIFT)
+#define LOONGARCH_CSR_ECFG 4
+
+/* Exception status */
+#define LOONGARCH_CSR_ESTAT 5
+#define CSR_ESTAT_ESUBCODE_SHIFT 22
+#define CSR_ESTAT_ESUBCODE_WIDTH 9
+#define CSR_ESTAT_ESUBCODE (_ULCAST_(0x1ff) << CSR_ESTAT_ESUBCODE_SHIFT)
+#define CSR_ESTAT_EXC_SHIFT 16
+#define CSR_ESTAT_EXC_WIDTH 6
+#define CSR_ESTAT_EXC (_ULCAST_(0x3f) << CSR_ESTAT_EXC_SHIFT)
+#define CSR_ESTAT_IS_SHIFT 0
+#define CSR_ESTAT_IS_WIDTH 15
+#define CSR_ESTAT_IS (_ULCAST_(0x7fff) << CSR_ESTAT_IS_SHIFT)
+
+#define LOONGARCH_CSR_EPC 6
+#define LOONGARCH_CSR_BADV 7
+#define LOONGARCH_CSR_BADINST 8
+#define LOONGARCH_CSR_BADI 8
+#define LOONGARCH_CSR_EBASE 0xc /* Exception entry base address */
+#define LOONGARCH_CSR_CPUNUM 0x20 /* CPU core number */
+
+/* register number save in stack on exception */
+#define FP_BASE_NUM 34
+#define BASE_NUM 32
+#define CSR_NUM 10
+#define FP_BASE_INDEX (CSR_NUM + BASE_NUM)
+#define BOOTCORE_ID 0
+
+#define LOONGSON_IOCSR_IPI_STATUS 0x1000
+#define LOONGSON_IOCSR_IPI_EN 0x1004
+#define LOONGSON_IOCSR_IPI_SET 0x1008
+#define LOONGSON_IOCSR_IPI_CLEAR 0x100c
+#define LOONGSON_CSR_MAIL_BUF0 0x1020
+#define LOONGSON_CSR_MAIL_BUF1 0x1028
+#define LOONGSON_CSR_MAIL_BUF2 0x1030
+#define LOONGSON_CSR_MAIL_BUF3 0x1038
+
+/* Bit Domains for CFG registers */
+#define LOONGARCH_CPUCFG4 0x4
+#define LOONGARCH_CPUCFG5 0x5
+
+/* Kscratch registers */
+#define LOONGARCH_CSR_KS0 0x30
+#define LOONGARCH_CSR_KS1 0x31
+
+/* Stable timer registers */
+#define LOONGARCH_CSR_TMCFG 0x41
+#define LOONGARCH_CSR_TMCFG_EN (1ULL << 0)
+#define LOONGARCH_CSR_TMCFG_PERIOD (1ULL << 1)
+#define LOONGARCH_CSR_TMCFG_TIMEVAL (0x3fffffffffffULL << 2)
+#define LOONGARCH_CSR_TVAL 0x42 /* Timer value */
+#define LOONGARCH_CSR_CNTC 0x43 /* Timer offset */
+#define LOONGARCH_CSR_TINTCLR 0x44 /* Timer interrupt clear */
+
+/* TLB refill exception base address */
+#define LOONGARCH_CSR_TLBREBASE 0x88
+#define LOONGARCH_CSR_TLBRSAVE 0x8b /* KScratch for TLB refill exception */
+#define LOONGARCH_CSR_PGD 0x1b /* Page table base */
+
+/* Invalid addr with global=1 or matched asid in current tlb */
+#define INVTLB_ADDR_GTRUE_OR_ASID 0x6
+
+/* Bits 8 and 9 of FPU Status Register specify the rounding mode */
+#define FPU_CSR_RM 0x300
+#define FPU_CSR_RN 0x000 /* nearest */
+#define FPU_CSR_RZ 0x100 /* towards zero */
+#define FPU_CSR_RU 0x200 /* towards +Infinity */
+#define FPU_CSR_RD 0x300 /* towards -Infinity */
+
+#endif
diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.h b/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.h
new file mode 100644
index 0000000000..e942e6a994
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.h
@@ -0,0 +1,95 @@
+/** @file
+ LoongArch Qemu Platform macro definition.
+
+ Copyright (c) 2022, Loongson Limited. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+
+#ifndef LOONGARCH_QEMU_PLATFORM_H_
+#define LOONGARCH_QEMU_PLATFORM_H_
+
+/* Acpi pm device */
+#define LS7A_PCH_REG_BASE 0x10000000UL
+#define LS7A_ACPI_REG_BASE (LS7A_PCH_REG_BASE + 0x000D0000)
+#define LS7A_PM_CNT_BLK (0x14) /* 2 bytes */
+#define LS7A_GPE0_RESET_REG (0x30) /* 4 bytes */
+
+#define ACPI_BITMASK_SLEEP_TYPE 0x1C00
+#define ACPI_BITMASK_SLEEP_ENABLE 0x2000
+
+//---------------------------------------------
+// UART Register Offsets
+//---------------------------------------------
+#define BAUD_LOW_OFFSET 0x00
+#define BAUD_HIGH_OFFSET 0x01
+#define IER_OFFSET 0x01
+#define LCR_SHADOW_OFFSET 0x01
+#define FCR_SHADOW_OFFSET 0x02
+#define IR_CONTROL_OFFSET 0x02
+#define FCR_OFFSET 0x02
+#define EIR_OFFSET 0x02
+#define BSR_OFFSET 0x03
+#define LCR_OFFSET 0x03
+#define MCR_OFFSET 0x04
+#define LSR_OFFSET 0x05
+#define MSR_OFFSET 0x06
+
+/* character format control register */
+#define CFCR_DLAB 0x80 /* divisor latch */
+#define CFCR_SBREAK 0x40 /* send break */
+#define CFCR_PZERO 0x30 /* zero parity */
+#define CFCR_PONE 0x20 /* one parity */
+#define CFCR_PEVEN 0x10 /* even parity */
+#define CFCR_PODD 0x00 /* odd parity */
+#define CFCR_PENAB 0x08 /* parity enable */
+#define CFCR_STOPB 0x04 /* 2 stop bits */
+#define CFCR_8BITS 0x03 /* 8 data bits */
+#define CFCR_7BITS 0x02 /* 7 data bits */
+#define CFCR_6BITS 0x01 /* 6 data bits */
+#define CFCR_5BITS 0x00 /* 5 data bits */
+/* modem control register */
+#define MCR_LOOPBACK 0x10 /* loopback */
+#define MCR_IENABLE 0x08 /* output 2 = int enable */
+#define MCR_DRS 0x04 /* output 1 = xxx */
+#define MCR_RTS 0x02 /* enable RTS */
+#define MCR_DTR 0x01 /* enable DTR */
+
+/* line status register */
+#define LSR_RCV_FIFO 0x80 /* error in receive fifo */
+#define LSR_TSRE 0x40 /* transmitter empty */
+#define LSR_TXRDY 0x20 /* transmitter ready */
+#define LSR_BI 0x10 /* break detected */
+#define LSR_FE 0x08 /* framing error */
+#define LSR_PE 0x04 /* parity error */
+#define LSR_OE 0x02 /* overrun error */
+#define LSR_RXRDY 0x01 /* receiver ready */
+#define LSR_RCV_MASK 0x1f
+
+/* 16550 UART register offsets and bitfields */
+#define R_UART_RXBUF 0
+#define R_UART_TXBUF 0
+#define R_UART_BAUD_LOW 0
+#define R_UART_BAUD_HIGH 1
+#define R_UART_FCR 2
+#define B_UART_FCR_FIFOE BIT0
+#define B_UART_FCR_FIFO64 BIT5
+#define R_UART_LCR 3
+#define B_UART_LCR_DLAB BIT7
+#define R_UART_MCR 4
+#define B_UART_MCR_DTRC BIT0
+#define B_UART_MCR_RTS BIT1
+#define R_UART_LSR 5
+#define B_UART_LSR_RXRDY BIT0
+#define B_UART_LSR_TXRDY BIT5
+#define B_UART_LSR_TEMT BIT6
+#define R_UART_MSR 6
+#define B_UART_MSR_CTS BIT4
+#define B_UART_MSR_DSR BIT5
+#define B_UART_MSR_RI BIT6
+#define B_UART_MSR_DCD BIT7
+#define UART_BASE_ADDRESS (0x1fe001e0)
+#define UART_BPS (115200)
+#define UART_WAIT_TIMOUT (1000000)
+#endif
diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.c b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.c
new file mode 100644
index 0000000000..7044db81ee
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.c
@@ -0,0 +1,593 @@
+/** @file
+ UART Serial Port library functions
+
+ Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - Bps - Bit Per Second
+ - CTL - Control
+ - Config - Configure
+**/
+
+#include <Base.h>
+#include <Library/Cpu.h>
+#include <Library/IoLib.h>
+#include <Library/SerialPortLib.h>
+#include <LoongArchQemuPlatform.h>
+
+UINTN gUartBase = UART_BASE_ADDRESS;
+UINTN gBps = UART_BPS;
+
+/**
+ Initialize the serial device hardware.
+
+ If no initialization is required, then return RETURN_SUCCESS.
+ If the serial device was successfuly 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 serail device could not be initialized.
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortInitialize (
+ VOID
+ )
+{
+ UINTN TimeOut;
+ //
+ // wait for Tx fifo to completely drain */
+ //
+ TimeOut = UART_WAIT_TIMOUT;
+ while (!(MmioRead8 ((UINTN) gUartBase + LSR_OFFSET) & LSR_TSRE)) {
+ if (--TimeOut == 0) {
+ break;
+ }
+ }
+ //
+ // Set communications format
+ //
+ MmioWrite8 ((UINTN) (gUartBase + LCR_OFFSET), CFCR_DLAB);
+
+ //
+ // Configure baud rate
+ //
+
+ MmioWrite8 ((UINTN) (gUartBase + LCR_OFFSET), CFCR_8BITS);
+ MmioWrite8 ((UINTN) (gUartBase + MCR_OFFSET), MCR_IENABLE | MCR_DTR | MCR_RTS);
+
+ 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
+UartCtlWrite (
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes,
+ IN UINTN CtlAddr
+)
+{
+ UINTN Result;
+ UINT8 Data;
+
+ if (Buffer == NULL) {
+ return 0;
+ }
+
+ Result = NumberOfBytes;
+
+ while (NumberOfBytes--) {
+ //
+ // Wait for the serail port to be ready.
+ //
+ do {
+ Data = MmioRead8 (CtlAddr + LSR_OFFSET);
+ } while ((Data & LSR_TXRDY) == 0);
+ MmioWrite8 (CtlAddr, *Buffer++);
+ }
+ return Result;
+}
+/**
+ Writes data to serial port.
+
+ @param Buffer Pointer to the data buffer to store the data writed to serial port.
+ @param NumberOfBytes Number of bytes to write to the serial port.
+
+ @retval 0 NumberOfBytes is 0.
+ @retval >0 The number of bytes write the serial port.
+ If this value is less than NumberOfBytes, then the write operation failed.
+**/
+UINTN
+EFIAPI
+SerialPortWrite (
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+)
+{
+ return UartCtlWrite (Buffer, NumberOfBytes, gUartBase);
+}
+/**
+ Reads data from a serial device into a buffer.
+
+ @param Buffer Pointer to the data buffer to store the data read from the serial device.
+ @param NumberOfBytes Number of bytes to read from the serial device.
+
+ @retval 0 NumberOfBytes is 0.
+ @retval >0 The number of bytes read from the serial device.
+ If this value is less than NumberOfBytes, then the read operation failed.
+**/
+UINTN
+EFIAPI
+UartCtlRead (
+ OUT UINT8 *Buffer,
+ IN UINTN NumberOfBytes,
+ IN UINTN CtlAddr
+)
+{
+ UINTN Result;
+ UINT8 Data;
+
+ if (NULL == Buffer) {
+ return 0;
+ }
+
+ Result = NumberOfBytes;
+
+ while (NumberOfBytes--) {
+ //
+ // Wait for the serail port to be ready.
+ //
+ do {
+ Data = MmioRead8 (CtlAddr + LSR_OFFSET);
+ } while ((Data & LSR_RXRDY) == 0);
+
+ *Buffer++ = MmioRead8 (CtlAddr);
+ }
+ return Result;
+}
+/**
+ Read data from serial port.
+
+ @param Buffer Pointer to the data buffer to store the data read from serial port.
+ @param NumberOfBytes Number of bytes to read from the serial port.
+
+ @retval 0 NumberOfBytes is 0.
+ @retval >0 The number of bytes read from the serial port.
+ If this value is less than NumberOfBytes, then the read operation failed.
+**/
+UINTN
+EFIAPI
+SerialPortRead (
+ OUT UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+)
+{
+ return UartCtlRead (Buffer, NumberOfBytes, gUartBase);
+}
+/**
+ Polls a serial device to see if there is any data waiting to be read.
+
+ Polls aserial 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
+ )
+{
+ UINT8 Data;
+
+ //
+ // Read the serial port status.
+ //
+ Data = MmioRead8 ((UINTN) gUartBase + LSR_OFFSET);
+
+ return (BOOLEAN) ((Data & LSR_RXRDY) != 0);
+}
+/**
+ To get serial register base address.
+
+ @param VOID
+
+ @return serial register base address.
+**/
+UINTN
+GetSerialRegisterBase (
+ VOID
+ )
+{
+ return gUartBase;
+}
+/**
+ Read an 8-bit register.
+ @param Base The base address register of UART device.
+ @param Offset The offset of the register to read.
+
+ @return The value read from the 16550 register.
+**/
+UINT8
+SerialPortReadRegister (
+ UINTN Base,
+ UINTN Offset
+ )
+{
+ return MmioRead8 (Base + Offset);
+}
+
+/**
+ Write an 8-bit register.
+ @param Base The base address register of UART device.
+ @param Offset The offset of the register to write.
+ @param Value The value to write to the register specified by Offset.
+
+ @return The value written to the 16550 register.
+**/
+UINT8
+SerialPortWriteRegister (
+ UINTN Base,
+ UINTN Offset,
+ UINT8 Value
+ )
+{
+ return MmioWrite8 (Base + Offset, Value);
+}
+
+/**
+ Sets the control bits on a serial device.
+
+ @param Control Sets the bits of Control that are settable.
+
+ @retval RETURN_SUCCESS The new control bits were set on the serial device.
+ @retval RETURN_UNSUPPORTED The serial device does not support this operation.
+ @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortSetControl (
+ IN UINT32 Control
+ )
+{
+ UINTN SerialRegisterBase;
+ UINT8 Mcr;
+
+ //
+ // First determine the parameter is invalid.
+ //
+ if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |
+ EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0)
+ {
+ return RETURN_UNSUPPORTED;
+ }
+
+ SerialRegisterBase = GetSerialRegisterBase ();
+ if (SerialRegisterBase ==0) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Read the Modem Control Register.
+ //
+ Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR);
+ Mcr &= (~(B_UART_MCR_DTRC | B_UART_MCR_RTS));
+
+ if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) {
+ Mcr |= B_UART_MCR_DTRC;
+ }
+
+ if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) {
+ Mcr |= B_UART_MCR_RTS;
+ }
+
+ //
+ // Write the Modem Control Register.
+ //
+ SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, Mcr);
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ 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_SUCCESS The control bits were read from the serial device.
+ @retval RETURN_UNSUPPORTED The serial device does not support this operation.
+ @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortGetControl (
+ OUT UINT32 *Control
+ )
+{
+ UINTN SerialRegisterBase;
+ UINT8 Msr;
+ UINT8 Mcr;
+ UINT8 Lsr;
+
+ SerialRegisterBase = GetSerialRegisterBase ();
+ if (SerialRegisterBase ==0) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ *Control = 0;
+
+ //
+ // Read the Modem Status Register.
+ //
+ Msr = SerialPortReadRegister (SerialRegisterBase, R_UART_MSR);
+
+ if ((Msr & B_UART_MSR_CTS) == B_UART_MSR_CTS) {
+ *Control |= EFI_SERIAL_CLEAR_TO_SEND;
+ }
+
+ if ((Msr & B_UART_MSR_DSR) == B_UART_MSR_DSR) {
+ *Control |= EFI_SERIAL_DATA_SET_READY;
+ }
+
+ if ((Msr & B_UART_MSR_RI) == B_UART_MSR_RI) {
+ *Control |= EFI_SERIAL_RING_INDICATE;
+ }
+
+ if ((Msr & B_UART_MSR_DCD) == B_UART_MSR_DCD) {
+ *Control |= EFI_SERIAL_CARRIER_DETECT;
+ }
+
+ //
+ // Read the Modem Control Register.
+ //
+ Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR);
+
+ if ((Mcr & B_UART_MCR_DTRC) == B_UART_MCR_DTRC) {
+ *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
+ }
+
+ if ((Mcr & B_UART_MCR_RTS) == B_UART_MCR_RTS) {
+ *Control |= EFI_SERIAL_REQUEST_TO_SEND;
+ }
+
+ if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
+ *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
+ }
+
+ //
+ // Read the Line Status Register.
+ //
+ Lsr = SerialPortReadRegister (SerialRegisterBase, R_UART_LSR);
+
+ if ((Lsr & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) == (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) {
+ *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
+ }
+
+ if ((Lsr & B_UART_LSR_RXRDY) == 0) {
+ *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ 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 time
+ out 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
+ vaule 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_SUCCESS The new attributes were set on the serial device.
+ @retval RETURN_UNSUPPORTED The serial device does not support this operation.
+ @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value.
+ @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.
+**/
+RETURN_STATUS
+EFIAPI
+UartCtlConfig (
+ 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,
+ IN UINTN CtlAddr
+ )
+{
+ UINTN SerialRegisterBase;
+ UINT8 Lcr;
+ UINT8 LcrData;
+ UINT8 LcrParity;
+ UINT8 LcrStop;
+
+ SerialRegisterBase = CtlAddr;
+ if (SerialRegisterBase ==0) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Check for default settings and fill in actual values.
+ //
+ if (*BaudRate == 0) {
+ *BaudRate = PcdGet32 (PcdSerialBaudRate);
+ }
+
+ if (*DataBits == 0) {
+ LcrData = (UINT8) (PcdGet8 (PcdSerialLineControl) & 0x3);
+ *DataBits = LcrData + 5;
+ } else {
+ if ((*DataBits < 5)
+ || (*DataBits > 8))
+ {
+ return RETURN_INVALID_PARAMETER;
+ }
+ //
+ // Map 5..8 to 0..3
+ //
+ LcrData = (UINT8) (*DataBits - (UINT8) 5);
+ }
+
+ if (*Parity == DefaultParity) {
+ LcrParity = (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 3) & 0x7);
+ switch (LcrParity) {
+ case 0:
+ *Parity = NoParity;
+ break;
+
+ case 3:
+ *Parity = EvenParity;
+ break;
+
+ case 1:
+ *Parity = OddParity;
+ break;
+
+ case 7:
+ *Parity = SpaceParity;
+ break;
+
+ case 5:
+ *Parity = MarkParity;
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ switch (*Parity) {
+ case NoParity:
+ LcrParity = 0;
+ break;
+
+ case EvenParity:
+ LcrParity = 3;
+ break;
+
+ case OddParity:
+ LcrParity = 1;
+ break;
+
+ case SpaceParity:
+ LcrParity = 7;
+ break;
+
+ case MarkParity:
+ LcrParity = 5;
+ break;
+
+ default:
+ return RETURN_INVALID_PARAMETER;
+ }
+ }
+
+ if (*StopBits == DefaultStopBits) {
+ LcrStop = (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 2) & 0x1);
+ switch (LcrStop) {
+ case 0:
+ *StopBits = OneStopBit;
+ break;
+
+ case 1:
+ if (*DataBits == 5) {
+ *StopBits = OneFiveStopBits;
+ } else {
+ *StopBits = TwoStopBits;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ switch (*StopBits) {
+ case OneStopBit:
+ LcrStop = 0;
+ break;
+
+ case OneFiveStopBits:
+ case TwoStopBits:
+ LcrStop = 1;
+ break;
+
+ default:
+ return RETURN_INVALID_PARAMETER;
+ }
+ }
+ SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB);
+
+ //
+ // Clear DLAB and configure Data Bits, Parity, and Stop Bits.
+ // Strip reserved bits from line control value
+ //
+ Lcr = (UINT8) ((LcrParity << 3) | (LcrStop << 2) | LcrData);
+ SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8) (Lcr & 0x3F));
+
+ return RETURN_SUCCESS;
+}
+/**
+ Set the serial port Attributes.
+
+ @param VOID
+
+ @return serial register base address.
+**/
+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 SerialRegisterBase;
+
+ SerialRegisterBase = GetSerialRegisterBase ();
+
+ return UartCtlConfig (&gBps, ReceiveFifoDepth, Timeout, Parity, DataBits, StopBits,
+ SerialRegisterBase);
+}
diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.inf
new file mode 100644
index 0000000000..22cf82cf79
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.inf
@@ -0,0 +1,39 @@
+## @file
+# UART Serial Port library functions
+#
+# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PcAtSerialPortLib
+ FILE_GUID = f4fb883d-8138-4f29-bb0c-c574e9312c74
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SerialPortLib
+
+#
+# VALID_ARCHITECTURES = LOONGARCH64
+#
+
+[Sources]
+ SerialPortLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Platform/Loongson/LoongArchQemuPkg/Loongson.dec
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ PcdLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialLineControl ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate ## CONSUMES
--
2.31.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#96273): https://edk2.groups.io/g/devel/message/96273
Mute This Topic: https://groups.io/mt/94955170/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Reviewed-by: Chao Li <lichao@loongson.cn> Thanks, Chao -------- On 11月 11 2022, at 5:12 下午, xianglai li <lixianglai@loongson.cn> wrote: > Serial Port library for LoongarchQemuPkg > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4054 > > > Cc: Bibo Mao <maobibo@loongson.cn> > Cc: Chao Li <lichao@loongson.cn> > Cc: Leif Lindholm <quic_llindhol@quicinc.com> > Cc: Liming Gao <gaoliming@byosoft.com.cn> > Cc: Michael D Kinney <michael.d.kinney@intel.com> > Signed-off-by: xianglai li <lixianglai@loongson.cn> > --- > .../LoongArchQemuPkg/Include/Library/Cpu.h | 237 +++++++ > .../Include/LoongArchQemuPlatform.h | 95 +++ > .../Library/SerialPortLib/SerialPortLib.c | 593 ++++++++++++++++++ > .../Library/SerialPortLib/SerialPortLib.inf | 39 ++ > 4 files changed, 964 insertions(+) > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/Cpu.h > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.h > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.c > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.inf > > > diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/Library/Cpu.h b/Platform/Loongson/LoongArchQemuPkg/Include/Library/Cpu.h > new file mode 100644 > index 0000000000..c6599c6ed7 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/Cpu.h > @@ -0,0 +1,237 @@ > +/** @file > + > + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + @par Glossary: > + - EXC - Exception > + - INT - Interrupt > + - FPU - Floating Point Unit > + - CSR - CPU Status Register > + - READQ - Read Quad Word > +**/ > +#ifndef LOONGARCH_CPU_H_ > +#define LOONGARCH_CPU_H_ > + > +/* Exception types decoded by machdep exception decoder */ > +#define EXC_INT 0 /* HW interrupt */ > +#define EXC_TLBL 1 /* TLB miss on a load */ > +#define EXC_TLBS 2 /* TLB miss on a store */ > +#define EXC_TLBI 3 /* TLB miss on a ifetch */ > +#define EXC_TLBM 4 /* TLB modified fault */ > +#define EXC_TLBRI 5 /* TLB Read-Inhibit exception */ > +#define EXC_TLBXI 6 /* TLB Execution-Inhibit exception */ > +#define EXC_TLBPE 7 /* TLB Privilege Error */ > +#define EXC_ADE 8 /* Address Error */ > +#define EXC_ALE 9 /* Unalign Access */ > +#define EXC_OOB 10 /* Out of bounds */ > +#define EXC_SYS 11 /* System call */ > +#define EXC_BP 12 /* Breakpoint */ > +#define EXC_INE 13 /* Inst. Not Exist */ > +#define EXC_IPE 14 /* Inst. Privileged Error */ > +#define EXC_FPDIS 15 /* FPU Disabled */ > +#define EXC_LSXDIS 16 /* LSX Disabled */ > +#define EXC_LASXDIS 17 /* LASX Disabled */ > +#define EXC_FPE 18 /* Floating Point Exception */ > +#define EXC_WATCH 19 /* Watch address reference */ > +#define EXC_BAD 255 /* Undecodeable */ > + > +#define COPY_SIGCODE // copy sigcode above user stack in exec > +#define ZERO $r0 /* wired zero */ > +#define RA $r1 /* return address */ > +#define GP $r2 /* global pointer - caller saved for PIC */ > +#define SP $r3 /* stack pointer */ > +#define V0 $r4 /* return value - caller saved */ > +#define V1 $r5 > +#define A0 $r4 /* argument registers */ > +#define A1 $r5 > +#define A2 $r6 > +#define A3 $r7 > +#define A4 $r8 /* arg reg 64 bit; caller saved in 32 bit */ > +#define A5 $r9 > +#define A6 $r10 > +#define A7 $r11 > +#define T0 $r12 /* caller saved */ > +#define T1 $r13 > +#define T2 $r14 > +#define T3 $r15 > +#define T4 $r16 /* callee saved */ > +#define T5 $r17 > +#define T6 $r18 > +#define T7 $r19 > +#define T8 $r20 /* caller saved */ > +#define TP $r21 /* TLS */ > +#define FP $r22 /* frame pointer */ > +#define S0 $r23 /* callee saved */ > +#define S1 $r24 > +#define S2 $r25 > +#define S3 $r26 > +#define S4 $r27 > +#define S5 $r28 > +#define S6 $r29 > +#define S7 $r30 > +#define S8 $r31 /* callee saved */ > + > +#define FCSR0 $r0 > + > +// > +// Location of the saved registers relative to ZERO. > +// Usage is p->p_regs[XX]. > +// > +#define RA_NUM 1 > +#define GP_NUM 2 > +#define SP_NUM 3 > +#define A0_NUM 4 > +#define A1_NUM 5 > +#define A2_NUM 6 > +#define A3_NUM 7 > +#define A4_NUM 8 > +#define A5_NUM 9 > +#define A6_NUM 10 > +#define A7_NUM 11 > +#define T0_NUM 12 > +#define T1_NUM 13 > +#define T2_NUM 14 > +#define T3_NUM 15 > +#define T4_NUM 16 > +#define T5_NUM 17 > +#define T6_NUM 18 > +#define T7_NUM 19 > +#define T8_NUM 20 > +#define TP_NUM 21 > +#define FP_NUM 22 > +#define S0_NUM 23 > +#define S1_NUM 24 > +#define S2_NUM 25 > +#define S3_NUM 26 > +#define S4_NUM 27 > +#define S5_NUM 28 > +#define S6_NUM 29 > +#define S7_NUM 30 > +#define S8_NUM 31 > + > +#define FP0_NUM 0 > +#define FP1_NUM 1 > +#define FP2_NUM 2 > +#define FP3_NUM 3 > +#define FP4_NUM 4 > +#define FP5_NUM 5 > +#define FP6_NUM 6 > +#define FP7_NUM 7 > +#define FP8_NUM 8 > +#define FP9_NUM 9 > +#define FP10_NUM 10 > +#define FP11_NUM 11 > +#define FP12_NUM 12 > +#define FP13_NUM 13 > +#define FP14_NUM 14 > +#define FP15_NUM 15 > +#define FP16_NUM 16 > +#define FP17_NUM 17 > +#define FP18_NUM 18 > +#define FP19_NUM 19 > +#define FP20_NUM 20 > +#define FP21_NUM 21 > +#define FP22_NUM 22 > +#define FP23_NUM 23 > +#define FP24_NUM 24 > +#define FP25_NUM 25 > +#define FP26_NUM 26 > +#define FP27_NUM 27 > +#define FP28_NUM 28 > +#define FP29_NUM 29 > +#define FP30_NUM 30 > +#define FP31_NUM 31 > +#define FCSR_NUM 32 > +#define FCC_NUM 33 > + > +#ifdef __ASSEMBLY__ > +#define _ULCAST_ > +#define _U64CAST_ > +#else > +#define _ULCAST_ (unsigned long) > +#define _U64CAST_ (u64) > +#endif > + > +#define LOONGARCH_CSR_CRMD 0 > +#define LOONGARCH_CSR_PRMD 1 > +#define LOONGARCH_CSR_EUEN 2 > +#define CSR_EUEN_LBTEN_SHIFT 3 > +#define CSR_EUEN_LBTEN (_ULCAST_(0x1) << CSR_EUEN_LBTEN_SHIFT) > +#define CSR_EUEN_LASXEN_SHIFT 2 > +#define CSR_EUEN_LASXEN (_ULCAST_(0x1) << CSR_EUEN_LASXEN_SHIFT) > +#define CSR_EUEN_LSXEN_SHIFT 1 > +#define CSR_EUEN_LSXEN (_ULCAST_(0x1) << CSR_EUEN_LSXEN_SHIFT) > +#define CSR_EUEN_FPEN_SHIFT 0 > +#define CSR_EUEN_FPEN (_ULCAST_(0x1) << CSR_EUEN_FPEN_SHIFT) > +#define LOONGARCH_CSR_ECFG 4 > + > +/* Exception status */ > +#define LOONGARCH_CSR_ESTAT 5 > +#define CSR_ESTAT_ESUBCODE_SHIFT 22 > +#define CSR_ESTAT_ESUBCODE_WIDTH 9 > +#define CSR_ESTAT_ESUBCODE (_ULCAST_(0x1ff) << CSR_ESTAT_ESUBCODE_SHIFT) > +#define CSR_ESTAT_EXC_SHIFT 16 > +#define CSR_ESTAT_EXC_WIDTH 6 > +#define CSR_ESTAT_EXC (_ULCAST_(0x3f) << CSR_ESTAT_EXC_SHIFT) > +#define CSR_ESTAT_IS_SHIFT 0 > +#define CSR_ESTAT_IS_WIDTH 15 > +#define CSR_ESTAT_IS (_ULCAST_(0x7fff) << CSR_ESTAT_IS_SHIFT) > + > +#define LOONGARCH_CSR_EPC 6 > +#define LOONGARCH_CSR_BADV 7 > +#define LOONGARCH_CSR_BADINST 8 > +#define LOONGARCH_CSR_BADI 8 > +#define LOONGARCH_CSR_EBASE 0xc /* Exception entry base address */ > +#define LOONGARCH_CSR_CPUNUM 0x20 /* CPU core number */ > + > +/* register number save in stack on exception */ > +#define FP_BASE_NUM 34 > +#define BASE_NUM 32 > +#define CSR_NUM 10 > +#define FP_BASE_INDEX (CSR_NUM + BASE_NUM) > +#define BOOTCORE_ID 0 > + > +#define LOONGSON_IOCSR_IPI_STATUS 0x1000 > +#define LOONGSON_IOCSR_IPI_EN 0x1004 > +#define LOONGSON_IOCSR_IPI_SET 0x1008 > +#define LOONGSON_IOCSR_IPI_CLEAR 0x100c > +#define LOONGSON_CSR_MAIL_BUF0 0x1020 > +#define LOONGSON_CSR_MAIL_BUF1 0x1028 > +#define LOONGSON_CSR_MAIL_BUF2 0x1030 > +#define LOONGSON_CSR_MAIL_BUF3 0x1038 > + > +/* Bit Domains for CFG registers */ > +#define LOONGARCH_CPUCFG4 0x4 > +#define LOONGARCH_CPUCFG5 0x5 > + > +/* Kscratch registers */ > +#define LOONGARCH_CSR_KS0 0x30 > +#define LOONGARCH_CSR_KS1 0x31 > + > +/* Stable timer registers */ > +#define LOONGARCH_CSR_TMCFG 0x41 > +#define LOONGARCH_CSR_TMCFG_EN (1ULL << 0) > +#define LOONGARCH_CSR_TMCFG_PERIOD (1ULL << 1) > +#define LOONGARCH_CSR_TMCFG_TIMEVAL (0x3fffffffffffULL << 2) > +#define LOONGARCH_CSR_TVAL 0x42 /* Timer value */ > +#define LOONGARCH_CSR_CNTC 0x43 /* Timer offset */ > +#define LOONGARCH_CSR_TINTCLR 0x44 /* Timer interrupt clear */ > + > +/* TLB refill exception base address */ > +#define LOONGARCH_CSR_TLBREBASE 0x88 > +#define LOONGARCH_CSR_TLBRSAVE 0x8b /* KScratch for TLB refill exception */ > +#define LOONGARCH_CSR_PGD 0x1b /* Page table base */ > + > +/* Invalid addr with global=1 or matched asid in current tlb */ > +#define INVTLB_ADDR_GTRUE_OR_ASID 0x6 > + > +/* Bits 8 and 9 of FPU Status Register specify the rounding mode */ > +#define FPU_CSR_RM 0x300 > +#define FPU_CSR_RN 0x000 /* nearest */ > +#define FPU_CSR_RZ 0x100 /* towards zero */ > +#define FPU_CSR_RU 0x200 /* towards +Infinity */ > +#define FPU_CSR_RD 0x300 /* towards -Infinity */ > + > +#endif > diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.h b/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.h > new file mode 100644 > index 0000000000..e942e6a994 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.h > @@ -0,0 +1,95 @@ > +/** @file > + LoongArch Qemu Platform macro definition. > + > + Copyright (c) 2022, Loongson Limited. All rights reserved. > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + **/ > + > +#ifndef LOONGARCH_QEMU_PLATFORM_H_ > +#define LOONGARCH_QEMU_PLATFORM_H_ > + > +/* Acpi pm device */ > +#define LS7A_PCH_REG_BASE 0x10000000UL > +#define LS7A_ACPI_REG_BASE (LS7A_PCH_REG_BASE + 0x000D0000) > +#define LS7A_PM_CNT_BLK (0x14) /* 2 bytes */ > +#define LS7A_GPE0_RESET_REG (0x30) /* 4 bytes */ > + > +#define ACPI_BITMASK_SLEEP_TYPE 0x1C00 > +#define ACPI_BITMASK_SLEEP_ENABLE 0x2000 > + > +//--------------------------------------------- > +// UART Register Offsets > +//--------------------------------------------- > +#define BAUD_LOW_OFFSET 0x00 > +#define BAUD_HIGH_OFFSET 0x01 > +#define IER_OFFSET 0x01 > +#define LCR_SHADOW_OFFSET 0x01 > +#define FCR_SHADOW_OFFSET 0x02 > +#define IR_CONTROL_OFFSET 0x02 > +#define FCR_OFFSET 0x02 > +#define EIR_OFFSET 0x02 > +#define BSR_OFFSET 0x03 > +#define LCR_OFFSET 0x03 > +#define MCR_OFFSET 0x04 > +#define LSR_OFFSET 0x05 > +#define MSR_OFFSET 0x06 > + > +/* character format control register */ > +#define CFCR_DLAB 0x80 /* divisor latch */ > +#define CFCR_SBREAK 0x40 /* send break */ > +#define CFCR_PZERO 0x30 /* zero parity */ > +#define CFCR_PONE 0x20 /* one parity */ > +#define CFCR_PEVEN 0x10 /* even parity */ > +#define CFCR_PODD 0x00 /* odd parity */ > +#define CFCR_PENAB 0x08 /* parity enable */ > +#define CFCR_STOPB 0x04 /* 2 stop bits */ > +#define CFCR_8BITS 0x03 /* 8 data bits */ > +#define CFCR_7BITS 0x02 /* 7 data bits */ > +#define CFCR_6BITS 0x01 /* 6 data bits */ > +#define CFCR_5BITS 0x00 /* 5 data bits */ > +/* modem control register */ > +#define MCR_LOOPBACK 0x10 /* loopback */ > +#define MCR_IENABLE 0x08 /* output 2 = int enable */ > +#define MCR_DRS 0x04 /* output 1 = xxx */ > +#define MCR_RTS 0x02 /* enable RTS */ > +#define MCR_DTR 0x01 /* enable DTR */ > + > +/* line status register */ > +#define LSR_RCV_FIFO 0x80 /* error in receive fifo */ > +#define LSR_TSRE 0x40 /* transmitter empty */ > +#define LSR_TXRDY 0x20 /* transmitter ready */ > +#define LSR_BI 0x10 /* break detected */ > +#define LSR_FE 0x08 /* framing error */ > +#define LSR_PE 0x04 /* parity error */ > +#define LSR_OE 0x02 /* overrun error */ > +#define LSR_RXRDY 0x01 /* receiver ready */ > +#define LSR_RCV_MASK 0x1f > + > +/* 16550 UART register offsets and bitfields */ > +#define R_UART_RXBUF 0 > +#define R_UART_TXBUF 0 > +#define R_UART_BAUD_LOW 0 > +#define R_UART_BAUD_HIGH 1 > +#define R_UART_FCR 2 > +#define B_UART_FCR_FIFOE BIT0 > +#define B_UART_FCR_FIFO64 BIT5 > +#define R_UART_LCR 3 > +#define B_UART_LCR_DLAB BIT7 > +#define R_UART_MCR 4 > +#define B_UART_MCR_DTRC BIT0 > +#define B_UART_MCR_RTS BIT1 > +#define R_UART_LSR 5 > +#define B_UART_LSR_RXRDY BIT0 > +#define B_UART_LSR_TXRDY BIT5 > +#define B_UART_LSR_TEMT BIT6 > +#define R_UART_MSR 6 > +#define B_UART_MSR_CTS BIT4 > +#define B_UART_MSR_DSR BIT5 > +#define B_UART_MSR_RI BIT6 > +#define B_UART_MSR_DCD BIT7 > +#define UART_BASE_ADDRESS (0x1fe001e0) > +#define UART_BPS (115200) > +#define UART_WAIT_TIMOUT (1000000) > +#endif > diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.c b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.c > new file mode 100644 > index 0000000000..7044db81ee > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.c > @@ -0,0 +1,593 @@ > +/** @file > + UART Serial Port library functions > + > + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + @par Glossary: > + - Bps - Bit Per Second > + - CTL - Control > + - Config - Configure > +**/ > + > +#include <Base.h> > +#include <Library/Cpu.h> > +#include <Library/IoLib.h> > +#include <Library/SerialPortLib.h> > +#include <LoongArchQemuPlatform.h> > + > +UINTN gUartBase = UART_BASE_ADDRESS; > +UINTN gBps = UART_BPS; > + > +/** > + Initialize the serial device hardware. > + > + If no initialization is required, then return RETURN_SUCCESS. > + If the serial device was successfuly 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 serail device could not be initialized. > +**/ > +RETURN_STATUS > +EFIAPI > +SerialPortInitialize ( > + VOID > + ) > +{ > + UINTN TimeOut; > + // > + // wait for Tx fifo to completely drain */ > + // > + TimeOut = UART_WAIT_TIMOUT; > + while (!(MmioRead8 ((UINTN) gUartBase + LSR_OFFSET) & LSR_TSRE)) { > + if (--TimeOut == 0) { > + break; > + } > + } > + // > + // Set communications format > + // > + MmioWrite8 ((UINTN) (gUartBase + LCR_OFFSET), CFCR_DLAB); > + > + // > + // Configure baud rate > + // > + > + MmioWrite8 ((UINTN) (gUartBase + LCR_OFFSET), CFCR_8BITS); > + MmioWrite8 ((UINTN) (gUartBase + MCR_OFFSET), MCR_IENABLE | MCR_DTR | MCR_RTS); > + > + 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 > +UartCtlWrite ( > + IN UINT8 *Buffer, > + IN UINTN NumberOfBytes, > + IN UINTN CtlAddr > +) > +{ > + UINTN Result; > + UINT8 Data; > + > + if (Buffer == NULL) { > + return 0; > + } > + > + Result = NumberOfBytes; > + > + while (NumberOfBytes--) { > + // > + // Wait for the serail port to be ready. > + // > + do { > + Data = MmioRead8 (CtlAddr + LSR_OFFSET); > + } while ((Data & LSR_TXRDY) == 0); > + MmioWrite8 (CtlAddr, *Buffer++); > + } > + return Result; > +} > +/** > + Writes data to serial port. > + > + @param Buffer Pointer to the data buffer to store the data writed to serial port. > + @param NumberOfBytes Number of bytes to write to the serial port. > + > + @retval 0 NumberOfBytes is 0. > + @retval >0 The number of bytes write the serial port. > + If this value is less than NumberOfBytes, then the write operation failed. > +**/ > +UINTN > +EFIAPI > +SerialPortWrite ( > + IN UINT8 *Buffer, > + IN UINTN NumberOfBytes > +) > +{ > + return UartCtlWrite (Buffer, NumberOfBytes, gUartBase); > +} > +/** > + Reads data from a serial device into a buffer. > + > + @param Buffer Pointer to the data buffer to store the data read from the serial device. > + @param NumberOfBytes Number of bytes to read from the serial device. > + > + @retval 0 NumberOfBytes is 0. > + @retval >0 The number of bytes read from the serial device. > + If this value is less than NumberOfBytes, then the read operation failed. > +**/ > +UINTN > +EFIAPI > +UartCtlRead ( > + OUT UINT8 *Buffer, > + IN UINTN NumberOfBytes, > + IN UINTN CtlAddr > +) > +{ > + UINTN Result; > + UINT8 Data; > + > + if (NULL == Buffer) { > + return 0; > + } > + > + Result = NumberOfBytes; > + > + while (NumberOfBytes--) { > + // > + // Wait for the serail port to be ready. > + // > + do { > + Data = MmioRead8 (CtlAddr + LSR_OFFSET); > + } while ((Data & LSR_RXRDY) == 0); > + > + *Buffer++ = MmioRead8 (CtlAddr); > + } > + return Result; > +} > +/** > + Read data from serial port. > + > + @param Buffer Pointer to the data buffer to store the data read from serial port. > + @param NumberOfBytes Number of bytes to read from the serial port. > + > + @retval 0 NumberOfBytes is 0. > + @retval >0 The number of bytes read from the serial port. > + If this value is less than NumberOfBytes, then the read operation failed. > +**/ > +UINTN > +EFIAPI > +SerialPortRead ( > + OUT UINT8 *Buffer, > + IN UINTN NumberOfBytes > +) > +{ > + return UartCtlRead (Buffer, NumberOfBytes, gUartBase); > +} > +/** > + Polls a serial device to see if there is any data waiting to be read. > + > + Polls aserial 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 > + ) > +{ > + UINT8 Data; > + > + // > + // Read the serial port status. > + // > + Data = MmioRead8 ((UINTN) gUartBase + LSR_OFFSET); > + > + return (BOOLEAN) ((Data & LSR_RXRDY) != 0); > +} > +/** > + To get serial register base address. > + > + @param VOID > + > + @return serial register base address. > +**/ > +UINTN > +GetSerialRegisterBase ( > + VOID > + ) > +{ > + return gUartBase; > +} > +/** > + Read an 8-bit register. > + @param Base The base address register of UART device. > + @param Offset The offset of the register to read. > + > + @return The value read from the 16550 register. > +**/ > +UINT8 > +SerialPortReadRegister ( > + UINTN Base, > + UINTN Offset > + ) > +{ > + return MmioRead8 (Base + Offset); > +} > + > +/** > + Write an 8-bit register. > + @param Base The base address register of UART device. > + @param Offset The offset of the register to write. > + @param Value The value to write to the register specified by Offset. > + > + @return The value written to the 16550 register. > +**/ > +UINT8 > +SerialPortWriteRegister ( > + UINTN Base, > + UINTN Offset, > + UINT8 Value > + ) > +{ > + return MmioWrite8 (Base + Offset, Value); > +} > + > +/** > + Sets the control bits on a serial device. > + > + @param Control Sets the bits of Control that are settable. > + > + @retval RETURN_SUCCESS The new control bits were set on the serial device. > + @retval RETURN_UNSUPPORTED The serial device does not support this operation. > + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. > +**/ > +RETURN_STATUS > +EFIAPI > +SerialPortSetControl ( > + IN UINT32 Control > + ) > +{ > + UINTN SerialRegisterBase; > + UINT8 Mcr; > + > + // > + // First determine the parameter is invalid. > + // > + if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY | > + EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0) > + { > + return RETURN_UNSUPPORTED; > + } > + > + SerialRegisterBase = GetSerialRegisterBase (); > + if (SerialRegisterBase ==0) { > + return RETURN_UNSUPPORTED; > + } > + > + // > + // Read the Modem Control Register. > + // > + Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR); > + Mcr &= (~(B_UART_MCR_DTRC | B_UART_MCR_RTS)); > + > + if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) { > + Mcr |= B_UART_MCR_DTRC; > + } > + > + if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) { > + Mcr |= B_UART_MCR_RTS; > + } > + > + // > + // Write the Modem Control Register. > + // > + SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, Mcr); > + > + return RETURN_SUCCESS; > +} > + > +/** > + 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_SUCCESS The control bits were read from the serial device. > + @retval RETURN_UNSUPPORTED The serial device does not support this operation. > + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. > +**/ > +RETURN_STATUS > +EFIAPI > +SerialPortGetControl ( > + OUT UINT32 *Control > + ) > +{ > + UINTN SerialRegisterBase; > + UINT8 Msr; > + UINT8 Mcr; > + UINT8 Lsr; > + > + SerialRegisterBase = GetSerialRegisterBase (); > + if (SerialRegisterBase ==0) { > + return RETURN_UNSUPPORTED; > + } > + > + *Control = 0; > + > + // > + // Read the Modem Status Register. > + // > + Msr = SerialPortReadRegister (SerialRegisterBase, R_UART_MSR); > + > + if ((Msr & B_UART_MSR_CTS) == B_UART_MSR_CTS) { > + *Control |= EFI_SERIAL_CLEAR_TO_SEND; > + } > + > + if ((Msr & B_UART_MSR_DSR) == B_UART_MSR_DSR) { > + *Control |= EFI_SERIAL_DATA_SET_READY; > + } > + > + if ((Msr & B_UART_MSR_RI) == B_UART_MSR_RI) { > + *Control |= EFI_SERIAL_RING_INDICATE; > + } > + > + if ((Msr & B_UART_MSR_DCD) == B_UART_MSR_DCD) { > + *Control |= EFI_SERIAL_CARRIER_DETECT; > + } > + > + // > + // Read the Modem Control Register. > + // > + Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR); > + > + if ((Mcr & B_UART_MCR_DTRC) == B_UART_MCR_DTRC) { > + *Control |= EFI_SERIAL_DATA_TERMINAL_READY; > + } > + > + if ((Mcr & B_UART_MCR_RTS) == B_UART_MCR_RTS) { > + *Control |= EFI_SERIAL_REQUEST_TO_SEND; > + } > + > + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { > + *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; > + } > + > + // > + // Read the Line Status Register. > + // > + Lsr = SerialPortReadRegister (SerialRegisterBase, R_UART_LSR); > + > + if ((Lsr & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) == (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) { > + *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY; > + } > + > + if ((Lsr & B_UART_LSR_RXRDY) == 0) { > + *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY; > + } > + > + return RETURN_SUCCESS; > +} > + > +/** > + 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 time > + out 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 > + vaule 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_SUCCESS The new attributes were set on the serial device. > + @retval RETURN_UNSUPPORTED The serial device does not support this operation. > + @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value. > + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. > +**/ > +RETURN_STATUS > +EFIAPI > +UartCtlConfig ( > + 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, > + IN UINTN CtlAddr > + ) > +{ > + UINTN SerialRegisterBase; > + UINT8 Lcr; > + UINT8 LcrData; > + UINT8 LcrParity; > + UINT8 LcrStop; > + > + SerialRegisterBase = CtlAddr; > + if (SerialRegisterBase ==0) { > + return RETURN_UNSUPPORTED; > + } > + > + // > + // Check for default settings and fill in actual values. > + // > + if (*BaudRate == 0) { > + *BaudRate = PcdGet32 (PcdSerialBaudRate); > + } > + > + if (*DataBits == 0) { > + LcrData = (UINT8) (PcdGet8 (PcdSerialLineControl) & 0x3); > + *DataBits = LcrData + 5; > + } else { > + if ((*DataBits < 5) > + || (*DataBits > 8)) > + { > + return RETURN_INVALID_PARAMETER; > + } > + // > + // Map 5..8 to 0..3 > + // > + LcrData = (UINT8) (*DataBits - (UINT8) 5); > + } > + > + if (*Parity == DefaultParity) { > + LcrParity = (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 3) & 0x7); > + switch (LcrParity) { > + case 0: > + *Parity = NoParity; > + break; > + > + case 3: > + *Parity = EvenParity; > + break; > + > + case 1: > + *Parity = OddParity; > + break; > + > + case 7: > + *Parity = SpaceParity; > + break; > + > + case 5: > + *Parity = MarkParity; > + break; > + > + default: > + break; > + } > + } else { > + switch (*Parity) { > + case NoParity: > + LcrParity = 0; > + break; > + > + case EvenParity: > + LcrParity = 3; > + break; > + > + case OddParity: > + LcrParity = 1; > + break; > + > + case SpaceParity: > + LcrParity = 7; > + break; > + > + case MarkParity: > + LcrParity = 5; > + break; > + > + default: > + return RETURN_INVALID_PARAMETER; > + } > + } > + > + if (*StopBits == DefaultStopBits) { > + LcrStop = (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 2) & 0x1); > + switch (LcrStop) { > + case 0: > + *StopBits = OneStopBit; > + break; > + > + case 1: > + if (*DataBits == 5) { > + *StopBits = OneFiveStopBits; > + } else { > + *StopBits = TwoStopBits; > + } > + break; > + > + default: > + break; > + } > + } else { > + switch (*StopBits) { > + case OneStopBit: > + LcrStop = 0; > + break; > + > + case OneFiveStopBits: > + case TwoStopBits: > + LcrStop = 1; > + break; > + > + default: > + return RETURN_INVALID_PARAMETER; > + } > + } > + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB); > + > + // > + // Clear DLAB and configure Data Bits, Parity, and Stop Bits. > + // Strip reserved bits from line control value > + // > + Lcr = (UINT8) ((LcrParity << 3) | (LcrStop << 2) | LcrData); > + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8) (Lcr & 0x3F)); > + > + return RETURN_SUCCESS; > +} > +/** > + Set the serial port Attributes. > + > + @param VOID > + > + @return serial register base address. > +**/ > +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 SerialRegisterBase; > + > + SerialRegisterBase = GetSerialRegisterBase (); > + > + return UartCtlConfig (&gBps, ReceiveFifoDepth, Timeout, Parity, DataBits, StopBits, > + SerialRegisterBase); > +} > diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.inf > new file mode 100644 > index 0000000000..22cf82cf79 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.inf > @@ -0,0 +1,39 @@ > +## @file > +# UART Serial Port library functions > +# > +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR> > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x00010005 > + BASE_NAME = PcAtSerialPortLib > + FILE_GUID = f4fb883d-8138-4f29-bb0c-c574e9312c74 > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = SerialPortLib > + > +# > +# VALID_ARCHITECTURES = LOONGARCH64 > +# > + > +[Sources] > + SerialPortLib.c > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + Platform/Loongson/LoongArchQemuPkg/Loongson.dec > + > +[LibraryClasses] > + BaseLib > + IoLib > + PcdLib > + > +[Pcd] > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl ## CONSUMES > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate ## CONSUMES > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialLineControl ## CONSUMES > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate ## CONSUMES > -- > 2.31.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#96286): https://edk2.groups.io/g/devel/message/96286 Mute This Topic: https://groups.io/mt/94955170/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2025 Red Hat, Inc.