blob: 33e6e74d6b9f25cb677e91eff0a75d14b0c77dad [file] [log] [blame]
#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