nmspi.c
Go to the documentation of this file.
1 
35 
36 #ifdef CONF_WINC_USE_SPI
37 
38 #define USE_OLD_SPI_SW
39 
41 #include "nmspi.h"
42 
43 #define NMI_PERIPH_REG_BASE 0x1000
44 #define NMI_INTR_REG_BASE (NMI_PERIPH_REG_BASE+0xa00)
45 #define NMI_CHIPID (NMI_PERIPH_REG_BASE)
46 #define NMI_PIN_MUX_0 (NMI_PERIPH_REG_BASE + 0x408)
47 #define NMI_INTR_ENABLE (NMI_INTR_REG_BASE)
48 
49 #define NMI_SPI_REG_BASE 0xe800
50 #define NMI_SPI_CTL (NMI_SPI_REG_BASE)
51 #define NMI_SPI_MASTER_DMA_ADDR (NMI_SPI_REG_BASE+0x4)
52 #define NMI_SPI_MASTER_DMA_COUNT (NMI_SPI_REG_BASE+0x8)
53 #define NMI_SPI_SLAVE_DMA_ADDR (NMI_SPI_REG_BASE+0xc)
54 #define NMI_SPI_SLAVE_DMA_COUNT (NMI_SPI_REG_BASE+0x10)
55 #define NMI_SPI_TX_MODE (NMI_SPI_REG_BASE+0x20)
56 #define NMI_SPI_PROTOCOL_CONFIG (NMI_SPI_REG_BASE+0x24)
57 #define NMI_SPI_INTR_CTL (NMI_SPI_REG_BASE+0x2c)
58 
59 #define NMI_SPI_PROTOCOL_OFFSET (NMI_SPI_PROTOCOL_CONFIG-NMI_SPI_REG_BASE)
60 
61 #define SPI_BASE NMI_SPI_REG_BASE
62 
63 //#define CMD_DMA_WRITE 0xc1
64 //#define CMD_DMA_READ 0xc2
65 #define CMD_INTERNAL_WRITE 0xc3
66 #define CMD_INTERNAL_READ 0xc4
67 //#define CMD_TERMINATE 0xc5
68 //#define CMD_REPEAT 0xc6
69 #define CMD_DMA_EXT_WRITE 0xc7
70 #define CMD_DMA_EXT_READ 0xc8
71 #define CMD_SINGLE_WRITE 0xc9
72 #define CMD_SINGLE_READ 0xca
73 #define CMD_RESET 0xcf
74 
75 #define N_OK 0
76 #define N_FAIL -1
77 #define N_RESET -2
78 #define N_RETRY -3
79 
80 
81 #define DATA_PKT_SZ_256 256
82 #define DATA_PKT_SZ_512 512
83 #define DATA_PKT_SZ_1K 1024
84 #define DATA_PKT_SZ_4K (4 * 1024)
85 #define DATA_PKT_SZ_8K (8 * 1024)
86 #define DATA_PKT_SZ DATA_PKT_SZ_8K
87 
88 static uint8 gu8Crc_off = 0;
89 #if (defined __SAMG55J19__) || (defined __SAM4SD32C__) || (defined __SAME70Q21__) || (defined __SAME70Q20B__) || (defined __SAME70Q21B__)
90 static sint8 nmi_spi_read(uint8* b, uint16 sz)
91 {
92  tstrNmSpiRw spi;
93  spi.pu8InBuf = NULL;
94  spi.pu8OutBuf = b;
95  spi.u16Sz = sz;
96  return nm_bus_ioctl(NM_BUS_IOCTL_RW, &spi);
97 }
98 
99 static sint8 nmi_spi_write(uint8* b, uint16 sz)
100 {
101  tstrNmSpiRw spi;
102  spi.pu8InBuf = b;
103  spi.pu8OutBuf = NULL;
104  spi.u16Sz = sz;
105  return nm_bus_ioctl(NM_BUS_IOCTL_RW, &spi);
106 }
107 
108 static sint8 nmi_spi_writeread(uint8* bw, uint8* br, uint16 sz)
109 {
110  nmi_spi_write(bw, sz);
111  return nmi_spi_read(br, sz);
112 }
113 #else
114 static inline sint8 nmi_spi_read(uint8* b, uint16 sz)
115 {
116  return nm_spi_rw(NULL, b, sz);
117 }
118 static inline sint8 nmi_spi_write(uint8* b, uint16 sz)
119 {
120  return nm_spi_rw(b, NULL, sz);
121 }
122 static sint8 nmi_spi_writeread(uint8* bw, uint8* br, uint16 sz)
123 {
124  return nm_spi_rw(bw, br, sz);
125 }
126 #endif
127 /********************************************
128 
129  Crc7
130 
131 ********************************************/
132 
133 static const uint8 crc7_syndrome_table[256] = {
134  0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
135  0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
136  0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26,
137  0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e,
138  0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d,
139  0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
140  0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14,
141  0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c,
142  0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b,
143  0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13,
144  0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42,
145  0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
146  0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69,
147  0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21,
148  0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70,
149  0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38,
150  0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e,
151  0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
152  0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67,
153  0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f,
154  0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
155  0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
156  0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55,
157  0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
158  0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a,
159  0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52,
160  0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03,
161  0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b,
162  0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28,
163  0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
164  0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31,
165  0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79
166 };
167 
168 
169 static inline uint8 crc7_byte(uint8 crc, uint8 data)
170 {
171  return crc7_syndrome_table[(crc << 1) ^ data];
172 }
173 
174 static inline uint8 crc7(uint8 crc, const uint8 *buffer, uint32 len)
175 {
176  while (len--)
177  crc = crc7_byte(crc, *buffer++);
178  return crc;
179 }
180 
181 /********************************************
182 
183  Spi protocol Function
184 
185 ********************************************/
186 
187 static sint8 spi_cmd(uint8 cmd, uint32 adr, uint32 u32data, uint32 sz,uint8 clockless)
188 {
189  uint8 bc[9];
190  uint8 len = 5;
191  sint8 result = N_OK;
192 
193  bc[0] = cmd;
194  switch (cmd) {
195  case CMD_SINGLE_READ: /* single word (4 bytes) read */
196  bc[1] = (uint8)(adr >> 16);
197  bc[2] = (uint8)(adr >> 8);
198  bc[3] = (uint8)adr;
199  len = 5;
200  break;
201  case CMD_INTERNAL_READ: /* internal register read */
202  bc[1] = (uint8)(adr >> 8);
203  if(clockless) bc[1] |= (1 << 7);
204  bc[2] = (uint8)adr;
205  bc[3] = 0x00;
206  len = 5;
207  break;
208 #if defined(CMD_TERMINATE)
209  case CMD_TERMINATE: /* termination */
210  bc[1] = 0x00;
211  bc[2] = 0x00;
212  bc[3] = 0x00;
213  len = 5;
214  break;
215 #endif
216 #if defined(CMD_REPEAT)
217  case CMD_REPEAT: /* repeat */
218  bc[1] = 0x00;
219  bc[2] = 0x00;
220  bc[3] = 0x00;
221  len = 5;
222  break;
223 #endif
224  case CMD_RESET: /* reset */
225  bc[1] = 0xff;
226  bc[2] = 0xff;
227  bc[3] = 0xff;
228  len = 5;
229  break;
230 #if defined(CMD_DMA_WRITE) || defined(CMD_DMA_READ)
231  case CMD_DMA_WRITE: /* dma write */
232  case CMD_DMA_READ: /* dma read */
233  bc[1] = (uint8)(adr >> 16);
234  bc[2] = (uint8)(adr >> 8);
235  bc[3] = (uint8)adr;
236  bc[4] = (uint8)(sz >> 8);
237  bc[5] = (uint8)(sz);
238  len = 7;
239  break;
240 #endif
241  case CMD_DMA_EXT_WRITE: /* dma extended write */
242  case CMD_DMA_EXT_READ: /* dma extended read */
243  bc[1] = (uint8)(adr >> 16);
244  bc[2] = (uint8)(adr >> 8);
245  bc[3] = (uint8)adr;
246  bc[4] = (uint8)(sz >> 16);
247  bc[5] = (uint8)(sz >> 8);
248  bc[6] = (uint8)(sz);
249  len = 8;
250  break;
251  case CMD_INTERNAL_WRITE: /* internal register write */
252  bc[1] = (uint8)(adr >> 8);
253  if(clockless) bc[1] |= (1 << 7);
254  bc[2] = (uint8)(adr);
255  bc[3] = (uint8)(u32data >> 24);
256  bc[4] = (uint8)(u32data >> 16);
257  bc[5] = (uint8)(u32data >> 8);
258  bc[6] = (uint8)(u32data);
259  len = 8;
260  break;
261  case CMD_SINGLE_WRITE: /* single word write */
262  bc[1] = (uint8)(adr >> 16);
263  bc[2] = (uint8)(adr >> 8);
264  bc[3] = (uint8)(adr);
265  bc[4] = (uint8)(u32data >> 24);
266  bc[5] = (uint8)(u32data >> 16);
267  bc[6] = (uint8)(u32data >> 8);
268  bc[7] = (uint8)(u32data);
269  len = 9;
270  break;
271  default:
272  result = N_FAIL;
273  break;
274  }
275 
276  if (result == N_OK) {
277  if (!gu8Crc_off)
278  bc[len-1] = (crc7(0x7f, (const uint8 *)&bc[0], len-1)) << 1;
279  else
280  len-=1;
281 
282  if (M2M_SUCCESS != nmi_spi_write(bc, len)) {
283  M2M_ERR("[nmi spi]: Failed cmd write, bus error...\n");
284  result = N_FAIL;
285  }
286  }
287 
288  return result;
289 }
290 
291 static sint8 spi_cmd_rsp(uint8 cmd)
292 {
293  uint8 rsp;
294  sint8 result = N_OK;
295  sint8 s8RetryCnt;
296 
300 #if defined(CMD_TERMINATE)
301  if (cmd == CMD_TERMINATE) {
302  if (M2M_SUCCESS != nmi_spi_read(&rsp, 1)) {
303  result = N_FAIL;
304  goto _fail_;
305  }
306  }
307 #endif
308 #if defined(CMD_REPEAT)
309  if (cmd == CMD_REPEAT) {
310  if (M2M_SUCCESS != nmi_spi_read(&rsp, 1)) {
311  result = N_FAIL;
312  goto _fail_;
313  }
314  }
315 #endif
316 
317  /* wait for response */
318  s8RetryCnt = 10;
319  do
320  {
321  if (M2M_SUCCESS != nmi_spi_read(&rsp, 1)) {
322  M2M_ERR("[nmi spi]: Failed cmd response read, bus error...\n");
323  result = N_FAIL;
324  goto _fail_;
325  }
326  } while((rsp != cmd) && (s8RetryCnt-- >0));
327  if (s8RetryCnt < 0)
328  {
329  M2M_ERR("[nmi spi]: Failed cmd response read\n");
330  result = N_FAIL;
331  goto _fail_;
332  }
336  /* wait for response */
337  s8RetryCnt = 10;
338  do
339  {
340  if (M2M_SUCCESS != nmi_spi_read(&rsp, 1)) {
341  M2M_ERR("[nmi spi]: Failed cmd response read, bus error...\n");
342  result = N_FAIL;
343  goto _fail_;
344  }
345  } while((rsp != 0x00) && (s8RetryCnt-- >0));
346  if (s8RetryCnt < 0)
347  {
348  M2M_ERR("[nmi spi]: Failed cmd response read\n");
349  result = N_FAIL;
350  goto _fail_;
351  }
352 _fail_:
353 
354  return result;
355 }
356 
357 static sint8 spi_reset(void)
358 {
359  M2M_INFO("Reset Spi\n");
360  spi_cmd(CMD_RESET, 0, 0, 0, 0);
361 
362  if (spi_cmd_rsp(CMD_RESET) != N_OK) {
363  // Reset command failed, need to send repeated 1's until reset occurs
364  // TODO This catchall reset code has not yet been tested.
365  uint8 w_buf[8] = {0xFF};
366  uint8 r_buf[8];
367  M2M_ERR("[nmi spi]: Failed rst cmd response\n");
368  nmi_spi_writeread(w_buf, r_buf, 8);
369  if (r_buf[7] != 0xFF)
370  {
371  M2M_ERR("[nmi spi]: Failed repeated reset\n");
372  return N_FAIL;
373  }
374  }
375  // TODO: May need to call spi_init() here
376  return N_OK;
377 }
378 
379 static sint8 spi_data_read(uint8 *b, uint16 sz,uint8 clockless)
380 {
381  sint16 retry, ix, nbytes;
382  sint8 result = N_OK;
383  uint8 crc[2];
384  uint8 rsp;
385 
389  ix = 0;
390  do {
391  if (sz <= DATA_PKT_SZ)
392  nbytes = sz;
393  else
394  nbytes = DATA_PKT_SZ;
395 
399  retry = 10;
400  do {
401  if (M2M_SUCCESS != nmi_spi_read(&rsp, 1)) {
402  M2M_ERR("[nmi spi]: Failed data response read, bus error...\n");
403  result = N_FAIL;
404  break;
405  }
406  //if (((rsp >> 4) & 0xf) == 0xf)
407  if ((rsp & 0xf0) == 0xf0)
408  break;
409  } while (retry--);
410 
411  if (result == N_FAIL)
412  break;
413 
414  if (retry <= 0) {
415  M2M_ERR("[nmi spi]: Failed data response read...(%02x)\n", rsp);
416  result = N_FAIL;
417  break;
418  }
419 
423  if (M2M_SUCCESS != nmi_spi_read(&b[ix], nbytes)) {
424  M2M_ERR("[nmi spi]: Failed data block read, bus error...\n");
425  result = N_FAIL;
426  break;
427  }
428  if(!clockless)
429  {
433  if (!gu8Crc_off) {
434  if (M2M_SUCCESS != nmi_spi_read(crc, 2)) {
435  M2M_ERR("[nmi spi]: Failed data block crc read, bus error...\n");
436  result = N_FAIL;
437  break;
438  }
439  }
440  }
441  ix += nbytes;
442  sz -= nbytes;
443 
444  } while (sz);
445 
446  return result;
447 }
448 
449 static sint8 spi_data_write(uint8 *b, uint16 sz)
450 {
451  sint16 ix = 0;
452  uint16 nbytes;
453  sint8 result = N_OK;
454  uint8 cmd, order, crc[2] = {0};
455  //uint8 rsp;
456 
460  do {
461  if (sz <= DATA_PKT_SZ)
462  nbytes = sz;
463  else
464  nbytes = DATA_PKT_SZ;
465 
469  cmd = 0xf0;
470  if (ix == 0) {
471  if (sz <= DATA_PKT_SZ)
472  order = 0x3;
473  else
474  order = 0x1;
475  } else {
476  if (sz <= DATA_PKT_SZ)
477  order = 0x3;
478  else
479  order = 0x2;
480  }
481  cmd |= order;
482  if (M2M_SUCCESS != nmi_spi_write(&cmd, 1)) {
483  M2M_ERR("[nmi spi]: Failed data block cmd write, bus error...\n");
484  result = N_FAIL;
485  break;
486  }
487 
491  if (M2M_SUCCESS != nmi_spi_write(&b[ix], nbytes)) {
492  M2M_ERR("[nmi spi]: Failed data block write, bus error...\n");
493  result = N_FAIL;
494  break;
495  }
496 
500  if (!gu8Crc_off) {
501  if (M2M_SUCCESS != nmi_spi_write(crc, 2)) {
502  M2M_ERR("[nmi spi]: Failed data block crc write, bus error...\n");
503  result = N_FAIL;
504  break;
505  }
506  }
507 
508  ix += nbytes;
509  sz -= nbytes;
510  } while (sz);
511 
512 
513  return result;
514 }
515 
516 /********************************************
517 
518  Spi Internal Read/Write Function
519 
520 ********************************************/
521 
522 /********************************************
523 
524  Spi interfaces
525 
526 ********************************************/
527 
528 /*
529 * @fn nm_spi_write_reg
530 * @brief write register
531 * @param [in] u32Addr
532 * Register address
533 * @param [in] u32Val
534 * Value to be written to the register
535 * @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
536 * @author M. Abdelmawla
537 * @date 11 July 2012
538 * @version 1.0
539 */
540 sint8 nm_spi_write_reg(uint32 addr, uint32 u32data)
541 {
542  sint8 result = N_OK;
543  uint8 cmd = CMD_SINGLE_WRITE;
544  uint8 clockless = 0;
545  if (addr <= 0x30)
546  {
550  cmd = CMD_INTERNAL_WRITE;
551  clockless = 1;
552  }
553  //else
554  //{
555  // cmd = CMD_SINGLE_WRITE;
556  // clockless = 0;
557  //}
558 
559 #if defined USE_OLD_SPI_SW
560  result = spi_cmd(cmd, addr, u32data, 4, clockless);
561  if (result != N_OK) {
562  M2M_ERR("[nmi spi]: Failed cmd, write reg (%08x)...\n", (unsigned int)addr);
563  return N_FAIL;
564  }
565 
566  result = spi_cmd_rsp(cmd);
567  if (result != N_OK) {
568  M2M_ERR("[nmi spi]: Failed cmd response, write reg (%08x)...\n", (unsigned int)addr);
569  spi_reset();
570  return N_FAIL;
571  }
572 
573  return N_OK;
574 #else
575 
576  result = spi_cmd_complete(cmd, addr, (uint8*)&u32data, 4, clockless);
577  if (result != N_OK) {
578  M2M_ERR( "[nmi spi]: Failed cmd, write reg (%08x)...\n", addr);
579  }
580 
581  return result;
582 
583 #endif
584 }
585 
586 
587 /*
588 * @fn nm_spi_write_block
589 * @brief Write block of data
590 * @param [in] u32Addr
591 * Start address
592 * @param [in] puBuf
593 * Pointer to the buffer holding the data to be written
594 * @param [in] u16Sz
595 * Number of bytes to write. The buffer size must be >= u16Sz
596 * @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
597 * @author M. Abdelmawla
598 * @date 11 July 2012
599 * @version 1.0
600 */
601 sint8 nm_spi_write_block(uint32 addr, uint8 *buf, uint16 size)
602 {
603  sint8 result;
604  uint8 cmd = CMD_DMA_EXT_WRITE;
605 
606 
610 #if defined USE_OLD_SPI_SW
611 
612  //Workaround hardware problem with single byte transfers over SPI bus
613  if (size == 1)
614  size = 2;
615 
616  result = spi_cmd(cmd, addr, 0, size,0);
617  if (result != N_OK) {
618  M2M_ERR("[nmi spi]: Failed cmd, write block (%08x)...\n", (unsigned int)addr);
619  return N_FAIL;
620  }
621 
622  result = spi_cmd_rsp(cmd);
623  if (result != N_OK) {
624  M2M_ERR("[nmi spi ]: Failed cmd response, write block (%08x)...\n", (unsigned int)addr);
625  spi_reset();
626  return N_FAIL;
627  }
628 #else
629  result = spi_cmd_complete(cmd, addr, NULL, size, 0);
630  if (result != N_OK) {
631  M2M_ERR( "[nmi spi]: Failed cmd, write block (%08x)...\n", addr);
632  return N_FAIL;
633  }
634 #endif
635 
639  result = spi_data_write(buf, size);
640  if (result != N_OK) {
641  M2M_ERR("[nmi spi]: Failed block data write...\n");
642  spi_reset();
643  return N_FAIL;
644  }
645 
646  return N_OK;
647 }
648 
649 /*
650 * @fn nm_spi_read_reg_with_ret
651 * @brief Read register with error code return
652 * @param [in] u32Addr
653 * Register address
654 * @param [out] pu32RetVal
655 * Pointer to u32 variable used to return the read value
656 * @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
657 * @author M. Abdelmawla
658 * @date 11 July 2012
659 * @version 1.0
660 */
662 {
663  sint8 result = N_OK;
664  uint8 cmd = CMD_SINGLE_READ;
665  uint8 tmp[4];
666  uint8 clockless = 0;
667 
668  if (addr <= 0xff)
669  {
673  cmd = CMD_INTERNAL_READ;
674  clockless = 1;
675  }
676  //else
677  //{
678  // cmd = CMD_SINGLE_READ;
679  // clockless = 0;
680  //}
681 
682 #if defined USE_OLD_SPI_SW
683  result = spi_cmd(cmd, addr, 0, 4, clockless);
684  if (result != N_OK) {
685  M2M_ERR("[nmi spi]: Failed cmd, read reg (%08x)...\n", (unsigned int)addr);
686  return N_FAIL;
687  }
688 
689  result = spi_cmd_rsp(cmd);
690  if (result != N_OK) {
691  M2M_ERR("[nmi spi]: Failed cmd response, read reg (%08x)...\n", (unsigned int)addr);
692  spi_reset();
693  return N_FAIL;
694  }
695 
696  /* to avoid endianess issues */
697  result = spi_data_read(tmp, 4, clockless);
698  if (result != N_OK) {
699  M2M_ERR("[nmi spi]: Failed data read...\n");
700  spi_reset();
701  return N_FAIL;
702  }
703 #else
704  result = spi_cmd_complete(cmd, addr, (uint8*)&tmp[0], 4, clockless);
705  if (result != N_OK) {
706  M2M_ERR( "[nmi spi]: Failed cmd, read reg (%08x)...\n", addr);
707  return N_FAIL;
708  }
709 
710 #endif
711 
712  *u32data = tmp[0] |
713  ((uint32)tmp[1] << 8) |
714  ((uint32)tmp[2] << 16) |
715  ((uint32)tmp[3] << 24);
716 
717  return N_OK;
718 }
719 
720 /*
721 * @fn nm_spi_read_block
722 * @brief Read block of data
723 * @param [in] u32Addr
724 * Start address
725 * @param [out] puBuf
726 * Pointer to a buffer used to return the read data
727 * @param [in] u16Sz
728 * Number of bytes to read. The buffer size must be >= u16Sz
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_read_block(uint32 addr, uint8 *buf, uint16 size)
735 {
736  uint8 cmd = CMD_DMA_EXT_READ;
737  sint8 result;
738 
739 #if defined USE_OLD_SPI_SW
740  uint8 tmp[2];
741  uint8 single_byte_workaround = 0;
742 #endif
743 
747 #if defined USE_OLD_SPI_SW
748  if (size == 1)
749  {
750  //Workaround hardware problem with single byte transfers over SPI bus
751  size = 2;
752  single_byte_workaround = 1;
753  }
754  result = spi_cmd(cmd, addr, 0, size,0);
755  if (result != N_OK) {
756  M2M_ERR("[nmi spi]: Failed cmd, read block (%08x)...\n", (unsigned int)addr);
757  return N_FAIL;
758  }
759 
760  result = spi_cmd_rsp(cmd);
761  if (result != N_OK) {
762  M2M_ERR("[nmi spi]: Failed cmd response, read block (%08x)...\n", (unsigned int)addr);
763  spi_reset();
764  return N_FAIL;
765  }
766 
770  if (single_byte_workaround)
771  {
772  result = spi_data_read(tmp, size,0);
773  buf[0] = tmp[0];
774  }
775  else
776  result = spi_data_read(buf, size,0);
777  if (result != N_OK) {
778  M2M_ERR("[nmi spi]: Failed block data read...\n");
779  spi_reset();
780  return N_FAIL;
781  }
782 #else
783  result = spi_cmd_complete(cmd, addr, buf, size, 0);
784  if (result != N_OK) {
785  M2M_ERR("[nmi spi]: Failed cmd, read block (%08x)...\n", addr);
786  return N_FAIL;
787  }
788 #endif
789 
790  return N_OK;
791 }
792 
793 /********************************************
794 
795  Bus interfaces
796 
797 ********************************************/
798 
799 static void spi_init_pkt_sz(void)
800 {
801  uint32 val32;
802 
803  /* Make sure SPI max. packet size fits the defined DATA_PKT_SZ. */
804  val32 = nm_spi_read_reg(SPI_BASE+0x24);
805  val32 &= ~(0x7 << 4);
806  switch(DATA_PKT_SZ)
807  {
808  case 256: val32 |= (0 << 4); break;
809  case 512: val32 |= (1 << 4); break;
810  case 1024: val32 |= (2 << 4); break;
811  case 2048: val32 |= (3 << 4); break;
812  case 4096: val32 |= (4 << 4); break;
813  case 8192: val32 |= (5 << 4); break;
814 
815  }
816  nm_spi_write_reg(SPI_BASE+0x24, val32);
817 }
818 
819 /*
820 * @fn nm_spi_init
821 * @brief Initialize the SPI
822 * @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
823 * @author M. Abdelmawla
824 * @date 11 July 2012
825 * @version 1.0
826 */
827 sint8 nm_spi_init(void)
828 {
829  uint32 chipid;
830  uint32 reg =0;
831 
835  gu8Crc_off = 0;
836 
837  // TODO: We can remove the CRC trials if there is a definite way to reset
838  // the SPI to it's initial value.
839  if (nm_spi_read_reg_with_ret(NMI_SPI_PROTOCOL_CONFIG, &reg) != M2M_SUCCESS) {
840  /* Read failed. Try with CRC off. This might happen when module
841  is removed but chip isn't reset*/
842  gu8Crc_off = 1;
843  M2M_ERR("[nmi spi]: Failed internal read protocol with CRC on, retyring with CRC off...\n");
844  if (nm_spi_read_reg_with_ret(NMI_SPI_PROTOCOL_CONFIG, &reg) != M2M_SUCCESS){
845  // Read failed with both CRC on and off, something went bad
846  M2M_ERR( "[nmi spi]: Failed internal read protocol...\n");
847  return M2M_ERR_BUS_FAIL;
848  }
849  }
850  if(gu8Crc_off == 0)
851  {
852  reg &= ~0xc; /* disable crc checking */
853  reg &= ~0x70;
854  reg |= (0x5 << 4);
855  if (nm_spi_write_reg(NMI_SPI_PROTOCOL_CONFIG, reg) != M2M_SUCCESS) {
856  M2M_ERR( "[nmi spi]: Failed internal write protocol reg...\n");
857  return M2M_ERR_BUS_FAIL;
858  }
859  gu8Crc_off = 1;
860  }
861 
865  if (nm_spi_read_reg_with_ret(0x1000, &chipid) != M2M_SUCCESS) {
866  M2M_ERR("[nmi spi]: Fail cmd read chip id...\n");
867  return M2M_ERR_BUS_FAIL;
868  }
869 
870  M2M_DBG("[nmi spi]: chipid (%08x)\n", (unsigned int)chipid);
871  spi_init_pkt_sz();
872 
873 
874  return M2M_SUCCESS;
875 }
876 
877 /*
878 * @fn nm_spi_init
879 * @brief DeInitialize the SPI
880 * @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
881 * @author Samer Sarhan
882 * @date 27 Feb 2015
883 * @version 1.0
884 */
885 sint8 nm_spi_deinit(void)
886 {
887  gu8Crc_off = 0;
888  return M2M_SUCCESS;
889 }
890 
891 /*
892 * @fn nm_spi_read_reg
893 * @brief Read register
894 * @param [in] u32Addr
895 * Register address
896 * @return Register value
897 * @author M. Abdelmawla
898 * @date 11 July 2012
899 * @version 1.0
900 */
902 {
903  uint32 u32Val=0;
904 
905  nm_spi_read_reg_with_ret(u32Addr, &u32Val);
906 
907  return u32Val;
908 }
909 
910 #endif
uint8 * pu8InBuf
uint8 * pu8OutBuf
Structure holding SPI R/W parameters.
This module contains common APIs declarations.
signed short sint16
Range of values between -32768 to 32767.
Definition: nm_bsp.h:118
signed char sint8
Range of values between -128 to 127.
Definition: nm_bsp.h:111
sint8 nm_spi_read_reg_with_ret(uint32 u32Addr, uint32 *pu32RetVal)
#define M2M_SUCCESS
Definition: nm_common.h:51
#define NULL
Definition: nm_bsp.h:52
This module contains WINC3400 bus wrapper APIs declarations.
unsigned short uint16
Range of values between 0 to 65535.
Definition: nm_bsp.h:96
static void spi_reset(Spi *p_spi)
Reset SPI and set it to Slave mode.
#define M2M_DBG(...)
Definition: nm_debug.h:81
#define M2M_ERR(...)
Definition: nm_debug.h:80
#define NM_BUS_IOCTL_RW
sint8 nm_spi_write_reg(uint32 u32Addr, uint32 u32Val)
sint8 nm_spi_init(void)
Initialize the SPI.
USBInterfaceDescriptor data
sint8 nm_spi_write_block(uint32 u32Addr, uint8 *puBuf, uint16 u16Sz)
#define M2M_INFO(...)
Definition: nm_debug.h:83
uint32 nm_spi_read_reg(uint32 u32Addr)
unsigned long uint32
Range of values between 0 to 4294967295.
Definition: nm_bsp.h:103
unsigned char uint8
Range of values between 0 to 255.
Definition: nm_bsp.h:89
sint8 nm_spi_read_block(uint32 u32Addr, uint8 *puBuf, uint16 u16Sz)
sint8 nm_bus_ioctl(uint8 u8Cmd, void *pvParameter)
static uint8 crc7(uint8 crc, const uint8 *buff, uint16 len)
Definition: nmflash.c:117
This module contains WINC3400 SPI protocol bus APIs implementation.
sint8 nm_spi_deinit(void)
DeInitialize the SPI.
#define M2M_ERR_BUS_FAIL
Definition: nm_common.h:57


inertial_sense_ros
Author(s):
autogenerated on Sun Feb 28 2021 03:17:58