diff options
author | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
commit | 871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch) | |
tree | 8718f573808810c2a1e8cb8fb6ac469093ca2784 /drivers/net/wireless/eagle/spi_sif_esp.c | |
parent | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff) | |
download | FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2 FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip |
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
Diffstat (limited to 'drivers/net/wireless/eagle/spi_sif_esp.c')
-rwxr-xr-x | drivers/net/wireless/eagle/spi_sif_esp.c | 1952 |
1 files changed, 1952 insertions, 0 deletions
diff --git a/drivers/net/wireless/eagle/spi_sif_esp.c b/drivers/net/wireless/eagle/spi_sif_esp.c new file mode 100755 index 00000000..9e6a2258 --- /dev/null +++ b/drivers/net/wireless/eagle/spi_sif_esp.c @@ -0,0 +1,1952 @@ +/* + * Copyright (c) 2010 -2013 Espressif System. + * + * sdio serial i/f driver + * - sdio device control routines + * - sync/async DMA/PIO read/write + * + */ +#ifdef ESP_USE_SPI + +#include <linux/module.h> +#include <net/mac80211.h> +#include <linux/time.h> +#include <linux/pm.h> +#include <linux/spi/spi.h> +#include <linux/interrupt.h> +#include <linux/kthread.h> + + +#include "esp_pub.h" +#include "esp_sif.h" +#include "esp_sip.h" +#include "esp_debug.h" +#include "slc_host_register.h" +#include "esp_version.h" +#include "esp_ctrl.h" +#ifdef ANDROID +#include "esp_android.h" +#endif /* ANDROID */ +#ifdef USE_EXT_GPIO +#include "esp_ext.h" +#endif /* USE_EXT_GPIO */ + +static int __init esp_spi_init(void); +static void __exit esp_spi_exit(void); + +#define SPI_BLOCK_SIZE (512) + +#define MAX_BUF_SIZE (48*1024) + +static unsigned char *buf_addr = NULL; +static unsigned char *tx_cmd; +static unsigned char *rx_cmd; + +struct task_struct *sif_irq_thread; + +#define ESP_DMA_IBUFSZ 2048 + +//unsigned int esp_msg_level = 0; +unsigned int esp_msg_level = ESP_DBG_ERROR | ESP_SHOW; + +static struct semaphore esp_powerup_sem; + +static enum esp_sdio_state sif_sdio_state; +struct esp_spi_ctrl *sif_sctrl = NULL; + +#ifdef ESP_ANDROID_LOGGER +bool log_off = false; +#endif /* ESP_ANDROID_LOGGER */ + +struct sif_req * sif_alloc_req(struct esp_spi_ctrl *sctrl); + +#include "spi_stub.c" + +void sif_lock_bus(struct esp_pub *epub) +{ + EPUB_FUNC_CHECK(epub); + + spi_bus_lock(EPUB_TO_FUNC(epub)->master); +} + +void sif_unlock_bus(struct esp_pub *epub) +{ + EPUB_FUNC_CHECK(epub); + + spi_bus_unlock(EPUB_TO_FUNC(epub)->master); +} + +int sif_spi_write_then_read(struct spi_device *spi, unsigned char* bufwrite, int sizesend, unsigned char* bufread, int sizeread) +{ + int error; + + error = spi_write_then_read(spi, bufwrite,sizesend, bufread, sizeread); + + if (error) { + esp_dbg(ESP_DBG_ERROR, "%s: failed, error: %d\n", + __func__, error); + return error; + } + + return 0; +} + + +int sif_spi_write_async_read(struct spi_device *spi, unsigned char* bufwrite,unsigned char* bufread,int size) +{ + struct spi_transfer xfer = { + .rx_buf = bufread, + .tx_buf = bufwrite, + .len = size, + .bits_per_word = 8, + .speed_hz = SPI_FREQ, + }; + struct spi_message msg; + int error; + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + + error = spi_sync_locked(spi, &msg); + if (error) { + esp_dbg(ESP_DBG_ERROR, "%s: failed, error: %d\n", + __func__, error); + return error; + } + + return 0; +} + +int sif_spi_write_raw(struct spi_device *spi, unsigned char* buf, int size) +{ + int err; + struct spi_transfer xfer = { + .tx_buf = buf, + .len = size, + .bits_per_word = 8, + .speed_hz = SPI_FREQ, + }; + struct spi_message msg; + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + + err = spi_sync_locked(spi, &msg); + + if (err) { + esp_dbg(ESP_DBG_ERROR, "%s: failed, error: %d\n", + __func__, err); + return err; + } + + return 0; +} + +int sif_spi_read_raw(struct spi_device *spi, unsigned char* buf, int size) +{ + memset(buf,0xff,size); + return sif_spi_write_async_read(spi,buf,buf,size); +} + +int sif_spi_write_bytes(struct spi_device *spi, unsigned int addr, unsigned char *src,int count, int check_idle) +{ + int i; + int pos,len; + unsigned char *tx_data = (unsigned char*)src; + int err_ret = 0; + + u32 timeout = 25000; + u32 busy_state = 0x00; + + ASSERT(spi != NULL); + + if (check_idle) { + timeout = 25000; + do { + busy_state = 0x00; + sif_spi_read_raw(spi, (u8 *)&busy_state, 4); + + if(busy_state != 0xffffffff) + esp_dbg(ESP_DBG_ERROR, "%s busy_state:%x\n", __func__, busy_state); + + } while (busy_state != 0xffffffff && --timeout > 0); + } + + if (timeout < 24000) + esp_dbg(ESP_DBG_ERROR, "%s timeout[%d]\n", __func__, timeout); + + + if(count > 512 ) + { + err_ret = -1; + goto goto_err; + } + + tx_cmd[0]=0x75; + + if( addr >= (1<<17) ) + { + err_ret = -2; + goto goto_err; + + } + else + { + tx_cmd[1]=0x90|0x04|(addr>>15); //0x94; + tx_cmd[2]=addr>>7; + + if(count == 512 ) + { + tx_cmd[3]=( addr<<1|0x0 ); + tx_cmd[4]= 0x00; //0x08; + } + else + { + tx_cmd[3]=( addr<<1|count>>7 ); + tx_cmd[4]= count; //0x08; + } + } + + tx_cmd[5]=0x01; + pos = 5+1; + +//Add cmd respon + memset(tx_cmd+pos,0xff,CMD_RESP_SIZE); + pos =pos+ CMD_RESP_SIZE; + +//Add token + tx_cmd[pos]=0xFE; + pos = pos+1; + +//Add data + memcpy(tx_cmd+pos,tx_data,count); + pos = pos+count; + +//Add data respon + memset(tx_cmd+pos,0xff,DATA_RESP_SIZE_W); + pos = pos+ DATA_RESP_SIZE_W; + + + if( pos%8 ) + { + len = (8 - pos%8); + memset(tx_cmd+pos,0xff,len); + } + else + len = 0; + sif_spi_write_async_read(spi, tx_cmd,tx_cmd,pos+len); + + + + pos = 5+1; + for(i=0;i<CMD_RESP_SIZE;i++) + { + if(tx_cmd[pos+i] == 0x00 && tx_cmd[pos+i-1] == 0xff) + { + if(tx_cmd[pos+i+1] == 0x00 && tx_cmd[pos+i+2] == 0xff) + break; + } + } + if(i>=CMD_RESP_SIZE) + { + esp_dbg(ESP_DBG_ERROR, "write data resp 0x00 no recv\n"); + err_ret = -3; + goto goto_err; + } + + pos = pos+CMD_RESP_SIZE+count+1; + for(i=0;i<DATA_RESP_SIZE_W;i++) + { + if(tx_cmd[pos+i] == 0xE5) + { + //esp_dbg(ESP_DBG_ERROR, "0xE5 pos:%d",i); + for(i++;i<DATA_RESP_SIZE_W;i++) + { + if( tx_cmd[pos+i] == 0xFF) + { + //esp_dbg(ESP_DBG_ERROR, "0xFF pos:%d",i); + break; + } + } + break; + } + } + if(i>=DATA_RESP_SIZE_W) + { + esp_dbg(ESP_DBG_ERROR, "write data resp 0xE5 no recv\n"); + err_ret = -3; + goto goto_err; + } + +goto_err: + return err_ret; +} + +int sif_spi_write_blocks(struct spi_device *spi, unsigned int addr,unsigned char *src, int count, int check_idle) +{ + int err_ret = 0; + int i,j; + int n; + int pos,len; + unsigned char *tx_data = (unsigned char*)src; + u32 busy_state = 0x00; + u32 timeout = 25000; + //esp_dbg(ESP_DBG_ERROR, "Block Write ---------"); + + ASSERT(spi != NULL); + + +#if 1 + if (check_idle) { + timeout = 25000; + do { + busy_state = 0x00; + sif_spi_read_raw(spi, (u8 *)&busy_state, 4); + + if(busy_state != 0xffffffff) + esp_dbg(ESP_DBG_ERROR, "%s busy_state:%x\n", __func__, busy_state); + + } while (busy_state != 0xffffffff && --timeout > 0); + } + + if (timeout < 24000) + esp_dbg(ESP_DBG_ERROR, "%s timeout[%d]\n", __func__, timeout); +#endif + +//esp_dbg(ESP_DBG_ERROR, "Block Write ---------"); + tx_cmd[0]=0x75; + + if( count <=0 ) + { + err_ret = -1; + goto goto_err; + } + + if( addr >= (1<<17) ) + { + err_ret = -2; + goto goto_err; + } + else + { + tx_cmd[1]=0x90|0x0C|(addr>>15); + tx_cmd[2]=addr>>7; + + if(count >= 512 ) + { + tx_cmd[3]=( addr<<1|0x0 ); + tx_cmd[4]= 0x00; + } + else + { + tx_cmd[3]=( addr<<1|count>>7 ); + tx_cmd[4]= count; + } + } + tx_cmd[5]=0x01; + + pos = 5+1; +//Add cmd respon + memset(tx_cmd+pos,0xff,CMD_RESP_SIZE); + pos =pos+ CMD_RESP_SIZE; + + for(j=0;j<count;j++) + { +//Add token + tx_cmd[pos]=0xFC; + pos = pos+1; +//Add data + memcpy(tx_cmd+pos,tx_data+j*SPI_BLOCK_SIZE, SPI_BLOCK_SIZE); + pos = pos+SPI_BLOCK_SIZE; +//Add data respon + if( j==(count- 1) ) + { + memset(tx_cmd+pos , 0xff , BLOCK_W_DATA_RESP_SIZE_FINAL); + pos = pos+ BLOCK_W_DATA_RESP_SIZE_FINAL; + continue; + } + memset(tx_cmd+pos , 0xff , BLOCK_W_DATA_RESP_SIZE_EACH); + pos = pos+ BLOCK_W_DATA_RESP_SIZE_EACH; + } + + if( pos%8 ) + { + len = (8 - pos%8); + memset(tx_cmd+pos,0xff,len); + } + else + len = 0; + + sif_spi_write_async_read(spi, tx_cmd,tx_cmd,pos+len); +//Judge Write cmd resp, and 1st block data resp. + pos = 5+1; + for(i=0;i<CMD_RESP_SIZE;i++) + { + if(tx_cmd[pos+i] == 0x00 && tx_cmd[pos+i-1] == 0xff) + { + if(tx_cmd[pos+i+1] == 0x00 && tx_cmd[pos+i+2] == 0xff) + break; + } + + } + if(i>=CMD_RESP_SIZE) + { + esp_dbg(ESP_DBG_ERROR, "1st block write cmd resp 0x00 no recv, %d\n", count); + err_ret = -3; + goto goto_err; + } + + pos = pos+CMD_RESP_SIZE; + + for(j=0;j<count;j++) + { +//Judge block data resp + pos = pos+1; + pos = pos+SPI_BLOCK_SIZE; + + if( j==(count-1) ) + n = BLOCK_W_DATA_RESP_SIZE_FINAL; + else + n= BLOCK_W_DATA_RESP_SIZE_EACH; + + for(i=0;i<n;i++) + { + if (tx_cmd[pos+i] != 0xff && tx_cmd[pos+i] != 0xe5) + esp_dbg(ESP_DBG_ERROR, " %s [0x%02x] %d block ,!0xff pos:%d\n", __func__, tx_cmd[pos+i], j,i); + //if(tx_cmd[pos+i] == 0xE5) + if( (tx_cmd[pos+i]&0x0F) == 0x05 ) + { +//esp_dbg(ESP_DBG_ERROR, "%d block ,0xE5 pos:%d",j,i); + for(i++;i<n;i++) + { + if( tx_cmd[pos+i] == 0xFF) + { +//esp_dbg(ESP_DBG_ERROR, "%d block ,0xFF pos:%d",j,i); + break; + } + } + break; + } + } + if(i>=n) + { + esp_dbg(ESP_DBG_ERROR, "%s block%d write data rsp error, %d\n", __func__, j+1, count); + err_ret = -4; + goto goto_err; + } + pos = pos+n; + } +#if 0 +//Add stop token + pos = 0; + tx_cmd[pos]=0xFD; + pos = pos+1; +//Add data respon + memset(tx_cmd+pos , 0xff , BLOCK_W_DATA_RESP_SIZE_FINAL); + pos = pos+ BLOCK_W_DATA_RESP_SIZE_FINAL; + eagle_spi_write_async_read(tx_cmd,tx_cmd,pos); + +//Judge Final busy bits. + pos = 1; + for(i=0;i<BLOCK_W_DATA_RESP_SIZE_FINAL;i++) + { + if(tx_cmd[pos+i] != 0xFF) + { +//esp_dbg(ESP_DBG_ERROR, "Final 0x00 pos:%d",i); + for(i++;i<BLOCK_W_DATA_RESP_SIZE_FINAL;i++) + { + if( tx_cmd[pos+i] == 0xFF) + { +//esp_dbg(ESP_DBG_ERROR, "Final 0xFF pos:%d",i); + break; + } + } + break; + } + } + + if(i>=BLOCK_W_DATA_RESP_SIZE_FINAL) + { + mutex_unlock(&RWMutex); + esp_dbg(ESP_DBG_ERROR, "blocks final busy bit no recv"); + return -5; + } +#endif + +goto_err: + + return err_ret; +} + +int sif_spi_write_mix_nosync(struct spi_device *spi, unsigned int addr, unsigned char *buf, int len, int check_idle) +{ + int blk_cnt; + int remain_len; + int err; + + blk_cnt = len/SPI_BLOCK_SIZE; + remain_len = len%SPI_BLOCK_SIZE; + + if (blk_cnt > 0) { + err = sif_spi_write_blocks(spi, addr, buf, blk_cnt, check_idle); + if (err) + return err; + } + + if (remain_len > 0) { + err = sif_spi_write_bytes(spi, addr, (buf + (blk_cnt*SPI_BLOCK_SIZE)), remain_len, check_idle); + if (err) + return err; + } + + return 0; + +} + +int sif_spi_write_mix_sync(struct spi_device *spi, unsigned int addr, unsigned char *buf, int len, int check_idle) +{ + int err; + + spi_bus_lock(spi->master); + err = sif_spi_write_mix_nosync(spi, addr, buf, len, check_idle); + spi_bus_unlock(spi->master); + + return err; +} + +int sif_spi_epub_write_mix_nosync(struct esp_pub *epub, unsigned int addr, unsigned char *buf,int len, int check_idle) +{ + struct esp_spi_ctrl *sctrl = NULL; + struct spi_device *spi = NULL; + + ASSERT(epub != NULL); + sctrl = (struct esp_spi_ctrl *)epub->sif; + spi = sctrl->spi; + ASSERT(spi != NULL); + + return sif_spi_write_mix_nosync(spi, addr, buf, len, check_idle); +} + +int sif_spi_epub_write_mix_sync(struct esp_pub *epub, unsigned int addr, unsigned char *buf,int len, int check_idle) +{ + struct esp_spi_ctrl *sctrl = NULL; + struct spi_device *spi = NULL; + + ASSERT(epub != NULL); + sctrl = (struct esp_spi_ctrl *)epub->sif; + spi = sctrl->spi; + ASSERT(spi != NULL); + + return sif_spi_write_mix_sync(spi, addr, buf, len, check_idle); +} + +int sif_spi_read_bytes(struct spi_device *spi, unsigned int addr,unsigned char *dst, int count, int check_idle) +{ + int pos,total_num,len; + int i; + unsigned char *rx_data = (unsigned char *)dst; + int err_ret = 0; + + u32 timeout = 25000; + u32 busy_state = 0x00; + + ASSERT(spi != NULL); + + + rx_cmd[0]=0x75; + + if (check_idle) { + timeout = 25000; + do { + busy_state = 0x00; + sif_spi_read_raw(spi, (u8 *)&busy_state, 4); + + if(busy_state != 0xffffffff) + esp_dbg(ESP_DBG_ERROR, "%s busy_state:%x\n", __func__, busy_state); + + } while (busy_state != 0xffffffff && --timeout > 0); + } + + if (timeout < 24000) + esp_dbg(ESP_DBG_ERROR, "%s timeout[%d]\n", __func__, timeout); + + if(count > 512 ) + { + err_ret = -1; + goto goto_err; + } + + if( addr >= (1<<17) ) + { + err_ret = -2; + goto goto_err; + } + else + { + rx_cmd[1]=0x10|0x04|(addr>>15); //0x94; + rx_cmd[2]=addr>>7; + + if(count == 512 ) + { + rx_cmd[3]=( addr<<1|0x0 ); + rx_cmd[4]= 0x00; //0x08; + } + else + { + rx_cmd[3]=( addr<<1|count>>7 ); + rx_cmd[4]= count; //0x08; + } + } + + rx_cmd[5]=0x01; + +#if 1 // one shot read + total_num = CMD_RESP_SIZE+DATA_RESP_SIZE_R+count+2; + memset(rx_cmd+6 , 0xFF ,total_num); + + + if( (6+total_num)%8 ) + { + len = (8 - (6+total_num)%8); + memset(rx_cmd+6+total_num,0xff,len); + } + else + len = 0; + sif_spi_write_async_read(spi, rx_cmd,rx_cmd,6+total_num+len); + + pos = 5+1; + for(i=0;i<CMD_RESP_SIZE;i++) + { + if(rx_cmd[pos+i] == 0x00 && rx_cmd[pos+i-1] == 0xff) + { + if(rx_cmd[pos+i+1] == 0x00 && rx_cmd[pos+i+2] == 0xff) + break; + } + } + if(i>=CMD_RESP_SIZE) + { + esp_dbg(ESP_DBG_ERROR, "read cmd resp 0x00 no recv\n"); +/***********error info************************/ +/* + char t = pos; + while ( t < pos+32) { + printk(KERN_ERR "rx:[0x%02x] ", rx_cmd[t]); + t++; + if ((t-pos)%8 == 0) + printk(KERN_ERR "\n"); + } +*/ + err_ret = -3; + goto goto_err; + } +//esp_dbg(ESP_DBG_ERROR, "0x00 pos:%d",pos+i); + pos = pos+i+2; + + for(i=0;i<DATA_RESP_SIZE_R;i++) + { + if(rx_cmd[pos+i]==0xFE) + break; + } + if(i>=DATA_RESP_SIZE_R) + { + esp_dbg(ESP_DBG_ERROR, "read data resp 0xFE no recv\n"); + err_ret = -4; + goto goto_err; + } +//esp_dbg(ESP_DBG_ERROR, "0xFE pos:%d",pos+i); + pos = pos+i+1; + memcpy(rx_data,rx_cmd+pos,count); +#else //wait method + + memset(rx_cmd+6,0xFF,CMD_RESP_SIZE+DATA_RESP_SIZE_R+count+2); +//printk(KERN_ERR "mark 1",pos+i); + sif_spi_write_async_read(spi, rx_cmd,rx_cmd,6+CMD_RESP_SIZE+DATA_RESP_SIZE_R+count+2); +//printk(KERN_ERR "mark 2",pos+i); + pos = 5+1; + for(i=0;i<CMD_RESP_SIZE;i++) + { + if(rx_cmd[pos+i] == 0x00 && rx_cmd[pos+i-1] == 0xff) + { + if(rx_cmd[pos+i+1] == 0x00 && rx_cmd[pos+i+2] == 0xff) + break; + } + } + if(i>=CMD_RESP_SIZE) + { + printk(KERN_ERR "read cmd resp 0x00 no recv\n"); + //kfree(rx_cmd); + err_ret = -3; + goto goto_err; + } +//printk(KERN_ERR "0x00 pos:%d",pos+i); + pos = pos+i+2; + + for(i=0;i<DATA_RESP_SIZE_R;i++) + { + if(rx_cmd[pos+i]==0xFE) + break; + } + if(i>=DATA_RESP_SIZE_R) + { + printk(KERN_ERR "read data resp 0xFE no recv\n"); + err_ret = -4; + goto goto_err; + } +//printk(KERN_ERR "0xFE pos:%d",pos+i); + pos = pos+i+1; + + for(i=0;i<count;i++) + { + *(rx_data+i) = rx_cmd[pos+i]; + } + + +#endif +goto_err: + + return err_ret; +} + +int sif_spi_read_blocks(struct spi_device *spi, unsigned int addr, unsigned char *dst, int count, int check_idle) +{ + int err_ret = 0; + int pos,len; + int i,j; + unsigned char *rx_data = (unsigned char *)dst; + int total_num; + u32 busy_state = 0x00; + u32 timeout = 25000; + + //esp_dbg(ESP_DBG_ERROR, "Block Read ---------"); + ASSERT(spi != NULL); + + +#if 1 + if (check_idle) { + timeout = 25000; + do { + busy_state = 0x00; + sif_spi_read_raw(spi, (u8 *)&busy_state, 4); + + if(busy_state != 0xffffffff) + esp_dbg(ESP_DBG_ERROR, "%s busy_state:%x\n", __func__, busy_state); + + } while (busy_state != 0xffffffff && --timeout > 0); + } + + if (timeout < 24000) + esp_dbg(ESP_DBG_ERROR, "%s timeout[%d]\n", __func__, timeout); +#endif + rx_cmd[0]=0x75; + + if( count <=0 ) + { + err_ret = -1; + goto goto_err; + } + if( addr >= (1<<17) ) + { + err_ret = -2; + goto goto_err; + } + else + { + rx_cmd[1]=0x10|0x0C|(addr>>15); + rx_cmd[2]=addr>>7; + + if(count >= 512 ) + { + rx_cmd[3]=( addr<<1|0x0 ); + rx_cmd[4]= 0x00; + } + else + { + rx_cmd[3]=( addr<<1|count>>7 ); + rx_cmd[4]= count; + } + } + rx_cmd[5]=0x01; + total_num = CMD_RESP_SIZE+BLOCK_R_DATA_RESP_SIZE_1ST+SPI_BLOCK_SIZE+ 2 + (count-1)*(BLOCK_R_DATA_RESP_SIZE_EACH+SPI_BLOCK_SIZE+2); + memset(rx_cmd+6, 0xFF ,total_num); + + if( (6+total_num)%8 ) + { + len = (8 - (6+total_num)%8); + memset(rx_cmd+6+total_num,0xff,len); + } + else + len = 0; + + sif_spi_write_async_read(spi, rx_cmd,rx_cmd,6+total_num+len ); + + pos = 5+1; + for(i=0;i<CMD_RESP_SIZE;i++) + { + if(rx_cmd[pos+i] == 0x00 && rx_cmd[pos+i-1] == 0xff) + { + if(rx_cmd[pos+i+1] == 0x00 && rx_cmd[pos+i+2] == 0xff) + break; + } + + } + if(i>=CMD_RESP_SIZE) + { + esp_dbg(ESP_DBG_ERROR, "block read cmd resp 0x00 no recv\n"); +#if 0 + char t = pos; + while ( t < pos+32) { + printk(KERN_ERR "rx:[0x%02x] ", rx_cmd[t]); + t++; + if ((t-pos)%8 == 0) + printk(KERN_ERR "\n"); + } +#endif + + err_ret = -3; + goto goto_err; + } + + pos = pos+i+2; + + for(i=0;i<BLOCK_R_DATA_RESP_SIZE_1ST;i++) + { + if(rx_cmd[pos+i]==0xFE) + { +//esp_dbg(ESP_DBG_ERROR, "0xFE pos:%d",i); + break; + } + } + if(i>=BLOCK_R_DATA_RESP_SIZE_1ST) + { + esp_dbg(ESP_DBG_ERROR, "1st block read data resp 0xFE no recv\n"); + err_ret = -4; + goto goto_err; + } + + pos = pos+i+1; + + memcpy(rx_data,rx_cmd+pos,SPI_BLOCK_SIZE); + + pos = pos +SPI_BLOCK_SIZE + 2; + + for(j=1;j<count;j++) + { + + for(i=0;i<BLOCK_R_DATA_RESP_SIZE_EACH;i++) + { + if(rx_cmd[pos+i]==0xFE) + { + //esp_dbg(ESP_DBG_ERROR, "0xFE pos:%d",i); + break; + } + } + if(i>=BLOCK_R_DATA_RESP_SIZE_EACH) + { + esp_dbg(ESP_DBG_ERROR, "block%d read data resp 0xFE no recv,total:%d\n",j+1,count); + err_ret = -4; + goto goto_err; + } + + pos = pos+i+1; + + memcpy(rx_data+j*SPI_BLOCK_SIZE,rx_cmd+pos,SPI_BLOCK_SIZE); + + pos = pos +SPI_BLOCK_SIZE + 2; + } + +goto_err: + + return err_ret; +} + +int sif_spi_read_mix_nosync(struct spi_device *spi, unsigned int addr, unsigned char *buf, int len, int check_idle) +{ + int blk_cnt; + int remain_len; + int err; + + blk_cnt = len/SPI_BLOCK_SIZE; + remain_len = len%SPI_BLOCK_SIZE; + + if (blk_cnt > 0) { + err = sif_spi_read_blocks(spi, addr, buf, blk_cnt, check_idle); + if (err) + return err; + } + + if (remain_len > 0) { + err = sif_spi_read_bytes(spi, addr, (buf + (blk_cnt*SPI_BLOCK_SIZE)), remain_len, check_idle); + if (err) + return err; + } + + return 0; +} + +int sif_spi_read_mix_sync(struct spi_device *spi, unsigned int addr, unsigned char *buf, int len, int check_idle) +{ + int err; + + spi_bus_lock(spi->master); + err = sif_spi_read_mix_nosync(spi, addr, buf, len, check_idle); + spi_bus_unlock(spi->master); + + return err; +} + +int sif_spi_epub_read_mix_nosync(struct esp_pub *epub, unsigned int addr, unsigned char *buf,int len, int check_idle) +{ + struct esp_spi_ctrl *sctrl = NULL; + struct spi_device *spi = NULL; + + ASSERT(epub != NULL); + sctrl = (struct esp_spi_ctrl *)epub->sif; + spi = sctrl->spi; + ASSERT(spi != NULL); + + return sif_spi_read_mix_nosync(spi, addr, buf, len, check_idle); +} + +int sif_spi_epub_read_mix_sync(struct esp_pub *epub, unsigned int addr, unsigned char *buf,int len, int check_idle) +{ + struct esp_spi_ctrl *sctrl = NULL; + struct spi_device *spi = NULL; + + ASSERT(epub != NULL); + sctrl = (struct esp_spi_ctrl *)epub->sif; + spi = sctrl->spi; + ASSERT(spi != NULL); + + return sif_spi_read_mix_sync(spi, addr, buf, len, check_idle); +} + +int sif_spi_read_sync(struct esp_pub *epub, unsigned char *buf, int len, int check_idle) +{ + struct esp_spi_ctrl *sctrl = NULL; + struct spi_device *spi = NULL; + u32 read_len; + + ASSERT(epub != NULL); + ASSERT(buf != NULL); + + sctrl = (struct esp_spi_ctrl *)epub->sif; + spi = sctrl->spi; + ASSERT(spi != NULL); + + switch(sctrl->target_id) { + case 0x100: + read_len = len; + break; + case 0x600: + read_len = roundup(len, sctrl->slc_blk_sz); + break; + default: + read_len = len; + break; + } + + return sif_spi_read_mix_sync(spi, sctrl->slc_window_end_addr - 2 - (len), buf, read_len, check_idle); +} + +int sif_spi_write_sync(struct esp_pub *epub, unsigned char *buf, int len, int check_idle) +{ + struct esp_spi_ctrl *sctrl = NULL; + struct spi_device *spi = NULL; + u32 write_len; + + ASSERT(epub != NULL); + ASSERT(buf != NULL); + + sctrl = (struct esp_spi_ctrl *)epub->sif; + spi = sctrl->spi; + ASSERT(spi != NULL); + + switch(sctrl->target_id) { + case 0x100: + write_len = len; + break; + case 0x600: + write_len = roundup(len, sctrl->slc_blk_sz); + break; + default: + write_len = len; + break; + } + return sif_spi_write_mix_sync(spi, sctrl->slc_window_end_addr - (len), buf, write_len, check_idle); +} + +int sif_spi_read_nosync(struct esp_pub *epub, unsigned char *buf, int len, int check_idle, bool noround) +{ + struct esp_spi_ctrl *sctrl = NULL; + struct spi_device *spi = NULL; + u32 read_len; + + ASSERT(epub != NULL); + ASSERT(buf != NULL); + + sctrl = (struct esp_spi_ctrl *)epub->sif; + spi = sctrl->spi; + ASSERT(spi != NULL); + + switch(sctrl->target_id) { + case 0x100: + read_len = len; + break; + case 0x600: + if (!noround) + read_len = roundup(len, sctrl->slc_blk_sz); + else + read_len = len; + break; + default: + read_len = len; + break; + } + + return sif_spi_read_mix_nosync(spi, sctrl->slc_window_end_addr - 2 - (len), buf, read_len, check_idle); +} + +int sif_spi_write_nosync(struct esp_pub *epub, unsigned char *buf, int len, int check_idle) +{ + struct esp_spi_ctrl *sctrl = NULL; + struct spi_device *spi = NULL; + u32 write_len; + + ASSERT(epub != NULL); + ASSERT(buf != NULL); + + sctrl = (struct esp_spi_ctrl *)epub->sif; + spi = sctrl->spi; + ASSERT(spi != NULL); + + switch(sctrl->target_id) { + case 0x100: + write_len = len; + break; + case 0x600: + write_len = roundup(len, sctrl->slc_blk_sz); + break; + default: + write_len = len; + break; + } + return sif_spi_write_mix_nosync(spi, sctrl->slc_window_end_addr - (len), buf, write_len, check_idle); +} + +void sif_spi_protocol_init(struct spi_device *spi) +{ + unsigned char spi_proto_ini_status = 0; + unsigned char rx_buf1[10]; + unsigned char tx_buf1[10]; + unsigned char dummy_tx_buf[10]; + memset(dummy_tx_buf,0xff,sizeof(dummy_tx_buf)); + do + { + if( spi_proto_ini_status == 0 ) + { + do + { + tx_buf1[0]=0x40; + tx_buf1[1]=0x00; + tx_buf1[2]=0x00; + tx_buf1[3]=0x00; + tx_buf1[4]=0x00; + tx_buf1[5]=0x95; + //printf("CMD0 \n"); + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + mdelay(100); + }while( rx_buf1[2] != 0x01 ); + // }while(1); + } + else if( spi_proto_ini_status == 1 ) + { + tx_buf1[0]=0x45; + tx_buf1[1]=0x00; + tx_buf1[2]=0x20; //0x04; + tx_buf1[3]=0x00; + tx_buf1[4]=0x00; + tx_buf1[5]=0x01; + //spi_err("CMD 5 1st\n"); + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + } + else if( spi_proto_ini_status == 2 ) + { + tx_buf1[0]=0x45; + tx_buf1[1]=0x00; + tx_buf1[2]=0x20; + tx_buf1[3]=0x00; + tx_buf1[4]=0x00; + tx_buf1[5]=0x01; + //spi_err("CMD5 2nd\n"); + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + } + else if( spi_proto_ini_status == 3 ) //CMD 52 addr 0x2, data 0x02; + { + tx_buf1[0]=0x74; + tx_buf1[1]=0x80; + tx_buf1[2]=0x00; + tx_buf1[3]=0x04; + tx_buf1[4]=0x02; + tx_buf1[5]=0x01; + //spi_err("CMD52 Write addr 02 \n"); + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + } + else if( spi_proto_ini_status == 4 ) + { + tx_buf1[0]=0x74; + tx_buf1[1]=0x80; + tx_buf1[2]=0x00; + tx_buf1[3]=0x08; + tx_buf1[4]=0x03; + tx_buf1[5]=0x01; + //spi_err("CMD52 Write addr 04 \n"); + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + } + else if( spi_proto_ini_status == 5 ) + { + tx_buf1[0]=0x74; + tx_buf1[1]=0x00; + tx_buf1[2]=0x00; + tx_buf1[3]=0x04; + tx_buf1[4]=0x00; + tx_buf1[5]=0x01; + //spi_err("CMD52 Read addr 0x2 \n"); + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + + } + else if( spi_proto_ini_status == 6 ) + { + tx_buf1[0]=0x74; + tx_buf1[1]=0x00; + tx_buf1[2]=0x00; + tx_buf1[3]=0x08; + tx_buf1[4]=0x00; + tx_buf1[5]=0x01; + //spi_err("CMD52 Read addr 0x4 \n"); + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + } + else if (spi_proto_ini_status>6 && spi_proto_ini_status<15) + { + tx_buf1[0]=0x74; + tx_buf1[1]=0x10; + tx_buf1[2]=0x00; + tx_buf1[3]=0xF0+2*(spi_proto_ini_status-7); + tx_buf1[4]=0x00; + tx_buf1[5]=0x01; + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + } + else if (spi_proto_ini_status==15) + { + //spi_err("CMD52 Write Reg addr 0x110 \n"); + tx_buf1[0]=0x74; + tx_buf1[1]=0x80; //func0 should be + tx_buf1[2]=0x02; + tx_buf1[3]=0x20; + tx_buf1[4]=(unsigned char)(SPI_BLOCK_SIZE & 0xff); //0x02; + tx_buf1[5]=0x01; + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + + //spi_err("CMD52 Write Reg addr 0x111 \n"); + tx_buf1[0]=0x74; + tx_buf1[1]=0x80; + tx_buf1[2]=0x02; + tx_buf1[3]=0x22; + tx_buf1[4]=(unsigned char)(SPI_BLOCK_SIZE>>8); //0x00; + tx_buf1[5]=0x01; + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + + //spi_err("CMD52 Write Reg addr 0x111 \n"); /* set boot mode */ + tx_buf1[0]=0x74; + tx_buf1[1]=0x80; + tx_buf1[2]=0x41; + tx_buf1[3]=0xe0; + tx_buf1[4]=0x01; //0x00; + tx_buf1[5]=0x01; + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + + } + else if (spi_proto_ini_status==16) + { +#if 0 + //printf("CMD52 Write Reg addr 0x40 \n"); + tx_buf1[0]=0x74; + tx_buf1[1]=0x90; + tx_buf1[2]=0x00; + tx_buf1[3]=0x80; + tx_buf1[4]=0x91; //0x02; + tx_buf1[5]=0x01; + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + + //sif_spi_read_bytes( 0x0c,rx_buf1, 4); + + //printf("CMD52 Write Reg addr 0x3c \n"); + tx_buf1[0]=0x74; + tx_buf1[1]=0x90; + tx_buf1[2]=0x00; + tx_buf1[3]=0x78; + tx_buf1[4]=0x3f; + tx_buf1[5]=0x01; + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + + //printf("CMD52 Write Reg addr 0x3d \n"); + tx_buf1[0]=0x74; + tx_buf1[1]=0x90; + tx_buf1[2]=0x00; + tx_buf1[3]=0x7a; + tx_buf1[4]=0x34; //0x02; + tx_buf1[5]=0x01; + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + + // printf("CMD52 Write Reg addr 0x3e \n"); + tx_buf1[0]=0x74; + tx_buf1[1]=0x90; + tx_buf1[2]=0x00; + tx_buf1[3]=0x7c; + tx_buf1[4]=0xfe; //0x02; + tx_buf1[5]=0x01; + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + + //printf("CMD52 Write Reg addr 0x3f \n"); + tx_buf1[0]=0x74; + tx_buf1[1]=0x90; + tx_buf1[2]=0x00; + tx_buf1[3]=0x7e; + tx_buf1[4]=0x00; //0x02; + tx_buf1[5]=0x01; + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + + //printf("CMD52 Write Reg addr 0x40 \n"); + tx_buf1[0]=0x74; + tx_buf1[1]=0x90; + tx_buf1[2]=0x00; + tx_buf1[3]=0x80; + tx_buf1[4]=0xd1; //0x02; + tx_buf1[5]=0x01; + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + + tx_buf1[0]=0x74; + tx_buf1[1]=0x90; + tx_buf1[2]=0x00; + tx_buf1[3]=0x52; + tx_buf1[4]=0x30; //0x02; + tx_buf1[5]=0x01; + sif_spi_write_raw(spi, tx_buf1, 6); + sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10); + esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1] + ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]); + +#endif + } + else + { + break; + } + // mdelay(500); + spi_proto_ini_status++; + } while (1); +} + +int sif_spi_read_reg(struct spi_device *spi, unsigned int addr, unsigned char *value ) +{ + unsigned char tx_cmd[6]; + unsigned char rx_cmd[20]; + int err_ret = 0; + + + tx_cmd[0]=0x74; + + if( addr >= (1<<17) ) + { + err_ret = -1; + goto goto_err; + //return err_ret; + } + else + { + tx_cmd[1]=0x10|0x00|(addr>>15); + tx_cmd[2]=addr>>7; + + tx_cmd[3]=( addr<<1 ); + tx_cmd[4]= 0x00; + } + + tx_cmd[5]=0x01; + + sif_spi_write_raw(spi, tx_cmd,6); + //printf("CMD52 Read \n"); +#if 0 +//Response read + + sif_spi_read_raw(spi, rx_cmd,20); + + esp_dbg(ESP_DBG_ERROR, "write resp:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_cmd[0],rx_cmd[1] + ,rx_cmd[2],rx_cmd[3],rx_cmd[4],rx_cmd[5],rx_cmd[6],rx_cmd[7],rx_cmd[8],rx_cmd[9]); + return 0; + #else + + //Read Response. + do + { + rx_cmd[0]=0xFF; + sif_spi_read_raw(spi, rx_cmd,1); + }while(rx_cmd[0]==0xFF); + rx_cmd[1]=0xFF; + sif_spi_read_raw(spi, rx_cmd+1,1); + + esp_dbg(ESP_DBG_ERROR, "read resp:[0x%02x],[0x%02x]\n",rx_cmd[0],rx_cmd[1]); + + if(rx_cmd[0]!=0) + err_ret = -1; + else + err_ret = 0; + + *value = rx_cmd[1]; + + //return err_ret; + #endif + +goto_err: + + return err_ret; +} + + +int sif_spi_write_reg(struct spi_device *spi, unsigned int addr, unsigned char value) +{ + unsigned char tx_cmd[6]; + unsigned char rx_cmd[20]; + int err_ret = 0; + + + + tx_cmd[0]=0x74; + + if( addr >= (1<<17) ) + { + err_ret = -1; + goto goto_err; + //return err_ret; + } + else + { + tx_cmd[1]=0x90|0x00|(addr>>15); //0x94; + tx_cmd[2]=addr>>7; + + tx_cmd[3]=( addr<<1 ); + tx_cmd[4]= value; + } + + tx_cmd[5]=0x01; + sif_spi_write_raw(spi, tx_cmd,6); + //printf("CMD52 <Write config> stauts=16 \n"); + + +#if 0 + //memset(rx_cmd,0xFF,20); + sif_spi_read_raw(spi, rx_cmd,20); + + esp_dbg(ESP_DBG_ERROR, "write resp:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_cmd[0],rx_cmd[1] + ,rx_cmd[2],rx_cmd[3],rx_cmd[4],rx_cmd[5],rx_cmd[6],rx_cmd[7],rx_cmd[8],rx_cmd[9]); + return 0; +#else + + do + { + rx_cmd[0]=0xFF; + sif_spi_read_raw(spi, rx_cmd,1); + }while(rx_cmd[0]==0xFF); + rx_cmd[1]=0xFF; + sif_spi_read_raw(spi, rx_cmd+1,1); + + if( rx_cmd[1]!=value ) + { + //printf("Write error,%X,%X", rx_cmd[0],rx_cmd[1]); + esp_dbg(ESP_DBG_ERROR, "write resp:[0x%02x],[0x%02x]\n",rx_cmd[0],rx_cmd[1]); + err_ret = -1; + goto goto_err; + + } + +goto_err: + + return err_ret; + +#endif +//Read Response. + +} + +static int spi_irq_thread(void *data) +{ + struct spi_device *spi = (struct spi_device *)data; + + do { + sif_dsr(spi); + + set_current_state(TASK_INTERRUPTIBLE); + sif_platform_irq_mask(0); + + if (!kthread_should_stop()) + schedule(); + + set_current_state(TASK_RUNNING); + + } while (!kthread_should_stop()); + return 0; +} + +int sif_setup_irq_thread(struct spi_device *spi) +{ + sif_irq_thread = kthread_run(spi_irq_thread, spi, "kspiirqd/eagle"); + if (IS_ERR(sif_irq_thread)) { + esp_dbg(ESP_DBG_ERROR, "setup irq thread error!\n"); + return -1; + } + return 0; +} + +static irqreturn_t sif_irq_handler(int irq, void *dev_id) +{ + sif_platform_irq_mask(1); + + if (sif_platform_is_irq_occur()) { + wake_up_process(sif_irq_thread); + } else { + sif_platform_irq_mask(0); + return IRQ_NONE; + } + + return IRQ_HANDLED; +} + +void sif_enable_irq(struct esp_pub *epub) +{ + int err; + struct esp_spi_ctrl *sctrl = NULL; + struct spi_device *spi = NULL; + + ASSERT(epub != NULL); + + sctrl = (struct esp_spi_ctrl *)epub->sif; + spi = sctrl->spi; + ASSERT(spi != NULL); + + mdelay(100); + + sif_platform_irq_init(); + err = sif_setup_irq_thread(spi); + if (err) { + esp_dbg(ESP_DBG_ERROR, "%s setup sif irq failed\n", __func__); + return; + } + +/******************compat with other device in some shared irq system ********************/ + +#ifdef REQUEST_IRQ_SHARED +#if defined(REQUEST_IRQ_RISING) + err = request_irq(sif_platform_get_irq_no(), sif_irq_handler, IRQF_TRIGGER_RISING | IRQF_SHARED, "esp_spi_irq", spi); +#elif defined(REQUEST_IRQ_FALLING) + err = request_irq(sif_platform_get_irq_no(), sif_irq_handler, IRQF_TRIGGER_FALLING | IRQF_SHARED, "esp_spi_irq", spi); +#elif defined(REQUEST_IRQ_LOWLEVEL) + err = request_irq(sif_platform_get_irq_no(), sif_irq_handler, IRQF_TRIGGER_LOW | IRQF_SHARED, "esp_spi_irq", spi); +#elif defined(REQUEST_IRQ_HIGHLEVEL) + err = request_irq(sif_platform_get_irq_no(), sif_irq_handler, IRQF_TRIGGER_HIGH | IRQF_SHARED, "esp_spi_irq", spi); +#else /* default */ + err = request_irq(sif_platform_get_irq_no(), sif_irq_handler, IRQF_TRIGGER_LOW | IRQF_SHARED, "esp_spi_irq", spi); +#endif /* TRIGGER MODE */ +#else + err = request_irq(sif_platform_get_irq_no(), sif_irq_handler, IRQF_TRIGGER_LOW, "esp_spi_irq", spi); +#endif /* ESP_IRQ_SHARED */ + + if (err) { + esp_dbg(ESP_DBG_ERROR, "sif %s failed\n", __func__); + return ; + } + + atomic_set(&sctrl->irq_installed, 1); +} + +void sif_disable_irq(struct esp_pub *epub) +{ + int i = 0; + struct esp_spi_ctrl *sctrl = NULL; + struct spi_device *spi = NULL; + + ASSERT(epub != NULL); + + sctrl = (struct esp_spi_ctrl *)epub->sif; + spi = sctrl->spi; + ASSERT(spi != NULL); + + + if (atomic_read(&sctrl->irq_installed) == 0) + return; + + while (atomic_read(&sctrl->irq_handling)) { + schedule_timeout(HZ / 100); + if (i++ >= 400) { + esp_dbg(ESP_DBG_ERROR, "%s force to stop irq\n", __func__); + break; + } + } + + free_irq(sif_platform_get_irq_no(), spi); + kthread_stop(sif_irq_thread); + + sif_platform_irq_deinit(); + + atomic_set(&sctrl->irq_installed, 0); +} + + +int esp_setup_spi(struct spi_device *spi) +{ + /**** alloc buffer for spi io */ + if (sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT) { + buf_addr = (unsigned char *)kmalloc (MAX_BUF_SIZE, GFP_KERNEL); + if (buf_addr == NULL) + return -ENOMEM; + + tx_cmd = buf_addr; + rx_cmd = buf_addr; + } + +#if 0 + spi->mode = 0x03; + spi->bits_per_word = 8; + spi->max_speed_hz = SPI_FREQ; + + return spi_setup(spi); +#endif + return 0; +} + + +static int esp_spi_probe(struct spi_device *spi); +static int esp_spi_remove(struct spi_device *spi); + +static int esp_spi_probe(struct spi_device *spi) +{ + int err; + struct esp_pub *epub; + struct esp_spi_ctrl *sctrl; + + esp_dbg(ESP_DBG_ERROR, "%s enter\n", __func__); + + err = esp_setup_spi(spi); + if (err) { + esp_dbg(ESP_DBG_ERROR, "%s setup_spi error[%d]\n", __func__, err); + goto _err_spi; + } + esp_dbg(ESP_DBG_ERROR, "%s init_protocol\n", __func__); + sif_spi_protocol_init(spi); + + if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT){ + sctrl = kzalloc(sizeof(struct esp_spi_ctrl), GFP_KERNEL); + + if (sctrl == NULL) { + assert(0); + return -ENOMEM; + } + + /* temp buffer reserved for un-dma-able request */ + sctrl->dma_buffer = kzalloc(ESP_DMA_IBUFSZ, GFP_KERNEL); + + if (sctrl->dma_buffer == NULL) { + assert(0); + goto _err_last; + } + sif_sctrl = sctrl; + sctrl->slc_blk_sz = SIF_SLC_BLOCK_SIZE; + + epub = esp_pub_alloc_mac80211(&spi->dev); + + if (epub == NULL) { + esp_dbg(ESP_DBG_ERROR, "no mem for epub \n"); + err = -ENOMEM; + goto _err_dma; + } + epub->sif = (void *)sctrl; + sctrl->epub = epub; + +#ifdef USE_EXT_GPIO + err = ext_gpio_init(epub); + if (err) { + esp_dbg(ESP_DBG_ERROR, "ext_irq_work_init failed %d\n", err); + return err; + } +#endif + + } else { + ASSERT(sif_sctrl != NULL); + sctrl = sif_sctrl; + sif_sctrl = NULL; + epub = sctrl->epub; + SET_IEEE80211_DEV(epub->hw, &spi->dev); + epub->dev = &spi->dev; + } + + epub->sdio_state = sif_sdio_state; + + sctrl->spi = spi; + spi_set_drvdata(spi, sctrl); + + if (err){ + if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT) + goto _err_epub; + else + goto _err_second_init; + } + check_target_id(epub); + +#ifdef SDIO_TEST + sif_test_tx(sctrl); +#else + err = esp_pub_init_all(epub); + + if (err) { + esp_dbg(ESP_DBG_ERROR, "esp_init_all failed: %d\n", err); + if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT){ + err = 0; + goto _err_first_init; + } + if(sif_sdio_state == ESP_SDIO_STATE_SECOND_INIT) + goto _err_second_init; + } + +#endif //SDIO_TEST + esp_dbg(ESP_DBG_TRACE, " %s return %d\n", __func__, err); + if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT){ + esp_dbg(ESP_DBG_ERROR, "first normal exit\n"); + sif_sdio_state = ESP_SDIO_STATE_FIRST_NORMAL_EXIT; + up(&esp_powerup_sem); + } + + return err; + +_err_epub: + esp_pub_dealloc_mac80211(epub); +_err_dma: + kfree(sctrl->dma_buffer); +_err_last: + kfree(sctrl); +_err_spi: + if (buf_addr) { + kfree(buf_addr); + buf_addr = NULL; + tx_cmd = NULL; + rx_cmd = NULL; + } +_err_first_init: + if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT){ + esp_dbg(ESP_DBG_ERROR, "first error exit\n"); + sif_sdio_state = ESP_SDIO_STATE_FIRST_ERROR_EXIT; + up(&esp_powerup_sem); + } + return err; +_err_second_init: + sif_sdio_state = ESP_SDIO_STATE_SECOND_ERROR_EXIT; + esp_spi_remove(spi); + return err; +} + +static int esp_spi_remove(struct spi_device *spi) +{ + struct esp_spi_ctrl *sctrl = NULL; + + sctrl = spi_get_drvdata(spi); + + if (sctrl == NULL) { + esp_dbg(ESP_DBG_ERROR, "%s no sctrl\n", __func__); + return -EINVAL; + } + + do { + if (sctrl->epub == NULL) { + esp_dbg(ESP_DBG_ERROR, "%s epub null\n", __func__); + break; + } + sctrl->epub->sdio_state = sif_sdio_state; + if(sif_sdio_state != ESP_SDIO_STATE_FIRST_NORMAL_EXIT){ + do{ + int err; + sif_lock_bus(sctrl->epub); + err = sif_interrupt_target(sctrl->epub, 7); + sif_unlock_bus(sctrl->epub); + }while(0); + + if (sctrl->epub->sip) { + sip_detach(sctrl->epub->sip); + sctrl->epub->sip = NULL; + esp_dbg(ESP_DBG_TRACE, "%s sip detached \n", __func__); +#ifdef USE_EXT_GPIO + ext_gpio_deinit(); +#endif + } + } else { + //sif_disable_target_interrupt(sctrl->epub); + atomic_set(&sctrl->epub->sip->state, SIP_STOP); + sif_disable_irq(sctrl->epub); + } + +#ifdef TEST_MODE + test_exit_netlink(); +#endif /* TEST_MODE */ + if(sif_sdio_state != ESP_SDIO_STATE_FIRST_NORMAL_EXIT){ + esp_pub_dealloc_mac80211(sctrl->epub); + esp_dbg(ESP_DBG_TRACE, "%s dealloc mac80211 \n", __func__); + + if (sctrl->dma_buffer) { + kfree(sctrl->dma_buffer); + sctrl->dma_buffer = NULL; + esp_dbg(ESP_DBG_TRACE, "%s free dma_buffer \n", __func__); + } + + kfree(sctrl); + + if (buf_addr) { + kfree(buf_addr); + buf_addr = NULL; + rx_cmd = NULL; + tx_cmd = NULL; + } + + } + + } while (0); + + spi_set_drvdata(spi,NULL); + + esp_dbg(ESP_DBG_TRACE, "eagle spi remove complete\n"); + + return 0; +} + +static int esp_spi_suspend(struct device *dev) +{ return 0; + +} + +static int esp_spi_resume(struct device *dev) +{ + esp_dbg(ESP_DBG_ERROR, "%s", __func__); + + return 0; +} + +static const struct dev_pm_ops esp_spi_pm_ops = { + .suspend= esp_spi_suspend, + .resume= esp_spi_resume, +}; + +extern struct spi_device_id esp_spi_id[]; + +struct spi_driver esp_spi_driver = { + .id_table = esp_spi_id, + .driver = { + .name = "eagle", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = esp_spi_probe, + .remove = esp_spi_remove, +}; + +static int esp_spi_dummy_probe(struct spi_device *spi) +{ + esp_dbg(ESP_DBG_ERROR, "%s enter\n", __func__); + + up(&esp_powerup_sem); + + return 0; +} + +static int esp_spi_dummy_remove(struct spi_device *spi) +{ + return 0; +} + +struct spi_driver esp_spi_dummy_driver = { + .id_table = esp_spi_id, + .driver = { + .name = "eagle_dummy", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = esp_spi_dummy_probe, + .remove = esp_spi_dummy_remove, +}; + +static int __init esp_spi_init(void) +{ +#define ESP_WAIT_UP_TIME_MS 11000 + int err; + u64 ver; + int retry = 3; + bool powerup = false; + int edf_ret = 0; + + esp_dbg(ESP_DBG_TRACE, "%s \n", __func__); + +#ifdef REGISTER_SPI_BOARD_INFO + sif_platform_register_board_info(); +#endif + +#ifdef DRIVER_VER + ver = DRIVER_VER; + esp_dbg(ESP_SHOW, "\n*****%s %s EAGLE DRIVER VER:%llx*****\n\n", __DATE__, __TIME__, ver); +#endif + edf_ret = esp_debugfs_init(); + +#ifdef ANDROID + android_request_init_conf(); +#endif /* defined(ANDROID)*/ + + esp_wakelock_init(); + esp_wake_lock(); + + do { + sema_init(&esp_powerup_sem, 0); + + sif_platform_target_poweron(); + + err = spi_register_driver(&esp_spi_dummy_driver); + if (err) { + esp_dbg(ESP_DBG_ERROR, "eagle spi driver registration failed, error code: %d\n", err); + goto _fail; + } + + if (down_timeout(&esp_powerup_sem, + msecs_to_jiffies(ESP_WAIT_UP_TIME_MS)) == 0) + { + + powerup = true; + msleep(200); + break; + } + + esp_dbg(ESP_SHOW, "%s ------ RETRY ------ \n", __func__); + + sif_record_retry_config(); + + spi_unregister_driver(&esp_spi_dummy_driver); + + sif_platform_target_poweroff(); + + } while (retry--); + + if (!powerup) { + esp_dbg(ESP_DBG_ERROR, "eagle spi can not power up!\n"); + + err = -ENODEV; + goto _fail; + } + + esp_dbg(ESP_SHOW, "%s power up OK\n", __func__); + + spi_unregister_driver(&esp_spi_dummy_driver); + + sif_sdio_state = ESP_SDIO_STATE_FIRST_INIT; + sema_init(&esp_powerup_sem, 0); + + spi_register_driver(&esp_spi_driver); + + if (down_timeout(&esp_powerup_sem, + msecs_to_jiffies(ESP_WAIT_UP_TIME_MS)) == 0) + { + if(sif_sdio_state == ESP_SDIO_STATE_FIRST_NORMAL_EXIT){ + spi_unregister_driver(&esp_spi_driver); + + msleep(80); + + sif_sdio_state = ESP_SDIO_STATE_SECOND_INIT; + + spi_register_driver(&esp_spi_driver); + } + + } + + + esp_register_early_suspend(); + esp_wake_unlock(); + return err; + +_fail: + esp_wake_unlock(); + esp_wakelock_destroy(); + + return err; +} + +static void __exit esp_spi_exit(void) +{ + esp_dbg(ESP_DBG_TRACE, "%s \n", __func__); + + esp_debugfs_exit(); + + esp_unregister_early_suspend(); + + spi_unregister_driver(&esp_spi_driver); + +#ifndef FPGA_DEBUG + sif_platform_target_poweroff(); +#endif /* !FPGA_DEBUG */ + + esp_wakelock_destroy(); +} + +MODULE_AUTHOR("Espressif System"); +MODULE_DESCRIPTION("Driver for SPI interconnected eagle low-power WLAN devices"); +MODULE_LICENSE("GPL"); +#endif /* ESP_USE_SPI */ |