📄 core_sgpio.c
字号:
#include "core_header.h"#include "Spi_hal.h"#include "core_init.h"#ifdef SUPPORT_SGPIO#include "core_exp.h"#include "core_inter.h"#include "core_sgpio.h"#ifdef SUPPORT_ERROR_HANDLINGextern void Core_ReqTimeout (MV_PVOID This, MV_PVOID temp);#endifMV_U32 SGPIO_ReadRegister(PCore_Driver_Extension pCore, MV_U8 regAddress) { MV_U32 reg; reg=0; reg = MV_PCI_READ_DWORD( pCore, regAddress ); return reg;}void SGPIO_WriteRegister(PCore_Driver_Extension pCore, MV_U8 regAddress, MV_U32 regValue) { MV_PCI_WRITE_DWORD( pCore, regValue, regAddress ); return;}/** Known Hardware issues for the SGPIO on Odin:* 1. The clock frequency by default is 1 KHz. Changing clock frequency to 100KHz * (SGPIO spec uses 100KHz) could cause a phase shift that result in data being written on * the falling edge instead of rising edge. * Possible solution: Write to register of target multiple times until the desired data is* correctly written into the register.* 2. The SGPIO pins stated on the spec could be wrong. The following is the correct pin layout.*/voidSGPIO_SendSGPIOFrame(MV_PVOID This, MV_U32 value){ PCore_Driver_Extension pCore=(PCore_Driver_Extension)This; MV_U32 SGPIO_CtlReg; MV_U32 SGPIO_DataOut_L; MV_U32 SGPIO_DataOut_H; SGPIO_CtlReg = SGPIO_ReadRegister( pCore, SGPIO_Control ); MV_PRINT("* SGPIO_CtlReg before (start) = 0x%x \n", SGPIO_CtlReg ); SGPIO_DataOut_L = SGPIO_ReadRegister( pCore, SGPIO_Data_Out_L ); SGPIO_DataOut_H = SGPIO_ReadRegister( pCore, SGPIO_Data_Out_H ); MV_PRINT("SGPIO_DataOut_L before write (start) = 0x%x \n", SGPIO_DataOut_L ); MV_PRINT("SGPIO_DataOut_H before write (start) = 0x%x \n", SGPIO_DataOut_H ); SGPIO_WriteRegister( pCore, SGPIO_Data_Out_L, value); SGPIO_WriteRegister( pCore, SGPIO_Data_Out_H, 0x0); SGPIO_DataOut_L = SGPIO_ReadRegister( pCore, SGPIO_Data_Out_L ); SGPIO_DataOut_H = SGPIO_ReadRegister( pCore, SGPIO_Data_Out_H ); MV_PRINT("SGPIO_DataOut_L after write (start) = 0x%x \n", SGPIO_DataOut_L ); MV_PRINT("SGPIO_DataOut_H after write (start) = 0x%x \n", SGPIO_DataOut_H ); // Setup the desired SGPIO_Control register value SGPIO_CtlReg |= SGPIO_TRANSFER_LEN(64)|SGPIO_START_BIT; MV_PRINT("* 1 SGPIO_CtlReg going to be written into register (start) = 0x%x \n", SGPIO_CtlReg ); // Write to SGPIO_Control register and start data transfer SGPIO_WriteRegister( pCore, SGPIO_Control, SGPIO_CtlReg); SGPIO_CtlReg = SGPIO_ReadRegister( pCore, SGPIO_Control ); MV_PRINT("* SGPIO_CtlReg what is in the register now (start) = 0x%x \n", SGPIO_CtlReg );}voidSGPIO_StopSGPIOFrame(MV_PVOID This, MV_U32 value){ PCore_Driver_Extension pCore=(PCore_Driver_Extension)This; MV_U32 SGPIO_CtlReg; MV_PRINT(" \n"); SGPIO_CtlReg = SGPIO_ReadRegister( pCore, SGPIO_Control ); MV_PRINT("* SGPIO_CtlReg first (stop) = 0x%x \n", SGPIO_CtlReg ); SGPIO_WriteRegister( pCore, SGPIO_Data_Out_L, value); SGPIO_WriteRegister( pCore, SGPIO_Data_Out_H, value); SGPIO_CtlReg &= ~SGPIO_START_BIT; MV_PRINT("* SGPIO_CtlReg middle (stop) = 0x%x \n", SGPIO_CtlReg ); SGPIO_WriteRegister( pCore, SGPIO_Control, SGPIO_CtlReg); SGPIO_CtlReg = SGPIO_ReadRegister( pCore, SGPIO_Control ); MV_PRINT("* SGPIO_CtlReg last (stop) = 0x%x \n", SGPIO_CtlReg );} void SGPIO_Initialize( MV_PVOID This ) { PCore_Driver_Extension pCore=(PCore_Driver_Extension)This; MV_U32 SGPIO_InitReg=0; MV_U32 SGPIO_CtlReg=0; SGPIO_InitReg = SGPIO_ReadRegister( pCore, SGPIO_Init ); MV_PRINT("* SGPIO_InitReg before initialization = 0x%x \n", SGPIO_InitReg ); // Set mode to SGPIO mode SGPIO_InitReg |= SGPIO_Mode; // The following lines setup the desired clock frequency in SGPIO_Control register // before clk is started by SGPIO_Init. Allowing clk to switch frequency during run-time // could result in writing on the wrong edge of the clk. SGPIO_CtlReg |= SGPIO_SELECT_SPEED(SGPIO_100KHz); MV_PRINT("* 0 SGPIO_CtlReg going to be written into register (start) = 0x%x \n", SGPIO_CtlReg ); SGPIO_WriteRegister( pCore, SGPIO_Control, SGPIO_CtlReg ); // Clock starts once SGPIO mode is set and written to register. SGPIO_WriteRegister( pCore, SGPIO_Init, SGPIO_InitReg ); SGPIO_InitReg = SGPIO_ReadRegister( pCore, SGPIO_Init ); MV_PRINT("* SGPIO_InitReg after initialization = 0x%x \n", SGPIO_InitReg );}/* used to send out test signals of the SGPIO. Currently capable of sending data through DataOut */void SGPIOtest(MV_PVOID This){ PCore_Driver_Extension pCore=(PCore_Driver_Extension)This; SGPIO_Initialize( pCore ); SGPIO_SendSGPIOFrame(This,0x249); DelayMSec(5000); SGPIO_StopSGPIOFrame(This,0);}void SGPIO_SMPReq_Callback( IN PCore_Driver_Extension pCore, IN PMV_Request pReq ){ MV_U8 portId, TgtId; struct _Domain_Expander *pTgt; struct SMPResponse *pSMPResp; PDomain_Port pPort; PDomain_SGPIO SGPIO_Result = &pCore->SGPIO_Result; portId = MapTgtPortId(pCore, pReq->Device_Id); pPort = &pCore->Ports[MapPortEntry(pCore,portId)]; pSMPResp= (struct SMPResponse *)pReq->Scratch_Buffer; /*TgtId = (MV_U8)pReq->Device_Id; pTgt= &pCore->Expanders[MapTgtId(pCore, pReq->Device_Id)]; pSMPResp= (struct SMPResponse *)pReq->Data_Buffer; MV_PRINT("SMP Function 0x%x Done For Port[0x%x].Target[0x%x] " "Result 0x%x\n", pSMPResp->Function, portId, TgtId, pSMPResp->FunctionResult);*/ switch(pSMPResp->Function) { case READ_GPIO_REGISTER: MV_PRINT("Read GPIO Register Response: \n"); MV_PRINT("Data In High 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", pSMPResp->Response.ReadGPIORegister.Data_In_High[0], pSMPResp->Response.ReadGPIORegister.Data_In_High[1], pSMPResp->Response.ReadGPIORegister.Data_In_High[2], pSMPResp->Response.ReadGPIORegister.Data_In_High[3], pSMPResp->Response.ReadGPIORegister.Data_In_High[4], pSMPResp->Response.ReadGPIORegister.Data_In_High[5], pSMPResp->Response.ReadGPIORegister.Data_In_High[6], pSMPResp->Response.ReadGPIORegister.Data_In_High[7]); MV_PRINT("Data In Low 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", pSMPResp->Response.ReadGPIORegister.Data_In_Low[0], pSMPResp->Response.ReadGPIORegister.Data_In_Low[1], pSMPResp->Response.ReadGPIORegister.Data_In_Low[2], pSMPResp->Response.ReadGPIORegister.Data_In_Low[3], pSMPResp->Response.ReadGPIORegister.Data_In_Low[4], pSMPResp->Response.ReadGPIORegister.Data_In_Low[5], pSMPResp->Response.ReadGPIORegister.Data_In_Low[6], pSMPResp->Response.ReadGPIORegister.Data_In_Low[7]); break; case WRITE_GPIO_REGISTER: MV_PRINT("Receive Write GPIO Register Response: \n"); break; } MV_CopyMemory(SGPIO_Result, pReq->Scratch_Buffer, sizeof(pReq->Scratch_Buffer) ); if( pReq->Scratch_Buffer ) FreeSMPScratchToPool( pCore, (PSMP_Scratch_Buffer)pReq->Scratch_Buffer ); FreeInternalReqToPool( pCore, pReq );}void SGPIO_SMPRequest_Read( IN PCore_Driver_Extension pCore, IN PMV_Request pReq ){ PSMP_Scratch_Buffer pSMPSB; struct SMPRequest *pSMPReq; PMV_SG_Table pSGTable; if( pReq == NULL ) { MV_DPRINT(("ERROR: No more free internal requests. Request aborted.\n")); return; } pSMPSB = GetSMPScratchFromPool(pCore); if( pSMPSB == NULL ) { MV_DPRINT(("ERROR: No more free SMP scratch buffer. Request aborted.\n")); return; } pSGTable = &pReq->SG_Table; /* Prepare identify ATA task */ pReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC; pReq->Cdb[1] = CDB_CORE_MODULE; pReq->Cdb[2] = CDB_CORE_SMP; pReq->Tag = 0xbb; pReq->Device_Id = 0xFFFF; // Indicating SGPIO operation //pReq->Req_Flag; pReq->Cmd_Initiator = pCore; pReq->Data_Transfer_Length = sizeof(struct SMPRequest); pReq->Data_Buffer = &pSMPSB->SMP_Req; pReq->Scratch_Buffer = pSMPSB; pSMPReq=(struct SMPRequest *)pReq->Data_Buffer; pSMPReq->Function=READ_GPIO_REGISTER; pSMPReq->SMPFrameType=SMP_REQUEST_FRAME; pReq->Completion = (void(*)(MV_PVOID,PMV_Request))SGPIO_SMPReq_Callback; /* Make SG table */ SGTable_Init(pSGTable, 0); /* Send this internal request */ Core_ModuleSendRequest(pCore, pReq);}void SGPIO_SMPRequest_Write( IN PCore_Driver_Extension pCore ){ PMV_Request pReq = GetInternalReqFromPool(pCore); PSMP_Scratch_Buffer pSMPSB; struct SMPRequest *pSMPReq; PMV_SG_Table pSGTable; if( pReq == NULL ) { MV_DPRINT(("ERROR: No more free internal requests. Request aborted.\n")); return; } pSMPSB = GetSMPScratchFromPool(pCore); if( pSMPSB == NULL ) { MV_DPRINT(("ERROR: No more free SMP scratch buffer. Request aborted.\n")); return; } pSGTable = &pReq->SG_Table; /* Prepare identify ATA task */ pReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC; pReq->Cdb[1] = CDB_CORE_MODULE; pReq->Cdb[2] = CDB_CORE_SMP; pReq->Tag = 0xbb; pReq->Device_Id = 0xFFFF; // Indicating SGPIO operation //pReq->Req_Flag; pReq->Cmd_Initiator = pCore; pReq->Data_Transfer_Length = sizeof(struct SMPRequest); pReq->Data_Buffer = &pSMPSB->SMP_Req; pReq->Scratch_Buffer = pSMPSB; pSMPReq=(struct SMPRequest *)pReq->Data_Buffer; pSMPReq->Function=WRITE_GPIO_REGISTER; pSMPReq->SMPFrameType=SMP_REQUEST_FRAME; pReq->Completion = (void(*)(MV_PVOID,PMV_Request))SGPIO_SMPReq_Callback; /* Make SG table */ SGTable_Init(pSGTable, 0); /* Send this internal request */ Core_ModuleSendRequest(pCore, pReq);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -