1 /*
2  * Copyright 2018, 2020 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 /*! *********************************************************************************
10 *************************************************************************************
11 * Include
12 *************************************************************************************
13 ********************************************************************************** */
14 #include "fsl_common.h"
15 #include "fsl_adapter_spi.h"
16 #include "fsl_adapter_eeprom.h"
17 /*! *********************************************************************************
18 *************************************************************************************
19 * Private macros
20 *************************************************************************************
21 ********************************************************************************** */
22 #if (!defined(GCOV_DO_COVERAGE) || (GCOV_DO_COVERAGE == 0))
23 #define EEPROM_STATIC static
24 #define EEPROM_PUBLIC
25 #else
26 #define EEPROM_STATIC __WEAK
27 #define EEPROM_PUBLIC __WEAK
28 #endif
29 
30 #define EEPROM_RDSR      0x05U
31 #define EEPROM_READ      0x03U
32 #define EEPROM_WRITE     0x02U
33 #define EEPROM_WR_ENABLE 0x06U
34 
35 #define EEPROM_BUSY_FLAG_MASK 0x01U
36 #define EEPROM_WRITE_ENABLED  0x02U
37 
38 #define EEPROM_PAGE_SIZE  (256U)
39 #define EEPROM_BLOCK_SIZE (8U * EEPROM_PAGE_SIZE)
40 #define EEPROM_PAGE_MASK  (EEPROM_PAGE_SIZE - 1U)
41 
42 /* adress mask */
43 #define ADDRESS_MASK 0x000000FFUL
44 /******************************************************************************
45 *******************************************************************************
46 * Private Prototypes
47 *******************************************************************************
48 ******************************************************************************/
49 typedef struct _eeprom_state
50 {
51     uint8_t eepromEraseBitmap[32];
52     HAL_SPI_MASTER_HANDLE_DEFINE(spiHandle); /*!< spi handle*/
53     eeprom_type_t eeType;                    /*!< eeprom type*/
54 } eeprom_state_t;
55 
56 EEPROM_STATIC eeprom_state_t s_eeState;
57 /*! *********************************************************************************
58 *************************************************************************************
59 * Private Memory Declarations
60 *************************************************************************************
61 ********************************************************************************** */
62 
63 /*! *********************************************************************************
64 *************************************************************************************
65 * Private Memory function
66 *************************************************************************************
67 ********************************************************************************** */
68 
EEPROM_SetSpiTransferValue(hal_spi_transfer_t * transferValue,uint8_t * txData,uint8_t * rxData,size_t dataSize,uint32_t flags)69 EEPROM_STATIC void EEPROM_SetSpiTransferValue(
70     hal_spi_transfer_t *transferValue, uint8_t *txData, uint8_t *rxData, size_t dataSize, uint32_t flags)
71 {
72     transferValue->txData   = txData;
73     transferValue->rxData   = rxData;
74     transferValue->dataSize = dataSize;
75     transferValue->flags    = flags;
76 }
77 
EEPROM_ReadStatusReq(void)78 EEPROM_STATIC uint8_t EEPROM_ReadStatusReq(void)
79 {
80     uint8_t cmd = EEPROM_RDSR;
81     hal_spi_transfer_t xfer;
82     uint8_t data[1] = {0U};
83 
84     EEPROM_SetSpiTransferValue(&xfer, &cmd, NULL, sizeof(cmd), (SPI_FIFOWR_RXIGNORE(1) | SPI_FIFOWR_EOF(1)));
85     (void)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
86 
87     EEPROM_SetSpiTransferValue(&xfer, NULL, data, 1, (SPI_FIFOWR_TXIGNORE(1) | SPI_FIFOWR_EOF(1) | SPI_FIFOWR_EOT(1)));
88     (void)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
89 
90     return *((uint8_t *)((void *)data));
91 }
92 
EEPROM_isBusy(void)93 EEPROM_STATIC uint8_t EEPROM_isBusy(void)
94 {
95     return ((EEPROM_ReadStatusReq() & EEPROM_BUSY_FLAG_MASK) == 0U) ? 0U : 1U;
96 }
97 
EEPROM_WaitForReady(bool isInfinite)98 EEPROM_STATIC eeprom_status_t EEPROM_WaitForReady(bool isInfinite)
99 {
100     volatile uint16_t wait = 0x400; /* near 50 ms @ 50 us/cycle */
101 
102     while ((bool)EEPROM_isBusy())
103     {
104         if (!isInfinite)
105         {
106             if (0U != wait)
107             {
108                 wait--;
109             }
110             else
111             {
112                 break;
113             }
114         }
115     }
116 
117     if (0U != wait)
118     {
119         return kStatus_EeSuccess;
120     }
121     return kStatus_EeError;
122 }
123 
EEPROM_PrepareForWrite()124 EEPROM_STATIC eeprom_status_t EEPROM_PrepareForWrite()
125 {
126     uint8_t cmd = EEPROM_WR_ENABLE;
127     hal_spi_transfer_t xfer;
128     uint8_t status = EEPROM_ReadStatusReq();
129 
130     if ((status & EEPROM_WRITE_ENABLED) == 0U)
131     {
132         EEPROM_SetSpiTransferValue(&xfer, &cmd, NULL, sizeof(cmd),
133                                    (SPI_FIFOWR_RXIGNORE(1) | SPI_FIFOWR_EOF(1) | SPI_FIFOWR_EOT(1)));
134         (void)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
135     }
136     return kStatus_EeSuccess;
137 }
138 
EEPROM_Command(uint8_t opCode,uint32_t addre)139 EEPROM_STATIC eeprom_status_t EEPROM_Command(uint8_t opCode, uint32_t addre)
140 {
141     uint8_t cmd[4];
142     hal_spi_transfer_t xfer;
143 
144     cmd[0] = opCode;
145     cmd[1] = (uint8_t)((addre >> 16) & ADDRESS_MASK);
146     cmd[2] = (uint8_t)((addre >> 8) & ADDRESS_MASK);
147     cmd[3] = (uint8_t)((addre >> 0) & ADDRESS_MASK);
148 
149     EEPROM_SetSpiTransferValue(&xfer, (uint8_t *)cmd, NULL, sizeof(cmd), SPI_FIFOWR_RXIGNORE(1));
150     return (eeprom_status_t)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
151 }
152 
153 /*!*********************************************************************************
154 *************************************************************************************
155 * Public Functions
156 *************************************************************************************
157 ********************************************************************************** */
158 
EEPROM_Init(eeprom_config_t * eepromConfig)159 eeprom_status_t EEPROM_Init(eeprom_config_t *eepromConfig)
160 {
161     static uint8_t initialized = 0U;
162 
163     hal_spi_master_config_t spiMasterConfig = {
164         .srcClock_Hz  = eepromConfig->spiSrcClock_Hz,
165         .baudRate_Bps = 9600U,
166         .enableMaster = true,
167         .polarity     = kHAL_SpiClockPolarityActiveHigh,
168         .phase        = kHAL_SpiClockPhaseFirstEdge,
169         .direction    = kHAL_SpiMsbFirst,
170         .instance     = eepromConfig->spiInstance,
171     };
172 
173     uint32_t i;
174 
175     /* Mark Flash as Unerased */
176     for (i = 0; i < sizeof(s_eeState.eepromEraseBitmap) / sizeof(s_eeState.eepromEraseBitmap[0]); i++)
177     {
178         s_eeState.eepromEraseBitmap[i] = 0;
179     }
180 
181     if (0U == initialized)
182     {
183         s_eeState.eeType = eepromConfig->eeType;
184 
185         (void)HAL_SpiMasterInit((hal_spi_master_handle_t)s_eeState.spiHandle, (void *)&spiMasterConfig);
186 
187         initialized = 1;
188     }
189 
190     return kStatus_EeSuccess;
191 }
192 
EEPROM_WritePage(uint32_t noOfBytes,uint32_t addre,uint8_t * Outbuf)193 static eeprom_status_t EEPROM_WritePage(uint32_t noOfBytes, uint32_t addre, uint8_t *Outbuf)
194 {
195     hal_spi_transfer_t xfer;
196 
197     if (0U == noOfBytes)
198     {
199         return kStatus_EeSuccess;
200     }
201 
202     (void)EEPROM_WaitForReady(true);
203 
204     (void)EEPROM_PrepareForWrite();
205 
206     (void)EEPROM_WaitForReady(true);
207 
208     if (kStatus_EeSuccess != EEPROM_Command(EEPROM_WRITE, addre))
209     {
210         return kStatus_EeError;
211     }
212     EEPROM_SetSpiTransferValue(&xfer, Outbuf, NULL, noOfBytes, SPI_FIFOWR_EOT(1));
213     if (kStatus_HAL_SpiSuccess != HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer))
214     {
215         return kStatus_EeError;
216     }
217 
218     return kStatus_EeSuccess;
219 }
220 /*****************************************************************************
221  *  EEPROM_WriteData
222  *
223  *  Writes a data buffer into EEPROM, at a given address
224  *
225  *****************************************************************************/
EEPROM_WriteData(uint32_t noOfBytes,uint32_t addr2eeprom,uint8_t * Outbuf)226 eeprom_status_t EEPROM_WriteData(uint32_t noOfBytes, uint32_t addr2eeprom, uint8_t *Outbuf)
227 {
228     eeprom_status_t retval;
229 
230     while ((addr2eeprom & EEPROM_PAGE_MASK) + noOfBytes > EEPROM_PAGE_MASK)
231     {
232         uint32_t bytes = EEPROM_PAGE_SIZE - (addr2eeprom & EEPROM_PAGE_MASK);
233 
234         retval = EEPROM_WritePage(bytes, addr2eeprom, Outbuf);
235         noOfBytes -= bytes;
236         addr2eeprom += bytes;
237 
238         for (uint32_t j = 0; j < bytes; j++)
239         {
240             Outbuf++; /*Outbuf += bytes;*/
241         }
242 
243         if (kStatus_EeSuccess != retval)
244         {
245             return retval;
246         }
247     }
248     retval = EEPROM_WritePage(noOfBytes, addr2eeprom, Outbuf);
249 
250     return retval;
251 }
252 
253 /*****************************************************************************
254  *  EEPROM_ReadData
255  *
256  *  Reads a data buffer from EEPROM, from a given address
257  *
258  *****************************************************************************/
EEPROM_ReadData(uint16_t noOfBytes,uint32_t addr2eeprom,uint8_t * inbuf)259 eeprom_status_t EEPROM_ReadData(uint16_t noOfBytes, uint32_t addr2eeprom, uint8_t *inbuf)
260 {
261     hal_spi_transfer_t xfer;
262     (void)EEPROM_WaitForReady(true);
263 
264     if (kStatus_EeSuccess != EEPROM_Command(EEPROM_READ, addr2eeprom))
265     {
266         return kStatus_EeError;
267     }
268     EEPROM_SetSpiTransferValue(&xfer, NULL, inbuf, noOfBytes, SPI_FIFOWR_EOT(1));
269     if (kStatus_HAL_SpiSuccess != HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer))
270     {
271         return kStatus_EeError;
272     }
273 
274     return kStatus_EeSuccess;
275 }
276