[processor-sdk/performance-audio-sr.git] / psdk_cust / pdk_k2g_1_0_1_2_eng / packages / ti / board / src / flash / platform_flash / evmc66x_qspi_norflash.c
1 /*
2 * Copyright (c) 2015, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
34 /**
35 *
36 * \file evmc66x_qspi_norflash.c
37 *
38 * \brief This file contains qspi norflash functions.
39 *
40 ******************************************************************************/
41 #include "platform_internal.h"
43 #if (PLATFORM_QSPI_FLASH_IN)
45 /**
46 * \brief To check whether the FLASH device is busy or in standby mode by
47 * reading WIP(Write in Progress) bit of Status register.
48 *
49 * \param timeOut [IN] : Time out given to wait for the device to come
50 * to standby mode to accept commands.
51 *
52 * \return QSPI_SUCCESS : if success.
53 * QSPI_ERR : if error.
54 *
55 **/
56 static QSPI_STATUS qspiFlashWaitReady(uint32_t timeOut)
57 {
58 QSPI_STATUS ret;
59 uint8_t status;
60 uint8_t cmd = QSPI_FLASH_CMD_RDSR;
62 do
63 {
64 ret = qspiCommandRead(&cmd, 1, &status, 1);
65 if (ret) {
66 IFPRINT (platform_write("Sending RDSR command failed\n"));
67 return ret;
68 }
69 if ((status & QSPI_FLASH_SR_WIP) == 0) {
70 break;
71 }
73 timeOut--;
74 if (!timeOut) {
75 break;
76 }
78 } while (TRUE);
80 if ((status & QSPI_FLASH_SR_WIP) == 0) {
81 return QSPI_SUCCESS;
82 }
84 IFPRINT (platform_write("qspiFlashWaitReady() : Timed out error\n"));
86 /* Timed out */
87 return QSPI_ERR;
88 }
90 /**
91 * \brief Enables/Disables the QUAD mode of the FLASH device.
92 *
93 * \param pDevice [IN] : Platform device handle.
94 * \param enable [IN] : Enables or disables the QUAD mode.
95 * 1 - Enable QUAD mode
96 * 0 - Disable QUAD mode.
97 *
98 * \return QSPI_SUCCESS : if success.
99 * QSPI_ERR : if error.
100 *
101 **/
102 QSPI_STATUS qspiFlashQuadModeCtrl(PLATFORM_DEVICE_info *pDevice,
103 uint8_t enable)
104 {
105 uint8_t cmdRdsr = QSPI_FLASH_CMD_RDSR;
106 uint8_t cmdWrr = QSPI_FLASH_CMD_WRR;
107 uint8_t cmdWren = QSPI_FLASH_CMD_WREN;
108 uint8_t cmdRdcr = QSPI_FLASH_CMD_RDCR;
109 uint8_t status;
110 uint8_t data[2];
112 /* Write enable command */
113 if (qspiCommandWrite(&cmdWren, 1, NULL, 0)) {
114 IFPRINT (platform_write("qspiFlashQuadModeCtrl: Sending WREN command failed\n"));
115 goto err;
116 }
118 /* Read status register */
119 if (qspiCommandRead(&cmdRdsr, 1, &status, 1)) {
120 IFPRINT (platform_write("qspiFlashQuadModeCtrl: Sending RDSR command failed\n"));
121 goto err;
122 }
124 data[0] = status;
126 /* The first byte will be written to the status register, while the
127 second byte will be written to the configuration register */
129 if (enable) {
130 /* Write enabled, quad enabled, no protected blocks */
131 data[1] = 0x02;
132 } else {
133 /* Write enabled, quad disabled, no protected block */
134 data[1] = 0x0;
135 }
137 if (qspiCommandWrite(&cmdWrr, 1, data, 2)) {
138 IFPRINT (platform_write("qspiFlashQuadModeCtrl: Sending WRR command failed\n"));
139 goto err;
140 }
142 if (qspiFlashWaitReady(QSPI_FLASH_WRR_WRITE_TIMEOUT)) {
143 IFPRINT (platform_write("qspiFlashQuadModeCtrl: WRR timeout error\n"));
144 goto err;
145 }
147 if (qspiCommandRead(&cmdRdcr, 1, &status, 1)) {
148 IFPRINT (platform_write("qspiFlashQuadModeCtrl: Sending RDCR command failed\n"));
149 goto err;
150 }
152 if (status != data[1]) {
153 IFPRINT (platform_write("qspiFlashQuadModeCtrl: Quad Mode Configuration Failed\n"));
154 goto err;
155 }
157 return QSPI_SUCCESS;
159 err :
160 return QSPI_ERR;
161 }
163 /**
164 * \brief Reads the device ID and manufacture ID of the FLASH device.
165 *
166 * \param pDevice [IN] : Platform device handle.
167 *
168 * \return QSPI_SUCCESS : if success.
169 * QSPI_ERR : if error.
170 *
171 **/
172 QSPI_STATUS qspiFlashReadId(PLATFORM_DEVICE_info *pDevice)
173 {
174 QSPI_STATUS ret;
175 uint8_t idcode[3];
176 uint8_t cmd = QSPI_FLASH_CMD_RDID;
177 uint32_t deviceId;
179 ret = qspiCommandRead(&cmd, 1, idcode, sizeof(idcode));
180 if (ret) {
181 IFPRINT (platform_write("qspiFlashReadId: Error in reading the idcode\n"));
182 return ret;
183 }
185 IFPRINT (platform_write("qspiFlashReadId: Flash idcode %02x %02x %02x\n",
186 idcode[0], idcode[1], idcode[2]));
188 deviceId = (idcode[1] << 8) | (idcode[2]);
190 IFPRINT (platform_write("qspiFlashReadId: Flash Device Id = 0x%x\n", deviceId));
192 if (pDevice) {
193 /* Get the actuals */
194 pDevice->manufacturer_id = idcode[0];
195 pDevice->device_id = deviceId;
197 /* No blocks are bad for QSPI flash */
198 pDevice->bblist = NULL;
199 }
201 return QSPI_SUCCESS;
202 }
204 #if (PLATFORM_QSPI_FLASH_READ_IN)
206 /**
207 * \brief Reads the data from the FLASH device.
208 *
209 * \param pDevice [IN] : Platform device handle.
210 * \param addr [IN] : Address of the FLASH device in bytes.
211 * \param len [IN] : Length of the data to be read in bytes.
212 * \param buf [IN] : Pointer to the buffer of read data.
213 * \param mode [IN] : Mode of the FLASH device to be operated.
214 * QSPI_FLASH_SINGLE_READ - Single mode.
215 * QSPI_FLASH_DUAL_READ - Dual mode.
216 * QSPI_FLASH_QUAD_READ - Quad mode.
217 *
218 *
219 * \return QSPI_SUCCESS : if success.
220 * QSPI_ERR : if error.
221 *
222 **/
223 QSPI_STATUS qspiFlashRead(PLATFORM_DEVICE_info *pDevice, uint32_t addr,
224 uint32_t len, uint8_t *buf, uint8_t mode)
225 {
226 uint8_t cmd[3];
227 uint8_t command;
228 uint8_t dummyCycles;
229 QSPI_STATUS ret;
231 /* Validate address input */
232 if ((addr + len) > QSPI_FLASH_SIZE) {
233 IFPRINT (platform_write("qspiFlashRead() : Invalid Flash Address\n"));
235 return QSPI_ERR;
236 }
238 switch(mode)
239 {
240 case QSPI_FLASH_SINGLE_READ :
241 command = QSPI_FLASH_CMD_READ;
242 dummyCycles = QSPI_FLASH_SINGLE_READ_DUMMY_CYCLE;
243 break;
244 case QSPI_FLASH_DUAL_READ :
245 command = QSPI_FLASH_CMD_DUAL_READ;
246 dummyCycles = QSPI_FLASH_DUAL_READ_DUMMY_CYCLE;
247 break;
248 case QSPI_FLASH_QUAD_READ :
249 command = QSPI_FLASH_CMD_QUAD_READ;
250 dummyCycles = QSPI_FLASH_QUAD_READ_DUMMY_CYCLE;
251 break;
252 default :
253 IFPRINT (platform_write("qspiFlashRead() : Invalid Flash Read Mode!"));
254 IFPRINT (platform_write("Setting to Single Mode Read \n"));
255 command = QSPI_FLASH_CMD_READ;
256 dummyCycles = QSPI_FLASH_SINGLE_READ_DUMMY_CYCLE;
257 mode = QSPI_FLASH_SINGLE_READ;
258 break;
259 }
261 /* Initialize the command to be sent serially */
262 cmd[0] = command;
263 cmd[1] = mode;
264 cmd[2] = dummyCycles;
266 IFPRINT (platform_write("%s: Reading from 0x%x of len 0x%x\n",__FUNCTION__,addr,len));
267 ret = qspiRead(addr, cmd, buf, len);
269 return ret;
270 }
271 #endif /* #if (PLATFORM_QSPI_FLASH_READ_IN) */
273 #if (PLATFORM_QSPI_FLASH_WRITE_IN)
274 /**
275 * \brief Writes the data into the FLASH device.
276 *
277 * \param pDevice [IN] : Platform device handle.
278 * \param addr [IN] : Address of the FLASH device in bytes.
279 * \param len [IN] : Length of the data to be written in bytes.
280 * \param buf [IN] : Pointer to the buffer of data to be
281 * written.
282 * \param mode [IN] : Mode of the FLASH device to be
283 * operated.
284 * QSPI_FLASH_SINGLE_PAGE_PROG - Single mode.
285 * QSPI_FLASH_QUAD_PAGE_PROG - Quad mode.
286 *
287 *
288 * \return QSPI_SUCCESS : if success.
289 * QSPI_ERR : if error.
290 *
291 **/
292 QSPI_STATUS qspiFlashWrite(PLATFORM_DEVICE_info *pDevice, uint32_t addr,
293 uint32_t len, uint8_t *buf, uint8_t mode)
294 {
295 uint32_t byteAddr;
296 uint32_t pageSize;
297 uint32_t loopCount;
298 uint32_t chunkLen;
299 uint32_t actual;
300 uint8_t cmd[2];
301 uint8_t cmdWren = QSPI_FLASH_CMD_WREN;
302 QSPI_STATUS ret;
304 /* Validate address input */
305 if ((addr + len) > QSPI_FLASH_SIZE) {
306 IFPRINT (platform_write("qspiFlashWrite() : Invalid Flash Address\n"));
307 return QSPI_ERR;
308 }
310 switch(mode)
311 {
312 case QSPI_FLASH_SINGLE_PAGE_PROG :
313 cmd[0] = QSPI_FLASH_CMD_PAGE_PROG;
314 break;
315 case QSPI_FLASH_QUAD_PAGE_PROG:
316 cmd[0] = QSPI_FLASH_CMD_QUAD_PAGE_PROG;
317 break;
318 default :
319 IFPRINT (platform_write("qspiFlashWrite() : Invalid Flash Write Mode!"));
320 IFPRINT (platform_write("Setting to Single Mode Write \n"));
321 cmd[0] = QSPI_FLASH_CMD_PAGE_PROG;
322 mode = QSPI_FLASH_SINGLE_PAGE_PROG;
323 break;
324 }
326 /* Initialize the command to be sent serially */
327 cmd[1] = mode;
329 /* The QSPI Flash Controller will automatically issue
330 the WREN command before triggering a write command via the direct or
331 indirect access controllers (DAC/INDAC) – i.e the user does not need
332 to perform this operation.
333 */
334 pageSize = QSPI_FLASH_PAGE_SIZE;
335 byteAddr = addr & (QSPI_FLASH_PAGE_SIZE - 1); /* % page_size; */
337 ret = 0;
338 for (actual = 0; actual < len; actual += chunkLen)
339 {
340 /* Send Write Enable command */
341 if (qspiCommandWrite(&cmdWren, 1, NULL, 0)) {
342 return QSPI_ERR;
343 }
345 /* Send Page Program command */
346 chunkLen = ((len - actual) < (pageSize - byteAddr) ?
347 (len - actual) : (pageSize - byteAddr));
349 IFPRINT (platform_write("%s: Writing to 0x%x of len 0x%x\n",__FUNCTION__,addr,chunkLen));
350 ret = qspiWrite(addr, cmd, buf + actual, chunkLen);
351 if (ret) {
352 return ret;
353 }
355 ret = qspiFlashWaitReady(QSPI_FLASH_PAGE_PROG_TIMEOUT);
356 if (ret) {
357 return ret;
358 }
360 addr += chunkLen;
361 byteAddr = 0;
363 loopCount = 4000;
364 while (loopCount--) {
365 asm(" NOP");
366 }
367 }
369 return ret;
370 }
372 /**
373 * \brief Erase the FLASH device.
374 *
375 * This function can perform sector erase or complete device erase of the
376 * flash.
377 * Pass sector number as parameter for sector erase.
378 * Pass 'QSPI_FLASH_BE_SECTOR_NUM' as parameter for bulk or device erase.
379 *
380 * \param pDevice [IN] : Platform device handle.
381 * \param sector [IN] : Sector number to be erased.
382 * 0 to 255 - SECTOR ERASE.
383 * QSPI_FLASH_BE_SECTOR_NUM - BULK ERASE.
384 *
385 * \return QSPI_SUCCESS : if success.
386 * QSPI_ERR : if error.
387 *
388 **/
389 QSPI_STATUS qspiFlashErase(PLATFORM_DEVICE_info *pDevice, int32_t sector)
390 {
391 uint8_t cmd[5];
392 uint32_t cmdLen;
393 uint32_t address = 0;
394 uint8_t cmdWren = QSPI_FLASH_CMD_WREN;
395 QSPI_STATUS ret;
397 if (sector == QSPI_FLASH_BE_SECTOR_NUM) {
398 cmd[0] = QSPI_FLASH_CMD_BULK_ERASE;
399 cmdLen = 1;
400 } else if (sector >= QSPI_FLASH_NUM_SECTORS) {
401 IFPRINT (platform_write("qspiFlashErase: Not a valid sector number\n"));
402 return QSPI_ERR;
403 } else {
404 address = sector * QSPI_FLASH_SECTOR_SIZE;
405 cmd[0] = QSPI_FLASH_CMD_SECTOR_ERASE;
406 cmd[1] = (address >> 24) & 0xff; /* 64MB flash device */
407 cmd[2] = (address >> 16) & 0xff;
408 cmd[3] = (address >> 8) & 0xff;
409 cmd[4] = (address >> 0) & 0xff;
411 cmdLen = 5;
412 }
414 IFPRINT (platform_write("%s: Erasing sector 0x%x of len 0x%x\n",__FUNCTION__,address,QSPI_FLASH_SECTOR_SIZE));
416 ret = qspiCommandWrite(&cmdWren, 1, NULL, 0);
417 if (ret) {
418 goto err;
419 }
421 if (qspiFlashWaitReady(QSPI_FLASH_WRR_WRITE_TIMEOUT)) {
422 IFPRINT (platform_write("qspiFlashQuadModeCtrl: WRR timeout error\n"));
423 goto err;
424 }
426 ret = qspiCommandWrite(cmd, cmdLen, NULL, 0);
427 if (ret) {
428 goto err;
429 }
431 ret = qspiFlashWaitReady(QSPI_FLASH_BULK_ERASE_TIMEOUT);
433 err :
434 return ret;
435 }
437 #endif /* #if (PLATFORM_QSPI_FLASH_WRITE_IN) */
439 /**
440 * \brief Initializes the FLASH device and configure communication
441 * between FLASH and QSPI controller.
442 *
443 * \param pDevice [IN] : Platform device handle.
444 *
445 * \return QSPI_SUCCESS : if success.
446 * QSPI_ERR : if error.
447 *
448 **/
449 QSPI_STATUS qspiFlashInit(PLATFORM_DEVICE_info *pDevice)
450 {
451 QSPI_STATUS ret;
453 ret = qspiInit(QSPI_FLASH_PAGE_SIZE);
455 return ret;
456 }
458 #endif /* #if (PLATFORM_QSPI_FLASH_IN) */
460 /* Nothing past this point */