[processor-sdk/performance-audio-sr.git] / psdk_cust / pdk_k2g_1_0_1_2_eng / packages / ti / board / src / flash / platform_flash / evmc66x_nor.c
1 /*
2 * Copyright (c) 2010-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 #include "platform_internal.h"
36 #if (PLATFORM_NOR_IN)
38 /**
39 *
40 * \file evmc66x_nor.c
41 *
42 * \brief This file implements NOR flash driver for Nymonyx N25Q128 NOR flash
43 *
44 *****************************************************************************/
46 /************************
47 * Include Files
48 ************************/
50 #if (PLATFORM_NOR_WRITE_IN)
51 static NOR_STATUS
52 nor_wait_ready
53 (
54 uint32_t timeout
55 )
56 {
57 NOR_STATUS ret;
58 uint8_t status;
59 uint8_t cmd = SPI_NOR_CMD_RDSR;
61 do
62 {
64 /* Send Read Status command */
65 ret = spi_xfer(NOR_SPI_PORT,1, &cmd, NULL, FALSE);
66 if (ret)
67 {
68 return ret;
69 }
71 /* Read status value */
72 ret = spi_xfer(NOR_SPI_PORT,1, NULL, &status, TRUE);
73 if (ret)
74 {
75 return ret;
76 }
78 if ((status & SPI_NOR_SR_WIP) == 0)
79 {
80 break;
81 }
83 timeout--;
84 if (!timeout)
85 {
86 break;
87 }
89 } while (TRUE);
91 if ((status & SPI_NOR_SR_WIP) == 0)
92 return NOR_EOK;
94 /* Timed out */
95 return NOR_EFAIL;
96 }
97 #endif
99 /******************************************************************************
100 *
101 * Function: nor_get_details
102 *
103 * Description: This function the details of NOR flash device.
104 *
105 * Parameters: NOR_INFO nor_info - structure for information
106 *
107 * Return Value: status
108 ******************************************************************************/
109 uint32_t
110 nor_get_details
111 (
112 PLATFORM_DEVICE_info* nor_info
113 )
114 {
115 uint32_t uiStatus = SUCCESS, ret;
116 uint8_t idcode[3]; /* Initialize the SPI interface */
118 /* Claim the SPI controller */
119 spi_claim(NOR_SPI_PORT,SPI_NOR_CS, SPI_MAX_FREQ);
121 /* Read the ID codes */
122 ret = spi_cmd(NOR_SPI_PORT,SPI_NOR_CMD_RDID, idcode, sizeof(idcode));
123 if (ret) {
124 spi_release(NOR_SPI_PORT);
125 platform_errno = PLATFORM_ERRNO_NOR;
126 return FAIL;
127 }
129 /* Get the actuals */
130 nor_info->manufacturer_id = idcode[0];
131 nor_info->device_id = (idcode[1] << SPI_NOR_CHAR_LENTH) | (idcode[2]);
133 /* No blocks are bad for NOR.. for now */
134 nor_info->bblist = NULL;
136 spi_release(NOR_SPI_PORT);
138 return uiStatus;
139 }
141 /******************************************************************************
142 *
143 * Function: nor_init
144 *
145 * Description: This function configures the SPI controller communication
146 * between the DSP and the NOR flash
147 *
148 * Parameters: None
149 *
150 * Return Value: error status
151 *
152 ******************************************************************************/
153 NOR_STATUS
154 nor_init
155 (
156 void
157 )
158 {
159 NOR_STATUS ret;
160 uint8_t idcode[3]; /* Initialize the SPI interface */
162 /* Claim the SPI controller */
163 spi_claim(NOR_SPI_PORT,SPI_NOR_CS, SPI_MAX_FREQ);
165 /* Read the ID codes */
166 ret = spi_cmd(NOR_SPI_PORT,SPI_NOR_CMD_RDID, idcode, sizeof(idcode));
167 if (ret)
168 {
169 IFPRINT (platform_write( "nor_init: Error in reading the idcode\n"));
170 spi_release(NOR_SPI_PORT);
171 platform_errno = PLATFORM_ERRNO_NOR;
172 return NOR_EFAIL;
173 }
175 IFPRINT (platform_write("SF: Got idcode %02x %02x %02x\n", idcode[0], idcode[1], idcode[2]));
177 if (idcode[0] != SPI_NOR_MANUFACTURE_ID) {
178 /* Expected Manufacturer ID does not match */
179 spi_release(NOR_SPI_PORT);
180 platform_errno = PLATFORM_ERRNO_BADFLASHDEV;
181 return NOR_EFAIL;
182 }
184 spi_release(NOR_SPI_PORT);
185 return NOR_EOK;
186 }
188 /******************************************************************************
189 *
190 * Function: nor_read
191 *
192 * Description: This function reads data from the NOR flash
193 *
194 * Parameters: uint32_t addr - Byte address of the NOR flash
195 * uint32_t len - Lenth in bytes to read
196 * uint8_t* buf - Pointer of the buffer to store the bytes read
197 *
198 * Return Value: error status
199 *
200 ******************************************************************************/
201 #if (PLATFORM_NOR_READ_IN)
202 NOR_STATUS
203 nor_read
204 (
205 PLATFORM_DEVICE_info* p_device,
206 uint32_t addr,
207 uint32_t len,
208 uint8_t* buf
209 )
210 {
211 uint8_t cmd[4];
212 NOR_STATUS ret_val;
214 /* Claim the SPI controller */
215 spi_claim(NOR_SPI_PORT,SPI_NOR_CS, SPI_MAX_FREQ);
217 /* Validate address input */
218 if(addr + len > SPI_NOR_MAX_FLASH_SIZE)
219 {
220 platform_errno = PLATFORM_ERRNO_FLASHADDR;
221 spi_release(NOR_SPI_PORT);
222 return NOR_EFAIL;
223 }
225 /* Initialize the command to be sent serially */
226 cmd[0] = SPI_NOR_CMD_READ;
227 cmd[1] = (uint8_t)(addr>>16);
228 cmd[2] = (uint8_t)(addr>>8);
229 cmd[3] = (uint8_t)addr;
231 ret_val = (spi_cmd_read(NOR_SPI_PORT,cmd, 4, buf, len));
233 spi_release(NOR_SPI_PORT);
234 return (ret_val);
235 }
236 #endif
238 /******************************************************************************
239 *
240 * Function: nor_write
241 *
242 * Description: This function writes data to the NOR flash
243 *
244 * Parameters: uint32_t addr - Byte address of the NOR flash
245 * uint32_t len - Lenth in bytes to write
246 * uint8_t* buf - Pointer of the buffer to store the write data
247 *
248 * Return Value: error status
249 *
250 ******************************************************************************/
251 #if (PLATFORM_NOR_WRITE_IN)
252 NOR_STATUS
253 nor_write
254 (
255 PLATFORM_DEVICE_info* p_device,
256 uint32_t addr,
257 uint32_t len,
258 uint8_t* buf
259 )
260 {
261 uint32_t page_addr;
262 uint32_t byte_addr;
263 uint32_t page_size;
264 uint32_t loopCount;
266 uint32_t chunk_len;
267 uint32_t actual;
268 uint32_t ret;
269 uint8_t cmd[4];
271 /* Claim the SPI controller */
272 spi_claim(NOR_SPI_PORT,SPI_NOR_CS, SPI_MAX_FREQ);
274 /* Validate address input */
275 if(addr + len > SPI_NOR_MAX_FLASH_SIZE)
276 {
277 platform_errno = PLATFORM_ERRNO_NOFREEBLOCKS;
278 spi_release(NOR_SPI_PORT);
279 return NOR_EFAIL;
280 }
282 page_size = SPI_NOR_PAGE_SIZE;
283 page_addr = addr / page_size;
284 byte_addr = addr & (SPI_NOR_PAGE_SIZE - 1); /* % page_size; */
286 ret = NOR_EOK;
287 for (actual = 0; actual < len; actual += chunk_len)
288 {
289 /* Send Write Enable command */
290 ret = spi_cmd(NOR_SPI_PORT,SPI_NOR_CMD_WREN, NULL, 0);
291 if (ret)
292 {
293 platform_errno = PLATFORM_ERRNO_DEV_FAIL;
294 spi_release(NOR_SPI_PORT);
295 return NOR_EFAIL;
296 }
298 /* Send Page Program command */
299 chunk_len = ((len - actual) < (page_size - byte_addr) ?
300 (len - actual) : (page_size - byte_addr));
302 cmd[0] = SPI_NOR_CMD_PP;
303 cmd[1] = (uint8_t)(addr>>16);
304 cmd[2] = (uint8_t)(addr>>8);
305 cmd[3] = (uint8_t)addr;
307 ret = spi_cmd_write(NOR_SPI_PORT,cmd, 4, buf + actual, chunk_len);
308 if (ret)
309 {
310 platform_errno = PLATFORM_ERRNO_DEV_FAIL;
311 spi_release(NOR_SPI_PORT);
312 return NOR_EFAIL;
313 }
315 ret = nor_wait_ready(SPI_NOR_PROG_TIMEOUT);
316 if (ret)
317 {
318 platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
319 spi_release(NOR_SPI_PORT);
320 return NOR_EFAIL;
321 }
323 page_addr++;
324 addr += chunk_len;
325 byte_addr = 0;
327 loopCount = 4000;
328 while (loopCount--) {
329 asm(" NOP");
330 }
332 }
334 spi_release(NOR_SPI_PORT);
335 return ((NOR_STATUS) ret);
336 }
337 #endif
339 /******************************************************************************
340 *
341 * Function: nor_erase
342 *
343 * Description: This function writes data to the NOR flash
344 *
345 * Parameters: uint32_t sector_number - Sector number to erase,
346 * if sector_number = -1, do bulk erase
347 *
348 * Return Value: error status
349 *
350 ******************************************************************************/
351 #if (PLATFORM_NOR_WRITE_IN)
352 NOR_STATUS
353 nor_erase
354 (
355 PLATFORM_DEVICE_info* p_device,
356 uint32_t sector_number
357 )
358 {
359 NOR_STATUS ret;
360 uint8_t cmd[4];
361 uint32_t cmd_len;
362 uint32_t address;
364 /* Claim the SPI controller */
365 spi_claim(NOR_SPI_PORT,SPI_NOR_CS, SPI_MAX_FREQ);
367 /*
368 * This function currently uses sector erase only.
369 * probably speed things up by using bulk erase
370 * when possible.
371 */
373 if (sector_number == SPI_NOR_BE_SECTOR_NUM)
374 {
375 cmd[0] = SPI_NOR_CMD_BE;
376 cmd_len = 1;
378 }
379 else if (sector_number >= SPI_NOR_SECTOR_COUNT)
380 {
381 platform_errno = PLATFORM_ERRNO_NORADDR;
382 return NOR_EFAIL;
383 }
384 else
385 {
386 address = sector_number * SPI_NOR_SECTOR_SIZE;
387 cmd[0] = SPI_NOR_CMD_SE;
388 cmd[1] = (address >> 16) & 0xff;
389 cmd[2] = (address >> 8) & 0xff;
390 cmd[3] = (address >> 0) & 0xff;
392 cmd_len = 4;
393 }
395 /* Send Write Enable command */
396 ret = spi_cmd(NOR_SPI_PORT,SPI_NOR_CMD_WREN, NULL, 0);
397 if (ret)
398 {
399 platform_errno = PLATFORM_ERRNO_DEV_FAIL;
400 spi_release(NOR_SPI_PORT);
401 return NOR_EFAIL;
402 }
404 ret = spi_cmd_write(NOR_SPI_PORT,cmd, cmd_len, NULL, 0);
405 if (ret)
406 {
407 platform_errno = PLATFORM_ERRNO_DEV_FAIL;
408 spi_release(NOR_SPI_PORT);
409 return NOR_EFAIL;
410 }
412 ret = nor_wait_ready(SPI_NOR_SECTOR_ERASE_TIMEOUT);
413 if (ret)
414 {
415 platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
416 spi_release(NOR_SPI_PORT);
417 return NOR_EFAIL;
418 }
419 spi_release(NOR_SPI_PORT);
420 return ret;
421 }
422 #endif
424 #endif /*(PLATFORM_NOR_IN)*/