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(hal_spi_transfer_t *transferValue,
70                                               uint8_t *txData,
71                                               uint8_t *rxData,
72                                               size_t dataSize,
73                                               uint32_t flags)
74 {
75     transferValue->txData   = txData;
76     transferValue->rxData   = rxData;
77     transferValue->dataSize = dataSize;
78     transferValue->flags    = flags;
79 }
80 
EEPROM_ReadStatusReq(void)81 EEPROM_STATIC uint8_t EEPROM_ReadStatusReq(void)
82 {
83     uint8_t cmd = EEPROM_RDSR;
84     hal_spi_transfer_t xfer;
85     uint8_t data[1] = {0U};
86 
87     EEPROM_SetSpiTransferValue(&xfer, &cmd, NULL, sizeof(cmd),
88                 (SPI_FIFOWR_RXIGNORE(1)|SPI_FIFOWR_EOF(1)));
89     (void)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
90 
91     EEPROM_SetSpiTransferValue(&xfer, NULL, data, 1,
92                 (SPI_FIFOWR_TXIGNORE(1)|SPI_FIFOWR_EOF(1)|SPI_FIFOWR_EOT(1)));
93     (void)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
94 
95     return *((uint8_t *)((void *)data));
96 }
97 
EEPROM_isBusy(void)98 EEPROM_STATIC uint8_t EEPROM_isBusy(void)
99 {
100     return ((EEPROM_ReadStatusReq() & EEPROM_BUSY_FLAG_MASK) == 0U) ? 0U : 1U;
101 }
102 
EEPROM_WaitForReady(bool isInfinite)103 EEPROM_STATIC eeprom_status_t EEPROM_WaitForReady(bool isInfinite)
104 {
105     volatile uint16_t wait = 0x400; /* near 50 ms @ 50 us/cycle */
106 
107     while ((bool)EEPROM_isBusy())
108     {
109         if (!isInfinite)
110         {
111             if (0U != wait)
112             {
113                 wait--;
114             }
115             else
116             {
117                 break;
118             }
119         }
120     }
121 
122     if (0U != wait)
123     {
124         return kStatus_EeSuccess;
125     }
126     return kStatus_EeError;
127 }
128 
EEPROM_PrepareForWrite()129 EEPROM_STATIC eeprom_status_t EEPROM_PrepareForWrite()
130 {
131     uint8_t cmd = EEPROM_WR_ENABLE;
132     hal_spi_transfer_t xfer;
133     uint8_t status = EEPROM_ReadStatusReq();
134 
135     if ((status & EEPROM_WRITE_ENABLED) == 0U)
136     {
137         EEPROM_SetSpiTransferValue(&xfer, &cmd, NULL, sizeof(cmd),
138                 (SPI_FIFOWR_RXIGNORE(1)|SPI_FIFOWR_EOF(1)|SPI_FIFOWR_EOT(1)));
139         (void)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
140     }
141     return kStatus_EeSuccess;
142 }
143 
EEPROM_Command(uint8_t opCode,uint32_t addre)144 EEPROM_STATIC eeprom_status_t EEPROM_Command(uint8_t opCode, uint32_t addre)
145 {
146     uint8_t cmd[4];
147     hal_spi_transfer_t xfer;
148 
149     cmd[0] = opCode;
150     cmd[1] = (uint8_t)((addre >> 16) & ADDRESS_MASK);
151     cmd[2] = (uint8_t)((addre >> 8) & ADDRESS_MASK);
152     cmd[3] = (uint8_t)((addre >> 0) & ADDRESS_MASK);
153 
154     EEPROM_SetSpiTransferValue(&xfer, (uint8_t *)cmd, NULL, sizeof(cmd), SPI_FIFOWR_RXIGNORE(1));
155     return (eeprom_status_t)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
156 }
157 
158 /*!*********************************************************************************
159 *************************************************************************************
160 * Public Functions
161 *************************************************************************************
162 ********************************************************************************** */
163 
EEPROM_Init(eeprom_config_t * eepromConfig)164 eeprom_status_t EEPROM_Init(eeprom_config_t *eepromConfig)
165 {
166     static uint8_t initialized = 0U;
167 
168     hal_spi_master_config_t spiMasterConfig = {
169         .srcClock_Hz  = eepromConfig->spiSrcClock_Hz,
170         .baudRate_Bps = 9600U,
171         .enableMaster = true,
172         .polarity     = kHAL_SpiClockPolarityActiveHigh,
173         .phase        = kHAL_SpiClockPhaseFirstEdge,
174         .direction    = kHAL_SpiMsbFirst,
175         .instance     = eepromConfig->spiInstance,
176     };
177 
178     uint32_t i;
179 
180     /* Mark Flash as Unerased */
181     for (i = 0; i < sizeof(s_eeState.eepromEraseBitmap) / sizeof(s_eeState.eepromEraseBitmap[0]); i++)
182     {
183         s_eeState.eepromEraseBitmap[i] = 0;
184     }
185 
186     if (0U == initialized)
187     {
188         s_eeState.eeType = eepromConfig->eeType;
189 
190         (void)HAL_SpiMasterInit((hal_spi_master_handle_t)s_eeState.spiHandle, (void *)&spiMasterConfig);
191 
192         initialized = 1;
193     }
194 
195     return kStatus_EeSuccess;
196 }
197 
EEPROM_WritePage(uint32_t noOfBytes,uint32_t addre,uint8_t * Outbuf)198 static eeprom_status_t EEPROM_WritePage(uint32_t noOfBytes, uint32_t addre, uint8_t *Outbuf)
199 {
200     hal_spi_transfer_t xfer;
201 
202     if (0U == noOfBytes)
203     {
204         return kStatus_EeSuccess;
205     }
206 
207     (void)EEPROM_WaitForReady(true);
208 
209     (void)EEPROM_PrepareForWrite();
210 
211     (void)EEPROM_WaitForReady(true);
212 
213     if (kStatus_EeSuccess != EEPROM_Command(EEPROM_WRITE, addre))
214     {
215         return kStatus_EeError;
216     }
217     EEPROM_SetSpiTransferValue(&xfer, Outbuf, NULL, noOfBytes, SPI_FIFOWR_EOT(1));
218     if (kStatus_HAL_SpiSuccess != HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer))
219     {
220         return kStatus_EeError;
221     }
222 
223     return kStatus_EeSuccess;
224 }
225 /*****************************************************************************
226  *  EEPROM_WriteData
227  *
228  *  Writes a data buffer into EEPROM, at a given address
229  *
230  *****************************************************************************/
EEPROM_WriteData(uint32_t noOfBytes,uint32_t addr2eeprom,uint8_t * Outbuf)231 eeprom_status_t EEPROM_WriteData(uint32_t noOfBytes, uint32_t addr2eeprom, uint8_t *Outbuf)
232 {
233     eeprom_status_t retval;
234 
235     while ((addr2eeprom & EEPROM_PAGE_MASK) + noOfBytes > EEPROM_PAGE_MASK)
236     {
237         uint32_t bytes = EEPROM_PAGE_SIZE - (addr2eeprom & EEPROM_PAGE_MASK);
238 
239         retval = EEPROM_WritePage(bytes, addr2eeprom, Outbuf);
240         noOfBytes -= bytes;
241         addr2eeprom += bytes;
242 
243         for (uint32_t j = 0; j < bytes; j++)
244         {
245             Outbuf++; /*Outbuf += bytes;*/
246         }
247 
248         if (kStatus_EeSuccess != retval)
249         {
250             return retval;
251         }
252     }
253     retval = EEPROM_WritePage(noOfBytes, addr2eeprom, Outbuf);
254 
255     return retval;
256 }
257 
258 /*****************************************************************************
259  *  EEPROM_ReadData
260  *
261  *  Reads a data buffer from EEPROM, from a given address
262  *
263  *****************************************************************************/
EEPROM_ReadData(uint16_t noOfBytes,uint32_t addr2eeprom,uint8_t * inbuf)264 eeprom_status_t EEPROM_ReadData(uint16_t noOfBytes, uint32_t addr2eeprom, uint8_t *inbuf)
265 {
266     hal_spi_transfer_t xfer;
267     (void)EEPROM_WaitForReady(true);
268 
269     if (kStatus_EeSuccess != EEPROM_Command(EEPROM_READ, addr2eeprom))
270     {
271         return kStatus_EeError;
272     }
273     EEPROM_SetSpiTransferValue(&xfer, NULL, inbuf, noOfBytes, SPI_FIFOWR_EOT(1));
274     if (kStatus_HAL_SpiSuccess != HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer))
275     {
276         return kStatus_EeError;
277     }
278 
279     return kStatus_EeSuccess;
280 }
281