#include "proslic_api_config.h" | |
#include "spi.h" | |
#define SI_OPEN_FAIL -1 | |
#ifdef TARGET_mmp_asr1901 | |
#define SI_SPI_BASE_DEV "/dev/spidev2.0" | |
#else | |
#define SI_SPI_BASE_DEV "/dev/spidev1.0" | |
#endif | |
/* | |
** Function: SPI_Init | |
** | |
** Description: | |
** Initializes the SPI interface | |
** | |
** Input Parameters: | |
** none | |
** | |
** Return: | |
** none | |
*/ | |
int SPI_Init (si_hctrl_t * hSpi){ | |
int ret; | |
ret= si_setup_spi(hSpi); | |
return ret; | |
} | |
/* | |
** Function: spiGci_ResetWrapper | |
** | |
** Description: | |
** Sets the reset pin of the ProSLIC | |
*/ | |
int ctrl_ResetWrapper (void * hSpiGci, int status){ | |
if( (hSpiGci != NULL) && (((si_hctrl_t *)hSpiGci)->spi_fd[0] != SI_OPEN_FAIL)) | |
{ | |
if(status == 1) /* Put the device(s) in reset */ | |
{ | |
//system("echo reset 0 > /sys/devices/nz3-slic/ctrl"); | |
system("cd /sys/devices/platform/nz3-slic* && echo reset 0 > ctrl"); | |
} | |
else | |
{ | |
//system("echo reset 1 > /sys/devices/nz3-slic/ctrl"); | |
system("cd /sys/devices/platform/nz3-slic* && echo reset 1 > ctrl"); | |
} | |
} | |
return( RC_UNSUPPORTED_FEATURE); | |
return 0; | |
} | |
/* | |
** SPI/GCI register read | |
** | |
** Description: | |
** Reads a single ProSLIC register | |
** | |
** Input Parameters: | |
** channel: ProSLIC channel to read from | |
** num: number of reads to perform | |
** regAddr: Address of register to read | |
** addr_inc: whether to increment address after each read | |
** data: data to read from register | |
** | |
** Return: | |
** none | |
*/ | |
#define SI_BCAST_MODE 0xFF /* This is used for broadcast writes */ | |
#define CHAN_NUM_TO_CID(c) ((((c) << 4) & 0x10) | \ | |
(((c) << 2) & 0x8) | \ | |
(((c) >> 2) & 0x2) | \ | |
(((c) >> 4) & 0x1) | \ | |
((c) & 0x4)) | |
uInt8 ctrl_ReadRegisterWrapper (void * hSpiGci, uInt8 channel,uInt8 regAddr){ | |
uInt8 buf[3]; | |
uInt8 data; | |
memset(buf, 0, sizeof(buf)); | |
if( (hSpiGci != NULL) && (((si_hctrl_t *)hSpiGci)->spi_fd[channel/CHAN_PER_DEVICE] != SI_OPEN_FAIL)) | |
{ | |
/* Convert channel to CID and or in the read bit */ | |
buf[0] = CHAN_NUM_TO_CID(channel) | 0x60; | |
buf[1] = regAddr; | |
write(((si_hctrl_t *)hSpiGci)->spi_fd[channel], &buf[0], 1); | |
write(((si_hctrl_t *)hSpiGci)->spi_fd[channel], &buf[1], 1); | |
read(((si_hctrl_t *)hSpiGci)->spi_fd[channel],&data,1); | |
return(data); | |
} | |
return(0); /* There is no error code to pass back in this case */ | |
} | |
/* | |
** Function: spiGci_WriteRegisterWrapper | |
** | |
** Description: | |
** Writes a single ProSLIC register | |
** | |
** Input Parameters: | |
** channel: ProSLIC channel to write to | |
** address: Address of register to write | |
** data: data to write to register | |
** | |
** Return: | |
** none | |
*/ | |
int ctrl_WriteRegisterWrapper (void * hSpiGci, uInt8 channel, uInt8 regAddr, uInt8 data){ | |
uInt8 buf[3]; | |
memset(buf, 0, sizeof(buf)); | |
if( (hSpiGci != NULL) && (((si_hctrl_t *)hSpiGci)->spi_fd[channel] != SI_OPEN_FAIL)) | |
{ | |
if(channel == SI_BCAST_MODE) | |
{ | |
/* This is valid for Si3217x, Si324x and 3226x */ | |
buf[0] = 0xA0; /* set the bcast and reg bits */ | |
} | |
else | |
{ | |
buf[0] = CHAN_NUM_TO_CID(channel)|0x20; | |
} | |
buf[1] = regAddr; | |
buf[2] = data; | |
write(((si_hctrl_t *)hSpiGci)->spi_fd[channel], &buf[0], 1); | |
write(((si_hctrl_t *)hSpiGci)->spi_fd[channel], &buf[1], 1); | |
write(((si_hctrl_t *)hSpiGci)->spi_fd[channel], &buf[2], 1); | |
} | |
return( RC_UNSUPPORTED_FEATURE); | |
return 0; | |
} | |
/* | |
** Function: SPI_ReadRAMWrapper | |
** | |
** Description: | |
** Reads a single ProSLIC RAM location | |
** | |
** Input Parameters: | |
** channel: ProSLIC channel to read from | |
** address: Address of RAM location to read | |
** pData: data to read from RAM location | |
** | |
** Return: | |
** none | |
*/ | |
#define RAM_STAT_REG 4 | |
#define RAM_ADDR_HI_REG 5 | |
#define RAM_DATA_B0_REG 6 | |
#define RAM_DATA_B1_REG 7 | |
#define RAM_DATA_B2_REG 8 | |
#define RAM_DATA_B3_REG 9 | |
#define RAM_ADDR_LO_REG 10 | |
#define RAM_ADDR_HI(X) (((X)>>3)&0xE0) | |
#define SI_MAX_RAMWAIT 1000 | |
static int ctrl_ramWait(void *hCtrl, uInt8 channel) | |
{ | |
uInt8 data; | |
int countdown = SI_MAX_RAMWAIT; | |
do | |
{ | |
data = ctrl_ReadRegisterWrapper(hCtrl,channel, RAM_STAT_REG); | |
if(data & 0x1) | |
{ | |
time_DelayWrapper(NULL,1); /* Sleep 1 mSec to avoid busy polling*/ | |
} | |
}while((data&0x1) && (countdown--)); | |
if(countdown > 0) | |
{ | |
return(RC_NONE); | |
} | |
else | |
{ | |
LOGPRINT("Proslic: RAM interface gets busy, status: 0x%x\n",data); | |
return(RC_UNSUPPORTED_FEATURE); | |
} | |
} | |
uInt32 ctrl_ReadRAMWrapper (void * hSpiGci, uInt8 channel, uInt16 ramAddr){ | |
ramData rd_buf; | |
if(ctrl_ramWait(hSpiGci,channel) == RC_NONE) | |
{ | |
ctrl_WriteRegisterWrapper(hSpiGci,channel,RAM_ADDR_HI_REG,RAM_ADDR_HI(ramAddr)); | |
ctrl_WriteRegisterWrapper(hSpiGci,channel,RAM_ADDR_LO_REG,ramAddr&0xff); | |
/* Wait for the data to be valid prior to reading it */ | |
if( ctrl_ramWait(hSpiGci, channel) != RC_NONE) | |
{ | |
return(0); | |
} | |
rd_buf = (ctrl_ReadRegisterWrapper(hSpiGci,channel,RAM_DATA_B0_REG) >> 3) & 0x0000001FL; | |
rd_buf |= ((((ramData )ctrl_ReadRegisterWrapper(hSpiGci,channel,RAM_DATA_B1_REG))<<5) & 0x000001FE0L); | |
rd_buf |= ((((ramData )ctrl_ReadRegisterWrapper(hSpiGci,channel,RAM_DATA_B2_REG))<<13) & 0x0001FE000L); | |
rd_buf |= ((((ramData )ctrl_ReadRegisterWrapper(hSpiGci,channel,RAM_DATA_B3_REG))<<21) & 0x1FE00000L); | |
return(rd_buf); | |
} | |
return(0); | |
} | |
/* | |
** Function: SPI_WriteRAMWrapper | |
** | |
** Description: | |
** Writes a single ProSLIC RAM location | |
** | |
** Input Parameters: | |
** channel: ProSLIC channel to write to | |
** address: Address of RAM location to write | |
** data: data to write to RAM location | |
** | |
** Return: | |
** none | |
*/ | |
int ctrl_WriteRAMWrapper (void * hSpiGci, uInt8 channel, uInt16 ramAddr, ramData data){ | |
if( (hSpiGci == NULL) || (((si_hctrl_t *)hSpiGci)->spi_fd[channel] == 0)) | |
{ | |
return( RC_UNSUPPORTED_FEATURE); | |
} | |
if (channel == SI_BCAST_MODE) | |
{ | |
if(ctrl_ramWait(hSpiGci,0) != RC_NONE) | |
{ | |
return( RC_UNSUPPORTED_FEATURE ); | |
} | |
} | |
else | |
{ | |
if(ctrl_ramWait(hSpiGci,channel) != RC_NONE) | |
{ | |
return( RC_UNSUPPORTED_FEATURE ); | |
} | |
} | |
ctrl_WriteRegisterWrapper(hSpiGci,channel,RAM_ADDR_HI_REG,RAM_ADDR_HI(ramAddr)); | |
ctrl_WriteRegisterWrapper(hSpiGci,channel,RAM_DATA_B0_REG,(data<<3)&0x000000F8L); | |
ctrl_WriteRegisterWrapper(hSpiGci,channel,RAM_DATA_B1_REG,(data>>5)&0xFF); | |
ctrl_WriteRegisterWrapper(hSpiGci,channel,RAM_DATA_B2_REG,(data>>13)&0xFF); | |
ctrl_WriteRegisterWrapper(hSpiGci,channel,RAM_DATA_B3_REG,(data>>21)&0xFF); | |
ctrl_WriteRegisterWrapper(hSpiGci,channel,RAM_ADDR_LO_REG,ramAddr&0xff); | |
return(RC_NONE); | |
} | |
int si_setup_spi(si_hctrl_t *hCtrl) | |
{ | |
int i; | |
char dev_name[20]; | |
for(i = 0; i < NUMBER_OF_SPI_FD; i++) | |
{ | |
sprintf(dev_name,"%s",SI_SPI_BASE_DEV); | |
hCtrl->spi_fd[i] = open(dev_name,O_RDWR,0); | |
if(hCtrl->spi_fd[i] == SI_OPEN_FAIL) | |
{ | |
return(RC_UNSUPPORTED_FEATURE); | |
} | |
} | |
memset(&(hCtrl->mutex),0,sizeof(pthread_mutex_t)); | |
return(RC_NONE);} | |
/* Deallocate any resources for the Silabs system Interfaces */ | |
int si_teardown_spi(si_hctrl_t *hCtrl) | |
{ | |
int i; | |
for(i = 0; i < NUMBER_OF_SPI_FD; i++) | |
{ | |
close(hCtrl->spi_fd[i]); | |
} | |
return(RC_NONE); | |
} | |
#if 0 | |
int test_spi() | |
{ | |
int fd; | |
char dev_name[20]; | |
si_hctrl_t hw_ctrl; | |
unsigned char reg_data; | |
int ret; | |
unsigned int i; | |
ramData ramValue = 0xff; | |
sprintf(dev_name,"%s",SI_SPI_BASE_DEV); | |
fd = open(dev_name,O_RDWR); | |
if(fd == SI_OPEN_FAIL) | |
{ | |
printf("open device %s error\n", dev_name); | |
return(RC_UNSUPPORTED_FEATURE); | |
} | |
hw_ctrl.spi_fd[0] = fd; | |
while(1) | |
{ | |
for(i = 0; i < 0xff; i++) | |
{ | |
ctrl_WriteRegisterWrapper(&hw_ctrl, 0, 14, i); | |
usleep(3000); | |
reg_data = ctrl_ReadRegisterWrapper(&hw_ctrl, 0, 14); | |
printf("write 14 = %x\n", i); | |
printf("read 14 = %x\n", reg_data); | |
if(reg_data != i) | |
{ | |
printf("error i=%x, reg_data=%x\n", i, reg_data); | |
break; | |
} | |
} | |
if(reg_data != (i-1)) | |
{ | |
printf("not same i=%x, reg_data=%x\n", i, reg_data); | |
break; | |
} | |
} | |
//return; | |
while(1) | |
{ | |
for(i = 0; i < 0xff; i++) | |
{ | |
ret = ctrl_WriteRAMWrapper(&hw_ctrl, 0, 0x0, i); | |
if(ret != RC_NONE) | |
{ | |
printf("write ram error\n"); | |
break; | |
} | |
usleep(3000); | |
ramValue = ctrl_ReadRAMWrapper(&hw_ctrl, 0, 0x0); | |
printf("write ram = %x\n", i); | |
printf("read ram = %x\n", ramValue); | |
if(ramValue != i) | |
{ | |
printf("error i=%x, ramValue=%x\n", i, ramValue); | |
break; | |
} | |
} | |
if(ramValue != (i-1)) | |
{ | |
printf("not same i=%x, ramValue=%x\n", i, ramValue); | |
break; | |
} | |
} | |
close(fd); | |
return 0; | |
} | |
#endif | |