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