add Qualcomm GENI SerialPortLib
authorBigfootACA <bigfoot@classfun.cn>
星期六, 5 Feb 2022 12:19:32 +0000 (20:19 +0800)
committerBigfootACA <bigfoot@classfun.cn>
星期三, 9 Feb 2022 18:32:42 +0000 (02:32 +0800)
sdm845Pkg/Library/QcomGeniSerialPortLib/GeniSerial.h [new file with mode: 0644]
sdm845Pkg/Library/QcomGeniSerialPortLib/QcomGeniSerialPortLib.c [new file with mode: 0644]
sdm845Pkg/Library/QcomGeniSerialPortLib/QcomGeniSerialPortLib.inf [new file with mode: 0644]
sdm845Pkg/sdm845Pkg.dsc

diff --git a/sdm845Pkg/Library/QcomGeniSerialPortLib/GeniSerial.h b/sdm845Pkg/Library/QcomGeniSerialPortLib/GeniSerial.h
new file mode 100644 (file)
index 0000000..f92035a
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef UARTQUPV3_H
+#define UARTQUPV3_H
+#define UART_DEBUG_PORT_BASE                             0xA84000
+#define UART_BASE_ADDR                                   UART_DEBUG_PORT_BASE
+#define RING_SIZE                                        256
+#define MemWrite(off1,off2,val)                          (*((volatile UINT32*)(UINTN)(UART_BASE_ADDR+(off1)+(off2)))=((UINT32)(val)))
+#define MemRead(off1,off2,v)                             ((*((volatile UINT32*)(UINTN)(UART_BASE_ADDR+(off1)+(off2))))&(v))
+#define MemReadMask(off1,k)                              MemRead(off1,k##_ADDR,k##_MASK)
+#define GENI4_CFG                                        0x0
+#define GENI4_IMAGE_REGS                                 0x100
+#define GENI4_DATA                                       0x600
+#define QUPV3_SE_DMA                                     0xC00
+#define GENI4_IMAGE                                      0x1000
+#define GENI_STATUS_ADDR                                 0x00000040
+#define GENI_S_IRQ_STATUS_ADDR                           0x00000040
+#define GENI_RX_FIFO_ADDR                                0x00000180
+#define GENI_TX_FIFO_STATUS_ADDR                         0x00000200
+#define GENI_RX_FIFO_STATUS_ADDR                         0x00000204
+#define SE_HW_PARAM_0_ADDR                               0x00000224
+#define GENI_STATUS_MASK                                 0x1fffff
+#define GENI_S_IRQ_STATUS_MASK                           0xfc07f3f
+#define GENI_RX_FIFO_MASK                                0xffffffff
+#define GENI_TX_FIFO_STATUS_MASK                         0xffffffff
+#define GENI_RX_FIFO_STATUS_MASK                         0xffffffff
+#define SE_HW_PARAM_0_MASK                               0x3f3f79ff
+#define GENI_M_CMD0_ADDR                                 0x00000000
+#define GENI_M_IRQ_EN_SET_ADDR                           0x0000001c
+#define GENI_M_IRQ_EN_CLEAR_ADDR                         0x00000020
+#define GENI_S_IRQ_CLEAR_ADDR                            0x00000048
+#define GENI_S_IRQ_EN_SET_ADDR                           0x0000004c
+#define GENI_S_IRQ_EN_CLEAR_ADDR                         0x00000050
+#define GENI_TX_FIFO_ADDR                                0x00000100
+#define UART_TX_TRANS_CFG_ADDR                           0x0000015c
+#define GENI_TX_PACKING_CFG0_ADDR                        0x00000160
+#define GENI_TX_PACKING_CFG1_ADDR                        0x00000164
+#define UART_TX_TRANS_LEN_ADDR                           0x00000170
+#define TX_FIFO_WC                                       0xfffffff
+#define RX_FIFO_WC                                       0x1ffffff
+#define RX_LAST_IRQ                                      0x8000000
+#define TX_FIFO_DEPTH_MASK                               0x3f0000
+#define TX_FIFO_DEPTH_SHIFT                              0x10
+#define TX_FIFO_WATERMARK_IRQ                            0x40000000
+#define RX_FIFO_WATERMARK_IRQ                            0x4000000
+#define RX_LAST_VALID_BYTES_MASK                         0x70000000
+#define RX_LAST_VALID_BYTES_SHIFT                        0x1c
+#define M_GENI_CMD_ACTIVE                                0x1
+#endif
diff --git a/sdm845Pkg/Library/QcomGeniSerialPortLib/QcomGeniSerialPortLib.c b/sdm845Pkg/Library/QcomGeniSerialPortLib/QcomGeniSerialPortLib.c
new file mode 100644 (file)
index 0000000..9ac2fc4
--- /dev/null
@@ -0,0 +1,111 @@
+#include <Base.h>
+#include <PiDxe.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/SerialPortLib.h>
+#include "GeniSerial.h"
+STATIC UINT32 ReadIndex=0,WriteIndex=0,TxFIFOSize=0;
+UINTN EFIAPI SerialPortRead(OUT UINT8*Buffer,IN UINTN Bytes){
+       CHAR8*ReadBuffer;
+       BOOLEAN Status;
+       STATIC UINT8 RxBuffer[255];
+       UINT8*Buff=Buffer;
+       UINT32 Room=Bytes,Copied=0,Avail=0,Num,WriteOffset,BytesRead,WordsRead,Index,FIFOStatus,Word,IRQStatus,AvailBytes;
+       while(1){
+               if(ReadIndex==WriteIndex)ReadIndex=WriteIndex=0;
+               if(sizeof(RxBuffer)-WriteIndex>4){
+                       ReadBuffer=(CHAR8*)(RxBuffer+WriteIndex);
+                       WriteOffset=0,BytesRead=0,WordsRead=0;
+                       MemWrite(GENI4_DATA,GENI_S_IRQ_EN_SET_ADDR,RX_LAST_IRQ|RX_FIFO_WATERMARK_IRQ);
+                       IRQStatus=MemReadMask(GENI4_DATA,GENI_S_IRQ_STATUS);
+                       FIFOStatus=MemReadMask(GENI4_DATA,GENI_RX_FIFO_STATUS);
+                       if(IRQStatus&(RX_LAST_IRQ|RX_FIFO_WATERMARK_IRQ)){
+                               BytesRead=(FIFOStatus&RX_LAST_VALID_BYTES_MASK)>>RX_LAST_VALID_BYTES_SHIFT;
+                               WordsRead=FIFOStatus&RX_FIFO_WC;
+                               if(BytesRead!=0&&BytesRead!=4)WordsRead-=1;
+                               else BytesRead=0;
+                       }
+                       AvailBytes=WordsRead*4+BytesRead;
+                       if(WriteOffset+AvailBytes>sizeof(RxBuffer)-WriteIndex){
+                               if(sizeof(RxBuffer)-WriteIndex-WriteOffset<4){
+                                       MemWrite(GENI4_DATA,GENI_S_IRQ_CLEAR_ADDR,IRQStatus);
+                                       MemWrite(GENI4_DATA,GENI_S_IRQ_EN_CLEAR_ADDR,RX_LAST_IRQ|RX_FIFO_WATERMARK_IRQ);
+                                       goto ok;
+                               }else{
+                                       WordsRead=((sizeof(RxBuffer)-WriteIndex-WriteOffset)&0x3)>>2;
+                                       BytesRead=0,AvailBytes=WordsRead*4;
+                               }
+                       }else MemWrite(GENI4_DATA,GENI_S_IRQ_CLEAR_ADDR,(IRQStatus&RX_LAST_IRQ));
+                       ReadBuffer+=WriteOffset;
+                       Status=(ReadBuffer-(CHAR8*)NULL)&0x03;
+                       for(Index=0;Index<WordsRead;Index++){
+                               Word=MemReadMask(GENI4_DATA,GENI_RX_FIFO);
+                               if(Status){
+                                       ReadBuffer[0]=(UINT8)(Word>>0),ReadBuffer[1]=(UINT8)(Word>>8);
+                                       ReadBuffer[2]=(UINT8)(Word>>16),ReadBuffer[3]=(UINT8)(Word>>24);
+                               }else *(UINT32*)ReadBuffer=Word;
+                               ReadBuffer+=4;
+                       }
+                       if(BytesRead){
+                               Word=MemReadMask(GENI4_DATA,GENI_RX_FIFO);
+                               for(Index=0;Index<BytesRead;Index++)ReadBuffer[Index]=(UINT8)(Word>>Index*8);
+                       }
+                       WriteOffset+=AvailBytes;
+                       MemWrite(GENI4_DATA,GENI_S_IRQ_CLEAR_ADDR,(IRQStatus&RX_FIFO_WATERMARK_IRQ));
+                       ok:WriteIndex+=WriteOffset;
+               }
+               Avail=ReadIndex<WriteIndex?WriteIndex-ReadIndex:0;
+               Num=Room<Avail?Room:Avail;
+               if(Num==0)break;
+               for(Index=0;Index<Num;Index++)*Buff++=RxBuffer[ReadIndex++&(sizeof(RxBuffer)-1)];
+               Copied+=Num,Room-=Num;
+       }
+       return Copied;
+}
+UINTN EFIAPI SerialPortWrite(IN UINT8*Buffer,IN UINTN Bytes){
+       UINT8*MsgBuff=Buffer;
+       UINT32 Slots,FIFOSize,WordValue,Index,WordsSend,BytesSend,Full,Partial;
+       UINTN BytesRemain=Bytes,Send;
+       FIFOSize=(MemReadMask(QUPV3_SE_DMA,SE_HW_PARAM_0)&TX_FIFO_DEPTH_MASK)>>TX_FIFO_DEPTH_SHIFT;
+       if(TxFIFOSize==0)TxFIFOSize=FIFOSize<<2;
+       while(BytesRemain>0){
+               Send=(BytesRemain>TxFIFOSize)?TxFIFOSize:BytesRemain;
+               if(MemReadMask(GENI4_CFG,GENI_STATUS)&M_GENI_CMD_ACTIVE)continue;
+               MemWrite(GENI4_IMAGE_REGS,UART_TX_TRANS_LEN_ADDR,Send);
+               MemWrite(GENI4_DATA,GENI_M_CMD0_ADDR,0x08000000);
+               if(Send){
+                       Full=Send>>2,Partial=Send&0x03;
+                       Slots=FIFOSize-(MemReadMask(GENI4_DATA,GENI_TX_FIFO_STATUS)&TX_FIFO_WC);
+                       WordsSend=Full>Slots?Slots:Full,BytesSend=Full>=Slots?0:Partial;
+                       BOOLEAN k=((CHAR8*)Buffer-(CHAR8*)NULL)&0x03;
+                       for(Index=0;Index<WordsSend;Index++){
+                               MemWrite(
+                                       GENI4_DATA,GENI_TX_FIFO_ADDR,(k?(
+                                               Buffer[0]<<0|Buffer[1]<<8|
+                                               Buffer[2]<<16|Buffer[3]<<24
+                                       ):(*(UINT32*)Buffer))
+                               );
+                               Buffer+=4;
+                       }
+                       if(BytesSend){
+                               WordValue=0;
+                               for(Index=0;Index<BytesSend;Index++)WordValue|=Buffer[Index]<<Index*8;
+                               MemWrite(GENI4_DATA,GENI_TX_FIFO_ADDR,WordValue);
+                       }
+                       MemWrite(
+                               GENI4_DATA,
+                               (Send==WordsSend*4+BytesSend)?
+                               GENI_M_IRQ_EN_CLEAR_ADDR:GENI_M_IRQ_EN_SET_ADDR,
+                               TX_FIFO_WATERMARK_IRQ
+                       );
+               }
+               MsgBuff+=Send,BytesRemain-=Send;
+       }
+       return Bytes;
+}
+UINTN EFIAPI SerialPortControl(IN UINTN Arg,IN UINTN Param){return 0;}
+BOOLEAN EFIAPI SerialPortPoll(VOID){return (MemReadMask(GENI4_DATA,GENI_S_IRQ_STATUS)&(RX_LAST_IRQ|RX_FIFO_WATERMARK_IRQ))||(WriteIndex-ReadIndex>0);}
+EFI_STATUS EFIAPI SerialPortSetAttributes(IN OUT UINT64*BaudRate,IN OUT UINT32*ReceiveFifoDepth,IN OUT UINT32*Timeout,IN OUT EFI_PARITY_TYPE*Parity,IN OUT UINT8*DataBits,IN OUT EFI_STOP_BITS_TYPE *StopBits){return EFI_UNSUPPORTED;}
+EFI_STATUS EFIAPI SerialPortGetControl(OUT UINT32*Control){return EFI_UNSUPPORTED;}
+EFI_STATUS EFIAPI SerialPortSetControl(IN UINT32 Control){return EFI_UNSUPPORTED;}
+EFI_STATUS EFIAPI SerialPortInitialize(VOID){return EFI_SUCCESS;}
diff --git a/sdm845Pkg/Library/QcomGeniSerialPortLib/QcomGeniSerialPortLib.inf b/sdm845Pkg/Library/QcomGeniSerialPortLib/QcomGeniSerialPortLib.inf
new file mode 100644 (file)
index 0000000..0e96c7e
--- /dev/null
@@ -0,0 +1,13 @@
+[Defines]
+  INF_VERSION    = 0x00010005
+  BASE_NAME      = QcomGeniSerialPortLib
+  MODULE_TYPE    = BASE
+  VERSION_STRING = 1.0
+  LIBRARY_CLASS  = SerialPortLib
+
+[Sources]
+  GeniSerial.h
+  QcomGeniSerialPortLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
index 99eb689f5bb72f3ce4392cc01b7e7cc8b23e935e..dfb2316d632d34fe2369f58b8e97e557a472e152 100644 (file)
@@ -34,7 +34,7 @@
   BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
 
 !if $(TARGET) != RELEASE
-  SerialPortLib|sdm845Pkg/Library/InMemorySerialPortLib/InMemorySerialPortLib.inf
+  SerialPortLib|sdm845Pkg/Library/QcomGeniSerialPortLib/QcomGeniSerialPortLib.inf
 !else
   SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
 !endif
   # SimpleFbDxe
   FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
 
-!if $(TARGET) != RELEASE
-  SerialPortLib|sdm845Pkg/Library/FrameBufferSerialPortLib/FrameBufferSerialPortLib.inf
-!endif
-
   PlatformBootManagerLib|sdm845Pkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
   MemoryInitPeiLib|sdm845Pkg/Library/MemoryInitPeiLib/PeiMemoryAllocationLib.inf
   PlatformPeiLib|sdm845Pkg/Library/PlatformPeiLib/PlatformPeiLib.inf