From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from walk.intel-email.com (walk.intel-email.com [101.227.64.242]) by mx.groups.io with SMTP id smtpd.web08.4406.1662713089622529092 for ; Fri, 09 Sep 2022 01:44:50 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@byosoft.com.cn header.s=cloud-union header.b=dSqHEaec; spf=pass (domain: byosoft.com.cn, ip: 101.227.64.242, mailfrom: gaoliming@byosoft.com.cn) Received: from walk.intel-email.com (localhost [127.0.0.1]) by walk.intel-email.com (Postfix) with ESMTP id DB5E1CD1F696 for ; Fri, 9 Sep 2022 16:44:45 +0800 (CST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=byosoft.com.cn; s=cloud-union; t=1662713086; bh=5TcjDW5yzgrwdSZRn6D3rR0lFEDHo2oPXYzbi0WQWWI=; h=From:To:Cc:References:In-Reply-To:Subject:Date; b=dSqHEaecmOm3Hz7v8ptSFb9uvtk4yCO20RQP7njNJEe74msLY0cHCC9gyhxeUcA57 0UVHufZxMGEGIN7KWpnbYh583y7+fG0xlg9dPZAkpfPnXquPMt958DV/Bq4i4V2Lyx 8mQqfZDOq0QCOJigL5eyK3mSLe7wNlL1dc4qMjvc= Received: from localhost (localhost [127.0.0.1]) by walk.intel-email.com (Postfix) with ESMTP id D6E40CD1F693 for ; Fri, 9 Sep 2022 16:44:45 +0800 (CST) X-Virus-Scanned: by SpamTitan at intel-email.com Received: from walk.intel-email.com (localhost [127.0.0.1]) by walk.intel-email.com (Postfix) with ESMTP id 8E557CD1F76E for ; Fri, 9 Sep 2022 16:44:45 +0800 (CST) Authentication-Results: walk.intel-email.com; none Received: from mail.byosoft.com.cn (mail.byosoft.com.cn [58.240.74.242]) by walk.intel-email.com (Postfix) with SMTP id 222E4CD1F760 for ; Fri, 9 Sep 2022 16:44:42 +0800 (CST) Received: from DESKTOPS6D0PVI ([58.246.60.130]) (envelope-sender ) by 192.168.6.13 with ESMTP for ; Fri, 09 Sep 2022 16:44:40 +0800 X-WM-Sender: gaoliming@byosoft.com.cn X-Originating-IP: 58.246.60.130 X-WM-AuthFlag: YES X-WM-AuthUser: gaoliming@byosoft.com.cn From: "gaoliming" To: , Cc: References: <7775be2be248a91ee072180e9bebc00d94a21298.1662691771.git.lixianglai@loongson.cn> In-Reply-To: <7775be2be248a91ee072180e9bebc00d94a21298.1662691771.git.lixianglai@loongson.cn> Subject: =?UTF-8?B?5Zue5aSNOiBbZWRrMi1kZXZlbF0gW2VkazItcGxhdGZvcm1zXVtQQVRDSCBWMSAwMS8xNl0gUGxhdGZvcm0vTG9vbmdzb246IEFkZCBTZXJpYWwgUG9ydCBsaWJyYXJ5?= Date: Fri, 9 Sep 2022 16:44:42 +0800 Message-ID: <027c01d8c428$67c63ad0$3752b070$@byosoft.com.cn> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 16.0 Thread-Index: AQFAl0cqWgBvdVeIrldPKucK3lVYLQDdljc8rwA1QQA= Sender: "gaoliming" Content-Type: text/plain; charset="gb2312" Content-Transfer-Encoding: quoted-printable Content-Language: zh-cn Xianglai: Please share the github link to get all patches.=20 Thanks Liming > -----=D3=CA=BC=FE=D4=AD=BC=FE----- > =B7=A2=BC=FE=C8=CB: devel@edk2.groups.io = =B4=FA=B1=ED xianglai > =B7=A2=CB=CD=CA=B1=BC=E4: 2022=C4=EA9=D4=C29=C8=D5 11:12 > =CA=D5=BC=FE=C8=CB: devel@edk2.groups.io > =B3=AD=CB=CD: maobibo@loongson.cn > =D6=F7=CC=E2: [edk2-devel] [edk2-platforms][PATCH V1 01/16] = Platform/Loongson: > Add Serial Port library >=20 > Serial Port library for LoongarchQemuPkg >=20 > Signed-off-by: xianglai li > --- > .../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 >=20 > 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 >=20 > + >=20 > + Copyright (c) 2021 Loongson Technology Corporation Limited. All = rights > reserved.
>=20 > + >=20 > + SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > + @par Glossary: >=20 > + - EXC - Exception >=20 > + - INT - Interrupt >=20 > + - FPU - Floating Point Unit >=20 > + - CSR - CPU Status Register >=20 > + - READQ - Read Quad Word >=20 > +**/ >=20 > +#ifndef LOONGARCH_CPU_H_ >=20 > +#define LOONGARCH_CPU_H_ >=20 > + >=20 > +/* Exception types decoded by machdep exception decoder */ >=20 > +#define EXC_INT 0 /* HW interrupt */ >=20 > +#define EXC_TLBL 1 /* TLB miss on a load */ >=20 > +#define EXC_TLBS 2 /* TLB miss on a store */ >=20 > +#define EXC_TLBI 3 /* TLB miss on a ifetch */ >=20 > +#define EXC_TLBM 4 /* TLB modified fault */ >=20 > +#define EXC_TLBRI 5 /* TLB Read-Inhibit exception */ >=20 > +#define EXC_TLBXI 6 /* TLB Execution-Inhibit exception */ >=20 > +#define EXC_TLBPE 7 /* TLB Privilege Error */ >=20 > +#define EXC_ADE 8 /* Address Error */ >=20 > +#define EXC_ALE 9 /* Unalign Access */ >=20 > +#define EXC_OOB 10 /* Out of bounds */ >=20 > +#define EXC_SYS 11 /* System call */ >=20 > +#define EXC_BP 12 /* Breakpoint */ >=20 > +#define EXC_INE 13 /* Inst. Not Exist */ >=20 > +#define EXC_IPE 14 /* Inst. Privileged Error */ >=20 > +#define EXC_FPDIS 15 /* FPU Disabled */ >=20 > +#define EXC_LSXDIS 16 /* LSX Disabled */ >=20 > +#define EXC_LASXDIS 17 /* LASX Disabled */ >=20 > +#define EXC_FPE 18 /* Floating Point Exception */ >=20 > +#define EXC_WATCH 19 /* Watch address reference */ >=20 > +#define EXC_BAD 255 /* Undecodeable */ >=20 > + >=20 > +#define COPY_SIGCODE // copy sigcode above user stack in exec >=20 > +#define ZERO $r0 /* wired zero */ >=20 > +#define RA $r1 /* return address */ >=20 > +#define GP $r2 /* global pointer - caller saved for PIC */ >=20 > +#define SP $r3 /* stack pointer */ >=20 > +#define V0 $r4 /* return value - caller saved */ >=20 > +#define V1 $r5 >=20 > +#define A0 $r4 /* argument registers */ >=20 > +#define A1 $r5 >=20 > +#define A2 $r6 >=20 > +#define A3 $r7 >=20 > +#define A4 $r8 /* arg reg 64 bit; caller saved in 32 bit */ >=20 > +#define A5 $r9 >=20 > +#define A6 $r10 >=20 > +#define A7 $r11 >=20 > +#define T0 $r12 /* caller saved */ >=20 > +#define T1 $r13 >=20 > +#define T2 $r14 >=20 > +#define T3 $r15 >=20 > +#define T4 $r16 /* callee saved */ >=20 > +#define T5 $r17 >=20 > +#define T6 $r18 >=20 > +#define T7 $r19 >=20 > +#define T8 $r20 /* caller saved */ >=20 > +#define TP $r21 /* TLS */ >=20 > +#define FP $r22 /* frame pointer */ >=20 > +#define S0 $r23 /* callee saved */ >=20 > +#define S1 $r24 >=20 > +#define S2 $r25 >=20 > +#define S3 $r26 >=20 > +#define S4 $r27 >=20 > +#define S5 $r28 >=20 > +#define S6 $r29 >=20 > +#define S7 $r30 >=20 > +#define S8 $r31 /* callee saved */ >=20 > + >=20 > +#define FCSR0 $r0 >=20 > + >=20 > +// >=20 > +// Location of the saved registers relative to ZERO. >=20 > +// Usage is p->p_regs[XX]. >=20 > +// >=20 > +#define RA_NUM 1 >=20 > +#define GP_NUM 2 >=20 > +#define SP_NUM 3 >=20 > +#define A0_NUM 4 >=20 > +#define A1_NUM 5 >=20 > +#define A2_NUM 6 >=20 > +#define A3_NUM 7 >=20 > +#define A4_NUM 8 >=20 > +#define A5_NUM 9 >=20 > +#define A6_NUM 10 >=20 > +#define A7_NUM 11 >=20 > +#define T0_NUM 12 >=20 > +#define T1_NUM 13 >=20 > +#define T2_NUM 14 >=20 > +#define T3_NUM 15 >=20 > +#define T4_NUM 16 >=20 > +#define T5_NUM 17 >=20 > +#define T6_NUM 18 >=20 > +#define T7_NUM 19 >=20 > +#define T8_NUM 20 >=20 > +#define TP_NUM 21 >=20 > +#define FP_NUM 22 >=20 > +#define S0_NUM 23 >=20 > +#define S1_NUM 24 >=20 > +#define S2_NUM 25 >=20 > +#define S3_NUM 26 >=20 > +#define S4_NUM 27 >=20 > +#define S5_NUM 28 >=20 > +#define S6_NUM 29 >=20 > +#define S7_NUM 30 >=20 > +#define S8_NUM 31 >=20 > + >=20 > +#define FP0_NUM 0 >=20 > +#define FP1_NUM 1 >=20 > +#define FP2_NUM 2 >=20 > +#define FP3_NUM 3 >=20 > +#define FP4_NUM 4 >=20 > +#define FP5_NUM 5 >=20 > +#define FP6_NUM 6 >=20 > +#define FP7_NUM 7 >=20 > +#define FP8_NUM 8 >=20 > +#define FP9_NUM 9 >=20 > +#define FP10_NUM 10 >=20 > +#define FP11_NUM 11 >=20 > +#define FP12_NUM 12 >=20 > +#define FP13_NUM 13 >=20 > +#define FP14_NUM 14 >=20 > +#define FP15_NUM 15 >=20 > +#define FP16_NUM 16 >=20 > +#define FP17_NUM 17 >=20 > +#define FP18_NUM 18 >=20 > +#define FP19_NUM 19 >=20 > +#define FP20_NUM 20 >=20 > +#define FP21_NUM 21 >=20 > +#define FP22_NUM 22 >=20 > +#define FP23_NUM 23 >=20 > +#define FP24_NUM 24 >=20 > +#define FP25_NUM 25 >=20 > +#define FP26_NUM 26 >=20 > +#define FP27_NUM 27 >=20 > +#define FP28_NUM 28 >=20 > +#define FP29_NUM 29 >=20 > +#define FP30_NUM 30 >=20 > +#define FP31_NUM 31 >=20 > +#define FCSR_NUM 32 >=20 > +#define FCC_NUM 33 >=20 > + >=20 > +#ifdef __ASSEMBLY__ >=20 > +#define _ULCAST_ >=20 > +#define _U64CAST_ >=20 > +#else >=20 > +#define _ULCAST_ (unsigned long) >=20 > +#define _U64CAST_ (u64) >=20 > +#endif >=20 > + >=20 > +#define LOONGARCH_CSR_CRMD 0 >=20 > +#define LOONGARCH_CSR_PRMD 1 >=20 > +#define LOONGARCH_CSR_EUEN 2 >=20 > +#define CSR_EUEN_LBTEN_SHIFT 3 >=20 > +#define CSR_EUEN_LBTEN (_ULCAST_(0x1) << > CSR_EUEN_LBTEN_SHIFT) >=20 > +#define CSR_EUEN_LASXEN_SHIFT 2 >=20 > +#define CSR_EUEN_LASXEN (_ULCAST_(0x1) << > CSR_EUEN_LASXEN_SHIFT) >=20 > +#define CSR_EUEN_LSXEN_SHIFT 1 >=20 > +#define CSR_EUEN_LSXEN (_ULCAST_(0x1) << > CSR_EUEN_LSXEN_SHIFT) >=20 > +#define CSR_EUEN_FPEN_SHIFT 0 >=20 > +#define CSR_EUEN_FPEN (_ULCAST_(0x1) << > CSR_EUEN_FPEN_SHIFT) >=20 > +#define LOONGARCH_CSR_ECFG 4 >=20 > + >=20 > +/* Exception status */ >=20 > +#define LOONGARCH_CSR_ESTAT 5 >=20 > +#define CSR_ESTAT_ESUBCODE_SHIFT 22 >=20 > +#define CSR_ESTAT_ESUBCODE_WIDTH 9 >=20 > +#define CSR_ESTAT_ESUBCODE (_ULCAST_(0x1ff) << > CSR_ESTAT_ESUBCODE_SHIFT) >=20 > +#define CSR_ESTAT_EXC_SHIFT 16 >=20 > +#define CSR_ESTAT_EXC_WIDTH 6 >=20 > +#define CSR_ESTAT_EXC (_ULCAST_(0x3f) << > CSR_ESTAT_EXC_SHIFT) >=20 > +#define CSR_ESTAT_IS_SHIFT 0 >=20 > +#define CSR_ESTAT_IS_WIDTH 15 >=20 > +#define CSR_ESTAT_IS (_ULCAST_(0x7fff) << > CSR_ESTAT_IS_SHIFT) >=20 > +#define LOONGARCH_CSR_EPC 6 >=20 > +#define LOONGARCH_CSR_BADV 7 >=20 > +#define LOONGARCH_CSR_BADINST 8 >=20 > +#define LOONGARCH_CSR_BADI 8 >=20 > +#define LOONGARCH_CSR_EBASE 0xc /* Exception entry base > address */ >=20 > +#define LOONGARCH_CSR_CPUNUM 0x20 /* CPU core number */ >=20 > + >=20 > +/* register number save in stack on exception */ >=20 > +#define FP_BASE_NUM 34 >=20 > +#define BASE_NUM 32 >=20 > +#define CSR_NUM 10 >=20 > +#define FP_BASE_INDEX (CSR_NUM + BASE_NUM) >=20 > +#define BOOTCORE_ID 0 >=20 > + >=20 > +#define LOONGSON_IOCSR_IPI_STATUS 0x1000 >=20 > +#define LOONGSON_IOCSR_IPI_EN 0x1004 >=20 > +#define LOONGSON_IOCSR_IPI_SET 0x1008 >=20 > +#define LOONGSON_IOCSR_IPI_CLEAR 0x100c >=20 > +#define LOONGSON_CSR_MAIL_BUF0 0x1020 >=20 > +#define LOONGSON_CSR_MAIL_BUF1 0x1028 >=20 > +#define LOONGSON_CSR_MAIL_BUF2 0x1030 >=20 > +#define LOONGSON_CSR_MAIL_BUF3 0x1038 >=20 > + >=20 > +/* Bit Domains for CFG registers */ >=20 > +#define LOONGARCH_CPUCFG4 0x4 >=20 > +#define LOONGARCH_CPUCFG5 0x5 >=20 > + >=20 > +/* Kscratch registers */ >=20 > +#define LOONGARCH_CSR_KS0 0x30 >=20 > +#define LOONGARCH_CSR_KS1 0x31 >=20 > + >=20 > +/* Stable timer registers */ >=20 > +#define LOONGARCH_CSR_TMCFG 0x41 >=20 > +#define LOONGARCH_CSR_TMCFG_EN (1ULL << 0) >=20 > +#define LOONGARCH_CSR_TMCFG_PERIOD (1ULL << 1) >=20 > +#define LOONGARCH_CSR_TMCFG_TIMEVAL (0x3fffffffffffULL << 2) >=20 > +#define LOONGARCH_CSR_TVAL 0x42 /* Timer value */ >=20 > +#define LOONGARCH_CSR_CNTC 0x43 /* Timer offset */ >=20 > +#define LOONGARCH_CSR_TINTCLR 0x44 /* Timer interrupt > clear */ >=20 > + >=20 > +/* TLB refill exception base address */ >=20 > +#define LOONGARCH_CSR_TLBREBASE 0x88 >=20 > +#define LOONGARCH_CSR_TLBRSAVE 0x8b /* KScratch for TLB > refill exception */ >=20 > +#define LOONGARCH_CSR_PGD 0x1b /* Page table base */ >=20 > + >=20 > +/* Bits 8 and 9 of FPU Status Register specify the rounding mode */ >=20 > +#define FPU_CSR_RM 0x300 >=20 > +#define FPU_CSR_RN 0x000 /* nearest */ >=20 > +#define FPU_CSR_RZ 0x100 /* towards zero */ >=20 > +#define FPU_CSR_RU 0x200 /* towards +Infinity */ >=20 > +#define FPU_CSR_RD 0x300 /* towards -Infinity */ >=20 > + >=20 > +/* >=20 > + Reads data from the specified CSR register. >=20 > + >=20 > + @param[OUT] val The value is read from the CSR specified = register. >=20 > + @param[IN] reg Specifies the register number of the CSR to read > the data. >=20 > + >=20 > + @retval VOID >=20 > + */ >=20 > +#define LOONGARCH_CSR_READQ(val, reg) \ >=20 > +do { \ >=20 > + UINT64 __res; \ >=20 > + /* csrrd rd, csr_num */ \ >=20 > + __asm__ __volatile__( \ >=20 > + "csrrd %0, %1 \n\t" \ >=20 > + :"=3Dr"(__res) \ >=20 > + :"i"(reg) \ >=20 > + : \ >=20 > + ); \ >=20 > + (val) =3D __res; \ >=20 > +} while(0) >=20 > + >=20 > +/* >=20 > + Write data to the specified CSR register. >=20 > + >=20 > + @param[OUT] val The value is write to the CSR specified = register. >=20 > + @param[IN] reg Specifies the register number of the CSR to = write > the data. >=20 > + >=20 > + @retval VOID >=20 > + */ >=20 > +#define LOONGARCH_CSR_WRITEQ(val, reg) \ >=20 > +do { \ >=20 > + UINT64 __val =3D val; \ >=20 > + /* csrwr rd, csr_num */ \ >=20 > + __asm__ __volatile__( \ >=20 > + "csrwr %0, %1 \n\t" \ >=20 > + : "+r"(__val) \ >=20 > + : "i"(reg), "r"(__val) \ >=20 > + : "memory" \ >=20 > + ); \ >=20 > +} while(0) >=20 > + >=20 > +/* >=20 > + Exchange specified bit data with the specified CSR registers >=20 > + >=20 > + @param[IN] val The value Exchanged with the CSR specified > register. >=20 > + @param[IN] mask Specifies the mask for swapping bits >=20 > + @param[IN] reg Specifies the register number of the CSR to > Exchange the data. >=20 > + >=20 > + @retval VOID >=20 > + */ >=20 > +#define LOONGARCH_CSR_XCHGQ(val, mask, reg) \ >=20 > +do { \ >=20 > + UINT64 __val =3D val; \ >=20 > + UINT64 __mask =3D mask; \ >=20 > + /* csrwr rd, csr_num */ \ >=20 > + __asm__ __volatile__( \ >=20 > + "csrxchg %0, %1, %2 \n\t" \ >=20 > + : "+r"(__val) \ >=20 > + : "r"(__mask), "i"(reg), "r"(__val) \ >=20 > + : "memory" \ >=20 > + ); \ >=20 > +} while(0) >=20 > +/* >=20 > + Reads data from the specified CPUCFG register. >=20 > + >=20 > + @param[OUT] val The value is read from the CPUCFG specified > register. >=20 > + @param[IN] reg Specifies the register number of the CPUCFG to > read the data. >=20 > + >=20 > + @retval VOID >=20 > + */ >=20 > +#define LOONGARCH_GET_CPUCFG(val, reg) \ >=20 > +do { \ >=20 > + UINT64 __res; \ >=20 > + /* cpucfg rd, rj */ \ >=20 > + __asm__ __volatile__( \ >=20 > + "cpucfg %0, %1 \n\t" \ >=20 > + :"=3Dr"(__res) \ >=20 > + :"r"(reg) \ >=20 > + : \ >=20 > + ); \ >=20 > + val =3D (UINT32)__res; \ >=20 > +} while(0) >=20 > + >=20 > +/* >=20 > + Enables floating-point unit >=20 > + >=20 > + @param VOID >=20 > + >=20 > + @retval VOID >=20 > + */ >=20 > +#define LOONGARCH_ENABLR_FPU() \ >=20 > +do { \ >=20 > + LOONGARCH_CSR_XCHGQ(CSR_EUEN_FPEN, \ >=20 > + CSR_EUEN_FPEN, \ >=20 > + LOONGARCH_CSR_EUEN); \ >=20 > +} while (0) >=20 > + >=20 > +/* >=20 > + Disable floating-point unit >=20 > + >=20 > + @param VOID >=20 > + >=20 > + @retval VOID >=20 > + */ >=20 > +#define LOONGARCH_DISABLE_FPU() \ >=20 > +do { \ >=20 > + LOONGARCH_CSR_XCHGQ(0, \ >=20 > + CSR_EUEN_FPEN, \ >=20 > + LOONGARCH_CSR_EUEN); \ >=20 > +} while (0) >=20 > + >=20 > +#endif >=20 > 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 >=20 > + LoongArch Qemu Platform macro definition. >=20 > + >=20 > + Copyright (c) 2021, Loongson Limited. All rights reserved. >=20 > + >=20 > + SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > + **/ >=20 > + >=20 > +#ifndef LOONGARCH_QEMU_PLATFORM_H_ >=20 > +#define LOONGARCH_QEMU_PLATFORM_H_ >=20 > + >=20 > + >=20 > +/* Acpi pm device */ >=20 > +#define LS7A_PCH_REG_BASE 0x10000000UL >=20 > +#define LS7A_ACPI_REG_BASE (LS7A_PCH_REG_BASE + > 0x000D0000) >=20 > +#define LS7A_PM_CNT_BLK (0x14) /* 2 bytes */ >=20 > +#define LS7A_GPE0_RESET_REG (0x30) /* 4 bytes */ >=20 > + >=20 > +#define ACPI_BITMASK_SLEEP_TYPE 0x1C00 >=20 > +#define ACPI_BITMASK_SLEEP_ENABLE 0x2000 >=20 > + >=20 > + >=20 > +//--------------------------------------------- >=20 > +// UART Register Offsets >=20 > +//--------------------------------------------- >=20 > +#define BAUD_LOW_OFFSET 0x00 >=20 > +#define BAUD_HIGH_OFFSET 0x01 >=20 > +#define IER_OFFSET 0x01 >=20 > +#define LCR_SHADOW_OFFSET 0x01 >=20 > +#define FCR_SHADOW_OFFSET 0x02 >=20 > +#define IR_CONTROL_OFFSET 0x02 >=20 > +#define FCR_OFFSET 0x02 >=20 > +#define EIR_OFFSET 0x02 >=20 > +#define BSR_OFFSET 0x03 >=20 > +#define LCR_OFFSET 0x03 >=20 > +#define MCR_OFFSET 0x04 >=20 > +#define LSR_OFFSET 0x05 >=20 > +#define MSR_OFFSET 0x06 >=20 > + >=20 > +/* character format control register */ >=20 > +#define CFCR_DLAB 0x80 /* divisor latch */ >=20 > +#define CFCR_SBREAK 0x40 /* send break */ >=20 > +#define CFCR_PZERO 0x30 /* zero parity */ >=20 > +#define CFCR_PONE 0x20 /* one parity */ >=20 > +#define CFCR_PEVEN 0x10 /* even parity */ >=20 > +#define CFCR_PODD 0x00 /* odd parity */ >=20 > +#define CFCR_PENAB 0x08 /* parity enable */ >=20 > +#define CFCR_STOPB 0x04 /* 2 stop bits */ >=20 > +#define CFCR_8BITS 0x03 /* 8 data bits */ >=20 > +#define CFCR_7BITS 0x02 /* 7 data bits */ >=20 > +#define CFCR_6BITS 0x01 /* 6 data bits */ >=20 > +#define CFCR_5BITS 0x00 /* 5 data bits */ >=20 > +/* modem control register */ >=20 > +#define MCR_LOOPBACK 0x10 /* loopback */ >=20 > +#define MCR_IENABLE 0x08 /* output 2 =3D int enable */ >=20 > +#define MCR_DRS 0x04 /* output 1 =3D xxx */ >=20 > +#define MCR_RTS 0x02 /* enable RTS */ >=20 > +#define MCR_DTR 0x01 /* enable DTR */ >=20 > + >=20 > +/* line status register */ >=20 > +#define LSR_RCV_FIFO 0x80 /* error in receive fifo */ >=20 > +#define LSR_TSRE 0x40 /* transmitter empty */ >=20 > +#define LSR_TXRDY 0x20 /* transmitter ready */ >=20 > +#define LSR_BI 0x10 /* break detected */ >=20 > +#define LSR_FE 0x08 /* framing error */ >=20 > +#define LSR_PE 0x04 /* parity error */ >=20 > +#define LSR_OE 0x02 /* overrun error */ >=20 > +#define LSR_RXRDY 0x01 /* receiver ready */ >=20 > +#define LSR_RCV_MASK 0x1f >=20 > + >=20 > +/* 16550 UART register offsets and bitfields */ >=20 > +#define R_UART_RXBUF 0 >=20 > +#define R_UART_TXBUF 0 >=20 > +#define R_UART_BAUD_LOW 0 >=20 > +#define R_UART_BAUD_HIGH 1 >=20 > +#define R_UART_FCR 2 >=20 > +#define B_UART_FCR_FIFOE BIT0 >=20 > +#define B_UART_FCR_FIFO64 BIT5 >=20 > +#define R_UART_LCR 3 >=20 > +#define B_UART_LCR_DLAB BIT7 >=20 > +#define R_UART_MCR 4 >=20 > +#define B_UART_MCR_DTRC BIT0 >=20 > +#define B_UART_MCR_RTS BIT1 >=20 > +#define R_UART_LSR 5 >=20 > +#define B_UART_LSR_RXRDY BIT0 >=20 > +#define B_UART_LSR_TXRDY BIT5 >=20 > +#define B_UART_LSR_TEMT BIT6 >=20 > +#define R_UART_MSR 6 >=20 > +#define B_UART_MSR_CTS BIT4 >=20 > +#define B_UART_MSR_DSR BIT5 >=20 > +#define B_UART_MSR_RI BIT6 >=20 > +#define B_UART_MSR_DCD BIT7 >=20 > +#define UART_BASE_ADDRESS (0x1fe001e0) >=20 > +#define UART_BPS (115200) >=20 > +#define UART_WAIT_TIMOUT (1000000) >=20 > +//--------------------------------------------- >=20 > +// UART Settings >=20 > +//--------------------------------------------- >=20 > +#define PHYS_TO_CACHED(x) ((x)) >=20 > +#define PHYS_TO_UNCACHED(x) ((x)) >=20 > + >=20 > +#endif >=20 > 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 >=20 > + UART Serial Port library functions >=20 > + >=20 > + Copyright (c) 2021 Loongson Technology Corporation Limited. All = rights > reserved.
>=20 > + >=20 > + SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > + @par Glossary: >=20 > + - Bps - Bit Per Second >=20 > + - CTL - Control >=20 > + - Config - Configure >=20 > +**/ >=20 > + >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > + >=20 > +UINTN gUartBase =3D PHYS_TO_UNCACHED(UART_BASE_ADDRESS); >=20 > +UINTN gBps =3D UART_BPS; >=20 > + >=20 > +/** >=20 > + Initialize the serial device hardware. >=20 > + >=20 > + If no initialization is required, then return RETURN_SUCCESS. >=20 > + If the serial device was successfuly initialized, then return > RETURN_SUCCESS. >=20 > + If the serial device could not be initialized, then return > RETURN_DEVICE_ERROR. >=20 > + >=20 > + @retval RETURN_SUCCESS The serial device was initialized. >=20 > + @retval RETURN_DEVICE_ERROR The serail device could not be > initialized. >=20 > + >=20 > +**/ >=20 > +RETURN_STATUS >=20 > +EFIAPI >=20 > +SerialPortInitialize ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + UINTN TimeOut; >=20 > + // >=20 > + // wait for Tx fifo to completely drain */ >=20 > + // >=20 > + TimeOut =3D UART_WAIT_TIMOUT; >=20 > + while (!(MmioRead8 ((UINTN) gUartBase + LSR_OFFSET) & LSR_TSRE)) { >=20 > + if (--TimeOut =3D=3D 0) { >=20 > + break; >=20 > + } >=20 > + } >=20 > + // >=20 > + // Set communications format >=20 > + // >=20 > + MmioWrite8 ((UINTN) (gUartBase + LCR_OFFSET), CFCR_DLAB); >=20 > + >=20 > + // >=20 > + // Configure baud rate >=20 > + // >=20 > + >=20 > + >=20 > + MmioWrite8 ((UINTN) (gUartBase + LCR_OFFSET), CFCR_8BITS); >=20 > + MmioWrite8 ((UINTN) (gUartBase + MCR_OFFSET), MCR_IENABLE | > MCR_DTR | MCR_RTS); >=20 > + // >=20 > + // if enable interrupt the kernel of lemote will error in STR mode during > wake up phase. >=20 > + // >=20 > + //MmioWrite8 ((UINTN) (gUartBase + IER_OFFSET), CFCR_8BITS); >=20 > + >=20 > + return RETURN_SUCCESS; >=20 > +} >=20 > + >=20 > +/** >=20 > + Write data from buffer to serial device. >=20 > + >=20 > + Writes NumberOfBytes data bytes from Buffer to the serial device. >=20 > + The number of bytes actually written to the serial device is = returned. >=20 > + If the return value is less than NumberOfBytes, then the write operation > failed. >=20 > + >=20 > + If Buffer is NULL, then ASSERT (). >=20 > + >=20 > + If NumberOfBytes is zero, then return 0. >=20 > + >=20 > + @param Buffer Pointer to the data buffer to be written. >=20 > + @param NumberOfBytes Number of bytes to written to the serial > device. >=20 > + >=20 > + @retval 0 NumberOfBytes is 0. >=20 > + @retval >0 The number of bytes written to the serial > device. >=20 > + If this value is less than NumberOfBytes, > then the read operation failed. >=20 > + >=20 > +**/ >=20 > +UINTN >=20 > +EFIAPI >=20 > +UartCtlWrite ( >=20 > + IN UINT8 *Buffer, >=20 > + IN UINTN NumberOfBytes, >=20 > + IN UINTN CtlAddr >=20 > +) >=20 > +{ >=20 > + UINTN Result; >=20 > + UINT8 Data; >=20 > + >=20 > + if (Buffer =3D=3D NULL) { >=20 > + return 0; >=20 > + } >=20 > + >=20 > + Result =3D NumberOfBytes; >=20 > + >=20 > + while (NumberOfBytes--) { >=20 > + // >=20 > + // Wait for the serail port to be ready. >=20 > + // >=20 > + do { >=20 > + Data =3D MmioRead8 (CtlAddr + LSR_OFFSET); >=20 > + } while ((Data & LSR_TXRDY) =3D=3D 0); >=20 > + MmioWrite8 (CtlAddr, *Buffer++); >=20 > + } >=20 > + >=20 > + return Result; >=20 > +} >=20 > +/** >=20 > + Writes data to serial port. >=20 > + >=20 > + @param Buffer Pointer to the data buffer to store the = data > writed to serial port. >=20 > + @param NumberOfBytes Number of bytes to write to the serial > port. >=20 > + >=20 > + @retval 0 NumberOfBytes is 0. >=20 > + @retval >0 The number of bytes write the serial port. >=20 > + If this value is less than NumberOfBytes, > then the write operation failed. >=20 > + >=20 > +**/ >=20 > +UINTN >=20 > +EFIAPI >=20 > +SerialPortWrite ( >=20 > + IN UINT8 *Buffer, >=20 > + IN UINTN NumberOfBytes >=20 > +) >=20 > +{ >=20 > + return UartCtlWrite (Buffer, NumberOfBytes, gUartBase); >=20 > +} >=20 > +/** >=20 > + Reads data from a serial device into a buffer. >=20 > + >=20 > + @param Buffer Pointer to the data buffer to store the = data > read from the serial device. >=20 > + @param NumberOfBytes Number of bytes to read from the serial > device. >=20 > + >=20 > + @retval 0 NumberOfBytes is 0. >=20 > + @retval >0 The number of bytes read from the serial > device. >=20 > + If this value is less than NumberOfBytes, > then the read operation failed. >=20 > + >=20 > +**/ >=20 > +UINTN >=20 > +EFIAPI >=20 > +UartCtlRead ( >=20 > + OUT UINT8 *Buffer, >=20 > + IN UINTN NumberOfBytes, >=20 > + IN UINTN CtlAddr >=20 > +) >=20 > +{ >=20 > + UINTN Result; >=20 > + UINT8 Data; >=20 > + >=20 > + if (NULL =3D=3D Buffer) { >=20 > + return 0; >=20 > + } >=20 > + >=20 > + Result =3D NumberOfBytes; >=20 > + >=20 > + while (NumberOfBytes--) { >=20 > + // >=20 > + // Wait for the serail port to be ready. >=20 > + // >=20 > + do { >=20 > + Data =3D MmioRead8 (CtlAddr + LSR_OFFSET); >=20 > + } while ((Data & LSR_RXRDY) =3D=3D 0); >=20 > + >=20 > + *Buffer++ =3D MmioRead8 (CtlAddr); >=20 > + } >=20 > + >=20 > + return Result; >=20 > +} >=20 > +/** >=20 > + Read data from serial port. >=20 > + >=20 > + @param Buffer Pointer to the data buffer to store the = data > read from serial port. >=20 > + @param NumberOfBytes Number of bytes to read from the serial > port. >=20 > + >=20 > + @retval 0 NumberOfBytes is 0. >=20 > + @retval >0 The number of bytes read from the serial > port. >=20 > + If this value is less than NumberOfBytes, > then the read operation failed. >=20 > + >=20 > +**/ >=20 > +UINTN >=20 > +EFIAPI >=20 > +SerialPortRead ( >=20 > + OUT UINT8 *Buffer, >=20 > + IN UINTN NumberOfBytes >=20 > +) >=20 > +{ >=20 > + return UartCtlRead (Buffer, NumberOfBytes, gUartBase); >=20 > +} >=20 > +/** >=20 > + Polls a serial device to see if there is any data waiting to be = read. >=20 > + >=20 > + Polls aserial device to see if there is any data waiting to be = read. >=20 > + If there is data waiting to be read from the serial device, then = TRUE is > returned. >=20 > + If there is no data waiting to be read from the serial device, then FALSE is > returned. >=20 > + >=20 > + @retval TRUE Data is waiting to be read from the serial > device. >=20 > + @retval FALSE There is no data waiting to be read from = the > serial device. >=20 > + >=20 > +**/ >=20 > +BOOLEAN >=20 > +EFIAPI >=20 > +SerialPortPoll ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + UINT8 Data; >=20 > + >=20 > + // >=20 > + // Read the serial port status. >=20 > + // >=20 > + Data =3D MmioRead8 ((UINTN) gUartBase + LSR_OFFSET); >=20 > + >=20 > + return (BOOLEAN) ((Data & LSR_RXRDY) !=3D 0); >=20 > +} >=20 > +/** >=20 > + To get serial register base address. >=20 > + >=20 > + @param VOID >=20 > + >=20 > + @return serial register base address. >=20 > +**/ >=20 > +UINTN >=20 > +GetSerialRegisterBase ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + return gUartBase; >=20 > +} >=20 > +/** >=20 > + Read an 8-bit register. >=20 > + @param Base The base address register of UART device. >=20 > + @param Offset The offset of the register to read. >=20 > + >=20 > + @return The value read from the 16550 register. >=20 > + >=20 > +**/ >=20 > +UINT8 >=20 > +SerialPortReadRegister ( >=20 > + UINTN Base, >=20 > + UINTN Offset >=20 > + ) >=20 > +{ >=20 > + return MmioRead8 (Base + Offset); >=20 > +} >=20 > + >=20 > +/** >=20 > + Write an 8-bit register. >=20 > + @param Base The base address register of UART device. >=20 > + @param Offset The offset of the register to write. >=20 > + @param Value The value to write to the register specified by = Offset. >=20 > + >=20 > + @return The value written to the 16550 register. >=20 > + >=20 > +**/ >=20 > +UINT8 >=20 > +SerialPortWriteRegister ( >=20 > + UINTN Base, >=20 > + UINTN Offset, >=20 > + UINT8 Value >=20 > + ) >=20 > +{ >=20 > + return MmioWrite8 (Base + Offset, Value); >=20 > +} >=20 > + >=20 > +/** >=20 > + Sets the control bits on a serial device. >=20 > + >=20 > + @param Control Sets the bits of Control that are > settable. >=20 > + >=20 > + @retval RETURN_SUCCESS The new control bits were set on the > serial device. >=20 > + @retval RETURN_UNSUPPORTED The serial device does not support > this operation. >=20 > + @retval RETURN_DEVICE_ERROR The serial device is not functioning > correctly. >=20 > + >=20 > +**/ >=20 > +RETURN_STATUS >=20 > +EFIAPI >=20 > +SerialPortSetControl ( >=20 > + IN UINT32 Control >=20 > + ) >=20 > +{ >=20 > + UINTN SerialRegisterBase; >=20 > + UINT8 Mcr; >=20 > + >=20 > + // >=20 > + // First determine the parameter is invalid. >=20 > + // >=20 > + if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | > EFI_SERIAL_DATA_TERMINAL_READY | >=20 > + > EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) !=3D 0) >=20 > + { >=20 > + return RETURN_UNSUPPORTED; >=20 > + } >=20 > + >=20 > + SerialRegisterBase =3D GetSerialRegisterBase (); >=20 > + if (SerialRegisterBase =3D=3D0) { >=20 > + return RETURN_UNSUPPORTED; >=20 > + } >=20 > + >=20 > + // >=20 > + // Read the Modem Control Register. >=20 > + // >=20 > + Mcr =3D SerialPortReadRegister (SerialRegisterBase, R_UART_MCR); >=20 > + Mcr &=3D (~(B_UART_MCR_DTRC | B_UART_MCR_RTS)); >=20 > + >=20 > + if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) =3D=3D > EFI_SERIAL_DATA_TERMINAL_READY) { >=20 > + Mcr |=3D B_UART_MCR_DTRC; >=20 > + } >=20 > + >=20 > + if ((Control & EFI_SERIAL_REQUEST_TO_SEND) =3D=3D > EFI_SERIAL_REQUEST_TO_SEND) { >=20 > + Mcr |=3D B_UART_MCR_RTS; >=20 > + } >=20 > + >=20 > + // >=20 > + // Write the Modem Control Register. >=20 > + // >=20 > + SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, Mcr); >=20 > + >=20 > + return RETURN_SUCCESS; >=20 > +} >=20 > + >=20 > +/** >=20 > + Retrieve the status of the control bits on a serial device. >=20 > + >=20 > + @param Control A pointer to return the current > control signals from the serial device. >=20 > + >=20 > + @retval RETURN_SUCCESS The control bits were read from the > serial device. >=20 > + @retval RETURN_UNSUPPORTED The serial device does not support > this operation. >=20 > + @retval RETURN_DEVICE_ERROR The serial device is not functioning > correctly. >=20 > + >=20 > +**/ >=20 > +RETURN_STATUS >=20 > +EFIAPI >=20 > +SerialPortGetControl ( >=20 > + OUT UINT32 *Control >=20 > + ) >=20 > +{ >=20 > + UINTN SerialRegisterBase; >=20 > + UINT8 Msr; >=20 > + UINT8 Mcr; >=20 > + UINT8 Lsr; >=20 > + >=20 > + SerialRegisterBase =3D GetSerialRegisterBase (); >=20 > + if (SerialRegisterBase =3D=3D0) { >=20 > + return RETURN_UNSUPPORTED; >=20 > + } >=20 > + >=20 > + *Control =3D 0; >=20 > + >=20 > + // >=20 > + // Read the Modem Status Register. >=20 > + // >=20 > + Msr =3D SerialPortReadRegister (SerialRegisterBase, R_UART_MSR); >=20 > + >=20 > + if ((Msr & B_UART_MSR_CTS) =3D=3D B_UART_MSR_CTS) { >=20 > + *Control |=3D EFI_SERIAL_CLEAR_TO_SEND; >=20 > + } >=20 > + >=20 > + if ((Msr & B_UART_MSR_DSR) =3D=3D B_UART_MSR_DSR) { >=20 > + *Control |=3D EFI_SERIAL_DATA_SET_READY; >=20 > + } >=20 > + >=20 > + if ((Msr & B_UART_MSR_RI) =3D=3D B_UART_MSR_RI) { >=20 > + *Control |=3D EFI_SERIAL_RING_INDICATE; >=20 > + } >=20 > + >=20 > + if ((Msr & B_UART_MSR_DCD) =3D=3D B_UART_MSR_DCD) { >=20 > + *Control |=3D EFI_SERIAL_CARRIER_DETECT; >=20 > + } >=20 > + >=20 > + // >=20 > + // Read the Modem Control Register. >=20 > + // >=20 > + Mcr =3D SerialPortReadRegister (SerialRegisterBase, R_UART_MCR); >=20 > + >=20 > + if ((Mcr & B_UART_MCR_DTRC) =3D=3D B_UART_MCR_DTRC) { >=20 > + *Control |=3D EFI_SERIAL_DATA_TERMINAL_READY; >=20 > + } >=20 > + >=20 > + if ((Mcr & B_UART_MCR_RTS) =3D=3D B_UART_MCR_RTS) { >=20 > + *Control |=3D EFI_SERIAL_REQUEST_TO_SEND; >=20 > + } >=20 > + >=20 > + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { >=20 > + *Control |=3D EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; >=20 > + } >=20 > + >=20 > + // >=20 > + // Read the Line Status Register. >=20 > + // >=20 > + Lsr =3D SerialPortReadRegister (SerialRegisterBase, R_UART_LSR); >=20 > + >=20 > + if ((Lsr & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) =3D=3D > (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) { >=20 > + *Control |=3D EFI_SERIAL_OUTPUT_BUFFER_EMPTY; >=20 > + } >=20 > + >=20 > + if ((Lsr & B_UART_LSR_RXRDY) =3D=3D 0) { >=20 > + *Control |=3D EFI_SERIAL_INPUT_BUFFER_EMPTY; >=20 > + } >=20 > + >=20 > + return RETURN_SUCCESS; >=20 > +} >=20 > + >=20 > +/** >=20 > + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, >=20 > + data bits, and stop bits on a serial device. >=20 > + >=20 > + @param BaudRate The requested baud rate. A BaudRate > value of 0 will use the >=20 > + device's default interface speed. >=20 > + On output, the value actually set. >=20 > + @param ReveiveFifoDepth The requested depth of the FIFO on the > receive side of the >=20 > + serial interface. A ReceiveFifoDepth = value > of 0 will use >=20 > + the device's default FIFO depth. >=20 > + On output, the value actually set. >=20 > + @param Timeout The requested time out for a single > character in microseconds. >=20 > + This timeout applies to both the transmit > and receive side of the >=20 > + interface. A Timeout value of 0 will use > the device's default time >=20 > + out value. >=20 > + On output, the value actually set. >=20 > + @param Parity The type of parity to use on this serial > device. A Parity value of >=20 > + DefaultParity will use the device's = default > parity value. >=20 > + On output, the value actually set. >=20 > + @param DataBits The number of data bits to use on the > serial device. A DataBits >=20 > + vaule of 0 will use the device's default > data bit setting. >=20 > + On output, the value actually set. >=20 > + @param StopBits The number of stop bits to use on this > serial device. A StopBits >=20 > + value of DefaultStopBits will use the > device's default number of >=20 > + stop bits. >=20 > + On output, the value actually set. >=20 > + >=20 > + @retval RETURN_SUCCESS The new attributes were set on > the serial device. >=20 > + @retval RETURN_UNSUPPORTED The serial device does not > support this operation. >=20 > + @retval RETURN_INVALID_PARAMETER One or more of the attributes > has an unsupported value. >=20 > + @retval RETURN_DEVICE_ERROR The serial device is not > functioning correctly. >=20 > + >=20 > +**/ >=20 > +RETURN_STATUS >=20 > +EFIAPI >=20 > +UartCtlConfig ( >=20 > + IN OUT UINT64 *BaudRate, >=20 > + IN OUT UINT32 *ReceiveFifoDepth, >=20 > + IN OUT UINT32 *Timeout, >=20 > + IN OUT EFI_PARITY_TYPE *Parity, >=20 > + IN OUT UINT8 *DataBits, >=20 > + IN OUT EFI_STOP_BITS_TYPE *StopBits, >=20 > + IN UINTN CtlAddr >=20 > + ) >=20 > +{ >=20 > + UINTN SerialRegisterBase; >=20 > + UINT8 Lcr; >=20 > + UINT8 LcrData; >=20 > + UINT8 LcrParity; >=20 > + UINT8 LcrStop; >=20 > + >=20 > + >=20 > + SerialRegisterBase =3D CtlAddr; >=20 > + if (SerialRegisterBase =3D=3D0) { >=20 > + return RETURN_UNSUPPORTED; >=20 > + } >=20 > + >=20 > + // >=20 > + // Check for default settings and fill in actual values. >=20 > + // >=20 > + if (*BaudRate =3D=3D 0) { >=20 > + *BaudRate =3D PcdGet32 (PcdSerialBaudRate); >=20 > + } >=20 > + >=20 > + if (*DataBits =3D=3D 0) { >=20 > + LcrData =3D (UINT8) (PcdGet8 (PcdSerialLineControl) & 0x3); >=20 > + *DataBits =3D LcrData + 5; >=20 > + } else { >=20 > + if ((*DataBits < 5) >=20 > + || (*DataBits > 8)) >=20 > + { >=20 > + return RETURN_INVALID_PARAMETER; >=20 > + } >=20 > + // >=20 > + // Map 5..8 to 0..3 >=20 > + // >=20 > + LcrData =3D (UINT8) (*DataBits - (UINT8) 5); >=20 > + } >=20 > + >=20 > + if (*Parity =3D=3D DefaultParity) { >=20 > + LcrParity =3D (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 3) & = 0x7); >=20 > + switch (LcrParity) { >=20 > + case 0: >=20 > + *Parity =3D NoParity; >=20 > + break; >=20 > + >=20 > + case 3: >=20 > + *Parity =3D EvenParity; >=20 > + break; >=20 > + >=20 > + case 1: >=20 > + *Parity =3D OddParity; >=20 > + break; >=20 > + >=20 > + case 7: >=20 > + *Parity =3D SpaceParity; >=20 > + break; >=20 > + >=20 > + case 5: >=20 > + *Parity =3D MarkParity; >=20 > + break; >=20 > + >=20 > + default: >=20 > + break; >=20 > + } >=20 > + } else { >=20 > + switch (*Parity) { >=20 > + case NoParity: >=20 > + LcrParity =3D 0; >=20 > + break; >=20 > + >=20 > + case EvenParity: >=20 > + LcrParity =3D 3; >=20 > + break; >=20 > + >=20 > + case OddParity: >=20 > + LcrParity =3D 1; >=20 > + break; >=20 > + >=20 > + case SpaceParity: >=20 > + LcrParity =3D 7; >=20 > + break; >=20 > + >=20 > + case MarkParity: >=20 > + LcrParity =3D 5; >=20 > + break; >=20 > + >=20 > + default: >=20 > + return RETURN_INVALID_PARAMETER; >=20 > + } >=20 > + } >=20 > + >=20 > + if (*StopBits =3D=3D DefaultStopBits) { >=20 > + LcrStop =3D (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 2) & = 0x1); >=20 > + switch (LcrStop) { >=20 > + case 0: >=20 > + *StopBits =3D OneStopBit; >=20 > + break; >=20 > + >=20 > + case 1: >=20 > + if (*DataBits =3D=3D 5) { >=20 > + *StopBits =3D OneFiveStopBits; >=20 > + } else { >=20 > + *StopBits =3D TwoStopBits; >=20 > + } >=20 > + break; >=20 > + >=20 > + default: >=20 > + break; >=20 > + } >=20 > + } else { >=20 > + switch (*StopBits) { >=20 > + case OneStopBit: >=20 > + LcrStop =3D 0; >=20 > + break; >=20 > + >=20 > + case OneFiveStopBits: >=20 > + case TwoStopBits: >=20 > + LcrStop =3D 1; >=20 > + break; >=20 > + >=20 > + default: >=20 > + return RETURN_INVALID_PARAMETER; >=20 > + } >=20 > + } >=20 > + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, > B_UART_LCR_DLAB); >=20 > + >=20 > + // >=20 > + // Clear DLAB and configure Data Bits, Parity, and Stop Bits. >=20 > + // Strip reserved bits from line control value >=20 > + // >=20 > + Lcr =3D (UINT8) ((LcrParity << 3) | (LcrStop << 2) | LcrData); >=20 > + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8) = (Lcr & > 0x3F)); >=20 > + >=20 > + return RETURN_SUCCESS; >=20 > +} >=20 > +/** >=20 > + Set the serial port Attributes. >=20 > + >=20 > + @param VOID >=20 > + >=20 > + @return serial register base address. >=20 > +**/ >=20 > +RETURN_STATUS >=20 > +EFIAPI >=20 > +SerialPortSetAttributes ( >=20 > + IN OUT UINT64 *BaudRate, >=20 > + IN OUT UINT32 *ReceiveFifoDepth, >=20 > + IN OUT UINT32 *Timeout, >=20 > + IN OUT EFI_PARITY_TYPE *Parity, >=20 > + IN OUT UINT8 *DataBits, >=20 > + IN OUT EFI_STOP_BITS_TYPE *StopBits >=20 > + ) >=20 > +{ >=20 > + UINTN SerialRegisterBase; >=20 > + >=20 > + SerialRegisterBase =3D GetSerialRegisterBase (); >=20 > + >=20 > + return UartCtlConfig (&gBps, ReceiveFifoDepth, Timeout, Parity, > DataBits, StopBits, >=20 > + SerialRegisterBase); >=20 > +} >=20 > 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 >=20 > +# UART Serial Port library functions >=20 > +# >=20 > +# Copyright (c) 2021 Loongson Technology Corporation Limited. All = rights > reserved.
>=20 > +# >=20 > +# SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > +# >=20 > +## >=20 > + >=20 > + >=20 > +[Defines] >=20 > + INF_VERSION =3D 0x00010005 >=20 > + BASE_NAME =3D PcAtSerialPortLib >=20 > + FILE_GUID =3D > f4fb883d-8138-4f29-bb0c-c574e9312c74 >=20 > + MODULE_TYPE =3D BASE >=20 > + VERSION_STRING =3D 1.0 >=20 > + LIBRARY_CLASS =3D SerialPortLib >=20 > + >=20 > +[Packages] >=20 > + MdePkg/MdePkg.dec >=20 > + MdeModulePkg/MdeModulePkg.dec >=20 > + Platform/Loongson/LoongArchQemuPkg/Loongson.dec >=20 > + >=20 > +[LibraryClasses] >=20 > + BaseLib >=20 > + IoLib >=20 > + PcdLib >=20 > + >=20 > +[Sources] >=20 > + SerialPortLib.c >=20 > + >=20 > +[Pcd] >=20 > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl > ## CONSUMES >=20 > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate > ## CONSUMES >=20 > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialLineControl > ## CONSUMES >=20 > + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate > ## CONSUMES >=20 > -- > 2.31.1 >=20 >=20 >=20 > -=3D-=3D-=3D-=3D-=3D-=3D > 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] > -=3D-=3D-=3D-=3D-=3D-=3D >=20 >=20 >=20