1 /*
2 *
3 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
4 *
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * Neither the name of Texas Instruments Incorporated nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
38 /********************************************************************************
39 * FILE PURPOSE: Hardware nand driver for 8 bit hwGpio driven nand
40 ********************************************************************************
41 * FILE NAME: nandhwGpio.c
42 *
43 * DESCRIPTION: The low level nand driver which accesses the nand through hwGpio
44 *
45 * @file nandhwGpio.c
46 *
47 * @brief
48 * The low level nand driver which accesses the nand through hwGpio
49 *
50 ********************************************************************************/
51 #include "types.h"
52 #include "ibl.h"
53 #include "iblcfg.h"
54 #include "nandhwapi.h"
55 #include "gpio.h"
56 #include "ecc.h"
57 #include "target.h"
58 #include "nandgpioloc.h"
60 /* Pointer to the device configuration */
61 extern volatile cregister Uint32 TSCL;
62 nandDevInfo_t *hwDevInfo;
64 /**
65 * @brief
66 * Delay for a number of cycles (approximate)
67 */
69 void ndelay(Uint32 uiDelay)
70 {
71 Uint32 t;
72 TSCL = 1;
74 t = TSCL;
75 while(TSCL < (t + uiDelay));
76 }
78 Uint32 ptNandWaitRdy(Uint32 in_timeout)
79 {
80 Uint32 t;
82 ndelay(NAND_WAIT_PIN_POLL_ST_DLY);
84 TSCL = 1;
85 t = TSCL;
87 while(!hwGpioReadInput(NAND_BSY_GPIO_PIN))
88 {
89 if( TSCL > (t + in_timeout) )
90 {
91 return 0; /* fail */
92 }
93 }
94 return 1; /* success */
95 }
97 /**
98 * @brief
99 * Write to the flash (command for the boot loader)
100 */
101 void ptNandWriteDataByte(Uint8 data)
102 {
103 // Data is written to the data register on the rising edge of WE# when
104 // \95 CE#, CLE, and ALE are LOW, and
105 // \95 the device is not busy.
106 hwGpioClearOutput(NAND_NWE_GPIO_PIN);
107 ndelay(TARGET_NAND_STD_DELAY);
108 hwGpioClearDataBus(GPIO_DATAMASK);
109 hwGpioWriteDataBus(data);
110 ndelay(TARGET_NAND_STD_DELAY);
111 hwGpioSetOutput(NAND_NWE_GPIO_PIN); // At posedge clock, make WE# = 1.
112 ndelay(TARGET_NAND_STD_DELAY);
113 }
116 /**
117 * @brief
118 * Set the address latch
119 */
120 void ptNandAleSet(Uint32 addr)
121 {
122 // ALE HIGH indicates address cycle occurring
123 hwGpioSetOutput(NAND_ALE_GPIO_PIN);
124 ptNandWriteDataByte(addr);
125 hwGpioClearOutput(NAND_ALE_GPIO_PIN);
126 }
128 /**
129 * @brief
130 * Write a command to the nand flash
131 */
132 void ptNandCmdSet(Uint32 cmd)
133 {
134 // Commands are written to the command register on the rising edge of WE# when
135 // \95 CE# and ALE are LOW, and
136 // \95 CLE is HIGH, and : CLE HIGH indicates command cycle occurring
137 // \95 the device is not busy
138 hwGpioSetOutput(NAND_CLE_GPIO_PIN);
139 ptNandWriteDataByte(cmd);
140 hwGpioClearOutput(NAND_CLE_GPIO_PIN);
141 }
144 /**
145 * @brief
146 * Setup hwGpio to drive the NAND interface
147 */
148 void ptNandConfig (void)
149 {
150 // Set direction of control signals as OUT
151 hwGpioSetDirection(NAND_CLE_GPIO_PIN, GPIO_OUT);
152 hwGpioSetDirection(NAND_NCE_GPIO_PIN, GPIO_OUT);
153 hwGpioSetDirection(NAND_NWE_GPIO_PIN, GPIO_OUT);
154 hwGpioSetDirection(NAND_ALE_GPIO_PIN, GPIO_OUT);
155 hwGpioSetDirection(NAND_NRE_GPIO_PIN, GPIO_OUT);
157 // Set Data Bus direction as OUT
158 hwGpioSetDataBusDirection(GPIO_OUT);
160 hwGpioSetOutput(NAND_NCE_GPIO_PIN); // Chip Enable = 1
161 hwGpioClearOutput(NAND_CLE_GPIO_PIN); // Command Latch enable = 0
162 hwGpioClearOutput(NAND_ALE_GPIO_PIN); // Address latch Enable = 0
163 hwGpioSetOutput(NAND_NWE_GPIO_PIN); // Write Enable = 1
164 hwGpioSetOutput(NAND_NRE_GPIO_PIN); // Read Enable = 1
165 }
167 /**
168 * @brief Initialize the driver
169 *
170 */
171 Int32 nandHwGpioDriverInit (int32 cs, void *vdevInfo)
172 {
173 Uint32 cmd;
174 Uint32 ret;
175 nandDevInfo_t *devInfo = (nandDevInfo_t *)vdevInfo;
177 hwDevInfo = devInfo;
179 if (devInfo->addressBytes > 4)
180 return (NAND_INVALID_ADDR_SIZE);
182 // Initialize NAND interface
183 ptNandConfig();
184 ndelay(TARGET_NAND_STD_DELAY*10);
186 cmd = hwDevInfo->resetCommand;
187 // Send reset command to NAND
188 hwGpioClearOutput(NAND_NCE_GPIO_PIN); // Chip EN = 0
189 ptNandCmdSet(cmd);
190 hwGpioSetOutput(NAND_NCE_GPIO_PIN);
192 ret = ptNandWaitRdy(100000);
193 if (ret != 1)
194 return -1;
196 return (0);
197 }
199 /**
200 * @brief
201 * Read a single data byte
202 */
203 void ptNandReadDataByte(Uint8* puchValue)
204 {
205 // Set Data Bus direction as IN
206 hwGpioSetDataBusDirection(GPIO_IN);
208 hwGpioClearOutput(NAND_NRE_GPIO_PIN);
209 ndelay(TARGET_NAND_STD_DELAY);
211 *puchValue = hwGpioReadDataBus();
212 hwGpioSetOutput(NAND_NRE_GPIO_PIN);
213 ndelay(TARGET_NAND_STD_DELAY);
215 // Set Data Bus direction as OUT
216 hwGpioSetDataBusDirection(GPIO_OUT);
217 ndelay(TARGET_NAND_STD_DELAY);
218 }
220 /**
221 * @brief
222 * Read multiple bytes
223 */
224 Uint32 ptNandReadDataBytes(Uint32 numBytes, Uint8 *destAddr)
225 {
226 Uint32 i;
228 // 8-bit NAND
229 for (i = 0; i < numBytes; i++)
230 {
231 // NANDRead done directly without checking for nand width
232 ptNandReadDataByte((Uint8 *)destAddr);
233 destAddr++;
234 }
235 return SUCCESS;
236 }
238 /**
239 * @brief
240 * Swap the bytes in a 4 byte field
241 */
242 Uint32 swapBytes (Uint32 v)
243 {
244 Uint32 w;
246 w = (((v >> 24) & 0xff) << 0) |
247 (((v >> 16) & 0xff) << 8) |
248 (((v >> 8) & 0xff) << 16) |
249 (((v >> 0) & 0xff) << 24) ;
251 return (w);
253 }
256 /**
257 * @brief
258 * Read a complete page including the extra page bytes.
259 */
261 Int32 nandHwGpioDriverReadBytes (Uint32 block, Uint32 page, Uint32 byte, Uint32 nbytes, Uint8 *data)
262 {
264 Uint32 addr;
265 Uint32 cmd;
266 Uint32 ret;
267 if (data == NULL)
268 return (NAND_NULL_ARG);
270 if ( (block >= hwDevInfo->totalBlocks) ||
271 (page >= hwDevInfo->pagesPerBlock) )
272 return (NAND_INVALID_ADDR);
274 ndelay(TARGET_NAND_STD_DELAY*10);
276 hwGpioClearOutput(NAND_NCE_GPIO_PIN);
277 ndelay(TARGET_NAND_STD_DELAY*5);
279 if (byte < hwDevInfo->pageSizeBytes)
280 {
281 /* Read page data */
282 cmd = hwDevInfo->readCommandPre;
283 }
284 else
285 {
286 /* Read spare area data */
287 cmd = 0x50;
288 }
290 ptNandCmdSet(cmd); // First cycle send 0
292 /*
293 * Send address of the block + page to be read
294 * Address cycles = 4, Block shift = 14,
295 * Page Shift = 9, Bigblock = 0
296 */
297 addr = PACK_ADDR(0x0, page, block);
299 ptNandAleSet((addr >> 0u) & 0xFF); /* A0-A7 1st Cycle; column addr */
300 ndelay(TARGET_NAND_STD_DELAY);
301 ptNandAleSet((addr >> 9u) & 0xFF); /* A9-A16 2nd Cycle; page addr & blk */
302 ndelay(TARGET_NAND_STD_DELAY);
303 ptNandAleSet((addr >> 17u) & 0xFF); /* A17-A24 3rd Cycle; Block addr */
304 ndelay(TARGET_NAND_STD_DELAY);
305 ptNandAleSet((addr >> 25u) & 0x1); /* A25 4th Cycle; Plane addr */
306 ndelay(TARGET_NAND_STD_DELAY);
309 // Wait for Ready Busy Pin to go HIGH
310 ret = ptNandWaitRdy(100000);
312 ptNandReadDataBytes(nbytes, data);
314 // Set Chip enable
315 hwGpioSetOutput(NAND_NCE_GPIO_PIN);
316 ndelay(TARGET_NAND_STD_DELAY*5);
318 return (0);
319 }
324 /**
325 * @brief
326 * Read a complete page including the extra page bytes
327 */
328 Int32 nandHwGpioDriverReadPage(Uint32 block, Uint32 page, Uint8 *data)
329 {
330 Int32 ret;
331 Int32 i;
332 Int32 nblocks;
333 Uint8 *blockp;
334 Uint8 *eccp;
335 Uint8 eccCalc[3];
336 int32 iErrors = ECC_SUCCESS;
337 Uint8 *SpareAreaBuf = NULL;
338 Uint8 tempSpareAreaBuf[3];
340 SpareAreaBuf = data + NAND_BYTES_PER_PAGE;
342 /* Read the page, including the extra bytes */
343 ret = nandHwGpioDriverReadBytes (block, page, 0, hwDevInfo->pageSizeBytes + hwDevInfo->pageEccBytes, data);
344 if (ret < 0)
345 return (ret);
347 /* Perform ECC on 256 byte blocks. Three bytes of ecc per 256 byte block are used. The last
348 * 3 bytes are used for the last block, the previous three for the block before that, etc */
350 for(i = 0; i < NAND_BYTES_PER_PAGE / ECC_BLOCK_SIZE; i++)
351 {
352 /* Correct ecc error for each 256 byte blocks */
353 eccComputeECC(data + i * ECC_BLOCK_SIZE, eccCalc);
355 if ( i == 0) {
356 iErrors = eccCorrectData(data + (i * ECC_BLOCK_SIZE),
357 (SpareAreaBuf + (i * 3)), eccCalc);
358 }
360 if (i == 1) {
361 tempSpareAreaBuf[0] = SpareAreaBuf[3];
362 tempSpareAreaBuf[1] = SpareAreaBuf[6];
363 tempSpareAreaBuf[2] = SpareAreaBuf[7];
365 iErrors = eccCorrectData(data + (i * ECC_BLOCK_SIZE),
366 tempSpareAreaBuf, eccCalc);
367 }
369 // if(iErrors != ECC_SUCCESS)
370 // return (NAND_ECC_FAILURE);
371 }
373 return (0);
375 }
379 /**
380 * @brief
381 * Close the driver
382 */
383 int32 nandHwGpioDriverClose (void)
384 {
385 return (0);
387 }