You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
398 lines
9.9 KiB
398 lines
9.9 KiB
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
#define SPI_SUCCESS 0
|
|
#define SPI_FAIL -1
|
|
|
|
typedef struct {
|
|
uint32_t ch;
|
|
int32_t handle;
|
|
}spi_property_desc;
|
|
|
|
typedef void *HANDLE;
|
|
|
|
#define HI_SPI_NODE_PATH "/dev/soc_spi"
|
|
|
|
#define MAX_CH 2
|
|
|
|
#define SPI_HANDLE(handle) ((spi_property_desc *)handle)
|
|
|
|
typedef struct {
|
|
uint8_t dev_id;
|
|
uint8_t *s_data;
|
|
uint32_t s_data_cnt;
|
|
} spi_data_s;
|
|
|
|
typedef struct {
|
|
uint8_t dev_id;
|
|
uint32_t s_data;
|
|
uint32_t s_data_cnt;
|
|
} spi_data_compat_s;
|
|
|
|
typedef struct {
|
|
uint8_t dev_id;
|
|
uint8_t *s_data;
|
|
uint32_t s_data_cnt;
|
|
uint8_t *r_data;
|
|
uint32_t r_data_cnt;
|
|
} spi_dataex_s;
|
|
|
|
typedef struct {
|
|
uint8_t dev_id;
|
|
uint32_t s_data;
|
|
uint32_t s_data_cnt;
|
|
uint32_t r_data;
|
|
uint32_t r_data_cnt;
|
|
} spi_dataex_compat_s;
|
|
|
|
typedef struct {
|
|
uint8_t dev_id;
|
|
uint8_t mode;
|
|
uint8_t spo;
|
|
uint8_t sph;
|
|
uint8_t dss;
|
|
uint8_t cscfg;
|
|
} spi_fform_s;
|
|
|
|
typedef struct {
|
|
uint8_t dev_id;
|
|
uint32_t set_bend;
|
|
} spi_blend_s;
|
|
|
|
typedef struct {
|
|
uint8_t dev_id;
|
|
uint8_t set_loop;
|
|
} spi_loop_s;
|
|
|
|
#define MAX_SPI_CHANNEL 4
|
|
|
|
#define SOC_ID_SPI 23
|
|
|
|
#define CMD_SPI_READ _IOWR(SOC_ID_SPI, 0x1, spi_data_s)
|
|
#define CMD_COMPAT_SPI_READ _IOWR(SOC_ID_SPI, 0x1, spi_data_compat_s)
|
|
#define CMD_SPI_WRITE _IOWR(SOC_ID_SPI, 0x2, spi_data_s)
|
|
#define CMD_COMPAT_SPI_WRITE _IOWR(SOC_ID_SPI, 0x2, spi_data_compat_s)
|
|
#define CMD_SPI_SET_ATTR _IOWR(SOC_ID_SPI, 0x3, spi_fform_s)
|
|
#define CMD_SPI_GET_ATTR _IOWR(SOC_ID_SPI, 0x4, spi_fform_s)
|
|
#define CMD_SPI_OPEN _IOW (SOC_ID_SPI, 0x5, uint32_t)
|
|
#define CMD_SPI_CLOSE _IOW (SOC_ID_SPI, 0x6, uint32_t)
|
|
#define CMD_SPI_SET_BLEND _IOWR(SOC_ID_SPI, 0x7, spi_blend_s)
|
|
#define CMD_SPI_GET_BLEND _IOWR(SOC_ID_SPI, 0x8, spi_blend_s)
|
|
#define CMD_SPI_SET_CLK _IOW (SOC_ID_SPI, 0x9, uint32_t)
|
|
#define CMD_SPI_READEX _IOWR(SOC_ID_SPI, 0xa, spi_dataex_s)
|
|
#define CMD_COMPAT_SPI_READEX _IOWR(SOC_ID_SPI, 0xa, spi_dataex_compat_s)
|
|
#define CMD_SPI_SET_LOOP _IOW (SOC_ID_SPI, 0xb, spi_loop_s)
|
|
#define CMD_SPI_RW_LOOP _IOWR(SOC_ID_SPI, 0xc, spi_dataex_s)
|
|
#define CMD_COMPAT_SPI_RW_LOOP _IOWR(SOC_ID_SPI, 0xc, spi_dataex_compat_s)
|
|
|
|
HANDLE spi_init(uint32_t ch)
|
|
{
|
|
spi_property_desc *handle = malloc(sizeof(spi_property_desc));
|
|
if(handle == NULL) return NULL;
|
|
|
|
handle->handle = open(HI_SPI_NODE_PATH, O_RDWR,0);
|
|
if(handle->handle < 0)
|
|
{
|
|
printf("open dev %s fail.errno:%d,errstr:%s\n",HI_SPI_NODE_PATH,errno,strerror(errno));
|
|
free(handle);
|
|
return NULL;
|
|
}
|
|
|
|
if(ch >= MAX_CH)
|
|
{
|
|
printf("spi init fail. ch:%d is invalid\n",ch);
|
|
close(handle->handle);
|
|
free(handle);
|
|
return NULL;
|
|
}
|
|
|
|
handle->ch = ch;
|
|
|
|
if(ioctl(handle->handle, CMD_SPI_OPEN, ch)!=0)
|
|
{
|
|
printf("spi init fail. open spi%d fail.errno:%d,errstr:%s\n",ch,errno,strerror(errno));
|
|
close(handle->handle);
|
|
free(handle);
|
|
return NULL;
|
|
}
|
|
|
|
spi_fform_s fform = {0};
|
|
fform.dev_id = ch;
|
|
fform.mode = 0;
|
|
fform.spo = 0;
|
|
fform.sph = 1;
|
|
fform.dss = 16;
|
|
fform.cscfg = 0;
|
|
if(ioctl(handle->handle, CMD_SPI_SET_ATTR, &fform)!=0)
|
|
{
|
|
printf("spi init fail. open spi%d set attr fail.errno:%d,errstr:%s\n",ch,errno,strerror(errno));
|
|
close(handle->handle);
|
|
free(handle);
|
|
return NULL;
|
|
}
|
|
|
|
spi_blend_s bigend = {0};
|
|
bigend.dev_id = ch;
|
|
bigend.set_bend = 1;
|
|
|
|
if(ioctl(handle->handle, CMD_SPI_SET_BLEND, &bigend)!=0)
|
|
{
|
|
printf("spi init fail. open spi%d set blend fail.errno:%d,errstr:%s\n",ch,errno,strerror(errno));
|
|
close(handle->handle);
|
|
free(handle);
|
|
return NULL;
|
|
}
|
|
|
|
return handle;
|
|
}
|
|
|
|
void spi_deinit(HANDLE handle)
|
|
{
|
|
if(handle == NULL) return;
|
|
|
|
ioctl(SPI_HANDLE(handle)->handle, CMD_SPI_CLOSE, SPI_HANDLE(handle)->ch);
|
|
|
|
close(SPI_HANDLE(handle)->handle);
|
|
free(handle);
|
|
handle = NULL;
|
|
}
|
|
|
|
int8_t spi_read(HANDLE handle,uint8_t *data,uint32_t len)
|
|
{
|
|
if(handle == NULL) return -1;
|
|
|
|
spi_data_s spi_data = {0};
|
|
spi_data.dev_id = SPI_HANDLE(handle)->ch;
|
|
spi_data.s_data = data;
|
|
spi_data.s_data_cnt = len;
|
|
|
|
if(ioctl(SPI_HANDLE(handle)->handle,CMD_SPI_READ,&data) != 0)
|
|
{
|
|
printf("spi read fail.errno:%d,errstr:%s\n",errno,strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int8_t spi_write(HANDLE handle,uint8_t *data,uint32_t len)
|
|
{
|
|
if(handle == NULL) return -1;
|
|
|
|
spi_data_s spi_data = {0};
|
|
spi_data.dev_id = SPI_HANDLE(handle)->ch;
|
|
spi_data.s_data = data;
|
|
spi_data.s_data_cnt = len;
|
|
|
|
if(ioctl(SPI_HANDLE(handle)->handle,CMD_SPI_WRITE,&data) != 0)
|
|
{
|
|
printf("spi write fail.errno:%d,errstr:%s\n",errno,strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int8_t spi_transmit(HANDLE handle,uint8_t *w_data,uint32_t w_len,uint8_t *r_data,uint32_t r_len)
|
|
{
|
|
if(handle == NULL) return -1;
|
|
|
|
spi_dataex_s data = {0};
|
|
data.dev_id = SPI_HANDLE(handle)->ch;
|
|
data.s_data = w_data;
|
|
data.s_data_cnt = w_len;
|
|
data.r_data = r_data;
|
|
data.r_data_cnt = r_len;
|
|
|
|
if(ioctl(SPI_HANDLE(handle)->handle,CMD_SPI_READEX,&data) != 0)
|
|
{
|
|
printf("spi transmit fail.errno:%d,errstr:%s\n",errno,strerror(errno));
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//spi_ctl 0 type
|
|
|
|
void PrintUsage()
|
|
{
|
|
printf("Usage: spi_ctl <ch> <type>\n");
|
|
printf("\t type r:<read_number>\n");
|
|
printf("\t type w:<write_number> <write_data0> <write_data n>\n");
|
|
printf("\t type t:<write_number> <read_number> <write_data0> <write_data n>\n");
|
|
}
|
|
|
|
#define CMD_TYPE_R "r"
|
|
#define CMD_TYPE_W "w"
|
|
#define CMD_TYPE_T "t"
|
|
|
|
int main(int argc,char **argv)
|
|
{
|
|
if(argc < 2)
|
|
{
|
|
printf("invalid parameter.\n");
|
|
PrintUsage();
|
|
return 0;
|
|
}
|
|
uint32_t ch =(uint32_t)strtol(argv[1], NULL, 0);
|
|
HANDLE handle = spi_init(ch);
|
|
|
|
if(handle == NULL)
|
|
return 0;
|
|
|
|
char *type = argv[2];
|
|
if(strcmp(type,CMD_TYPE_R)==0)
|
|
{
|
|
if(argc < 3)
|
|
{
|
|
printf("invalid parameter.\n");
|
|
PrintUsage();
|
|
spi_deinit(handle);
|
|
return 0;
|
|
}
|
|
|
|
uint32_t r_len = (uint32_t)strtol(argv[3], NULL, 0);
|
|
|
|
uint8_t *r_data = (uint8_t *)malloc(r_len);
|
|
if(r_data == NULL)
|
|
{
|
|
printf("malloc r_data size %d fail.\n",r_len);
|
|
PrintUsage();
|
|
spi_deinit(handle);
|
|
return 0;
|
|
}
|
|
|
|
memset(r_data,0,r_len);
|
|
|
|
if(spi_read(handle,r_data,r_len)!=SPI_SUCCESS)
|
|
{
|
|
free(r_data);
|
|
PrintUsage();
|
|
spi_deinit(handle);
|
|
|
|
printf("recv bytes:\n");
|
|
for(int i=0;i<r_len;i++) printf("<0x%02X>",r_data[i]);
|
|
printf("\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
printf("recv bytes:\n");
|
|
for(int i=0;i<r_len;i++) printf("<0x%02X>",r_data[i]);
|
|
printf("\n");
|
|
free(r_data);
|
|
|
|
}
|
|
else if(strcmp(type,CMD_TYPE_W)==0)
|
|
{
|
|
if(argc < 3)
|
|
{
|
|
printf("invalid parameter.\n");
|
|
PrintUsage();
|
|
spi_deinit(handle);
|
|
return 0;
|
|
}
|
|
|
|
uint32_t w_len = (uint32_t)strtol(argv[3], NULL, 0);
|
|
|
|
uint8_t *w_data = (uint8_t *)malloc(w_len);
|
|
if(w_data == NULL)
|
|
{
|
|
printf("malloc w_data size %d fail.\n",w_len);
|
|
PrintUsage();
|
|
spi_deinit(handle);
|
|
return 0;
|
|
}
|
|
|
|
memset(w_data,0,w_len);
|
|
|
|
for(int i=0;i<w_len;i++) w_data[i] = (uint8_t)strtol(argv[4+i], NULL, 0);
|
|
|
|
if(spi_write(handle,w_data,w_len)!=SPI_SUCCESS)
|
|
{
|
|
free(w_data);
|
|
PrintUsage();
|
|
spi_deinit(handle);
|
|
return 0;
|
|
}
|
|
|
|
printf("spi%d write data success.\n",ch);
|
|
|
|
free(w_data);
|
|
}
|
|
else if(strcmp(type,CMD_TYPE_T)==0)
|
|
{
|
|
if(argc < 4)
|
|
{
|
|
printf("invalid parameter.\n");
|
|
PrintUsage();
|
|
spi_deinit(handle);
|
|
return 0;
|
|
}
|
|
|
|
uint32_t w_len = (uint32_t)strtol(argv[3], NULL, 0);
|
|
uint32_t r_len = (uint32_t)strtol(argv[4], NULL, 0);
|
|
|
|
uint8_t *w_data = (uint8_t *)malloc(w_len);
|
|
if(w_data == NULL)
|
|
{
|
|
printf("malloc w_data size %d fail.\n",w_len);
|
|
PrintUsage();
|
|
spi_deinit(handle);
|
|
return 0;
|
|
}
|
|
memset(w_data,0,w_len);
|
|
|
|
uint8_t *r_data = (uint8_t *)malloc(r_len);
|
|
if(r_data == NULL)
|
|
{
|
|
printf("malloc r_data size %d fail.\n",r_len);
|
|
free(w_data);
|
|
PrintUsage();
|
|
spi_deinit(handle);
|
|
return 0;
|
|
}
|
|
memset(r_data,0,r_len);
|
|
|
|
for(int i=0;i<w_len;i++) w_data[i] = (uint8_t)strtol(argv[5+i], NULL, 0);
|
|
|
|
printf("ready write bytes:\n");
|
|
for(int i=0;i<w_len;i++) printf("<0x%02X>",w_data[i]);
|
|
printf("\n");
|
|
|
|
if(spi_transmit(handle,w_data,w_len, r_data,r_len)!=SPI_SUCCESS)
|
|
{
|
|
free(w_data);
|
|
free(r_data);
|
|
PrintUsage();
|
|
spi_deinit(handle);
|
|
return 0;
|
|
}
|
|
|
|
printf("recv bytes:\n");
|
|
for(int i=0;i<r_len;i++) printf("<0x%02X>",r_data[i]);
|
|
printf("\n");
|
|
free(w_data);
|
|
free(r_data);
|
|
}
|
|
else
|
|
{
|
|
printf("invalid parameter.\n");
|
|
PrintUsage();
|
|
spi_deinit(handle);
|
|
return 0;
|
|
}
|
|
|
|
spi_deinit(handle);
|
|
return 0;
|
|
}
|
|
|