2025-02-15 11:05:28 -05:00

979 lines
25 KiB
C

/*******************************************************************************
This module contains WINC3400 SPI protocol bus APIs implementation.
File Name:
nmspi.c
Summary:
This module contains WINC3400 SPI protocol bus APIs implementation.
Description:
This module contains WINC3400 SPI protocol bus APIs implementation.
*******************************************************************************/
//DOM-IGNORE-BEGIN
/*******************************************************************************
* Copyright (C) 2021 Microchip Technology Inc. and its subsidiaries.
*
* Subject to your compliance with these terms, you may use Microchip software
* and any derivatives exclusively with Microchip products. It is your
* responsibility to comply with third party license terms applicable to your
* use of third party software (including open source software) that may
* accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
* INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
* WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
* BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE
* FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN
* ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*******************************************************************************/
//#include "osal/osal.h"
#include "nm_common.h"
#include "nmspi.h"
#include "spi.h"
#include "BoardCfg.h"
//#include "wdrv_winc_common.h"
//#include "wdrv_winc_spi.h"
#define NMI_PERIPH_REG_BASE 0x1000
#define NMI_INTR_REG_BASE (NMI_PERIPH_REG_BASE+0xa00)
#define NMI_CHIPID (NMI_PERIPH_REG_BASE)
#define NMI_PIN_MUX_0 (NMI_PERIPH_REG_BASE + 0x408)
#define NMI_INTR_ENABLE (NMI_INTR_REG_BASE)
#define NMI_SPI_REG_BASE 0xe800
#define NMI_SPI_CTL (NMI_SPI_REG_BASE)
#define NMI_SPI_MASTER_DMA_ADDR (NMI_SPI_REG_BASE+0x4)
#define NMI_SPI_MASTER_DMA_COUNT (NMI_SPI_REG_BASE+0x8)
#define NMI_SPI_SLAVE_DMA_ADDR (NMI_SPI_REG_BASE+0xc)
#define NMI_SPI_SLAVE_DMA_COUNT (NMI_SPI_REG_BASE+0x10)
#define NMI_SPI_TX_MODE (NMI_SPI_REG_BASE+0x20)
#define NMI_SPI_PROTOCOL_CONFIG (NMI_SPI_REG_BASE+0x24)
#define NMI_SPI_INTR_CTL (NMI_SPI_REG_BASE+0x2c)
#define NMI_SPI_MISC_CTRL (NMI_SPI_REG_BASE+0x48)
#define NMI_SPI_PROTOCOL_OFFSET (NMI_SPI_PROTOCOL_CONFIG-NMI_SPI_REG_BASE)
#define SPI_BASE NMI_SPI_REG_BASE
//#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 0
#define N_FAIL -1
#define N_RESET -2
#define N_RETRY -3
#define SPI_RESP_RETRY_COUNT (10)
#define SPI_RETRY_COUNT (10)
#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 uint8_t gu8Crc_off = 0;
unsigned char mWifiSPIBaudrate;
//static OSAL_MUTEX_HANDLE_TYPE s_spiLock = 0;
static inline int8_t spi_read(uint8_t *b, uint16_t sz)
{
//JFM WINC Low Level
int i;
WIFI_SPI_SS_PIN = 0;
for(i = 0; i < sz; i++)
{
*b++ = SPITransaction(0xAA,mWifiSPIBaudrate);
}
WIFI_SPI_SS_PIN = 1;
return N_OK;
}
static inline int8_t spi_write(uint8_t *b, uint16_t sz)
{
//JFM WINC Low Level
int i;
WIFI_SPI_SS_PIN = 0;
for(i = 0; i < sz; i++)
{
SPITransaction(*b++,mWifiSPIBaudrate);
}
WIFI_SPI_SS_PIN = 1;
return N_OK;
}
/********************************************
Crc7
********************************************/
static const uint8_t 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 uint8_t crc7_byte(uint8_t crc, uint8_t data)
{
return crc7_syndrome_table[(crc << 1) ^ data];
}
static uint8_t crc7(uint8_t crc, const uint8_t *buffer, uint32_t len)
{
while (len--)
crc = crc7_byte(crc, *buffer++);
return crc;
}
/********************************************
Spi protocol Function
********************************************/
static int8_t spi_cmd(uint8_t cmd, uint32_t adr, uint32_t u32data, uint32_t sz, uint8_t clockless)
{
uint8_t bc[9];
uint8_t len = 5;
bc[0] = cmd;
switch (cmd)
{
case CMD_SINGLE_READ: /* single word (4 bytes) read */
bc[1] = (uint8_t)(adr >> 16);
bc[2] = (uint8_t)(adr >> 8);
bc[3] = (uint8_t)adr;
len = 5;
break;
case CMD_INTERNAL_READ: /* internal register read */
bc[1] = (uint8_t)(adr >> 8);
if(clockless)
bc[1] |= (1 << 7);
bc[2] = (uint8_t)adr;
bc[3] = 0x00;
len = 5;
break;
#ifdef CMD_TERMINATE
case CMD_TERMINATE: /* termination */
bc[1] = 0x00;
bc[2] = 0x00;
bc[3] = 0x00;
len = 5;
break;
#endif
#ifdef CMD_REPEAT
case CMD_REPEAT: /* repeat */
bc[1] = 0x00;
bc[2] = 0x00;
bc[3] = 0x00;
len = 5;
break;
#endif
case CMD_RESET: /* reset */
bc[1] = 0xff;
bc[2] = 0xff;
bc[3] = 0xff;
len = 5;
break;
#if defined(CMD_DMA_WRITE) || defined(CMD_DMA_READ)
case CMD_DMA_WRITE: /* dma write */
case CMD_DMA_READ: /* dma read */
bc[1] = (uint8_t)(adr >> 16);
bc[2] = (uint8_t)(adr >> 8);
bc[3] = (uint8_t)adr;
bc[4] = (uint8_t)(sz >> 8);
bc[5] = (uint8_t)(sz);
len = 7;
break;
#endif
case CMD_DMA_EXT_WRITE: /* dma extended write */
case CMD_DMA_EXT_READ: /* dma extended read */
bc[1] = (uint8_t)(adr >> 16);
bc[2] = (uint8_t)(adr >> 8);
bc[3] = (uint8_t)adr;
bc[4] = (uint8_t)(sz >> 16);
bc[5] = (uint8_t)(sz >> 8);
bc[6] = (uint8_t)(sz);
len = 8;
break;
case CMD_INTERNAL_WRITE: /* internal register write */
bc[1] = (uint8_t)(adr >> 8);
if(clockless) bc[1] |= (1 << 7);
bc[2] = (uint8_t)(adr);
bc[3] = (uint8_t)(u32data >> 24);
bc[4] = (uint8_t)(u32data >> 16);
bc[5] = (uint8_t)(u32data >> 8);
bc[6] = (uint8_t)(u32data);
len = 8;
break;
case CMD_SINGLE_WRITE: /* single word write */
bc[1] = (uint8_t)(adr >> 16);
bc[2] = (uint8_t)(adr >> 8);
bc[3] = (uint8_t)(adr);
bc[4] = (uint8_t)(u32data >> 24);
bc[5] = (uint8_t)(u32data >> 16);
bc[6] = (uint8_t)(u32data >> 8);
bc[7] = (uint8_t)(u32data);
len = 9;
break;
default:
return N_FAIL;
}
if (!gu8Crc_off)
{
bc[len-1] = (crc7(0x7f, (const uint8_t *)&bc[0], len-1)) << 1;
}
else
{
len -= 1;
}
if (N_OK != spi_write(bc, len))
{
M2M_ERR("[spi_cmd]: Failed cmd write, bus error...\r\n");
return N_FAIL;
}
return N_OK;
}
static int8_t spi_cmd_rsp(uint8_t cmd)
{
uint8_t rsp;
int8_t s8RetryCnt;
/**
Command/Control response
**/
if ((cmd == CMD_RESET)
#ifdef CMD_TERMINATE
|| (cmd == CMD_TERMINATE)
#endif
#ifdef CMD_REPEAT
|| (cmd == CMD_REPEAT)
#endif
)
{
if (N_OK != spi_read(&rsp, 1))
return N_FAIL;
}
/* wait for response */
s8RetryCnt = SPI_RESP_RETRY_COUNT;
do
{
if (N_OK != spi_read(&rsp, 1))
{
M2M_ERR("[spi_cmd_rsp]: Failed cmd response read, bus error...\r\n");
return N_FAIL;
}
}
while((rsp != cmd) && (s8RetryCnt-- > 0));
if (s8RetryCnt < 0)
{
M2M_ERR("[spi_cmd_rsp]: Failed cmd response read\n");
return N_FAIL;
}
/**
State response
**/
/* wait for response */
s8RetryCnt = SPI_RESP_RETRY_COUNT;
do
{
if (N_OK != spi_read(&rsp, 1))
{
M2M_ERR("[spi_cmd_rsp]: Failed cmd response read, bus error...\r\n");
return N_FAIL;
}
}
while((rsp != 0x00) && (s8RetryCnt-- > 0));
if (s8RetryCnt < 0)
{
M2M_ERR("[spi_cmd_rsp]: Failed cmd response read\n");
return N_FAIL;
}
return N_OK;
}
static void spi_reset(void)
{
nm_sleep(1);
spi_cmd(CMD_RESET, 0, 0, 0, 0);
spi_cmd_rsp(CMD_RESET);
nm_sleep(1);
}
/********************************************
Spi Internal Read/Write Function
********************************************/
static int8_t spi_data_read(uint8_t *b, uint16_t sz,uint8_t clockless)
{
int16_t retry, ix, nbytes;
int8_t result = N_OK;
uint8_t crc[2];
uint8_t rsp;
/**
Data
**/
ix = 0;
do {
if (sz <= DATA_PKT_SZ)
nbytes = sz;
else
nbytes = DATA_PKT_SZ;
/**
Data Response header
**/
retry = SPI_RESP_RETRY_COUNT;
do
{
if (N_OK != spi_read(&rsp, 1))
{
M2M_ERR("[spi_data_read]: Failed data response read, bus error...\r\n");
result = N_FAIL;
break;
}
if ((rsp & 0xf0) == 0xf0)
break;
}
while (retry--);
if (result == N_FAIL)
break;
if (retry <= 0)
{
M2M_ERR("[spi_data_read]: Failed data response read...(%02x)\r\n", rsp);
result = N_FAIL;
break;
}
/**
Read bytes
**/
if (N_OK != spi_read(&b[ix], nbytes))
{
M2M_ERR("[spi_data_read]: Failed data block read, bus error...\r\n");
result = N_FAIL;
break;
}
if(!clockless)
{
/**
Read Crc
**/
if (!gu8Crc_off)
{
if (N_OK != spi_read(crc, 2))
{
M2M_ERR("[spi_data_read]: Failed data block CRC read, bus error...\r\n");
result = N_FAIL;
break;
}
}
}
ix += nbytes;
sz -= nbytes;
} while (sz);
return result;
}
static int8_t spi_data_write(uint8_t *b, uint16_t sz)
{
int16_t ix = 0;
uint16_t nbytes;
int8_t result = N_OK;
uint8_t cmd, order, crc[2] = {0};
//uint8_t rsp;
/**
Data
**/
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 (N_OK != spi_write(&cmd, 1))
{
M2M_ERR("[spi_data_write]: Failed data block cmd write, bus error...\r\n");
result = N_FAIL;
break;
}
/**
Write data
**/
if (N_OK != spi_write(&b[ix], nbytes))
{
M2M_ERR("[spi_data_write]: Failed data block write, bus error...\r\n");
result = N_FAIL;
break;
}
/**
Write Crc
**/
if (!gu8Crc_off)
{
if (N_OK != spi_write(crc, 2))
{
M2M_ERR("[spi_data_write]: Failed data block CRC write, bus error...\r\n");
result = N_FAIL;
break;
}
}
ix += nbytes;
sz -= nbytes;
}
while (sz);
return result;
}
/********************************************
Spi interfaces
********************************************/
static int8_t spi_write_reg(uint32_t u32Addr, uint32_t u32Val)
{
uint8_t cmd = CMD_SINGLE_WRITE;
uint8_t clockless = 0;
if (u32Addr <= 0x30)
{
/**
NMC1000 clockless registers.
**/
cmd = CMD_INTERNAL_WRITE;
clockless = 1;
}
if (spi_cmd(cmd, u32Addr, u32Val, 4, clockless) != N_OK)
{
M2M_ERR("[spi_write_reg]: Failed cmd, write reg (%08" PRIx32 ")...\r\n", u32Addr);
return N_FAIL;
}
if (spi_cmd_rsp(cmd) != N_OK)
{
M2M_ERR("[spi_write_reg]: Failed cmd response, write reg (%08" PRIx32 ")...\r\n", u32Addr);
return N_FAIL;
}
return N_OK;
}
static int8_t spi_write_block(uint32_t u32Addr, uint8_t *puBuf, uint16_t u16Sz)
{
uint8_t len;
uint8_t rsp[3];
/**
Command
**/
if (spi_cmd(CMD_DMA_EXT_WRITE, u32Addr, 0, u16Sz, 0) != N_OK)
{
M2M_ERR("[spi_write_block]: Failed cmd, write block (%08" PRIx32 ")...\r\n", u32Addr);
return N_FAIL;
}
if (spi_cmd_rsp(CMD_DMA_EXT_WRITE) != N_OK)
{
M2M_ERR("[spi_write_block]: Failed cmd response, write block (%08" PRIx32 ")...\r\n", u32Addr);
return N_FAIL;
}
/**
Data
**/
if (spi_data_write(puBuf, u16Sz) != N_OK)
{
M2M_ERR("[spi_write_block]: Failed block data write...\r\n");
return N_FAIL;
}
/**
Data RESP
**/
if (!gu8Crc_off)
len = 2;
else
len = 3;
if (N_OK != spi_read(&rsp[0], len))
{
M2M_ERR("[spi_write_block]: Failed bus error...\r\n");
return N_FAIL;
}
if((rsp[len-1] != 0) || (rsp[len-2] != 0xC3))
{
M2M_ERR("[spi_write_block]: Failed data response read, %x %x %x\r\n", rsp[0], rsp[1], rsp[2]);
return N_FAIL;
}
return N_OK;
}
static int8_t spi_read_reg(uint32_t u32Addr, uint32_t* pu32RetVal)
{
uint8_t cmd = CMD_SINGLE_READ;
uint8_t tmp[4];
uint8_t clockless = 0;
if (u32Addr <= 0xff)
{
/**
NMC1000 clockless registers.
**/
cmd = CMD_INTERNAL_READ;
clockless = 1;
}
if (spi_cmd(cmd, u32Addr, 0, 4, clockless) != N_OK)
{
M2M_ERR("[spi_read_reg]: Failed cmd, read reg (%08" PRIx32 ")...\r\n", u32Addr);
return N_FAIL;
}
if (spi_cmd_rsp(cmd) != N_OK)
{
M2M_ERR("[spi_read_reg]: Failed cmd response, read reg (%08" PRIx32 ")...\r\n", u32Addr);
return N_FAIL;
}
/* to avoid endianess issues */
if (spi_data_read(&tmp[0], 4, clockless) != N_OK)
{
M2M_ERR("[spi_read_reg]: Failed data read...\r\n");
return N_FAIL;
}
*pu32RetVal = ((uint32_t)tmp[0]) |
((uint32_t)tmp[1] << 8) |
((uint32_t)tmp[2] << 16) |
((uint32_t)tmp[3] << 24);
return N_OK;
}
static int8_t spi_read_block(uint32_t u32Addr, uint8_t *puBuf, uint16_t u16Sz)
{
/**
Command
**/
if (spi_cmd(CMD_DMA_EXT_READ, u32Addr, 0, u16Sz, 0) != N_OK)
{
M2M_ERR("[spi_read_block]: Failed cmd, read block (%08" PRIx32 ")...\r\n", u32Addr);
return N_FAIL;
}
if (spi_cmd_rsp(CMD_DMA_EXT_READ) != N_OK)
{
M2M_ERR("[spi_read_block]: Failed cmd response, read block (%08" PRIx32 ")...\r\n", u32Addr);
return N_FAIL;
}
/**
Data
**/
if (spi_data_read(puBuf, u16Sz, 0) != N_OK)
{
M2M_ERR("[spi_read_block]: Failed block data read...\r\n");
return N_FAIL;
}
return N_OK;
}
static void spi_init_pkt_sz(void)
{
uint32_t val32;
/* Make sure SPI max. packet size fits the defined DATA_PKT_SZ. */
val32 = nm_spi_read_reg(SPI_BASE+0x24);
val32 &= ~(0x7 << 4);
switch(DATA_PKT_SZ)
{
case 256: val32 |= (0 << 4); break;
case 512: val32 |= (1 << 4); break;
case 1024: val32 |= (2 << 4); break;
case 2048: val32 |= (3 << 4); break;
case 4096: val32 |= (4 << 4); break;
case 8192: val32 |= (5 << 4); break;
}
nm_spi_write_reg(SPI_BASE+0x24, val32);
}
/********************************************
Bus interfaces
********************************************/
int8_t nm_spi_reset(void)
{
// if (OSAL_RESULT_TRUE != OSAL_MUTEX_Lock(&s_spiLock, OSAL_WAIT_FOREVER))
// return M2M_ERR_BUS_FAIL;
spi_cmd(CMD_RESET, 0, 0, 0, 0);
spi_cmd_rsp(CMD_RESET);
// OSAL_MUTEX_Unlock(&s_spiLock);
return M2M_SUCCESS;
}
void nm_spi_lock_init(void)
{
// OSAL_MUTEX_Create(&s_spiLock);
}
/*
* @fn nm_spi_init
* @brief Initialize the SPI
* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
*/
int8_t nm_spi_init(void)
{
uint32_t chipid;
uint32_t reg = 0;
mWifiSPIBaudrate = SPICalculateBRG(PERIPHERAL_FREQ, WIFI_MODULE_SPI_BAUDRATE);
/**
configure protocol
**/
gu8Crc_off = 0;
if (nm_spi_read_reg_with_ret(NMI_SPI_PROTOCOL_CONFIG, &reg) != M2M_SUCCESS)
{
/* Read failed. Try with CRC off. This might happen when module
is removed but chip isn't reset*/
gu8Crc_off = 1;
M2M_ERR("[nm_spi_init]: Failed internal read protocol with CRC on, retrying with CRC off...\r\n");
if (nm_spi_read_reg_with_ret(NMI_SPI_PROTOCOL_CONFIG, &reg) != M2M_SUCCESS)
{
// Reaad failed with both CRC on and off, something went bad
M2M_ERR("[nm_spi_init]: Failed internal read protocol...\r\n");
return M2M_ERR_BUS_FAIL;
}
}
if(gu8Crc_off == 0)
{
reg &= ~0xc; /* disable CRC checking */
reg &= ~0x70;
reg |= (0x5 << 4);
if (nm_spi_write_reg(NMI_SPI_PROTOCOL_CONFIG, reg) != M2M_SUCCESS)
{
M2M_ERR("[nm_spi_init]: Failed internal write protocol reg...\r\n");
return M2M_ERR_BUS_FAIL;
}
gu8Crc_off = 1;
}
/**
make sure can read back chip id correctly
**/
if (nm_spi_read_reg_with_ret(0x1000, &chipid) != M2M_SUCCESS)
{
M2M_ERR("[nm_spi_init]: Fail cmd read chip id...\r\n");
return M2M_ERR_BUS_FAIL;
}
M2M_DBG("[nm_spi_init]: chipid (%08x)\r\n", (unsigned int)chipid);
spi_init_pkt_sz();
return M2M_SUCCESS;
}
/*
* @fn nm_spi_deinit
* @brief DeInitialize the SPI
* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
*/
int8_t nm_spi_deinit(void)
{
gu8Crc_off = 0;
// OSAL_MUTEX_Delete(&s_spiLock);
return M2M_SUCCESS;
}
/*
* @fn nm_spi_read_reg
* @brief Read register
* @param [in] u32Addr
* Register address
* @return Register value
*/
uint32_t nm_spi_read_reg(uint32_t u32Addr)
{
uint32_t u32Val;
nm_spi_read_reg_with_ret(u32Addr, &u32Val);
return u32Val;
}
/*
* @fn nm_spi_read_reg_with_ret
* @brief Read register with error code return
* @param [in] u32Addr
* Register address
* @param [out] pu32RetVal
* Pointer to u32 variable used to return the read value
* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
*/
int8_t nm_spi_read_reg_with_ret(uint32_t u32Addr, uint32_t* pu32RetVal)
{
uint8_t retry = SPI_RETRY_COUNT;
// if (OSAL_RESULT_TRUE != OSAL_MUTEX_Lock(&s_spiLock, OSAL_WAIT_FOREVER))
// return M2M_ERR_BUS_FAIL;
while(retry--)
{
if (spi_read_reg(u32Addr, pu32RetVal) == N_OK)
{
// OSAL_MUTEX_Unlock(&s_spiLock);
return M2M_SUCCESS;
}
M2M_ERR("Reset and retry %d %" PRIx32 "\r\n", retry, u32Addr);
spi_reset();
}
// OSAL_MUTEX_Unlock(&s_spiLock);
return M2M_ERR_BUS_FAIL;
}
/*
* @fn nm_spi_write_reg
* @brief write register
* @param [in] u32Addr
* Register address
* @param [in] u32Val
* Value to be written to the register
* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
*/
int8_t nm_spi_write_reg(uint32_t u32Addr, uint32_t u32Val)
{
uint8_t retry = SPI_RETRY_COUNT;
// if (OSAL_RESULT_TRUE != OSAL_MUTEX_Lock(&s_spiLock, OSAL_WAIT_FOREVER))
// return M2M_ERR_BUS_FAIL;
while(retry--)
{
if (spi_write_reg(u32Addr, u32Val) == N_OK)
{
// OSAL_MUTEX_Unlock(&s_spiLock);
return M2M_SUCCESS;
}
M2M_ERR("Reset and retry %d %" PRIx32 " %" PRIx32 "\r\n", retry, u32Addr, u32Val);
spi_reset();
}
// OSAL_MUTEX_Unlock(&s_spiLock);
return M2M_ERR_BUS_FAIL;
}
/*
* @fn nm_spi_read_block
* @brief Read block of data
* @param [in] u32Addr
* Start address
* @param [out] puBuf
* Pointer to a buffer used to return the read data
* @param [in] u16Sz
* Number of bytes to read. The buffer size must be >= u16Sz
* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
*/
int8_t nm_spi_read_block(uint32_t u32Addr, uint8_t *puBuf, uint16_t u16Sz)
{
uint8_t retry = SPI_RETRY_COUNT;
uint8_t tmpBuf[2] = {0,0};
uint8_t *puTmpBuf;
// if (OSAL_RESULT_TRUE != OSAL_MUTEX_Lock(&s_spiLock, OSAL_WAIT_FOREVER))
// return M2M_ERR_BUS_FAIL;
if (u16Sz == 1)
{
u16Sz = 2;
puTmpBuf = tmpBuf;
}
else
{
puTmpBuf = puBuf;
}
while(retry--)
{
if (spi_read_block(u32Addr, puTmpBuf, u16Sz) == N_OK)
{
// OSAL_MUTEX_Unlock(&s_spiLock);
if (puTmpBuf == tmpBuf)
*puBuf = *tmpBuf;
return M2M_SUCCESS;
}
M2M_ERR("Reset and retry %d %" PRIx32 " %d\r\n", retry, u32Addr, u16Sz);
spi_reset();
}
// OSAL_MUTEX_Unlock(&s_spiLock);
return M2M_ERR_BUS_FAIL;
}
/*
* @fn nm_spi_write_block
* @brief Write block of data
* @param [in] u32Addr
* Start address
* @param [in] puBuf
* Pointer to the buffer holding the data to be written
* @param [in] u16Sz
* Number of bytes to write. The buffer size must be >= u16Sz
* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure
*/
int8_t nm_spi_write_block(uint32_t u32Addr, uint8_t *puBuf, uint16_t u16Sz)
{
uint8_t retry = SPI_RETRY_COUNT;
// if (OSAL_RESULT_TRUE != OSAL_MUTEX_Lock(&s_spiLock, OSAL_WAIT_FOREVER))
// return M2M_ERR_BUS_FAIL;
//Workaround hardware problem with single byte transfers over SPI bus
if (u16Sz == 1)
u16Sz = 2;
while(retry--)
{
if (spi_write_block(u32Addr, puBuf, u16Sz) == N_OK)
{
// OSAL_MUTEX_Unlock(&s_spiLock);
return M2M_SUCCESS;
}
M2M_ERR("Reset and retry %d %" PRIx32 " %d\r\n", retry, u32Addr, u16Sz);
spi_reset();
}
// OSAL_MUTEX_Unlock(&s_spiLock);
return M2M_ERR_BUS_FAIL;
}
//DOM-IGNORE-END