1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276 |
- /* ////////////////////////////////////////////////////////////////////////// */
- /* */
- /* Copyright (c) Atmel Corporation. All rights reserved. */
- /* */
- /* Module Name: wilc_spi.c */
- /* */
- /* */
- /* //////////////////////////////////////////////////////////////////////////// */
- #include <linux/string.h>
- #include "wilc_wlan_if.h"
- #include "wilc_wlan.h"
- typedef struct {
- void *os_context;
- int (*spi_tx)(u8 *, u32);
- int (*spi_rx)(u8 *, u32);
- int (*spi_trx)(u8 *, u8 *, u32);
- int (*spi_max_speed)(void);
- wilc_debug_func dPrint;
- int crc_off;
- int nint;
- int has_thrpt_enh;
- } wilc_spi_t;
- static wilc_spi_t g_spi;
- static int spi_read(u32, u8 *, u32);
- static int spi_write(u32, u8 *, u32);
- /********************************************
- *
- * Crc7
- *
- ********************************************/
- static const u8 crc7_syndrome_table[256] = {
- 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
- 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
- 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26,
- 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e,
- 0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d,
- 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
- 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14,
- 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c,
- 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b,
- 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13,
- 0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42,
- 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
- 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69,
- 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21,
- 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70,
- 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38,
- 0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e,
- 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
- 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67,
- 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f,
- 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
- 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
- 0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55,
- 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
- 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a,
- 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52,
- 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03,
- 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b,
- 0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28,
- 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
- 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31,
- 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79
- };
- static u8 crc7_byte(u8 crc, u8 data)
- {
- return crc7_syndrome_table[(crc << 1) ^ data];
- }
- static u8 crc7(u8 crc, const u8 *buffer, u32 len)
- {
- while (len--)
- crc = crc7_byte(crc, *buffer++);
- return crc;
- }
- /********************************************
- *
- * Spi protocol Function
- *
- ********************************************/
- #define CMD_DMA_WRITE 0xc1
- #define CMD_DMA_READ 0xc2
- #define CMD_INTERNAL_WRITE 0xc3
- #define CMD_INTERNAL_READ 0xc4
- #define CMD_TERMINATE 0xc5
- #define CMD_REPEAT 0xc6
- #define CMD_DMA_EXT_WRITE 0xc7
- #define CMD_DMA_EXT_READ 0xc8
- #define CMD_SINGLE_WRITE 0xc9
- #define CMD_SINGLE_READ 0xca
- #define CMD_RESET 0xcf
- #define N_OK 1
- #define N_FAIL 0
- #define N_RESET -1
- #define N_RETRY -2
- #define DATA_PKT_SZ_256 256
- #define DATA_PKT_SZ_512 512
- #define DATA_PKT_SZ_1K 1024
- #define DATA_PKT_SZ_4K (4 * 1024)
- #define DATA_PKT_SZ_8K (8 * 1024)
- #define DATA_PKT_SZ DATA_PKT_SZ_8K
- static int spi_cmd(u8 cmd, u32 adr, u32 data, u32 sz, u8 clockless)
- {
- u8 bc[9];
- int len = 5;
- int result = N_OK;
- bc[0] = cmd;
- switch (cmd) {
- case CMD_SINGLE_READ: /* single word (4 bytes) read */
- bc[1] = (u8)(adr >> 16);
- bc[2] = (u8)(adr >> 8);
- bc[3] = (u8)adr;
- len = 5;
- break;
- case CMD_INTERNAL_READ: /* internal register read */
- bc[1] = (u8)(adr >> 8);
- if (clockless)
- bc[1] |= BIT(7);
- bc[2] = (u8)adr;
- bc[3] = 0x00;
- len = 5;
- break;
- case CMD_TERMINATE: /* termination */
- bc[1] = 0x00;
- bc[2] = 0x00;
- bc[3] = 0x00;
- len = 5;
- break;
- case CMD_REPEAT: /* repeat */
- bc[1] = 0x00;
- bc[2] = 0x00;
- bc[3] = 0x00;
- len = 5;
- break;
- case CMD_RESET: /* reset */
- bc[1] = 0xff;
- bc[2] = 0xff;
- bc[3] = 0xff;
- len = 5;
- break;
- case CMD_DMA_WRITE: /* dma write */
- case CMD_DMA_READ: /* dma read */
- bc[1] = (u8)(adr >> 16);
- bc[2] = (u8)(adr >> 8);
- bc[3] = (u8)adr;
- bc[4] = (u8)(sz >> 8);
- bc[5] = (u8)(sz);
- len = 7;
- break;
- case CMD_DMA_EXT_WRITE: /* dma extended write */
- case CMD_DMA_EXT_READ: /* dma extended read */
- bc[1] = (u8)(adr >> 16);
- bc[2] = (u8)(adr >> 8);
- bc[3] = (u8)adr;
- bc[4] = (u8)(sz >> 16);
- bc[5] = (u8)(sz >> 8);
- bc[6] = (u8)(sz);
- len = 8;
- break;
- case CMD_INTERNAL_WRITE: /* internal register write */
- bc[1] = (u8)(adr >> 8);
- if (clockless)
- bc[1] |= BIT(7);
- bc[2] = (u8)(adr);
- bc[3] = (u8)(data >> 24);
- bc[4] = (u8)(data >> 16);
- bc[5] = (u8)(data >> 8);
- bc[6] = (u8)(data);
- len = 8;
- break;
- case CMD_SINGLE_WRITE: /* single word write */
- bc[1] = (u8)(adr >> 16);
- bc[2] = (u8)(adr >> 8);
- bc[3] = (u8)(adr);
- bc[4] = (u8)(data >> 24);
- bc[5] = (u8)(data >> 16);
- bc[6] = (u8)(data >> 8);
- bc[7] = (u8)(data);
- len = 9;
- break;
- default:
- result = N_FAIL;
- break;
- }
- if (result) {
- if (!g_spi.crc_off)
- bc[len - 1] = (crc7(0x7f, (const u8 *)&bc[0], len - 1)) << 1;
- else
- len -= 1;
- if (!g_spi.spi_tx(bc, len)) {
- PRINT_ER("[wilc spi]: Failed cmd write, bus error...\n");
- result = N_FAIL;
- }
- }
- return result;
- }
- static int spi_cmd_rsp(u8 cmd)
- {
- u8 rsp;
- int result = N_OK;
- /**
- * Command/Control response
- **/
- if ((cmd == CMD_RESET) ||
- (cmd == CMD_TERMINATE) ||
- (cmd == CMD_REPEAT)) {
- if (!g_spi.spi_rx(&rsp, 1)) {
- result = N_FAIL;
- goto _fail_;
- }
- }
- if (!g_spi.spi_rx(&rsp, 1)) {
- PRINT_ER("[wilc spi]: Failed cmd response read, bus error...\n");
- result = N_FAIL;
- goto _fail_;
- }
- if (rsp != cmd) {
- PRINT_ER("[wilc spi]: Failed cmd response, cmd (%02x), resp (%02x)\n", cmd, rsp);
- result = N_FAIL;
- goto _fail_;
- }
- /**
- * State response
- **/
- if (!g_spi.spi_rx(&rsp, 1)) {
- PRINT_ER("[wilc spi]: Failed cmd state read, bus error...\n");
- result = N_FAIL;
- goto _fail_;
- }
- if (rsp != 0x00) {
- PRINT_ER("[wilc spi]: Failed cmd state response state (%02x)\n", rsp);
- result = N_FAIL;
- }
- _fail_:
- return result;
- }
- static int spi_cmd_complete(u8 cmd, u32 adr, u8 *b, u32 sz, u8 clockless)
- {
- u8 wb[32], rb[32];
- u8 wix, rix;
- u32 len2;
- u8 rsp;
- int len = 0;
- int result = N_OK;
- wb[0] = cmd;
- switch (cmd) {
- case CMD_SINGLE_READ: /* single word (4 bytes) read */
- wb[1] = (u8)(adr >> 16);
- wb[2] = (u8)(adr >> 8);
- wb[3] = (u8)adr;
- len = 5;
- break;
- case CMD_INTERNAL_READ: /* internal register read */
- wb[1] = (u8)(adr >> 8);
- if (clockless == 1)
- wb[1] |= BIT(7);
- wb[2] = (u8)adr;
- wb[3] = 0x00;
- len = 5;
- break;
- case CMD_TERMINATE: /* termination */
- wb[1] = 0x00;
- wb[2] = 0x00;
- wb[3] = 0x00;
- len = 5;
- break;
- case CMD_REPEAT: /* repeat */
- wb[1] = 0x00;
- wb[2] = 0x00;
- wb[3] = 0x00;
- len = 5;
- break;
- case CMD_RESET: /* reset */
- wb[1] = 0xff;
- wb[2] = 0xff;
- wb[3] = 0xff;
- len = 5;
- break;
- case CMD_DMA_WRITE: /* dma write */
- case CMD_DMA_READ: /* dma read */
- wb[1] = (u8)(adr >> 16);
- wb[2] = (u8)(adr >> 8);
- wb[3] = (u8)adr;
- wb[4] = (u8)(sz >> 8);
- wb[5] = (u8)(sz);
- len = 7;
- break;
- case CMD_DMA_EXT_WRITE: /* dma extended write */
- case CMD_DMA_EXT_READ: /* dma extended read */
- wb[1] = (u8)(adr >> 16);
- wb[2] = (u8)(adr >> 8);
- wb[3] = (u8)adr;
- wb[4] = (u8)(sz >> 16);
- wb[5] = (u8)(sz >> 8);
- wb[6] = (u8)(sz);
- len = 8;
- break;
- case CMD_INTERNAL_WRITE: /* internal register write */
- wb[1] = (u8)(adr >> 8);
- if (clockless == 1)
- wb[1] |= BIT(7);
- wb[2] = (u8)(adr);
- wb[3] = b[3];
- wb[4] = b[2];
- wb[5] = b[1];
- wb[6] = b[0];
- len = 8;
- break;
- case CMD_SINGLE_WRITE: /* single word write */
- wb[1] = (u8)(adr >> 16);
- wb[2] = (u8)(adr >> 8);
- wb[3] = (u8)(adr);
- wb[4] = b[3];
- wb[5] = b[2];
- wb[6] = b[1];
- wb[7] = b[0];
- len = 9;
- break;
- default:
- result = N_FAIL;
- break;
- }
- if (result != N_OK) {
- return result;
- }
- if (!g_spi.crc_off)
- wb[len - 1] = (crc7(0x7f, (const u8 *)&wb[0], len - 1)) << 1;
- else
- len -= 1;
- #define NUM_SKIP_BYTES (1)
- #define NUM_RSP_BYTES (2)
- #define NUM_DATA_HDR_BYTES (1)
- #define NUM_DATA_BYTES (4)
- #define NUM_CRC_BYTES (2)
- #define NUM_DUMMY_BYTES (3)
- if ((cmd == CMD_RESET) ||
- (cmd == CMD_TERMINATE) ||
- (cmd == CMD_REPEAT)) {
- len2 = len + (NUM_SKIP_BYTES + NUM_RSP_BYTES + NUM_DUMMY_BYTES);
- } else if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ)) {
- if (!g_spi.crc_off) {
- len2 = len + (NUM_RSP_BYTES + NUM_DATA_HDR_BYTES + NUM_DATA_BYTES
- + NUM_CRC_BYTES + NUM_DUMMY_BYTES);
- } else {
- len2 = len + (NUM_RSP_BYTES + NUM_DATA_HDR_BYTES + NUM_DATA_BYTES
- + NUM_DUMMY_BYTES);
- }
- } else {
- len2 = len + (NUM_RSP_BYTES + NUM_DUMMY_BYTES);
- }
- #undef NUM_DUMMY_BYTES
- if (len2 > ARRAY_SIZE(wb)) {
- PRINT_ER("[wilc spi]: spi buffer size too small (%d) (%zu)\n",
- len2, ARRAY_SIZE(wb));
- result = N_FAIL;
- return result;
- }
- /* zero spi write buffers. */
- for (wix = len; wix < len2; wix++) {
- wb[wix] = 0;
- }
- rix = len;
- if (!g_spi.spi_trx(wb, rb, len2)) {
- PRINT_ER("[wilc spi]: Failed cmd write, bus error...\n");
- result = N_FAIL;
- return result;
- }
- /**
- * Command/Control response
- **/
- if ((cmd == CMD_RESET) ||
- (cmd == CMD_TERMINATE) ||
- (cmd == CMD_REPEAT)) {
- rix++; /* skip 1 byte */
- }
- /* do { */
- rsp = rb[rix++];
- /* if(rsp == cmd) break; */
- /* } while(&rptr[1] <= &rb[len2]); */
- if (rsp != cmd) {
- PRINT_ER("[wilc spi]: Failed cmd response, cmd (%02x)"
- ", resp (%02x)\n", cmd, rsp);
- result = N_FAIL;
- return result;
- }
- /**
- * State response
- **/
- rsp = rb[rix++];
- if (rsp != 0x00) {
- PRINT_ER("[wilc spi]: Failed cmd state response "
- "state (%02x)\n", rsp);
- result = N_FAIL;
- return result;
- }
- if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ)
- || (cmd == CMD_DMA_READ) || (cmd == CMD_DMA_EXT_READ)) {
- int retry;
- /* u16 crc1, crc2; */
- u8 crc[2];
- /**
- * Data Respnose header
- **/
- retry = 100;
- do {
- /* ensure there is room in buffer later to read data and crc */
- if (rix < len2) {
- rsp = rb[rix++];
- } else {
- retry = 0;
- break;
- }
- if (((rsp >> 4) & 0xf) == 0xf)
- break;
- } while (retry--);
- if (retry <= 0) {
- PRINT_ER("[wilc spi]: Error, data read "
- "response (%02x)\n", rsp);
- result = N_RESET;
- return result;
- }
- if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ)) {
- /**
- * Read bytes
- **/
- if ((rix + 3) < len2) {
- b[0] = rb[rix++];
- b[1] = rb[rix++];
- b[2] = rb[rix++];
- b[3] = rb[rix++];
- } else {
- PRINT_ER("[wilc spi]: buffer overrun when reading data.\n");
- result = N_FAIL;
- return result;
- }
- if (!g_spi.crc_off) {
- /**
- * Read Crc
- **/
- if ((rix + 1) < len2) {
- crc[0] = rb[rix++];
- crc[1] = rb[rix++];
- } else {
- PRINT_ER("[wilc spi]: buffer overrun when reading crc.\n");
- result = N_FAIL;
- return result;
- }
- }
- } else if ((cmd == CMD_DMA_READ) || (cmd == CMD_DMA_EXT_READ)) {
- int ix;
- /* some data may be read in response to dummy bytes. */
- for (ix = 0; (rix < len2) && (ix < sz); ) {
- b[ix++] = rb[rix++];
- }
- sz -= ix;
- if (sz > 0) {
- int nbytes;
- if (sz <= (DATA_PKT_SZ - ix))
- nbytes = sz;
- else
- nbytes = DATA_PKT_SZ - ix;
- /**
- * Read bytes
- **/
- if (!g_spi.spi_rx(&b[ix], nbytes)) {
- PRINT_ER("[wilc spi]: Failed data block read, bus error...\n");
- result = N_FAIL;
- goto _error_;
- }
- /**
- * Read Crc
- **/
- if (!g_spi.crc_off) {
- if (!g_spi.spi_rx(crc, 2)) {
- PRINT_ER("[wilc spi]: Failed data block crc read, bus error...\n");
- result = N_FAIL;
- goto _error_;
- }
- }
- ix += nbytes;
- sz -= nbytes;
- }
- /* if any data in left unread, then read the rest using normal DMA code.*/
- while (sz > 0) {
- int nbytes;
- if (sz <= DATA_PKT_SZ)
- nbytes = sz;
- else
- nbytes = DATA_PKT_SZ;
- /**
- * read data response only on the next DMA cycles not
- * the first DMA since data response header is already
- * handled above for the first DMA.
- **/
- /**
- * Data Respnose header
- **/
- retry = 10;
- do {
- if (!g_spi.spi_rx(&rsp, 1)) {
- PRINT_ER("[wilc spi]: Failed data response read, bus error...\n");
- result = N_FAIL;
- break;
- }
- if (((rsp >> 4) & 0xf) == 0xf)
- break;
- } while (retry--);
- if (result == N_FAIL)
- break;
- /**
- * Read bytes
- **/
- if (!g_spi.spi_rx(&b[ix], nbytes)) {
- PRINT_ER("[wilc spi]: Failed data block read, bus error...\n");
- result = N_FAIL;
- break;
- }
- /**
- * Read Crc
- **/
- if (!g_spi.crc_off) {
- if (!g_spi.spi_rx(crc, 2)) {
- PRINT_ER("[wilc spi]: Failed data block crc read, bus error...\n");
- result = N_FAIL;
- break;
- }
- }
- ix += nbytes;
- sz -= nbytes;
- }
- }
- }
- _error_:
- return result;
- }
- static int spi_data_read(u8 *b, u32 sz)
- {
- int retry, ix, nbytes;
- int result = N_OK;
- u8 crc[2];
- u8 rsp;
- /**
- * Data
- **/
- ix = 0;
- do {
- if (sz <= DATA_PKT_SZ)
- nbytes = sz;
- else
- nbytes = DATA_PKT_SZ;
- /**
- * Data Respnose header
- **/
- retry = 10;
- do {
- if (!g_spi.spi_rx(&rsp, 1)) {
- PRINT_ER("[wilc spi]: Failed data response read, bus error...\n");
- result = N_FAIL;
- break;
- }
- if (((rsp >> 4) & 0xf) == 0xf)
- break;
- } while (retry--);
- if (result == N_FAIL)
- break;
- if (retry <= 0) {
- PRINT_ER("[wilc spi]: Failed data response read...(%02x)\n", rsp);
- result = N_FAIL;
- break;
- }
- /**
- * Read bytes
- **/
- if (!g_spi.spi_rx(&b[ix], nbytes)) {
- PRINT_ER("[wilc spi]: Failed data block read, bus error...\n");
- result = N_FAIL;
- break;
- }
- /**
- * Read Crc
- **/
- if (!g_spi.crc_off) {
- if (!g_spi.spi_rx(crc, 2)) {
- PRINT_ER("[wilc spi]: Failed data block crc read, bus error...\n");
- result = N_FAIL;
- break;
- }
- }
- ix += nbytes;
- sz -= nbytes;
- } while (sz);
- return result;
- }
- static int spi_data_write(u8 *b, u32 sz)
- {
- int ix, nbytes;
- int result = 1;
- u8 cmd, order, crc[2] = {0};
- /* u8 rsp; */
- /**
- * Data
- **/
- ix = 0;
- do {
- if (sz <= DATA_PKT_SZ)
- nbytes = sz;
- else
- nbytes = DATA_PKT_SZ;
- /**
- * Write command
- **/
- cmd = 0xf0;
- if (ix == 0) {
- if (sz <= DATA_PKT_SZ)
- order = 0x3;
- else
- order = 0x1;
- } else {
- if (sz <= DATA_PKT_SZ)
- order = 0x3;
- else
- order = 0x2;
- }
- cmd |= order;
- if (!g_spi.spi_tx(&cmd, 1)) {
- PRINT_ER("[wilc spi]: Failed data block cmd write, bus error...\n");
- result = N_FAIL;
- break;
- }
- /**
- * Write data
- **/
- if (!g_spi.spi_tx(&b[ix], nbytes)) {
- PRINT_ER("[wilc spi]: Failed data block write, bus error...\n");
- result = N_FAIL;
- break;
- }
- /**
- * Write Crc
- **/
- if (!g_spi.crc_off) {
- if (!g_spi.spi_tx(crc, 2)) {
- PRINT_ER("[wilc spi]: Failed data block crc write, bus error...\n");
- result = N_FAIL;
- break;
- }
- }
- /**
- * No need to wait for response
- **/
- ix += nbytes;
- sz -= nbytes;
- } while (sz);
- return result;
- }
- /********************************************
- *
- * Spi Internal Read/Write Function
- *
- ********************************************/
- static int spi_internal_write(u32 adr, u32 dat)
- {
- int result;
- #ifdef BIG_ENDIAN
- dat = BYTE_SWAP(dat);
- #endif
- result = spi_cmd_complete(CMD_INTERNAL_WRITE, adr, (u8 *)&dat, 4, 0);
- if (result != N_OK) {
- PRINT_ER("[wilc spi]: Failed internal write cmd...\n");
- }
- return result;
- }
- static int spi_internal_read(u32 adr, u32 *data)
- {
- int result;
- result = spi_cmd_complete(CMD_INTERNAL_READ, adr, (u8 *)data, 4, 0);
- if (result != N_OK) {
- PRINT_ER("[wilc spi]: Failed internal read cmd...\n");
- return 0;
- }
- #ifdef BIG_ENDIAN
- *data = BYTE_SWAP(*data);
- #endif
- return 1;
- }
- /********************************************
- *
- * Spi interfaces
- *
- ********************************************/
- static int spi_write_reg(u32 addr, u32 data)
- {
- int result = N_OK;
- u8 cmd = CMD_SINGLE_WRITE;
- u8 clockless = 0;
- #ifdef BIG_ENDIAN
- data = BYTE_SWAP(data);
- #endif
- if (addr < 0x30) {
- /* Clockless register*/
- cmd = CMD_INTERNAL_WRITE;
- clockless = 1;
- }
- result = spi_cmd_complete(cmd, addr, (u8 *)&data, 4, clockless);
- if (result != N_OK) {
- PRINT_ER("[wilc spi]: Failed cmd, write reg (%08x)...\n", addr);
- }
- return result;
- }
- static int spi_write(u32 addr, u8 *buf, u32 size)
- {
- int result;
- u8 cmd = CMD_DMA_EXT_WRITE;
- /**
- * has to be greated than 4
- **/
- if (size <= 4)
- return 0;
- result = spi_cmd_complete(cmd, addr, NULL, size, 0);
- if (result != N_OK) {
- PRINT_ER("[wilc spi]: Failed cmd, write block (%08x)...\n", addr);
- return 0;
- }
- /**
- * Data
- **/
- result = spi_data_write(buf, size);
- if (result != N_OK) {
- PRINT_ER("[wilc spi]: Failed block data write...\n");
- }
- return 1;
- }
- static int spi_read_reg(u32 addr, u32 *data)
- {
- int result = N_OK;
- u8 cmd = CMD_SINGLE_READ;
- u8 clockless = 0;
- if (addr < 0x30) {
- /* PRINT_ER("***** read addr %d\n\n", addr); */
- /* Clockless register*/
- cmd = CMD_INTERNAL_READ;
- clockless = 1;
- }
- result = spi_cmd_complete(cmd, addr, (u8 *)data, 4, clockless);
- if (result != N_OK) {
- PRINT_ER("[wilc spi]: Failed cmd, read reg (%08x)...\n", addr);
- return 0;
- }
- #ifdef BIG_ENDIAN
- *data = BYTE_SWAP(*data);
- #endif
- return 1;
- }
- static int spi_read(u32 addr, u8 *buf, u32 size)
- {
- u8 cmd = CMD_DMA_EXT_READ;
- int result;
- if (size <= 4)
- return 0;
- result = spi_cmd_complete(cmd, addr, buf, size, 0);
- if (result != N_OK) {
- PRINT_ER("[wilc spi]: Failed cmd, read block (%08x)...\n", addr);
- return 0;
- }
- return 1;
- }
- /********************************************
- *
- * Bus interfaces
- *
- ********************************************/
- static int spi_clear_int(void)
- {
- u32 reg;
- if (!spi_read_reg(WILC_HOST_RX_CTRL_0, ®)) {
- PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_HOST_RX_CTRL_0);
- return 0;
- }
- reg &= ~0x1;
- spi_write_reg(WILC_HOST_RX_CTRL_0, reg);
- return 1;
- }
- static int spi_deinit(void *pv)
- {
- /**
- * TODO:
- **/
- return 1;
- }
- static int spi_sync(void)
- {
- u32 reg;
- int ret;
- /**
- * interrupt pin mux select
- **/
- ret = spi_read_reg(WILC_PIN_MUX_0, ®);
- if (!ret) {
- PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0);
- return 0;
- }
- reg |= BIT(8);
- ret = spi_write_reg(WILC_PIN_MUX_0, reg);
- if (!ret) {
- PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0);
- return 0;
- }
- /**
- * interrupt enable
- **/
- ret = spi_read_reg(WILC_INTR_ENABLE, ®);
- if (!ret) {
- PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_INTR_ENABLE);
- return 0;
- }
- reg |= BIT(16);
- ret = spi_write_reg(WILC_INTR_ENABLE, reg);
- if (!ret) {
- PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE);
- return 0;
- }
- return 1;
- }
- static int spi_init(wilc_wlan_inp_t *inp, wilc_debug_func func)
- {
- u32 reg;
- u32 chipid;
- static int isinit;
- if (isinit) {
- if (!spi_read_reg(0x1000, &chipid)) {
- PRINT_ER("[wilc spi]: Fail cmd read chip id...\n");
- return 0;
- }
- return 1;
- }
- memset(&g_spi, 0, sizeof(wilc_spi_t));
- g_spi.dPrint = func;
- g_spi.os_context = inp->os_context.os_private;
- if (inp->io_func.io_init) {
- if (!inp->io_func.io_init(g_spi.os_context)) {
- PRINT_ER("[wilc spi]: Failed io init bus...\n");
- return 0;
- }
- } else {
- return 0;
- }
- g_spi.spi_tx = inp->io_func.u.spi.spi_tx;
- g_spi.spi_rx = inp->io_func.u.spi.spi_rx;
- g_spi.spi_trx = inp->io_func.u.spi.spi_trx;
- g_spi.spi_max_speed = inp->io_func.u.spi.spi_max_speed;
- /**
- * configure protocol
- **/
- g_spi.crc_off = 0;
- /* TODO: We can remove the CRC trials if there is a definite way to reset */
- /* the SPI to it's initial value. */
- if (!spi_internal_read(WILC_SPI_PROTOCOL_OFFSET, ®)) {
- /* Read failed. Try with CRC off. This might happen when module
- * is removed but chip isn't reset*/
- g_spi.crc_off = 1;
- PRINT_ER("[wilc spi]: Failed internal read protocol with CRC on, retyring with CRC off...\n");
- if (!spi_internal_read(WILC_SPI_PROTOCOL_OFFSET, ®)) {
- /* Reaad failed with both CRC on and off, something went bad */
- PRINT_ER("[wilc spi]: Failed internal read protocol...\n");
- return 0;
- }
- }
- if (g_spi.crc_off == 0) {
- reg &= ~0xc; /* disable crc checking */
- reg &= ~0x70;
- reg |= (0x5 << 4);
- if (!spi_internal_write(WILC_SPI_PROTOCOL_OFFSET, reg)) {
- PRINT_ER("[wilc spi %d]: Failed internal write protocol reg...\n", __LINE__);
- return 0;
- }
- g_spi.crc_off = 1;
- }
- /**
- * make sure can read back chip id correctly
- **/
- if (!spi_read_reg(0x1000, &chipid)) {
- PRINT_ER("[wilc spi]: Fail cmd read chip id...\n");
- return 0;
- }
- /* PRINT_ER("[wilc spi]: chipid (%08x)\n", chipid); */
- g_spi.has_thrpt_enh = 1;
- isinit = 1;
- return 1;
- }
- static void spi_max_bus_speed(void)
- {
- g_spi.spi_max_speed();
- }
- static void spi_default_bus_speed(void)
- {
- }
- static int spi_read_size(u32 *size)
- {
- int ret;
- if (g_spi.has_thrpt_enh) {
- ret = spi_internal_read(0xe840 - WILC_SPI_REG_BASE, size);
- *size = *size & IRQ_DMA_WD_CNT_MASK;
- } else {
- u32 tmp;
- u32 byte_cnt;
- ret = spi_read_reg(WILC_VMM_TO_HOST_SIZE, &byte_cnt);
- if (!ret) {
- PRINT_ER("[wilc spi]: Failed read WILC_VMM_TO_HOST_SIZE ...\n");
- goto _fail_;
- }
- tmp = (byte_cnt >> 2) & IRQ_DMA_WD_CNT_MASK;
- *size = tmp;
- }
- _fail_:
- return ret;
- }
- static int spi_read_int(u32 *int_status)
- {
- int ret;
- if (g_spi.has_thrpt_enh) {
- ret = spi_internal_read(0xe840 - WILC_SPI_REG_BASE, int_status);
- } else {
- u32 tmp;
- u32 byte_cnt;
- ret = spi_read_reg(WILC_VMM_TO_HOST_SIZE, &byte_cnt);
- if (!ret) {
- PRINT_ER("[wilc spi]: Failed read WILC_VMM_TO_HOST_SIZE ...\n");
- goto _fail_;
- }
- tmp = (byte_cnt >> 2) & IRQ_DMA_WD_CNT_MASK;
- {
- int happended, j;
- j = 0;
- do {
- u32 irq_flags;
- happended = 0;
- spi_read_reg(0x1a90, &irq_flags);
- tmp |= ((irq_flags >> 27) << IRG_FLAGS_OFFSET);
- if (g_spi.nint > 5) {
- spi_read_reg(0x1a94, &irq_flags);
- tmp |= (((irq_flags >> 0) & 0x7) << (IRG_FLAGS_OFFSET + 5));
- }
- {
- u32 unkmown_mask;
- unkmown_mask = ~((1ul << g_spi.nint) - 1);
- if ((tmp >> IRG_FLAGS_OFFSET) & unkmown_mask) {
- PRINT_ER("[wilc spi]: Unexpected interrupt (2): j=%d, tmp=%x, mask=%x\n", j, tmp, unkmown_mask);
- happended = 1;
- }
- }
- j++;
- } while (happended);
- }
- *int_status = tmp;
- }
- _fail_:
- return ret;
- }
- static int spi_clear_int_ext(u32 val)
- {
- int ret;
- if (g_spi.has_thrpt_enh) {
- ret = spi_internal_write(0xe844 - WILC_SPI_REG_BASE, val);
- } else {
- u32 flags;
- flags = val & (BIT(MAX_NUM_INT) - 1);
- if (flags) {
- int i;
- ret = 1;
- for (i = 0; i < g_spi.nint; i++) {
- /* No matter what you write 1 or 0, it will clear interrupt. */
- if (flags & 1)
- ret = spi_write_reg(0x10c8 + i * 4, 1);
- if (!ret)
- break;
- flags >>= 1;
- }
- if (!ret) {
- PRINT_ER("[wilc spi]: Failed spi_write_reg, set reg %x ...\n", 0x10c8 + i * 4);
- goto _fail_;
- }
- for (i = g_spi.nint; i < MAX_NUM_INT; i++) {
- if (flags & 1)
- PRINT_ER("[wilc spi]: Unexpected interrupt cleared %d...\n", i);
- flags >>= 1;
- }
- }
- {
- u32 tbl_ctl;
- tbl_ctl = 0;
- /* select VMM table 0 */
- if ((val & SEL_VMM_TBL0) == SEL_VMM_TBL0)
- tbl_ctl |= BIT(0);
- /* select VMM table 1 */
- if ((val & SEL_VMM_TBL1) == SEL_VMM_TBL1)
- tbl_ctl |= BIT(1);
- ret = spi_write_reg(WILC_VMM_TBL_CTL, tbl_ctl);
- if (!ret) {
- PRINT_ER("[wilc spi]: fail write reg vmm_tbl_ctl...\n");
- goto _fail_;
- }
- if ((val & EN_VMM) == EN_VMM) {
- /**
- * enable vmm transfer.
- **/
- ret = spi_write_reg(WILC_VMM_CORE_CTL, 1);
- if (!ret) {
- PRINT_ER("[wilc spi]: fail write reg vmm_core_ctl...\n");
- goto _fail_;
- }
- }
- }
- }
- _fail_:
- return ret;
- }
- static int spi_sync_ext(int nint /* how mant interrupts to enable. */)
- {
- u32 reg;
- int ret, i;
- if (nint > MAX_NUM_INT) {
- PRINT_ER("[wilc spi]: Too many interupts (%d)...\n", nint);
- return 0;
- }
- g_spi.nint = nint;
- /**
- * interrupt pin mux select
- **/
- ret = spi_read_reg(WILC_PIN_MUX_0, ®);
- if (!ret) {
- PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0);
- return 0;
- }
- reg |= BIT(8);
- ret = spi_write_reg(WILC_PIN_MUX_0, reg);
- if (!ret) {
- PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0);
- return 0;
- }
- /**
- * interrupt enable
- **/
- ret = spi_read_reg(WILC_INTR_ENABLE, ®);
- if (!ret) {
- PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_INTR_ENABLE);
- return 0;
- }
- for (i = 0; (i < 5) && (nint > 0); i++, nint--) {
- reg |= (BIT((27 + i)));
- }
- ret = spi_write_reg(WILC_INTR_ENABLE, reg);
- if (!ret) {
- PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE);
- return 0;
- }
- if (nint) {
- ret = spi_read_reg(WILC_INTR2_ENABLE, ®);
- if (!ret) {
- PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_INTR2_ENABLE);
- return 0;
- }
- for (i = 0; (i < 3) && (nint > 0); i++, nint--) {
- reg |= BIT(i);
- }
- ret = spi_read_reg(WILC_INTR2_ENABLE, ®);
- if (!ret) {
- PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_INTR2_ENABLE);
- return 0;
- }
- }
- return 1;
- }
- /********************************************
- *
- * Global spi HIF function table
- *
- ********************************************/
- wilc_hif_func_t hif_spi = {
- spi_init,
- spi_deinit,
- spi_read_reg,
- spi_write_reg,
- spi_read,
- spi_write,
- spi_sync,
- spi_clear_int,
- spi_read_int,
- spi_clear_int_ext,
- spi_read_size,
- spi_write,
- spi_read,
- spi_sync_ext,
- spi_max_bus_speed,
- spi_default_bus_speed,
- };
|