add Qualcomm GENI SerialPortLib

This commit is contained in:
BigfootACA 2022-02-05 20:19:32 +08:00
parent 95968d21ab
commit 798f7cc778
4 changed files with 172 additions and 5 deletions

View File

@ -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

View File

@ -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;}

View File

@ -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

View 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
@ -78,10 +78,6 @@
# 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