public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "xianglai" <lixianglai@loongson.cn>
To: gaoliming <gaoliming@byosoft.com.cn>
Cc: devel@edk2.groups.io, maobibo@loongson.cn
Subject: Re: 回复: [edk2-devel] [edk2-platforms][PATCH V1 01/16] Platform/Loongson: Add Serial Port library
Date: Fri, 9 Sep 2022 17:08:48 +0800 (GMT+08:00)	[thread overview]
Message-ID: <958f0bd.78c2.18321824253.Coremail.lixianglai@loongson.cn> (raw)
In-Reply-To: <027c01d8c428$67c63ad0$3752b070$@byosoft.com.cn>


Hi Liming:
  Thanks for writing back and for the tips. You can get all the patches at:
  https://github.com/loongson/edk2-platforms/tree/devel-LoongArch-patch

Thanks
xianglai

> -----原始邮件-----
> 发件人: gaoliming <gaoliming@byosoft.com.cn>
> 发送时间:2022-09-09 16:44:42 (星期五)
> 收件人: devel@edk2.groups.io, lixianglai@loongson.cn
> 抄送: maobibo@loongson.cn
> 主题: 回复: [edk2-devel] [edk2-platforms][PATCH V1 01/16] Platform/Loongson: Add Serial Port library
> 
> Xianglai:
>   Please share the github link to get all patches. 
> 
> Thanks
> Liming
> > -----邮件原件-----
> > 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 xianglai
> > 发送时间: 2022年9月9日 11:12
> > 收件人: devel@edk2.groups.io
> > 抄送: maobibo@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@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@edk2.groups.io
> > Unsubscribe: https://edk2.groups.io/g/devel/unsub
> > [gaoliming@byosoft.com.cn]
> > -=-=-=-=-=-=
> > 
> > 
> > 
> 
> 
> 
> 


本邮件及其附件含有龙芯中科的商业秘密信息,仅限于发送给上面地址中列出的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制或散发)本邮件及其附件中的信息。如果您错收本邮件,请您立即电话或邮件通知发件人并删除本邮件。 
This email and its attachments contain confidential information from Loongson Technology , which is intended only for the person or entity whose address is listed above. Any use of the information contained herein in any way (including, but not limited to, total or partial disclosure, reproduction or dissemination) by persons other than the intended recipient(s) is prohibited. If you receive this email in error, please notify the sender by phone or email immediately and delete it. 

  reply	other threads:[~2022-09-09  9:08 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-09  3:11 [edk2-platforms][PATCH V1 00/16] Platform: Add Loongson support xianglai
2022-09-09  3:11 ` [edk2-platforms][PATCH V1 01/16] Platform/Loongson: Add Serial Port library xianglai
2022-09-09  8:44   ` 回复: [edk2-devel] " gaoliming
2022-09-09  9:08     ` xianglai [this message]
2022-09-09 10:40       ` Chao Li
2022-09-09  3:11 ` [edk2-platforms][PATCH V1 02/16] Platform/Loongson: Support SEC And Add Readme.md xianglai
2022-09-09  3:11 ` [edk2-platforms][PATCH V1 03/16] Platform/Loongson: Add PeiServicesTablePointerLib xianglai
2022-09-09  3:12 ` [edk2-platforms][PATCH V1 04/16] Platform/Loongson: Add QemuFwCfgLib xianglai
2022-09-09  3:12 ` [edk2-platforms][PATCH V1 05/16] Platform/Loongson: Add MmuLib xianglai
2022-09-09  3:12 ` [edk2-platforms][PATCH V1 06/16] Platform/Loongson: Add StableTimerLib xianglai
2022-09-09 16:49   ` [edk2-devel] " Michael D Kinney
2022-09-13  2:35     ` xianglai
     [not found]     ` <17144AF1748B76B9.3485@groups.io>
2022-09-13  9:46       ` xianglai
2022-09-09  3:12 ` [edk2-platforms][PATCH V1 07/16] Platform/Loongson: Support PEI phase xianglai
2022-09-09  3:12 ` [edk2-platforms][PATCH V1 08/16] Platform/Loongson: Add CPU DXE driver xianglai
2022-09-09  3:12 ` [edk2-platforms][PATCH V1 09/16] Platform/Loongson: Add PciCpuIoDxe driver xianglai
2022-09-09  3:12 ` [edk2-platforms][PATCH V1 10/16] Platform/Loongson: Add timer Dxe driver xianglai
2022-09-09  3:12 ` [edk2-platforms][PATCH V1 11/16] Platform/Loongson: Add RealTime Clock lib xianglai
2022-09-09  3:12 ` [edk2-platforms][PATCH V1 12/16] Platform/Loongson: Add Platform Boot Manager Lib xianglai
2022-09-09  3:12 ` [edk2-platforms][PATCH V1 13/16] Platform/Loongson: Add Reset System Lib xianglai
2022-09-09  3:12 ` [edk2-platforms][PATCH V1 14/16] Platform/Loongson: Support Dxe xianglai
2022-09-09  3:12 ` [edk2-platforms][PATCH V1 15/16] Platform/Loongson: Add QemuFlashFvbServicesRuntimeDxe driver xianglai
2022-09-09  3:12 ` [edk2-platforms][PATCH V1 16/16] Platform/Loongson: Support for saving variables to flash xianglai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=958f0bd.78c2.18321824253.Coremail.lixianglai@loongson.cn \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox