You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

911 lines
21 KiB

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