mirror of
https://github.com/taubel/sdk-ameba-v4.0b-gcc.git
synced 2026-07-01 09:05:39 +00:00
initial commit
This commit is contained in:
commit
60a7afcc83
2528 changed files with 1001987 additions and 0 deletions
|
|
@ -0,0 +1,896 @@
|
|||
/*
|
||||
* Routines to access hardware
|
||||
*
|
||||
* Copyright (c) 2015 Realtek Semiconductor Corp.
|
||||
*
|
||||
* This module is a confidential and proprietary property of RealTek and
|
||||
* possession or use of this module requires written permission of RealTek.
|
||||
*/
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
#include "device.h"
|
||||
#include "rtl8710b_gspi_host.h"
|
||||
#include "rtl8710b_inic.h"
|
||||
#include "spi_api.h"
|
||||
#include "spi_ex_api.h"
|
||||
#include "gpio_api.h"
|
||||
#include "gpio_irq_api.h"
|
||||
#include "osdep_service.h"
|
||||
|
||||
#define CONFIG_GSPI_SLAVE 0
|
||||
#define CONFIG_USE_INTERRUPT 1
|
||||
#define PACK_SIZE 2048
|
||||
|
||||
#if !CONFIG_GSPI_SLAVE
|
||||
|
||||
/*host endian configuration
|
||||
little-endian (1)
|
||||
big-endan (0)
|
||||
*/
|
||||
#define CONFIG_HOST_ENDIAN 1
|
||||
|
||||
// SPI0
|
||||
#define SPI0_MOSI PA_23
|
||||
#define SPI0_MISO PA_22
|
||||
#define SPI0_SCLK PA_18
|
||||
#define SPI0_CS PA_19 // This pin is redundant
|
||||
#if CONFIG_USE_INTERRUPT
|
||||
#define GPIO_INT PA_27 // gspi external interrupt
|
||||
#endif
|
||||
#define GPIO_CS PA_28
|
||||
|
||||
#define SPI0_FREQUENCY (62500000/6)
|
||||
|
||||
static spi_t spi0_master;
|
||||
static gpio_irq_t gpio_int;
|
||||
static gpio_t gpio_cs;
|
||||
|
||||
typedef enum {
|
||||
READ_REG = 0,
|
||||
WRITE_REG
|
||||
}_reg_ops;
|
||||
|
||||
|
||||
// GSPI configuration (big endian recommended)
|
||||
#define GSPI_CONFIG SPI_LITTLE_ENDIAN_32
|
||||
|
||||
// SPI master configuration
|
||||
#define SPI_BITS 8 // Ameba SPI support 8bits and 16bits mode
|
||||
|
||||
|
||||
struct spi_more_data {
|
||||
unsigned long more_data;
|
||||
unsigned long len;
|
||||
};
|
||||
|
||||
|
||||
#define SLAVE_SELECT() gpio_write(&gpio_cs, 0)
|
||||
#define SLAVE_DESELECT() gpio_write(&gpio_cs, 1)
|
||||
|
||||
#define SPI_DUMMY 0xFF
|
||||
|
||||
// spi interrupt semaphore
|
||||
_sema pspiIrqSemaphore;
|
||||
// spi bus busy
|
||||
_mutex SPIbusbusy;
|
||||
|
||||
volatile bool txDone = FALSE;
|
||||
volatile bool rxDone = FALSE;
|
||||
volatile bool txbusIdle = FALSE;
|
||||
|
||||
|
||||
#define AGG_SIZE 5000
|
||||
#define MAX_DUMMY_LEN 3
|
||||
#define BUFFER_LEN GSPI_CMD_LEN+SIZE_RX_DESC+PACK_SIZE+8+MAX_DUMMY_LEN // GSPI_CMD + TX_DEC + DATA + GSPI_STATUS
|
||||
|
||||
unsigned char TX_DATA[PACK_SIZE];
|
||||
unsigned char RX_DATA[PACK_SIZE+SIZE_RX_DESC]; // extra 100 byte for SDIO header
|
||||
u32 rx_done=0;
|
||||
|
||||
unsigned char TX_BUFFER[BUFFER_LEN];
|
||||
unsigned char RX_BUFFER[BUFFER_LEN];
|
||||
|
||||
#endif
|
||||
|
||||
#define TASK_STACK_SIZE 2048
|
||||
#define TASK_PRIORITY (tskIDLE_PRIORITY + 1)
|
||||
|
||||
#if CONFIG_GSPI_SLAVE
|
||||
#include "spdio_api.h"
|
||||
struct spdio_t spdio_dev;
|
||||
|
||||
#define SPDIO_TX_BD_NUM 6 // n*2, must be rounded to 2
|
||||
#define SPDIO_RX_BD_NUM 6 //
|
||||
#define SPDIO_RX_BUFSZ PACK_SIZE+64 //n*64, must be rounded to 64, extra 64 for TX descriptor
|
||||
|
||||
#define CONFIG_RX_BUFFER_REUSE 1
|
||||
|
||||
/*
|
||||
* param: pdata, package
|
||||
*/
|
||||
char ex_gspi_tx(u8 *pdata, u16 size, u8 type){
|
||||
static int rx_cnt = 0;
|
||||
|
||||
// LOOPBACK
|
||||
printf("receive package, size = %d (cnt = %d) heap=%d\n", size, ++rx_cnt, xPortGetFreeHeapSize());
|
||||
|
||||
struct spdio_buf_t *tx_buf = (struct spdio_buf_t *)rtw_malloc(sizeof(struct spdio_buf_t));
|
||||
if(!tx_buf)
|
||||
return FAIL;
|
||||
tx_buf->buf_allocated = (u32)rtw_malloc(size + SPDIO_DMA_ALIGN_4);
|
||||
if(!tx_buf->buf_allocated)
|
||||
{
|
||||
rtw_mfree((u8 *)tx_buf, sizeof(struct spdio_buf_t));
|
||||
return FAIL;
|
||||
}
|
||||
tx_buf->size_allocated = size + SPDIO_DMA_ALIGN_4;
|
||||
|
||||
tx_buf->buf_addr = (u32)N_BYTE_ALIGMENT((u32)(tx_buf->buf_allocated), SPDIO_DMA_ALIGN_4);
|
||||
|
||||
//printf("buf_addr = %x\n", tx_buf->buf_addr);
|
||||
// copy data
|
||||
memcpy((void*)tx_buf->buf_addr, pdata, size);
|
||||
|
||||
tx_buf->buf_size = size;
|
||||
tx_buf->type = SPDIO_RX_DATA_USER; // you can define your own data type in spdio_rx_data_t and spdio_tx_data_t
|
||||
|
||||
// loopback
|
||||
spdio_tx(&spdio_dev, tx_buf);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*spdio rx done callback (HOST->Device), manage your package and buffer*/
|
||||
char ex_gspi_rx_done_cb(void *priv, void *pbuf, u8 *pdata, u16 size, u8 type){
|
||||
struct spdio_t *obj = (struct spdio_t *)priv;
|
||||
struct spdio_buf_t* rx_buf = (struct spdio_buf_t*)pbuf;
|
||||
|
||||
//2 handle package received
|
||||
ex_gspi_tx(pdata, size, type);
|
||||
|
||||
#if !CONFIG_RX_BUFFER_REUSE
|
||||
// manage rx_buf here
|
||||
rtw_mfree((char *)rx_buf->buf_allocated, rx_buf->size_allocated);
|
||||
|
||||
//2 assign new buffer to RX
|
||||
rx_buf->buf_allocated = (u32)rtw_malloc(obj->rx_bd_bufsz + SPDIO_DMA_ALIGN_4);
|
||||
rx_buf->size_allocated = obj->rx_bd_bufsz + SPDIO_DMA_ALIGN_4;
|
||||
|
||||
// this buffer must be 4 byte alignment
|
||||
rx_buf->buf_addr = (u32)N_BYTE_ALIGMENT((u32)(rx_buf->buf_allocated), SPDIO_DMA_ALIGN_4);
|
||||
#endif
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*spdio tx done callback(Device->HOST), manage buffer*/
|
||||
// this API will be called after package have been read by HOST
|
||||
char ex_gspi_tx_done_cb(void *priv, void *pbuf){
|
||||
|
||||
struct spdio_buf_t* tx_buf = (struct spdio_buf_t*)pbuf;
|
||||
|
||||
rtw_mfree((u8 *)tx_buf->buf_allocated, tx_buf->size_allocated);
|
||||
rtw_mfree((u8 *)tx_buf, sizeof(struct spdio_buf_t));
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int spi_transfer(uint8_t* buf, uint32_t buf_len)
|
||||
{
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
|
||||
rtw_mutex_get(&SPIbusbusy);
|
||||
SLAVE_SELECT();
|
||||
|
||||
txbusIdle = FALSE; // ensure TX done
|
||||
rxDone = FALSE; // ensure RX done
|
||||
|
||||
if(spi_master_write_read_stream(&spi0_master, buf, buf, buf_len)!=0x00){
|
||||
ret = -1;
|
||||
}else{
|
||||
ret = 0;
|
||||
while((!txbusIdle) || (!rxDone)){
|
||||
wait_us(20);
|
||||
if (++i > 2000) {
|
||||
DBG_8195A("SPI write and read Timeout...\r\n");
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Chip Select Pull High */
|
||||
SLAVE_DESELECT();
|
||||
rtw_mutex_put(&SPIbusbusy);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int addr_convert(u32 addr)
|
||||
{
|
||||
u32 domain_id = 0 ;
|
||||
u32 temp_addr = addr&0xffff0000;
|
||||
|
||||
switch (temp_addr) {
|
||||
case SPI_LOCAL_OFFSET:
|
||||
domain_id = SPI_LOCAL_DOMAIN;
|
||||
break;
|
||||
case SPI_TX_FIFO_OFFSET:
|
||||
domain_id = SPI_TXFIFO_DOMAIN;
|
||||
break;
|
||||
case SPI_RX_FIFO_OFFSET:
|
||||
domain_id = SPI_RXFIFO_DOMAIN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return domain_id;
|
||||
}
|
||||
|
||||
static inline u32 DWORD_endian_reverse(u32 src, _gspi_conf_t gspi_conf)
|
||||
{
|
||||
u32 temp = 0;
|
||||
switch(gspi_conf){
|
||||
#if CONFIG_HOST_ENDIAN /*host little-endian*/
|
||||
case SPI_LITTLE_ENDIAN_16:
|
||||
temp = (((src&0x000000ff)<<8)|((src&0x0000ff00)>>8)|
|
||||
((src&0x00ff0000)<<8)|((src&0xff000000)>>8));
|
||||
break;
|
||||
case SPI_LITTLE_ENDIAN_32:
|
||||
temp = (((src&0x000000ff)<<24)|((src&0x0000ff00)<<8)|
|
||||
((src&0x00ff0000)>>8)|((src&0xff000000)>>24));
|
||||
break;
|
||||
case SPI_BIG_ENDIAN_16:
|
||||
case SPI_BIG_ENDIAN_32:
|
||||
temp = src;
|
||||
break;
|
||||
#else /*host big-endian*/
|
||||
case SPI_LITTLE_ENDIAN_16:
|
||||
temp = (((src&0x0000ffff)<<16)|((src&0xffff0000)>>16);
|
||||
break;
|
||||
case SPI_LITTLE_ENDIAN_32:
|
||||
temp = src;
|
||||
break;
|
||||
case SPI_BIG_ENDIAN_16:
|
||||
case SPI_BIG_ENDIAN_32:
|
||||
temp = (((src&0x000000ff)<<24)|((src&0x0000ff00)<<8)|
|
||||
((src&0x00ff0000)>>8)|((src&0xff000000)>>24));
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*
|
||||
* src buffer bit reorder
|
||||
*/
|
||||
static void buf_endian_reverse(u8* src, u32 len, u8* dummy_bytes, _gspi_conf_t gspi_conf)
|
||||
{
|
||||
u32 *buf = (u32*)src;
|
||||
|
||||
u16 count = len/4;
|
||||
u16 remain = len%4;
|
||||
int i = 0;
|
||||
|
||||
if(remain)
|
||||
count ++;
|
||||
|
||||
for(i = 0;i < count; i++){
|
||||
buf[i] = DWORD_endian_reverse(buf[i], gspi_conf);
|
||||
}
|
||||
|
||||
if(remain)
|
||||
*dummy_bytes = 4 - remain;
|
||||
}
|
||||
|
||||
|
||||
int gspi_read_write_reg(_reg_ops ops_type, u32 addr, char * buf, int len,_gspi_conf_t gspi_conf)
|
||||
{
|
||||
int fun = 1, domain_id = 0x0; //LOCAL
|
||||
unsigned int cmd = 0 ;
|
||||
int byte_en = 0 ;//,i = 0 ;
|
||||
int ret = 0;
|
||||
unsigned char status[GSPI_STATUS_LEN] = {0};
|
||||
unsigned int data_tmp = 0;
|
||||
|
||||
u32 spi_buf[4] = {0};
|
||||
|
||||
if (len!=1 && len!=2 && len != 4) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
domain_id = addr_convert(addr);
|
||||
|
||||
addr &= 0x7fff;
|
||||
len &= 0xff;
|
||||
if (ops_type == WRITE_REG) //write register
|
||||
{
|
||||
int remainder = addr % 4;
|
||||
u32 val32 = *(u32 *)buf;
|
||||
switch(len) {
|
||||
case 1:
|
||||
byte_en = (0x1 << remainder);
|
||||
data_tmp = (val32& 0xff)<< (remainder*8);
|
||||
break;
|
||||
case 2:
|
||||
byte_en = (0x3 << remainder);
|
||||
data_tmp = (val32 & 0xffff)<< (remainder*8);
|
||||
break;
|
||||
case 4:
|
||||
byte_en = 0xf;
|
||||
data_tmp = val32 & 0xffffffff;
|
||||
break;
|
||||
default:
|
||||
byte_en = 0xf;
|
||||
data_tmp = val32 & 0xffffffff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else //read register
|
||||
{
|
||||
switch(len) {
|
||||
case 1:
|
||||
byte_en = 0x1;
|
||||
break;
|
||||
case 2:
|
||||
byte_en = 0x3;
|
||||
break;
|
||||
case 4:
|
||||
byte_en = 0xf;
|
||||
break;
|
||||
default:
|
||||
byte_en = 0xf;
|
||||
break;
|
||||
}
|
||||
|
||||
if(domain_id == SPI_LOCAL_DOMAIN)
|
||||
byte_en = 0;
|
||||
}
|
||||
|
||||
|
||||
cmd = FILL_SPI_CMD(byte_en, addr, domain_id, fun, ops_type);
|
||||
//4 command segment bytes reorder
|
||||
cmd = DWORD_endian_reverse(cmd, gspi_conf);
|
||||
|
||||
if ((ops_type == READ_REG)&& (domain_id!= SPI_RXFIFO_DOMAIN)) {
|
||||
u32 read_data = 0;
|
||||
|
||||
_memset(spi_buf, 0x00, sizeof(spi_buf));
|
||||
|
||||
//SPI_OUT:32bit cmd
|
||||
//SPI_IN:64bits status+ XXbits data
|
||||
spi_buf[0] = cmd;
|
||||
spi_buf[1] = 0;
|
||||
spi_buf[2] = 0;
|
||||
spi_buf[3] = 0;
|
||||
|
||||
spi_transfer((u8*)spi_buf, sizeof(spi_buf));
|
||||
|
||||
memcpy(status, (u8 *) &spi_buf[1], GSPI_STATUS_LEN);
|
||||
read_data = spi_buf[3];
|
||||
|
||||
*(u32*)buf = DWORD_endian_reverse(read_data, gspi_conf);
|
||||
}
|
||||
else if (ops_type == WRITE_REG ) {
|
||||
//4 data segment bytes reorder
|
||||
data_tmp = DWORD_endian_reverse(data_tmp, gspi_conf);
|
||||
//SPI_OUT:32bits cmd+ XXbits data
|
||||
//SPI_IN:64bits status
|
||||
spi_buf[0] = cmd;
|
||||
spi_buf[1] = data_tmp;
|
||||
spi_buf[2] = 0;
|
||||
spi_buf[3] = 0;
|
||||
|
||||
spi_transfer((u8*)spi_buf, sizeof(spi_buf));
|
||||
|
||||
memcpy(status, (u8 *) &spi_buf[2], GSPI_STATUS_LEN);
|
||||
}
|
||||
|
||||
// translate status
|
||||
return ret;
|
||||
}
|
||||
u8 gspi_read8(u32 addr, s32 *err)
|
||||
{
|
||||
u32 ret = 0;
|
||||
int val32 = 0 , remainder = 0 ;
|
||||
s32 _err = 0;
|
||||
|
||||
_err = gspi_read_write_reg(READ_REG, addr&0xFFFFFFFC, (char *)&ret, 4, GSPI_CONFIG);
|
||||
remainder = addr % 4;
|
||||
val32 = ret;
|
||||
val32 = (val32& (0xff<< (remainder<<3)))>>(remainder<<3);
|
||||
|
||||
if (err)
|
||||
*err = _err;
|
||||
|
||||
return (u8)val32;
|
||||
|
||||
}
|
||||
|
||||
|
||||
u16 gspi_read16(u32 addr, s32 *err)
|
||||
{
|
||||
u32 ret = 0;
|
||||
int val32 = 0 , remainder = 0 ;
|
||||
s32 _err = 0;
|
||||
|
||||
_err = gspi_read_write_reg(READ_REG, addr&0xFFFFFFFC,(char *)&ret, 4, GSPI_CONFIG);
|
||||
remainder = addr % 4;
|
||||
val32 = ret;
|
||||
val32 = (val32& (0xffff<< (remainder<<3)))>>(remainder<<3);
|
||||
|
||||
if (err)
|
||||
*err = _err;
|
||||
|
||||
return (u16)val32;
|
||||
}
|
||||
|
||||
|
||||
u32 gspi_read32(u32 addr, s32 *err)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
s32 _err = 0;
|
||||
|
||||
_err = gspi_read_write_reg(READ_REG, addr&0xFFFFFFFC,(char *)&ret,4 ,GSPI_CONFIG);
|
||||
if (err)
|
||||
*err = _err;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
s32 gspi_write8(u32 addr, u8 buf, s32 *err)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = gspi_read_write_reg(WRITE_REG, addr, (char *)&buf,1, GSPI_CONFIG);
|
||||
if (err)
|
||||
*err = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 gspi_write16(u32 addr, u16 buf, s32 *err)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = gspi_read_write_reg(WRITE_REG,addr,(char *)&buf,2, GSPI_CONFIG);
|
||||
if (err)
|
||||
*err = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 gspi_write32(u32 addr, u32 buf, s32 *err)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = gspi_read_write_reg(WRITE_REG, addr,(char *)&buf,4, GSPI_CONFIG);
|
||||
if (err)
|
||||
*err = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int gspi_read_rx_fifo(u8 *buf, u32 len, struct spi_more_data * pmore_data,_gspi_conf_t gspi_conf)
|
||||
{
|
||||
int fun = 1;
|
||||
u32 cmd = 0;
|
||||
u8* spi_buf = (u8 *) (buf);
|
||||
u8* spi_data = spi_buf + GSPI_CMD_LEN;
|
||||
u8* spi_status = spi_data + len;
|
||||
int spi_buf_len = GSPI_CMD_LEN + N_BYTE_ALIGMENT(len, 4) + GSPI_STATUS_LEN;
|
||||
u8 dummy_bytes = 0;
|
||||
|
||||
cmd = FILL_SPI_CMD(len, ((len&0xff00) >>8), SPI_RXFIFO_DOMAIN, fun, (unsigned int)0);
|
||||
|
||||
//4 command segment bytes reorder
|
||||
cmd = DWORD_endian_reverse(cmd, gspi_conf);
|
||||
memcpy(spi_buf, (u8 *)&cmd, GSPI_CMD_LEN);
|
||||
//4 clean data segment
|
||||
memset(spi_data,0x00, len);
|
||||
//4 clean status segment
|
||||
memset(spi_status, 0x00, GSPI_STATUS_LEN);
|
||||
|
||||
spi_transfer((u8 *) spi_buf, spi_buf_len);
|
||||
|
||||
// data segement reorder
|
||||
buf_endian_reverse(spi_data, len, &dummy_bytes, gspi_conf);
|
||||
// status segment reorder
|
||||
spi_status += dummy_bytes;
|
||||
buf_endian_reverse(spi_status, GSPI_STATUS_LEN, &dummy_bytes, gspi_conf);
|
||||
|
||||
pmore_data->more_data = GET_STATUS_HISR(spi_status) & SPI_HIMR_RX_REQUEST_MSK;
|
||||
pmore_data->len = GET_STATUS_RXQ_REQ_LEN(spi_status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gspi_write_tx_fifo(u8 *buf, u32 len, _gspi_conf_t gspi_conf)
|
||||
{
|
||||
int fun = 1; //TX_HIQ_FIFO
|
||||
unsigned int cmd = 0;
|
||||
u8 *spi_buf = (u8 *) (buf);
|
||||
u8* spi_data = spi_buf + GSPI_CMD_LEN;
|
||||
u8* spi_status;// = buf + len
|
||||
u32 spi_buf_len = 0;
|
||||
|
||||
u32 NumOfFreeSpace;
|
||||
u8 wait_num = 0;
|
||||
u8 dummy_bytes = 0;
|
||||
|
||||
NumOfFreeSpace = gspi_read32(LOCAL_REG_FREE_TX_SPACE, NULL);
|
||||
|
||||
while (NumOfFreeSpace * (PACK_SIZE+SIZE_TX_DESC) < len) {
|
||||
if((++wait_num) >= 4){
|
||||
DBG_8195A("%s(): wait_num is >= 4\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
rtw_udelay_os(100); //delay 100us
|
||||
NumOfFreeSpace = gspi_read32(LOCAL_REG_FREE_TX_SPACE, NULL);
|
||||
}
|
||||
cmd = FILL_SPI_CMD(len, ((len&0xff00) >>8), SPI_TXFIFO_DOMAIN, fun, (unsigned int)1);
|
||||
//4 command segment bytes reorder
|
||||
cmd = DWORD_endian_reverse(cmd, gspi_conf);
|
||||
memcpy(spi_buf, (u8 *)&cmd, GSPI_CMD_LEN);
|
||||
|
||||
//4 data segment bytes reorder
|
||||
buf_endian_reverse(spi_data, len, &dummy_bytes, gspi_conf);
|
||||
|
||||
//4 status segment
|
||||
spi_status = spi_data + len + dummy_bytes;
|
||||
memset(spi_status, 0x00, GSPI_STATUS_LEN);
|
||||
|
||||
spi_buf_len = GSPI_CMD_LEN + len + dummy_bytes + GSPI_STATUS_LEN;
|
||||
|
||||
spi_transfer((u8 *) spi_buf, spi_buf_len);
|
||||
|
||||
// parse status infomation
|
||||
// GET_STATUS_HISR(status)
|
||||
// GET_STATUS_FREE_TX(status)
|
||||
// GET_STATUS_RXQ_REQ_LEN(status)
|
||||
// GET_STATUS_TX_SEQ(status)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gspi_write_page(u8 *buf, u32 len, u8 agg_cnt){
|
||||
int res;
|
||||
u32 tot_len = SIZE_TX_DESC + len;
|
||||
PGSPI_TX_DESC ptxdesc;
|
||||
|
||||
// clean GSPI command and tx descriptor area
|
||||
memset(TX_BUFFER, 0, GSPI_CMD_LEN+SIZE_TX_DESC);
|
||||
|
||||
ptxdesc = (PGSPI_TX_DESC)(TX_BUFFER + GSPI_CMD_LEN); // reserve 4 byte for GSPI cmd
|
||||
ptxdesc->txpktsize = len;
|
||||
ptxdesc->offset = SIZE_TX_DESC;
|
||||
ptxdesc->bus_agg_num = agg_cnt;
|
||||
ptxdesc->type = GSPI_CMD_TX;
|
||||
|
||||
memcpy(TX_BUFFER+GSPI_CMD_LEN+SIZE_TX_DESC, buf, len);
|
||||
|
||||
res = gspi_write_tx_fifo(TX_BUFFER, tot_len, GSPI_CONFIG);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int gspi_configuration(_gspi_conf_t gspi_conf){
|
||||
|
||||
u8 conf = gspi_conf;
|
||||
u8 retry_t = 0;
|
||||
|
||||
retry:
|
||||
/*GSPI default mode: SPI_LITTLE_ENDIAN_32*/
|
||||
gspi_read_write_reg(WRITE_REG, SPI_LOCAL_OFFSET|SPI_REG_SPI_CFG,(char *)&conf,1 ,SPI_LITTLE_ENDIAN_32);
|
||||
|
||||
// read gspi config
|
||||
conf = 0xff;
|
||||
conf = gspi_read8(SPI_LOCAL_OFFSET|SPI_REG_SPI_CFG, NULL);
|
||||
|
||||
if(conf != gspi_conf){
|
||||
if(++ retry_t <= 3)
|
||||
goto retry;
|
||||
DBG_8195A("%s: config fail@ 0x%x\n", __FUNCTION__, conf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *s;
|
||||
switch (conf) {
|
||||
case SPI_LITTLE_ENDIAN_16:
|
||||
s = "LITTLE_ENDIAN|WORD_LEN_16"; break;
|
||||
case SPI_LITTLE_ENDIAN_32:
|
||||
s = "LITTLE_ENDIAN|WORD_LEN_32"; break;
|
||||
case SPI_BIG_ENDIAN_16:
|
||||
s = "BIG_ENDIAN|WORD_LEN_16"; break;
|
||||
case SPI_BIG_ENDIAN_32:
|
||||
s = "BIG_ENDIAN|WORD_LEN_32"; break;
|
||||
default:
|
||||
s = "UNKNOW CONFIGURATION"; break;
|
||||
};
|
||||
DBG_8195A("%s: Current configuration:%s\n", __FUNCTION__, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 check_trx_data(u8 *src,u8*dst,u16 len){
|
||||
u16 i;
|
||||
u8 result=1;
|
||||
for(i=0;i<len;i++)
|
||||
if(*(src+i) !=*(dst+i)){
|
||||
result=0;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#if CONFIG_USE_INTERRUPT
|
||||
void spi_interrupt_thread(){
|
||||
u32 spi_hisr;
|
||||
u32 spi_himr;
|
||||
u32 rx_cnt = 0;
|
||||
while(1){
|
||||
if (rtw_down_sema(&pspiIrqSemaphore) == _FAIL){
|
||||
DBG_8195A("%s, Take Semaphore Fail\n", __FUNCTION__);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
spi_himr = gspi_read32(SPI_LOCAL_OFFSET | SPI_REG_HIMR, NULL);
|
||||
spi_hisr = gspi_read32(SPI_LOCAL_OFFSET | SPI_REG_HISR, NULL);
|
||||
|
||||
if (spi_hisr & spi_himr){
|
||||
if(spi_hisr & SPI_HISR_RX_REQUEST) {
|
||||
u8* rx_buf = NULL;
|
||||
u8* payload = NULL;
|
||||
u32 rx_len = 0;
|
||||
u8 rx_len_rdy = 0;
|
||||
PINIC_RX_DESC prxdesc;
|
||||
struct spi_more_data more_data = {0};
|
||||
|
||||
// clean RX buffer
|
||||
memset(RX_DATA, 0, AGG_SIZE + 100);
|
||||
rx_buf = RX_DATA;
|
||||
|
||||
do {
|
||||
//validate RX_LEN_RDY before reading RX0_REQ_LEN
|
||||
if(rx_len==0){
|
||||
rx_len_rdy = gspi_read8(SPI_LOCAL_OFFSET|(SPI_REG_RX0_REQ_LEN + 3), NULL);
|
||||
if(rx_len_rdy & BIT7){
|
||||
rx_len = (gspi_read32(SPI_LOCAL_OFFSET | SPI_REG_RX0_REQ_LEN, NULL)) &0xffffff;
|
||||
}
|
||||
}
|
||||
|
||||
if (rx_len >(PACK_SIZE+SIZE_RX_DESC))
|
||||
rx_len = PACK_SIZE+SIZE_RX_DESC;
|
||||
|
||||
if(rx_len){
|
||||
|
||||
memset(RX_BUFFER, 0, BUFFER_LEN);
|
||||
|
||||
gspi_read_rx_fifo(RX_BUFFER, rx_len, &more_data,GSPI_CONFIG);
|
||||
|
||||
memcpy(rx_buf, RX_BUFFER+GSPI_CMD_LEN, rx_len);
|
||||
|
||||
prxdesc = (PINIC_RX_DESC)rx_buf;
|
||||
|
||||
DBG_8195A("Receive Data lenth = %d (cnt = %d)\n",prxdesc->pkt_len, ++rx_cnt);
|
||||
|
||||
payload = rx_buf + prxdesc->offset;
|
||||
rx_buf += rx_len;
|
||||
rx_len = 0;
|
||||
rx_done=1;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}while(1);
|
||||
}
|
||||
}
|
||||
// query other interrupt here
|
||||
}
|
||||
exit:
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// external GSPI interrupt handler
|
||||
void gspi_irq_handler (uint32_t id, gpio_irq_event event)
|
||||
{
|
||||
//DBG_8195A("gspi_irq_handler....\n");
|
||||
if(!pspiIrqSemaphore)
|
||||
return;
|
||||
rtw_up_sema_from_isr(&pspiIrqSemaphore);
|
||||
}
|
||||
|
||||
// SPI master interrupt callback if use interrupt mode
|
||||
void spi_tx_rx_intr_callback(void *pdata, SpiIrq event){
|
||||
|
||||
switch(event){
|
||||
case SpiRxIrq:
|
||||
rxDone = TRUE;
|
||||
break;
|
||||
case SpiTxIrq:
|
||||
txDone = TRUE;
|
||||
break;
|
||||
default:
|
||||
DBG_8195A("unknown interrput evnent!\n");
|
||||
}
|
||||
}
|
||||
|
||||
void spi_tx_bus_idle_callback(void *pdata, SpiIrq event){
|
||||
txbusIdle = TRUE;
|
||||
}
|
||||
|
||||
void spi_init_intr(){
|
||||
#if CONFIG_USE_INTERRUPT
|
||||
// init gspi external interrupt
|
||||
gpio_irq_init(&gpio_int, GPIO_INT, gspi_irq_handler, NULL);
|
||||
gpio_irq_set(&gpio_int, IRQ_FALL, 1); // Falling Edge Trigger
|
||||
gpio_irq_enable(&gpio_int);
|
||||
#endif
|
||||
// init spi master tx/rx done interrupt
|
||||
spi_irq_hook(&spi0_master, (spi_irq_handler)spi_tx_rx_intr_callback, NULL);
|
||||
|
||||
// init spi master tx bus idle interrupt
|
||||
spi_bus_tx_done_irq_hook(&spi0_master, (spi_irq_handler)spi_tx_bus_idle_callback, NULL);
|
||||
}
|
||||
void spi_init_master(){
|
||||
// init spi master
|
||||
spi0_master.spi_idx=MBED_SPI1;
|
||||
spi_init(&spi0_master, SPI0_MOSI, SPI0_MISO, SPI0_SCLK, SPI0_CS);
|
||||
spi_format(&spi0_master, SPI_BITS, 0, 0);
|
||||
spi_frequency(&spi0_master, SPI0_FREQUENCY);
|
||||
printf("spi master frequency %d Hz\n",SPI0_FREQUENCY);
|
||||
|
||||
gpio_init(&gpio_cs, GPIO_CS);
|
||||
gpio_mode(&gpio_cs, PullDown);
|
||||
gpio_dir(&gpio_cs, PIN_OUTPUT);
|
||||
|
||||
SLAVE_DESELECT(); // deselect slave
|
||||
}
|
||||
#endif
|
||||
|
||||
void gspi_demo(void)
|
||||
{
|
||||
#if CONFIG_GSPI_SLAVE
|
||||
int i;
|
||||
|
||||
DBG_8195A("Init GSPI slave....\n");
|
||||
|
||||
spdio_dev.priv = NULL;
|
||||
spdio_dev.rx_bd_num = SPDIO_RX_BD_NUM;
|
||||
spdio_dev.tx_bd_num = SPDIO_TX_BD_NUM;
|
||||
spdio_dev.rx_bd_bufsz = SPDIO_RX_BUFSZ;
|
||||
|
||||
spdio_dev.rx_buf = (struct spdio_buf_t *)rtw_malloc(SPDIO_RX_BD_NUM*sizeof(struct spdio_buf_t));
|
||||
|
||||
for(i=0;i<SPDIO_RX_BD_NUM;i++){
|
||||
spdio_dev.rx_buf[i].buf_allocated = (u32)rtw_malloc(SPDIO_RX_BUFSZ + SPDIO_DMA_ALIGN_4);
|
||||
if(!spdio_dev.rx_buf[i].buf_allocated){
|
||||
printf("malloc failed for spdio buffer!\n");
|
||||
return;
|
||||
}
|
||||
spdio_dev.rx_buf[i].size_allocated = SPDIO_RX_BUFSZ + SPDIO_DMA_ALIGN_4;
|
||||
// this buffer must be 4 byte alignment
|
||||
spdio_dev.rx_buf[i].buf_addr = (u32)N_BYTE_ALIGMENT((u32)(spdio_dev.rx_buf[i].buf_allocated), SPDIO_DMA_ALIGN_4);
|
||||
}
|
||||
|
||||
spdio_dev.rx_done_cb = ex_gspi_rx_done_cb;
|
||||
spdio_dev.tx_done_cb = ex_gspi_tx_done_cb;
|
||||
|
||||
DBG_INFO_MSG_OFF(_DBG_SDIO_);
|
||||
DBG_WARN_MSG_OFF(_DBG_SDIO_);
|
||||
DBG_ERR_MSG_ON(_DBG_SDIO_);
|
||||
|
||||
spdio_init(&spdio_dev);
|
||||
DBG_8195A("Init GSPI slave Done,Ready for TRx....\n");
|
||||
#else
|
||||
DBG_8195A("Init SPI master....\n");
|
||||
u32 spi_himr = 0;
|
||||
u32 spi_hisr = 0;
|
||||
u32 spi_ictlr = 0;
|
||||
u32 rx_agg_ctrl = 0;
|
||||
s8 res = 0;
|
||||
int test_loop = 1000;
|
||||
u16 counter=0;
|
||||
|
||||
//1 SPI host init
|
||||
spi_init_master();
|
||||
spi_init_intr();
|
||||
|
||||
rtw_init_sema(&pspiIrqSemaphore, 0);
|
||||
// used for sync SPI bus, SPI bus shold not be interrupt
|
||||
rtw_mutex_init(&SPIbusbusy);
|
||||
|
||||
if( xTaskCreate( (TaskFunction_t)spi_interrupt_thread, "SPI INTERRUPT", (TASK_STACK_SIZE/4), NULL, TASK_PRIORITY+2, NULL) != pdPASS) {
|
||||
DBG_8195A("Cannot create SPI INTERRUPT task\n\r");
|
||||
goto err;
|
||||
}
|
||||
|
||||
//1 GSPI slave configuration
|
||||
res = gspi_configuration(GSPI_CONFIG);
|
||||
if(res){
|
||||
DBG_8195A("gspi configure error....\n");
|
||||
while(1);
|
||||
}
|
||||
|
||||
// INT_CTRL-clean INT control register
|
||||
spi_ictlr = 0;
|
||||
gspi_write32(SPI_LOCAL_OFFSET |SPI_REG_INT_CTRL, spi_ictlr, NULL);
|
||||
|
||||
// HISR - clean interrupt status register
|
||||
gspi_write32(SPI_LOCAL_OFFSET |SPI_REG_HISR, 0xFFFFFFFF, NULL);
|
||||
|
||||
// HIMR - turn all off
|
||||
gspi_write32(SPI_LOCAL_OFFSET |SPI_REG_HIMR, SPI_HIMR_DISABLED, NULL);
|
||||
|
||||
// Set intterrupt mask
|
||||
spi_himr = (u32)(SPI_HISR_RX_REQUEST|SPI_HISR_CPWM1_INT);
|
||||
|
||||
// Write and enable interrupt
|
||||
gspi_write32(SPI_LOCAL_OFFSET | SPI_REG_HIMR, spi_himr, NULL);
|
||||
|
||||
#if 1
|
||||
// set RX AGG control register
|
||||
rx_agg_ctrl = 0;
|
||||
gspi_write32(SPI_LOCAL_OFFSET | SPI_REG_RX_AGG_CTL, rx_agg_ctrl, NULL);
|
||||
#endif
|
||||
|
||||
DBG_8195A("Loopback Test Start...\n");
|
||||
// prepare test data (0x00-0xFF, 0x00-0xFF......)
|
||||
for(int i=0;i<PACK_SIZE;i++)
|
||||
memset(TX_DATA+i, i%256, 1);
|
||||
|
||||
do{
|
||||
res = gspi_write_page(TX_DATA, PACK_SIZE, 1);
|
||||
if(res) {
|
||||
DBG_8195A("spi_write_page: Error!\n");
|
||||
// handle error msg here
|
||||
}
|
||||
counter=0;
|
||||
while (!rx_done){
|
||||
counter++;
|
||||
rtw_mdelay_os(10);
|
||||
if(counter==100){
|
||||
DBG_8195A("Master Rx data Timeout... test aborted!\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
rx_done=0;
|
||||
|
||||
if(check_trx_data(TX_DATA,RX_DATA+SIZE_RX_DESC,PACK_SIZE))
|
||||
DBG_8195A("loop %d Test Succeed!\n",1000-test_loop);
|
||||
else {
|
||||
DBG_8195A("loop %d Test Failed!\n",1000-test_loop);
|
||||
goto err;
|
||||
}
|
||||
rtw_mdelay_os(500);
|
||||
}while(--test_loop);
|
||||
|
||||
#if !CONFIG_USE_INTERRUPT
|
||||
|
||||
#endif
|
||||
#endif
|
||||
err:
|
||||
// spi_free(&spi0_master);
|
||||
|
||||
/* Kill init thread after all init tasks done */
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
// create demo Task
|
||||
if( xTaskCreate( (TaskFunction_t)gspi_demo, "GSPI DEMO", (TASK_STACK_SIZE/4), NULL, TASK_PRIORITY, NULL) != pdPASS) {
|
||||
DBG_8195A("Cannot create demo task\n\r");
|
||||
}
|
||||
|
||||
#if defined(CONFIG_KERNEL) && !TASK_SCHEDULER_DISABLED
|
||||
#ifdef PLATFORM_FREERTOS
|
||||
vTaskStartScheduler();
|
||||
#endif
|
||||
#else
|
||||
#error !!!Need FREERTOS!!!
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file rtl8710b_gspi_host.h
|
||||
* @author
|
||||
* @version V1.0.0
|
||||
* @date 2016-12-9
|
||||
* @brief This file contains all the functions prototypes for the GSPI firmware
|
||||
* library.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* This module is a confidential and proprietary property of RealTek and
|
||||
* possession or use of this module requires written permission of RealTek.
|
||||
*
|
||||
* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __RTL8710B_GSPI_H__
|
||||
#define __RTL8710B_GSPI_H__
|
||||
|
||||
#define SPI_LOCAL_DOMAIN 0x0
|
||||
#define SPI_TXFIFO_DOMAIN 0xc
|
||||
#define SPI_RXFIFO_DOMAIN 0x1f
|
||||
|
||||
//IO Bus domain address mapping
|
||||
#define DEFUALT_OFFSET 0x0
|
||||
#define SPI_LOCAL_OFFSET 0x10250000
|
||||
#define SPI_TX_FIFO_OFFSET 0x10310000
|
||||
#define SPI_RX_FIFO_OFFSET 0x10340000
|
||||
|
||||
#define SPI_LOCAL_DEVICE_ID 0
|
||||
#define SPI_TXQ_FIFO_DEVICE_ID 3
|
||||
#define SPI_RXQ_FIFO_DEVICE_ID 7
|
||||
#define SPI_UNDEFINED_DEVICE_ID (-1)
|
||||
|
||||
|
||||
//SPI Local registers
|
||||
#define SPI_REG_INT_CTRL 0x0004 // 4 bytes, SPI INT Control
|
||||
#define SPI_REG_INT_TIMEOUT 0x0006 // 2 bytes, SPI 32us INT timout
|
||||
#define SPI_REG_HIMR 0x0014 // 4 bytes, SPI Host Interrupt Mask
|
||||
#define SPI_REG_HISR 0x0018 // 4 bytes, SPI Host Interrupt Service Routine
|
||||
#define SPI_REG_RX0_REQ_LEN 0x001C // 4 bytes, RXDMA Request Length
|
||||
#define SPI_REG_FREE_TX_SPACE 0x0020 // 4 bytes, Free Tx Buffer Page
|
||||
#define SPI_REG_TX_SEQNUM 0x0024 // 1 byte, TX Sequence Number Definition
|
||||
#define SPI_REG_HCPWM 0x0038 // 1 byte, HCI Current Power Mode
|
||||
#define SPI_REG_HCPWM2 0x003A // 2 bytes, HCI Current Power Mode 2
|
||||
#define SPI_REG_AVAI_PATH_L 0x0040 // 4 bytes, SPI TX Available Low Size reg
|
||||
#define SPI_REG_AVAI_PATH_H 0x0044 // 4 bytes, SPI TX Available High Size reg
|
||||
#define SPI_REG_RX_AGG_CTL 0x0048 // 4 bytes, SPI RX AGG control
|
||||
#define SPI_REG_H2C_MSG 0x004C // 4 bytes, SPI_REG_H2C_MSG
|
||||
#define SPI_REG_C2H_MSG 0x0050 // 4 bytes, SPI_REG_C2H_MSG
|
||||
#define SPI_REG_HRPWM 0x0080 // 1 byte, SPI_REG_HRPWM
|
||||
#define SPI_REG_HRPWM2 0x82 // 2bytes, driver to FW, host domain, sync to CRPWM2
|
||||
#define SPI_REG_HPS_CLKR 0x0084 // 1 byte, not uesd
|
||||
#define SPI_REG_CPU_IND 0x0087 // 1 byte, firmware indication to host
|
||||
#define SPI_REG_32K_TRANS_CTL 0x0088 // 1 byte, 32K transparent control, BIT0 EN32K_TRANS
|
||||
#define SPI_REG_32K_IDLE_TIME 0x008B // 1 byte, 32K idle time,
|
||||
#define SPI_REG_DELY_LINE_SEL 0x008C // 1 byte, Delay line selection,
|
||||
#define SPI_REG_SPI_CFG 0x00F0 // 1 byte, SPI configuration,
|
||||
|
||||
#define LOCAL_REG_FREE_TX_SPACE (SPI_LOCAL_OFFSET | SPI_REG_FREE_TX_SPACE)
|
||||
|
||||
// Register SPI_REG_CPU_IND
|
||||
#define SPI_CPU_RDY_IND (BIT0)
|
||||
|
||||
#define SPI_MEM_WR_DONE (BIT1)
|
||||
|
||||
|
||||
/************************************************/
|
||||
// SPI_REG_HISR: SDIO Host Interrupt Service Routine
|
||||
#define SPI_HISR_RX_REQUEST (BIT0)
|
||||
#define SPI_HISR_AVAL_INT (BIT1)
|
||||
#define SPI_HISR_TXPKT_OVER_BUFF (BIT2)
|
||||
#define SPI_HISR_TX_AGG_SIZE_MISMATCH (BIT3)
|
||||
#define SPI_HISR_TXBD_OVF (BIT4)
|
||||
//BIT5~16 not used
|
||||
#define SPI_HISR_C2H_MSG_INT (BIT17)
|
||||
#define SPI_HISR_CPWM1_INT (BIT18)
|
||||
#define SPI_HISR_CPWM2_INT (BIT19)
|
||||
//BIT20~31 not used
|
||||
#define SPI_HISR_CPU_NOT_RDY (BIT22)
|
||||
|
||||
|
||||
/*
|
||||
#define MASK_SPI_HISR_CLEAR (SPI_HISR_RX_REQUEST |\
|
||||
SPI_HISR_AVAL_INT |\
|
||||
SPI_HISR_TXPKT_OVER_BUFF |\
|
||||
SPI_HISR_TX_AGG_SIZE_MISMATCH |\
|
||||
SPI_HISR_TXBD_OVF |\
|
||||
SPI_HISR_C2H_MSG_INT |\
|
||||
SPI_HISR_CPWM1_INT |\
|
||||
SPI_HISR_CPWM2_INT)
|
||||
*/
|
||||
#define MASK_SPI_HISR_CLEAR (SPI_HISR_TXPKT_OVER_BUFF |\
|
||||
SPI_HISR_TX_AGG_SIZE_MISMATCH |\
|
||||
SPI_HISR_TXBD_OVF |\
|
||||
SPI_HISR_C2H_MSG_INT |\
|
||||
SPI_HISR_CPWM1_INT |\
|
||||
SPI_HISR_CPWM2_INT)
|
||||
|
||||
// RTL8195A SPI Host Interrupt Mask Register
|
||||
#define SPI_HIMR_RX_REQUEST_MSK (BIT0)
|
||||
#define SPI_HIMR_AVAL_MSK (BIT1)
|
||||
#define SPI_HIMR_TXPKT_SIZE_OVER_BUFF_MSK (BIT2)
|
||||
#define SPI_HIMR_AGG_SIZE_MISMATCH_MSK (BIT3)
|
||||
#define SPI_HIMR_TXBD_OVF_MSK (BIT4)
|
||||
//BIT5~16 not used
|
||||
#define SPI_HIMR_C2H_MSG_INT_MSK (BIT17)
|
||||
#define SPI_HIMR_CPWM1_INT_MSK (BIT18)
|
||||
#define SPI_HIMR_CPWM2_INT_MSK (BIT19)
|
||||
//BIT20~31 not used
|
||||
#define SPI_HIMR_DISABLED 0
|
||||
|
||||
// Register SPI_REG_HCPWM
|
||||
#define SPI_HCPWM_WLAN_TRX (BIT1)
|
||||
|
||||
|
||||
enum{
|
||||
SPI_LITTLE_ENDIAN = 2,
|
||||
SPI_BIG_ENDIAN = 0
|
||||
};
|
||||
enum{
|
||||
SPI_WORD_LEN_16 = 0,
|
||||
SPI_WORD_LEN_32 = 1
|
||||
};
|
||||
|
||||
typedef enum{
|
||||
SPI_LITTLE_ENDIAN_16 = SPI_LITTLE_ENDIAN|SPI_WORD_LEN_16,
|
||||
SPI_LITTLE_ENDIAN_32 = SPI_LITTLE_ENDIAN|SPI_WORD_LEN_32, // default configure
|
||||
SPI_BIG_ENDIAN_16 = SPI_BIG_ENDIAN|SPI_WORD_LEN_16,
|
||||
SPI_BIG_ENDIAN_32 = SPI_BIG_ENDIAN|SPI_WORD_LEN_32
|
||||
}_gspi_conf_t;
|
||||
|
||||
#define GSPI_CMD_LEN 4
|
||||
#define GSPI_STATUS_LEN 8
|
||||
|
||||
|
||||
#define FILL_SPI_CMD(byte_en, addr, domain_id, fun, write_flag) ((byte_en & 0xff) | ((addr & 0xffff) << 8) \
|
||||
| ((domain_id & 0x1f) << 24) | ((fun & 0x3) << 29) | ((write_flag & 0x1) << 31))
|
||||
|
||||
|
||||
#define GET_STATUS_HISR(status) ((((*(u32*)status)) & 0x3) |((((*(u32*)status) >> 2) & 0x7) << 17))
|
||||
#define GET_STATUS_FREE_TX(status) ((((*(u32*)status) >> 5) & 0x7ffffff) << 2)
|
||||
#define GET_STATUS_RXQ_REQ_LEN(status) (((*(u32*)((u8 *)status + 4))) & 0xffffff)
|
||||
#define GET_STATUS_TX_SEQ(status) (((*(u32*)((u8 *)status + 4)) >> 24) & 0xff)
|
||||
|
||||
#define GSPI_CMD_TX 0x83 //
|
||||
#define GSPI_CMD_RX 0X82
|
||||
|
||||
// define transmit packat type
|
||||
#define GPSI_TX_PACKET_802_3 (0x83)
|
||||
#define GSPI_TX_PACKET_802_11 (0x81)
|
||||
#define GSPI_TX_H2C_CMD (0x11)
|
||||
#define GSPI_TX_MEM_READ (0x51)
|
||||
#define GSPI_TX_MEM_WRITE (0x53)
|
||||
#define GSPI_TX_MEM_SET (0x55)
|
||||
#define GSPI_TX_FM_FREETOGO (0x61)
|
||||
#define GSPI_TX_PACKET_USER (0x41)
|
||||
|
||||
//define receive packet type
|
||||
#define GSPI_RX_PACKET_802_3 (0x82)
|
||||
#define GSPI_RX_PACKET_802_11 (0x80)
|
||||
#define GSPI_RX_C2H_CMD (0x10)
|
||||
#define GSPI_RX_MEM_READ (0x50)
|
||||
#define GSPI_RX_MEM_WRITE (0x52)
|
||||
#define GSPI_RX_MEM_SET (0x54)
|
||||
#define GSPI_RX_FM_FREETOGO (0x60)
|
||||
#define GSPI_RX_PACKET_USER (0x40)
|
||||
|
||||
typedef struct {
|
||||
// u4Byte 0
|
||||
#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN)
|
||||
u32 txpktsize:16; // bit[15:0]
|
||||
u32 offset:8; // bit[23:16], store the sizeof(TX_DESC)
|
||||
u32 bus_agg_num:8; // bit[31:24], the bus aggregation number
|
||||
#else
|
||||
u32 bus_agg_num:8; // bit[31:24], the bus aggregation number
|
||||
u32 offset:8; // bit[23:16], store the sizeof(TX_DESC)
|
||||
u32 txpktsize:16; // bit[15:0]
|
||||
#endif
|
||||
|
||||
// u4Byte 1
|
||||
#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN)
|
||||
u32 type:8; // bit[7:0], the packet type
|
||||
u32 data:8; // bit[8:15], the value to be written to the memory
|
||||
u32 reply:1; // bit[16], request to send a reply message
|
||||
u32 rsvd0:15;
|
||||
#else
|
||||
u32 rsvd0:15;
|
||||
u32 reply:1; // bit[16], request to send a reply message
|
||||
u32 data:8; // bit[8:15], the value to be written to the memory
|
||||
u32 type:8; // bit[7:0], the packet type
|
||||
#endif
|
||||
|
||||
// u4Byte 2
|
||||
u32 start_addr; // memory write/read start address, function start address
|
||||
|
||||
// u4Byte 3
|
||||
#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN)
|
||||
u32 data_len:16; // bit[15:0], the length to write/read
|
||||
u32 rsvd2:16; // bit[31:16]
|
||||
#else
|
||||
u32 rsvd2:16; // bit[31:16]
|
||||
u32 data_len:16; // bit[15:0], the length to write/read
|
||||
#endif
|
||||
} GSPI_TX_DESC, *PGSPI_TX_DESC;
|
||||
|
||||
typedef struct {
|
||||
// u4Byte 0
|
||||
#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN)
|
||||
u32 pkt_len:16; // bit[15:0], the packet size
|
||||
u32 offset:8; // bit[23:16], the offset from the packet start to the buf start, also means the size of RX Desc
|
||||
u32 rsvd0:6; // bit[29:24]
|
||||
u32 icv:1; //icv error
|
||||
u32 crc:1; // crc error
|
||||
#else
|
||||
u32 rsvd0:6; // bit[29:24]
|
||||
u32 icv:1; //icv error
|
||||
u32 crc:1; // crc error
|
||||
u32 offset:8; // bit[23:16], the offset from the packet start to the buf start, also means the size of RX Desc
|
||||
u32 pkt_len:16; // bit[15:0], the packet size
|
||||
#endif
|
||||
|
||||
|
||||
// u4Byte 1
|
||||
/************************************************/
|
||||
/*****************receive packet type*********************/
|
||||
/* 0x82: 802.3 packet */
|
||||
/* 0x80: 802.11 packet */
|
||||
/* 0x10: C2H command */
|
||||
/* 0x50: Memory Read */
|
||||
/* 0x52: Memory Write */
|
||||
/* 0x54: Memory Set */
|
||||
/* 0x60: Indicate the firmware is started */
|
||||
#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN)
|
||||
u32 type:8; // bit[7:0], the type of this packet
|
||||
u32 rsvd1:24; // bit[31:8]
|
||||
#else
|
||||
u32 rsvd1:24; // bit[31:8]
|
||||
u32 type:8; // bit[7:0], the type of this packet
|
||||
#endif
|
||||
|
||||
// u4Byte 2
|
||||
u32 start_addr;
|
||||
|
||||
// u4Byte 3
|
||||
#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN)
|
||||
u32 data_len:16; // bit[15:0], the type of this packet
|
||||
u32 result:8; // bit[23:16], the result of memory write command
|
||||
u32 rsvd2:8; // bit[31:24]
|
||||
#else
|
||||
u32 rsvd2:8; // bit[31:24]
|
||||
u32 result:8; // bit[23:16], the result of memory write command
|
||||
u32 data_len:16; // bit[15:0], the type of this packet
|
||||
#endif
|
||||
} GSPI_RX_DESC, *PGSPI_RX_DESC;
|
||||
|
||||
#define SIZE_TX_DESC (sizeof(GSPI_TX_DESC))
|
||||
#define SIZE_RX_DESC (sizeof(GSPI_RX_DESC))
|
||||
|
||||
// CCPWM2 bit map definition for Firmware download
|
||||
#define GSPI_INIT_DONE (BIT0)
|
||||
#define GSPI_MEM_WR_DONE (BIT1)
|
||||
#define GSPI_MEM_RD_DONE (BIT2)
|
||||
#define GSPI_MEM_ST_DONE (BIT3)
|
||||
#define GSPI_CPWM2_TOGGLE (BIT15)
|
||||
|
||||
// Register REG_SPDIO_CPU_IND
|
||||
#define GPSI_SYSTEM_TRX_RDY_IND (BIT0)
|
||||
|
||||
#endif //__GSPI_REG_H__
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue