選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 

979 行
25 KiB

  1. /*******************************************************************************
  2. This module contains WINC3400 SPI protocol bus APIs implementation.
  3. File Name:
  4. nmspi.c
  5. Summary:
  6. This module contains WINC3400 SPI protocol bus APIs implementation.
  7. Description:
  8. This module contains WINC3400 SPI protocol bus APIs implementation.
  9. *******************************************************************************/
  10. //DOM-IGNORE-BEGIN
  11. /*******************************************************************************
  12. * Copyright (C) 2021 Microchip Technology Inc. and its subsidiaries.
  13. *
  14. * Subject to your compliance with these terms, you may use Microchip software
  15. * and any derivatives exclusively with Microchip products. It is your
  16. * responsibility to comply with third party license terms applicable to your
  17. * use of third party software (including open source software) that may
  18. * accompany Microchip software.
  19. *
  20. * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
  21. * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
  22. * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
  23. * PARTICULAR PURPOSE.
  24. *
  25. * IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
  26. * INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
  27. * WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
  28. * BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE
  29. * FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN
  30. * ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
  31. * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
  32. *******************************************************************************/
  33. //#include "osal/osal.h"
  34. #include "nm_common.h"
  35. #include "nmspi.h"
  36. #include "spi.h"
  37. #include "BoardCfg.h"
  38. //#include "wdrv_winc_common.h"
  39. //#include "wdrv_winc_spi.h"
  40. #define NMI_PERIPH_REG_BASE 0x1000
  41. #define NMI_INTR_REG_BASE (NMI_PERIPH_REG_BASE+0xa00)
  42. #define NMI_CHIPID (NMI_PERIPH_REG_BASE)
  43. #define NMI_PIN_MUX_0 (NMI_PERIPH_REG_BASE + 0x408)
  44. #define NMI_INTR_ENABLE (NMI_INTR_REG_BASE)
  45. #define NMI_SPI_REG_BASE 0xe800
  46. #define NMI_SPI_CTL (NMI_SPI_REG_BASE)
  47. #define NMI_SPI_MASTER_DMA_ADDR (NMI_SPI_REG_BASE+0x4)
  48. #define NMI_SPI_MASTER_DMA_COUNT (NMI_SPI_REG_BASE+0x8)
  49. #define NMI_SPI_SLAVE_DMA_ADDR (NMI_SPI_REG_BASE+0xc)
  50. #define NMI_SPI_SLAVE_DMA_COUNT (NMI_SPI_REG_BASE+0x10)
  51. #define NMI_SPI_TX_MODE (NMI_SPI_REG_BASE+0x20)
  52. #define NMI_SPI_PROTOCOL_CONFIG (NMI_SPI_REG_BASE+0x24)
  53. #define NMI_SPI_INTR_CTL (NMI_SPI_REG_BASE+0x2c)
  54. #define NMI_SPI_MISC_CTRL (NMI_SPI_REG_BASE+0x48)
  55. #define NMI_SPI_PROTOCOL_OFFSET (NMI_SPI_PROTOCOL_CONFIG-NMI_SPI_REG_BASE)
  56. #define SPI_BASE NMI_SPI_REG_BASE
  57. //#define CMD_DMA_WRITE 0xc1
  58. //#define CMD_DMA_READ 0xc2
  59. #define CMD_INTERNAL_WRITE 0xc3
  60. #define CMD_INTERNAL_READ 0xc4
  61. //#define CMD_TERMINATE 0xc5
  62. //#define CMD_REPEAT 0xc6
  63. #define CMD_DMA_EXT_WRITE 0xc7
  64. #define CMD_DMA_EXT_READ 0xc8
  65. #define CMD_SINGLE_WRITE 0xc9
  66. #define CMD_SINGLE_READ 0xca
  67. #define CMD_RESET 0xcf
  68. #define N_OK 0
  69. #define N_FAIL -1
  70. #define N_RESET -2
  71. #define N_RETRY -3
  72. #define SPI_RESP_RETRY_COUNT (10)
  73. #define SPI_RETRY_COUNT (10)
  74. #define DATA_PKT_SZ_256 256
  75. #define DATA_PKT_SZ_512 512
  76. #define DATA_PKT_SZ_1K 1024
  77. #define DATA_PKT_SZ_4K (4 * 1024)
  78. #define DATA_PKT_SZ_8K (8 * 1024)
  79. #define DATA_PKT_SZ DATA_PKT_SZ_8K
  80. static uint8_t gu8Crc_off = 0;
  81. unsigned char mWifiSPIBaudrate;
  82. //static OSAL_MUTEX_HANDLE_TYPE s_spiLock = 0;
  83. static inline int8_t spi_read(uint8_t *b, uint16_t sz)
  84. {
  85. //JFM WINC Low Level
  86. int i;
  87. WIFI_SPI_SS_PIN = 0;
  88. for(i = 0; i < sz; i++)
  89. {
  90. *b++ = SPITransaction(0xAA,mWifiSPIBaudrate);
  91. }
  92. WIFI_SPI_SS_PIN = 1;
  93. return N_OK;
  94. }
  95. static inline int8_t spi_write(uint8_t *b, uint16_t sz)
  96. {
  97. //JFM WINC Low Level
  98. int i;
  99. WIFI_SPI_SS_PIN = 0;
  100. for(i = 0; i < sz; i++)
  101. {
  102. SPITransaction(*b++,mWifiSPIBaudrate);
  103. }
  104. WIFI_SPI_SS_PIN = 1;
  105. return N_OK;
  106. }
  107. /********************************************
  108. Crc7
  109. ********************************************/
  110. static const uint8_t crc7_syndrome_table[256] = {
  111. 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
  112. 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
  113. 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26,
  114. 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e,
  115. 0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d,
  116. 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
  117. 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14,
  118. 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c,
  119. 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b,
  120. 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13,
  121. 0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42,
  122. 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
  123. 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69,
  124. 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21,
  125. 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70,
  126. 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38,
  127. 0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e,
  128. 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
  129. 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67,
  130. 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f,
  131. 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
  132. 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
  133. 0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55,
  134. 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
  135. 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a,
  136. 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52,
  137. 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03,
  138. 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b,
  139. 0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28,
  140. 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
  141. 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31,
  142. 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79
  143. };
  144. static uint8_t crc7_byte(uint8_t crc, uint8_t data)
  145. {
  146. return crc7_syndrome_table[(crc << 1) ^ data];
  147. }
  148. static uint8_t crc7(uint8_t crc, const uint8_t *buffer, uint32_t len)
  149. {
  150. while (len--)
  151. crc = crc7_byte(crc, *buffer++);
  152. return crc;
  153. }
  154. /********************************************
  155. Spi protocol Function
  156. ********************************************/
  157. static int8_t spi_cmd(uint8_t cmd, uint32_t adr, uint32_t u32data, uint32_t sz, uint8_t clockless)
  158. {
  159. uint8_t bc[9];
  160. uint8_t len = 5;
  161. bc[0] = cmd;
  162. switch (cmd)
  163. {
  164. case CMD_SINGLE_READ: /* single word (4 bytes) read */
  165. bc[1] = (uint8_t)(adr >> 16);
  166. bc[2] = (uint8_t)(adr >> 8);
  167. bc[3] = (uint8_t)adr;
  168. len = 5;
  169. break;
  170. case CMD_INTERNAL_READ: /* internal register read */
  171. bc[1] = (uint8_t)(adr >> 8);
  172. if(clockless)
  173. bc[1] |= (1 << 7);
  174. bc[2] = (uint8_t)adr;
  175. bc[3] = 0x00;
  176. len = 5;
  177. break;
  178. #ifdef CMD_TERMINATE
  179. case CMD_TERMINATE: /* termination */
  180. bc[1] = 0x00;
  181. bc[2] = 0x00;
  182. bc[3] = 0x00;
  183. len = 5;
  184. break;
  185. #endif
  186. #ifdef CMD_REPEAT
  187. case CMD_REPEAT: /* repeat */
  188. bc[1] = 0x00;
  189. bc[2] = 0x00;
  190. bc[3] = 0x00;
  191. len = 5;
  192. break;
  193. #endif
  194. case CMD_RESET: /* reset */
  195. bc[1] = 0xff;
  196. bc[2] = 0xff;
  197. bc[3] = 0xff;
  198. len = 5;
  199. break;
  200. #if defined(CMD_DMA_WRITE) || defined(CMD_DMA_READ)
  201. case CMD_DMA_WRITE: /* dma write */
  202. case CMD_DMA_READ: /* dma read */
  203. bc[1] = (uint8_t)(adr >> 16);
  204. bc[2] = (uint8_t)(adr >> 8);
  205. bc[3] = (uint8_t)adr;
  206. bc[4] = (uint8_t)(sz >> 8);
  207. bc[5] = (uint8_t)(sz);
  208. len = 7;
  209. break;
  210. #endif
  211. case CMD_DMA_EXT_WRITE: /* dma extended write */
  212. case CMD_DMA_EXT_READ: /* dma extended read */
  213. bc[1] = (uint8_t)(adr >> 16);
  214. bc[2] = (uint8_t)(adr >> 8);
  215. bc[3] = (uint8_t)adr;
  216. bc[4] = (uint8_t)(sz >> 16);
  217. bc[5] = (uint8_t)(sz >> 8);
  218. bc[6] = (uint8_t)(sz);
  219. len = 8;
  220. break;
  221. case CMD_INTERNAL_WRITE: /* internal register write */
  222. bc[1] = (uint8_t)(adr >> 8);
  223. if(clockless) bc[1] |= (1 << 7);
  224. bc[2] = (uint8_t)(adr);
  225. bc[3] = (uint8_t)(u32data >> 24);
  226. bc[4] = (uint8_t)(u32data >> 16);
  227. bc[5] = (uint8_t)(u32data >> 8);
  228. bc[6] = (uint8_t)(u32data);
  229. len = 8;
  230. break;
  231. case CMD_SINGLE_WRITE: /* single word write */
  232. bc[1] = (uint8_t)(adr >> 16);
  233. bc[2] = (uint8_t)(adr >> 8);
  234. bc[3] = (uint8_t)(adr);
  235. bc[4] = (uint8_t)(u32data >> 24);
  236. bc[5] = (uint8_t)(u32data >> 16);
  237. bc[6] = (uint8_t)(u32data >> 8);
  238. bc[7] = (uint8_t)(u32data);
  239. len = 9;
  240. break;
  241. default:
  242. return N_FAIL;
  243. }
  244. if (!gu8Crc_off)
  245. {
  246. bc[len-1] = (crc7(0x7f, (const uint8_t *)&bc[0], len-1)) << 1;
  247. }
  248. else
  249. {
  250. len -= 1;
  251. }
  252. if (N_OK != spi_write(bc, len))
  253. {
  254. M2M_ERR("[spi_cmd]: Failed cmd write, bus error...\r\n");
  255. return N_FAIL;
  256. }
  257. return N_OK;
  258. }
  259. static int8_t spi_cmd_rsp(uint8_t cmd)
  260. {
  261. uint8_t rsp;
  262. int8_t s8RetryCnt;
  263. /**
  264. Command/Control response
  265. **/
  266. if ((cmd == CMD_RESET)
  267. #ifdef CMD_TERMINATE
  268. || (cmd == CMD_TERMINATE)
  269. #endif
  270. #ifdef CMD_REPEAT
  271. || (cmd == CMD_REPEAT)
  272. #endif
  273. )
  274. {
  275. if (N_OK != spi_read(&rsp, 1))
  276. return N_FAIL;
  277. }
  278. /* wait for response */
  279. s8RetryCnt = SPI_RESP_RETRY_COUNT;
  280. do
  281. {
  282. if (N_OK != spi_read(&rsp, 1))
  283. {
  284. M2M_ERR("[spi_cmd_rsp]: Failed cmd response read, bus error...\r\n");
  285. return N_FAIL;
  286. }
  287. }
  288. while((rsp != cmd) && (s8RetryCnt-- > 0));
  289. if (s8RetryCnt < 0)
  290. {
  291. M2M_ERR("[spi_cmd_rsp]: Failed cmd response read\n");
  292. return N_FAIL;
  293. }
  294. /**
  295. State response
  296. **/
  297. /* wait for response */
  298. s8RetryCnt = SPI_RESP_RETRY_COUNT;
  299. do
  300. {
  301. if (N_OK != spi_read(&rsp, 1))
  302. {
  303. M2M_ERR("[spi_cmd_rsp]: Failed cmd response read, bus error...\r\n");
  304. return N_FAIL;
  305. }
  306. }
  307. while((rsp != 0x00) && (s8RetryCnt-- > 0));
  308. if (s8RetryCnt < 0)
  309. {
  310. M2M_ERR("[spi_cmd_rsp]: Failed cmd response read\n");
  311. return N_FAIL;
  312. }
  313. return N_OK;
  314. }
  315. static void spi_reset(void)
  316. {
  317. nm_sleep(1);
  318. spi_cmd(CMD_RESET, 0, 0, 0, 0);
  319. spi_cmd_rsp(CMD_RESET);
  320. nm_sleep(1);
  321. }
  322. /********************************************
  323. Spi Internal Read/Write Function
  324. ********************************************/
  325. static int8_t spi_data_read(uint8_t *b, uint16_t sz,uint8_t clockless)
  326. {
  327. int16_t retry, ix, nbytes;
  328. int8_t result = N_OK;
  329. uint8_t crc[2];
  330. uint8_t rsp;
  331. /**
  332. Data
  333. **/
  334. ix = 0;
  335. do {
  336. if (sz <= DATA_PKT_SZ)
  337. nbytes = sz;
  338. else
  339. nbytes = DATA_PKT_SZ;
  340. /**
  341. Data Response header
  342. **/
  343. retry = SPI_RESP_RETRY_COUNT;
  344. do
  345. {
  346. if (N_OK != spi_read(&rsp, 1))
  347. {
  348. M2M_ERR("[spi_data_read]: Failed data response read, bus error...\r\n");
  349. result = N_FAIL;
  350. break;
  351. }
  352. if ((rsp & 0xf0) == 0xf0)
  353. break;
  354. }
  355. while (retry--);
  356. if (result == N_FAIL)
  357. break;
  358. if (retry <= 0)
  359. {
  360. M2M_ERR("[spi_data_read]: Failed data response read...(%02x)\r\n", rsp);
  361. result = N_FAIL;
  362. break;
  363. }
  364. /**
  365. Read bytes
  366. **/
  367. if (N_OK != spi_read(&b[ix], nbytes))
  368. {
  369. M2M_ERR("[spi_data_read]: Failed data block read, bus error...\r\n");
  370. result = N_FAIL;
  371. break;
  372. }
  373. if(!clockless)
  374. {
  375. /**
  376. Read Crc
  377. **/
  378. if (!gu8Crc_off)
  379. {
  380. if (N_OK != spi_read(crc, 2))
  381. {
  382. M2M_ERR("[spi_data_read]: Failed data block CRC read, bus error...\r\n");
  383. result = N_FAIL;
  384. break;
  385. }
  386. }
  387. }
  388. ix += nbytes;
  389. sz -= nbytes;
  390. } while (sz);
  391. return result;
  392. }
  393. static int8_t spi_data_write(uint8_t *b, uint16_t sz)
  394. {
  395. int16_t ix = 0;
  396. uint16_t nbytes;
  397. int8_t result = N_OK;
  398. uint8_t cmd, order, crc[2] = {0};
  399. //uint8_t rsp;
  400. /**
  401. Data
  402. **/
  403. do
  404. {
  405. if (sz <= DATA_PKT_SZ)
  406. nbytes = sz;
  407. else
  408. nbytes = DATA_PKT_SZ;
  409. /**
  410. Write command
  411. **/
  412. cmd = 0xf0;
  413. if (ix == 0)
  414. {
  415. if (sz <= DATA_PKT_SZ)
  416. order = 0x3;
  417. else
  418. order = 0x1;
  419. }
  420. else
  421. {
  422. if (sz <= DATA_PKT_SZ)
  423. order = 0x3;
  424. else
  425. order = 0x2;
  426. }
  427. cmd |= order;
  428. if (N_OK != spi_write(&cmd, 1))
  429. {
  430. M2M_ERR("[spi_data_write]: Failed data block cmd write, bus error...\r\n");
  431. result = N_FAIL;
  432. break;
  433. }
  434. /**
  435. Write data
  436. **/
  437. if (N_OK != spi_write(&b[ix], nbytes))
  438. {
  439. M2M_ERR("[spi_data_write]: Failed data block write, bus error...\r\n");
  440. result = N_FAIL;
  441. break;
  442. }
  443. /**
  444. Write Crc
  445. **/
  446. if (!gu8Crc_off)
  447. {
  448. if (N_OK != spi_write(crc, 2))
  449. {
  450. M2M_ERR("[spi_data_write]: Failed data block CRC write, bus error...\r\n");
  451. result = N_FAIL;
  452. break;
  453. }
  454. }
  455. ix += nbytes;
  456. sz -= nbytes;
  457. }
  458. while (sz);
  459. return result;
  460. }
  461. /********************************************
  462. Spi interfaces
  463. ********************************************/
  464. static int8_t spi_write_reg(uint32_t u32Addr, uint32_t u32Val)
  465. {
  466. uint8_t cmd = CMD_SINGLE_WRITE;
  467. uint8_t clockless = 0;
  468. if (u32Addr <= 0x30)
  469. {
  470. /**
  471. NMC1000 clockless registers.
  472. **/
  473. cmd = CMD_INTERNAL_WRITE;
  474. clockless = 1;
  475. }
  476. if (spi_cmd(cmd, u32Addr, u32Val, 4, clockless) != N_OK)
  477. {
  478. M2M_ERR("[spi_write_reg]: Failed cmd, write reg (%08" PRIx32 ")...\r\n", u32Addr);
  479. return N_FAIL;
  480. }
  481. if (spi_cmd_rsp(cmd) != N_OK)
  482. {
  483. M2M_ERR("[spi_write_reg]: Failed cmd response, write reg (%08" PRIx32 ")...\r\n", u32Addr);
  484. return N_FAIL;
  485. }
  486. return N_OK;
  487. }
  488. static int8_t spi_write_block(uint32_t u32Addr, uint8_t *puBuf, uint16_t u16Sz)
  489. {
  490. uint8_t len;
  491. uint8_t rsp[3];
  492. /**
  493. Command
  494. **/
  495. if (spi_cmd(CMD_DMA_EXT_WRITE, u32Addr, 0, u16Sz, 0) != N_OK)
  496. {
  497. M2M_ERR("[spi_write_block]: Failed cmd, write block (%08" PRIx32 ")...\r\n", u32Addr);
  498. return N_FAIL;
  499. }
  500. if (spi_cmd_rsp(CMD_DMA_EXT_WRITE) != N_OK)
  501. {
  502. M2M_ERR("[spi_write_block]: Failed cmd response, write block (%08" PRIx32 ")...\r\n", u32Addr);
  503. return N_FAIL;
  504. }
  505. /**
  506. Data
  507. **/
  508. if (spi_data_write(puBuf, u16Sz) != N_OK)
  509. {
  510. M2M_ERR("[spi_write_block]: Failed block data write...\r\n");
  511. return N_FAIL;
  512. }
  513. /**
  514. Data RESP
  515. **/
  516. if (!gu8Crc_off)
  517. len = 2;
  518. else
  519. len = 3;
  520. if (N_OK != spi_read(&rsp[0], len))
  521. {
  522. M2M_ERR("[spi_write_block]: Failed bus error...\r\n");
  523. return N_FAIL;
  524. }
  525. if((rsp[len-1] != 0) || (rsp[len-2] != 0xC3))
  526. {
  527. M2M_ERR("[spi_write_block]: Failed data response read, %x %x %x\r\n", rsp[0], rsp[1], rsp[2]);
  528. return N_FAIL;
  529. }
  530. return N_OK;
  531. }
  532. static int8_t spi_read_reg(uint32_t u32Addr, uint32_t* pu32RetVal)
  533. {
  534. uint8_t cmd = CMD_SINGLE_READ;
  535. uint8_t tmp[4];
  536. uint8_t clockless = 0;
  537. if (u32Addr <= 0xff)
  538. {
  539. /**
  540. NMC1000 clockless registers.
  541. **/
  542. cmd = CMD_INTERNAL_READ;
  543. clockless = 1;
  544. }
  545. if (spi_cmd(cmd, u32Addr, 0, 4, clockless) != N_OK)
  546. {
  547. M2M_ERR("[spi_read_reg]: Failed cmd, read reg (%08" PRIx32 ")...\r\n", u32Addr);
  548. return N_FAIL;
  549. }
  550. if (spi_cmd_rsp(cmd) != N_OK)
  551. {
  552. M2M_ERR("[spi_read_reg]: Failed cmd response, read reg (%08" PRIx32 ")...\r\n", u32Addr);
  553. return N_FAIL;
  554. }
  555. /* to avoid endianess issues */
  556. if (spi_data_read(&tmp[0], 4, clockless) != N_OK)
  557. {
  558. M2M_ERR("[spi_read_reg]: Failed data read...\r\n");
  559. return N_FAIL;
  560. }
  561. *pu32RetVal = ((uint32_t)tmp[0]) |
  562. ((uint32_t)tmp[1] << 8) |
  563. ((uint32_t)tmp[2] << 16) |
  564. ((uint32_t)tmp[3] << 24);
  565. return N_OK;
  566. }
  567. static int8_t spi_read_block(uint32_t u32Addr, uint8_t *puBuf, uint16_t u16Sz)
  568. {
  569. /**
  570. Command
  571. **/
  572. if (spi_cmd(CMD_DMA_EXT_READ, u32Addr, 0, u16Sz, 0) != N_OK)
  573. {
  574. M2M_ERR("[spi_read_block]: Failed cmd, read block (%08" PRIx32 ")...\r\n", u32Addr);
  575. return N_FAIL;
  576. }
  577. if (spi_cmd_rsp(CMD_DMA_EXT_READ) != N_OK)
  578. {
  579. M2M_ERR("[spi_read_block]: Failed cmd response, read block (%08" PRIx32 ")...\r\n", u32Addr);
  580. return N_FAIL;
  581. }
  582. /**
  583. Data
  584. **/
  585. if (spi_data_read(puBuf, u16Sz, 0) != N_OK)
  586. {
  587. M2M_ERR("[spi_read_block]: Failed block data read...\r\n");
  588. return N_FAIL;
  589. }
  590. return N_OK;
  591. }
  592. static void spi_init_pkt_sz(void)
  593. {
  594. uint32_t val32;
  595. /* Make sure SPI max. packet size fits the defined DATA_PKT_SZ. */
  596. val32 = nm_spi_read_reg(SPI_BASE+0x24);
  597. val32 &= ~(0x7 << 4);
  598. switch(DATA_PKT_SZ)
  599. {
  600. case 256: val32 |= (0 << 4); break;
  601. case 512: val32 |= (1 << 4); break;
  602. case 1024: val32 |= (2 << 4); break;
  603. case 2048: val32 |= (3 << 4); break;
  604. case 4096: val32 |= (4 << 4); break;
  605. case 8192: val32 |= (5 << 4); break;
  606. }
  607. nm_spi_write_reg(SPI_BASE+0x24, val32);
  608. }
  609. /********************************************
  610. Bus interfaces
  611. ********************************************/
  612. int8_t nm_spi_reset(void)
  613. {
  614. // if (OSAL_RESULT_TRUE != OSAL_MUTEX_Lock(&s_spiLock, OSAL_WAIT_FOREVER))
  615. // return M2M_ERR_BUS_FAIL;
  616. spi_cmd(CMD_RESET, 0, 0, 0, 0);
  617. spi_cmd_rsp(CMD_RESET);
  618. // OSAL_MUTEX_Unlock(&s_spiLock);
  619. return M2M_SUCCESS;
  620. }
  621. void nm_spi_lock_init(void)
  622. {
  623. // OSAL_MUTEX_Create(&s_spiLock);
  624. }
  625. /*
  626. * @fn nm_spi_init
  627. * @brief Initialize the SPI
  628. * @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
  629. */
  630. int8_t nm_spi_init(void)
  631. {
  632. uint32_t chipid;
  633. uint32_t reg = 0;
  634. mWifiSPIBaudrate = SPICalculateBRG(PERIPHERAL_FREQ, WIFI_MODULE_SPI_BAUDRATE);
  635. /**
  636. configure protocol
  637. **/
  638. gu8Crc_off = 0;
  639. if (nm_spi_read_reg_with_ret(NMI_SPI_PROTOCOL_CONFIG, &reg) != M2M_SUCCESS)
  640. {
  641. /* Read failed. Try with CRC off. This might happen when module
  642. is removed but chip isn't reset*/
  643. gu8Crc_off = 1;
  644. M2M_ERR("[nm_spi_init]: Failed internal read protocol with CRC on, retrying with CRC off...\r\n");
  645. if (nm_spi_read_reg_with_ret(NMI_SPI_PROTOCOL_CONFIG, &reg) != M2M_SUCCESS)
  646. {
  647. // Reaad failed with both CRC on and off, something went bad
  648. M2M_ERR("[nm_spi_init]: Failed internal read protocol...\r\n");
  649. return M2M_ERR_BUS_FAIL;
  650. }
  651. }
  652. if(gu8Crc_off == 0)
  653. {
  654. reg &= ~0xc; /* disable CRC checking */
  655. reg &= ~0x70;
  656. reg |= (0x5 << 4);
  657. if (nm_spi_write_reg(NMI_SPI_PROTOCOL_CONFIG, reg) != M2M_SUCCESS)
  658. {
  659. M2M_ERR("[nm_spi_init]: Failed internal write protocol reg...\r\n");
  660. return M2M_ERR_BUS_FAIL;
  661. }
  662. gu8Crc_off = 1;
  663. }
  664. /**
  665. make sure can read back chip id correctly
  666. **/
  667. if (nm_spi_read_reg_with_ret(0x1000, &chipid) != M2M_SUCCESS)
  668. {
  669. M2M_ERR("[nm_spi_init]: Fail cmd read chip id...\r\n");
  670. return M2M_ERR_BUS_FAIL;
  671. }
  672. M2M_DBG("[nm_spi_init]: chipid (%08x)\r\n", (unsigned int)chipid);
  673. spi_init_pkt_sz();
  674. return M2M_SUCCESS;
  675. }
  676. /*
  677. * @fn nm_spi_deinit
  678. * @brief DeInitialize the SPI
  679. * @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
  680. */
  681. int8_t nm_spi_deinit(void)
  682. {
  683. gu8Crc_off = 0;
  684. // OSAL_MUTEX_Delete(&s_spiLock);
  685. return M2M_SUCCESS;
  686. }
  687. /*
  688. * @fn nm_spi_read_reg
  689. * @brief Read register
  690. * @param [in] u32Addr
  691. * Register address
  692. * @return Register value
  693. */
  694. uint32_t nm_spi_read_reg(uint32_t u32Addr)
  695. {
  696. uint32_t u32Val;
  697. nm_spi_read_reg_with_ret(u32Addr, &u32Val);
  698. return u32Val;
  699. }
  700. /*
  701. * @fn nm_spi_read_reg_with_ret
  702. * @brief Read register with error code return
  703. * @param [in] u32Addr
  704. * Register address
  705. * @param [out] pu32RetVal
  706. * Pointer to u32 variable used to return the read value
  707. * @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
  708. */
  709. int8_t nm_spi_read_reg_with_ret(uint32_t u32Addr, uint32_t* pu32RetVal)
  710. {
  711. uint8_t retry = SPI_RETRY_COUNT;
  712. // if (OSAL_RESULT_TRUE != OSAL_MUTEX_Lock(&s_spiLock, OSAL_WAIT_FOREVER))
  713. // return M2M_ERR_BUS_FAIL;
  714. while(retry--)
  715. {
  716. if (spi_read_reg(u32Addr, pu32RetVal) == N_OK)
  717. {
  718. // OSAL_MUTEX_Unlock(&s_spiLock);
  719. return M2M_SUCCESS;
  720. }
  721. M2M_ERR("Reset and retry %d %" PRIx32 "\r\n", retry, u32Addr);
  722. spi_reset();
  723. }
  724. // OSAL_MUTEX_Unlock(&s_spiLock);
  725. return M2M_ERR_BUS_FAIL;
  726. }
  727. /*
  728. * @fn nm_spi_write_reg
  729. * @brief write register
  730. * @param [in] u32Addr
  731. * Register address
  732. * @param [in] u32Val
  733. * Value to be written to the register
  734. * @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
  735. */
  736. int8_t nm_spi_write_reg(uint32_t u32Addr, uint32_t u32Val)
  737. {
  738. uint8_t retry = SPI_RETRY_COUNT;
  739. // if (OSAL_RESULT_TRUE != OSAL_MUTEX_Lock(&s_spiLock, OSAL_WAIT_FOREVER))
  740. // return M2M_ERR_BUS_FAIL;
  741. while(retry--)
  742. {
  743. if (spi_write_reg(u32Addr, u32Val) == N_OK)
  744. {
  745. // OSAL_MUTEX_Unlock(&s_spiLock);
  746. return M2M_SUCCESS;
  747. }
  748. M2M_ERR("Reset and retry %d %" PRIx32 " %" PRIx32 "\r\n", retry, u32Addr, u32Val);
  749. spi_reset();
  750. }
  751. // OSAL_MUTEX_Unlock(&s_spiLock);
  752. return M2M_ERR_BUS_FAIL;
  753. }
  754. /*
  755. * @fn nm_spi_read_block
  756. * @brief Read block of data
  757. * @param [in] u32Addr
  758. * Start address
  759. * @param [out] puBuf
  760. * Pointer to a buffer used to return the read data
  761. * @param [in] u16Sz
  762. * Number of bytes to read. The buffer size must be >= u16Sz
  763. * @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
  764. */
  765. int8_t nm_spi_read_block(uint32_t u32Addr, uint8_t *puBuf, uint16_t u16Sz)
  766. {
  767. uint8_t retry = SPI_RETRY_COUNT;
  768. uint8_t tmpBuf[2] = {0,0};
  769. uint8_t *puTmpBuf;
  770. // if (OSAL_RESULT_TRUE != OSAL_MUTEX_Lock(&s_spiLock, OSAL_WAIT_FOREVER))
  771. // return M2M_ERR_BUS_FAIL;
  772. if (u16Sz == 1)
  773. {
  774. u16Sz = 2;
  775. puTmpBuf = tmpBuf;
  776. }
  777. else
  778. {
  779. puTmpBuf = puBuf;
  780. }
  781. while(retry--)
  782. {
  783. if (spi_read_block(u32Addr, puTmpBuf, u16Sz) == N_OK)
  784. {
  785. // OSAL_MUTEX_Unlock(&s_spiLock);
  786. if (puTmpBuf == tmpBuf)
  787. *puBuf = *tmpBuf;
  788. return M2M_SUCCESS;
  789. }
  790. M2M_ERR("Reset and retry %d %" PRIx32 " %d\r\n", retry, u32Addr, u16Sz);
  791. spi_reset();
  792. }
  793. // OSAL_MUTEX_Unlock(&s_spiLock);
  794. return M2M_ERR_BUS_FAIL;
  795. }
  796. /*
  797. * @fn nm_spi_write_block
  798. * @brief Write block of data
  799. * @param [in] u32Addr
  800. * Start address
  801. * @param [in] puBuf
  802. * Pointer to the buffer holding the data to be written
  803. * @param [in] u16Sz
  804. * Number of bytes to write. The buffer size must be >= u16Sz
  805. * @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
  806. */
  807. int8_t nm_spi_write_block(uint32_t u32Addr, uint8_t *puBuf, uint16_t u16Sz)
  808. {
  809. uint8_t retry = SPI_RETRY_COUNT;
  810. // if (OSAL_RESULT_TRUE != OSAL_MUTEX_Lock(&s_spiLock, OSAL_WAIT_FOREVER))
  811. // return M2M_ERR_BUS_FAIL;
  812. //Workaround hardware problem with single byte transfers over SPI bus
  813. if (u16Sz == 1)
  814. u16Sz = 2;
  815. while(retry--)
  816. {
  817. if (spi_write_block(u32Addr, puBuf, u16Sz) == N_OK)
  818. {
  819. // OSAL_MUTEX_Unlock(&s_spiLock);
  820. return M2M_SUCCESS;
  821. }
  822. M2M_ERR("Reset and retry %d %" PRIx32 " %d\r\n", retry, u32Addr, u16Sz);
  823. spi_reset();
  824. }
  825. // OSAL_MUTEX_Unlock(&s_spiLock);
  826. return M2M_ERR_BUS_FAIL;
  827. }
  828. //DOM-IGNORE-END