回复: [edk2-devel] [edk2-platforms][PATCH V1 01/16] Platform/Loongson: Add Serial Port library

gaoliming via groups.io gaoliming=byosoft.com.cn at groups.io
Fri Sep 9 08:44:42 UTC 2022


Xianglai:
  Please share the github link to get all patches. 

Thanks
Liming
> -----邮件原件-----
> 发件人: devel at edk2.groups.io <devel at edk2.groups.io> 代表 xianglai
> 发送时间: 2022年9月9日 11:12
> 收件人: devel at edk2.groups.io
> 抄送: maobibo at loongson.cn
> 主题: [edk2-devel] [edk2-platforms][PATCH V1 01/16] Platform/Loongson:
> Add Serial Port library
> 
> Serial Port library for LoongarchQemuPkg
> 
> Signed-off-by: xianglai li <lixianglai at loongson.cn>
> ---
>  .../LoongArchQemuPkg/Include/Library/Cpu.h    | 344 ++++++++++
>  .../Include/LoongArchQemuPlatform.h           | 103 +++
>  .../Library/SerialPortLib/SerialPortLib.c     | 612 ++++++++++++++++++
>  .../Library/SerialPortLib/SerialPortLib.inf   |  36 ++
>  4 files changed, 1095 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.in
> f
> 
> diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/Library/Cpu.h
> b/Platform/Loongson/LoongArchQemuPkg/Include/Library/Cpu.h
> new file mode 100644
> index 0000000000..de466b7c6f
> --- /dev/null
> +++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/Cpu.h
> @@ -0,0 +1,344 @@
> +/** @file
> 
> +
> 
> +  Copyright (c) 2021 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 */
> 
> +
> 
> +/* 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 */
> 
> +
> 
> +/*
> 
> +  Reads data from the specified CSR register.
> 
> +
> 
> +  @param[OUT]  val   The value is read from the CSR specified register.
> 
> +  @param[IN]  reg    Specifies the register number of the CSR to read
> the data.
> 
> +
> 
> +  @retval  VOID
> 
> + */
> 
> +#define LOONGARCH_CSR_READQ(val, reg)                   \
> 
> +do {                                                    \
> 
> +  UINT64 __res;                                         \
> 
> +  /* csrrd rd, csr_num */                               \
> 
> +  __asm__ __volatile__(                                 \
> 
> +          "csrrd  %0, %1 \n\t"                          \
> 
> +          :"=r"(__res)                                  \
> 
> +          :"i"(reg)                                     \
> 
> +          :                                             \
> 
> +          );                                            \
> 
> +  (val) = __res;                                        \
> 
> +} while(0)
> 
> +
> 
> +/*
> 
> +  Write data to the specified CSR register.
> 
> +
> 
> +  @param[OUT]  val   The value is write to the CSR specified register.
> 
> +  @param[IN]  reg    Specifies the register number of the CSR to write
> the data.
> 
> +
> 
> +  @retval  VOID
> 
> + */
> 
> +#define LOONGARCH_CSR_WRITEQ(val, reg)                 \
> 
> +do {                                                   \
> 
> +  UINT64 __val = val;                                  \
> 
> +  /* csrwr rd, csr_num */                              \
> 
> +  __asm__ __volatile__(                                \
> 
> +          "csrwr  %0, %1 \n\t"                         \
> 
> +          : "+r"(__val)                                \
> 
> +          : "i"(reg), "r"(__val)                       \
> 
> +          : "memory"                                   \
> 
> +          );                                           \
> 
> +} while(0)
> 
> +
> 
> +/*
> 
> +  Exchange specified bit data with the specified CSR registers
> 
> +
> 
> +  @param[IN]  val   The value Exchanged with the CSR specified
> register.
> 
> +  @param[IN]  mask   Specifies the mask for swapping bits
> 
> +  @param[IN]  reg    Specifies the register number of the CSR to
> Exchange the data.
> 
> +
> 
> +  @retval  VOID
> 
> + */
> 
> +#define LOONGARCH_CSR_XCHGQ(val, mask, reg)          \
> 
> +do {                                                 \
> 
> +  UINT64 __val = val;                                \
> 
> +  UINT64 __mask = mask;                              \
> 
> +  /* csrwr rd, csr_num */                            \
> 
> +  __asm__ __volatile__(                              \
> 
> +          "csrxchg  %0, %1, %2 \n\t"                 \
> 
> +          : "+r"(__val)                              \
> 
> +          : "r"(__mask), "i"(reg), "r"(__val)        \
> 
> +          : "memory"                                 \
> 
> +          );                                         \
> 
> +} while(0)
> 
> +/*
> 
> +  Reads data from the specified CPUCFG register.
> 
> +
> 
> +  @param[OUT]  val   The value is read from the CPUCFG specified
> register.
> 
> +  @param[IN]  reg    Specifies the register number of the CPUCFG to
> read the data.
> 
> +
> 
> +  @retval  VOID
> 
> + */
> 
> +#define LOONGARCH_GET_CPUCFG(val, reg)               \
> 
> +do {                                                 \
> 
> +  UINT64 __res;                                      \
> 
> +  /* cpucfg rd, rj */                                \
> 
> +  __asm__ __volatile__(                              \
> 
> +          "cpucfg  %0, %1 \n\t"                      \
> 
> +          :"=r"(__res)                               \
> 
> +          :"r"(reg)                                  \
> 
> +          :                                          \
> 
> +          );                                         \
> 
> +  val = (UINT32)__res;                               \
> 
> +} while(0)
> 
> +
> 
> +/*
> 
> +  Enables  floating-point unit
> 
> +
> 
> +  @param  VOID
> 
> +
> 
> +  @retval  VOID
> 
> + */
> 
> +#define LOONGARCH_ENABLR_FPU()                       \
> 
> +do {                                                 \
> 
> +  LOONGARCH_CSR_XCHGQ(CSR_EUEN_FPEN,                 \
> 
> +                      CSR_EUEN_FPEN,                 \
> 
> +                      LOONGARCH_CSR_EUEN);           \
> 
> +} while (0)
> 
> +
> 
> +/*
> 
> +  Disable  floating-point unit
> 
> +
> 
> +  @param  VOID
> 
> +
> 
> +  @retval  VOID
> 
> + */
> 
> +#define LOONGARCH_DISABLE_FPU()                      \
> 
> +do {                                                 \
> 
> +  LOONGARCH_CSR_XCHGQ(0,                             \
> 
> +                      CSR_EUEN_FPEN,                 \
> 
> +                      LOONGARCH_CSR_EUEN);           \
> 
> +} while (0)
> 
> +
> 
> +#endif
> 
> diff --git
> a/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.
> h
> b/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.
> h
> new file mode 100644
> index 0000000000..62b81d88c3
> --- /dev/null
> +++
> b/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.
> h
> @@ -0,0 +1,103 @@
> +/** @file
> 
> +   LoongArch Qemu Platform macro definition.
> 
> +
> 
> +   Copyright (c) 2021, 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)
> 
> +//---------------------------------------------
> 
> +// UART Settings
> 
> +//---------------------------------------------
> 
> +#define PHYS_TO_CACHED(x)       ((x))
> 
> +#define PHYS_TO_UNCACHED(x)     ((x))
> 
> +
> 
> +#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..5b2f3a8194
> --- /dev/null
> +++
> b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib
> .c
> @@ -0,0 +1,612 @@
> +/** @file
> 
> +  UART Serial Port library functions
> 
> +
> 
> +  Copyright (c) 2021 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 = PHYS_TO_UNCACHED(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);
> 
> +  //
> 
> +  // if enable interrupt the kernel of lemote will error in STR mode
during
> wake up phase.
> 
> +  //
> 
> +  //MmioWrite8 ((UINTN) (gUartBase + IER_OFFSET), CFCR_8BITS);
> 
> +
> 
> +  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..6c4674151b
> --- /dev/null
> +++
> b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib
> .inf
> @@ -0,0 +1,36 @@
> +## @file
> 
> +#  UART Serial Port library functions
> 
> +#
> 
> +#  Copyright (c) 2021 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
> 
> +
> 
> +[Packages]
> 
> +  MdePkg/MdePkg.dec
> 
> +  MdeModulePkg/MdeModulePkg.dec
> 
> +  Platform/Loongson/LoongArchQemuPkg/Loongson.dec
> 
> +
> 
> +[LibraryClasses]
> 
> +  BaseLib
> 
> +  IoLib
> 
> +  PcdLib
> 
> +
> 
> +[Sources]
> 
> +  SerialPortLib.c
> 
> +
> 
> +[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 (#93568): https://edk2.groups.io/g/devel/message/93568
> Mute This Topic: https://groups.io/mt/93565591/4905953
> Group Owner: devel+owner at edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub
> [gaoliming at byosoft.com.cn]
> -=-=-=-=-=-=
> 
> 
> 






-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#93571): https://edk2.groups.io/g/devel/message/93571
Mute This Topic: https://groups.io/mt/93568646/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list