1 /********************************************************************************
2 * FILE PURPOSE: Hardware nand driver for 8 bit hwGpio driven nand
3 ********************************************************************************
4 * FILE NAME: nandhwGpio.c
5 *
6 * DESCRIPTION: The low level nand driver which accesses the nand through hwGpio
7 *
8 * @file nandhwGpio.c
9 *
10 * @brief
11 * The low level nand driver which accesses the nand through hwGpio
12 *
13 ********************************************************************************/
14 #include "types.h"
15 #include "ibl.h"
16 #include "nandhwapi.h"
17 #include "gpio.h"
18 #include "ecc.h"
19 #include "target.h"
21 /* Pointer to the device configuration */
22 nandDevInfo_t *hwDevInfo;
25 /**
26 * @brief
27 * Delay for a number of cycles (approximate)
28 */
30 void ndelay(Uint32 uiDelay)
31 {
32 volatile Uint32 i;
34 for (i = 0; i < uiDelay>>3; i++);
35 }
39 /**
40 * @brief
41 * a 100us delay
42 */
43 void ptNandWaitRdy(void)
44 {
45 ndelay(100 * 1000); // 100 usec
46 }
49 /**
50 * @brief
51 * Write to the flash (command for the boot loader)
52 */
53 void ptNandWriteDataByte(Uint8 data)
54 {
55 // Data is written to the data register on the rising edge of WE# when
56 // \95 CE#, CLE, and ALE are LOW, and
57 // \95 the device is not busy.
58 hwGpioClearOutput(NAND_NWE_GPIO_PIN);
59 ndelay(TARGET_NAND_STD_DELAY);
60 hwGpioClearDataBus(GPIO_DATAMASK);
61 hwGpioWriteDataBus(data);
62 ndelay(TARGET_NAND_STD_DELAY);
63 hwGpioSetOutput(NAND_NWE_GPIO_PIN); // At posedge clock, make WE# = 1.
64 ndelay(TARGET_NAND_STD_DELAY);
65 }
68 /**
69 * @brief
70 * Set the address latch
71 */
72 void ptNandAleSet(Uint32 addr)
73 {
74 // ALE HIGH indicates address cycle occurring
75 hwGpioSetOutput(NAND_ALE_GPIO_PIN);
76 ptNandWriteDataByte(addr);
77 hwGpioClearOutput(NAND_ALE_GPIO_PIN);
78 }
80 /**
81 * @brief
82 * Write a command to the nand flash
83 */
84 void ptNandCmdSet(Uint32 cmd)
85 {
86 // Commands are written to the command register on the rising edge of WE# when
87 // \95 CE# and ALE are LOW, and
88 // \95 CLE is HIGH, and : CLE HIGH indicates command cycle occurring
89 // \95 the device is not busy
90 hwGpioSetOutput(NAND_CLE_GPIO_PIN);
91 ptNandWriteDataByte(cmd);
92 hwGpioClearOutput(NAND_CLE_GPIO_PIN);
93 }
96 /**
97 * @brief
98 * Setup hwGpio to drive the NAND interface
99 */
100 void ptNandConfig (void)
101 {
102 // Set direction of control signals as OUT
103 hwGpioSetDirection(NAND_CLE_GPIO_PIN, GPIO_OUT);
104 hwGpioSetDirection(NAND_NCE_GPIO_PIN, GPIO_OUT);
105 hwGpioSetDirection(NAND_NWE_GPIO_PIN, GPIO_OUT);
106 hwGpioSetDirection(NAND_ALE_GPIO_PIN, GPIO_OUT);
107 hwGpioSetDirection(NAND_NRE_GPIO_PIN, GPIO_OUT);
109 // Set Data Bus direction as OUT
110 hwGpioSetDataBusDirection(GPIO_OUT);
112 hwGpioSetOutput(NAND_NCE_GPIO_PIN); // Chip Enable = 1
113 hwGpioClearOutput(NAND_CLE_GPIO_PIN); // Command Latch enable = 0
114 hwGpioClearOutput(NAND_ALE_GPIO_PIN); // Address latch Enable = 0
115 hwGpioSetOutput(NAND_NWE_GPIO_PIN); // Write Enable = 1
116 hwGpioSetOutput(NAND_NRE_GPIO_PIN); // Read Enable = 1
117 }
119 /**
120 * @brief Initialize the driver
121 *
122 */
123 Int32 nandHwDriverInit (nandDevInfo_t *devInfo)
124 {
125 Uint32 cmd;
127 hwDevInfo = devInfo;
129 if (devInfo->addressBytes > 4)
130 return (NAND_INVALID_ADDR_SIZE);
132 // Initialize NAND interface
133 ptNandConfig();
134 ndelay(TARGET_NAND_STD_DELAY*10);
136 cmd = hwDevInfo->resetCommand;
137 // Send reset command to NAND
138 hwGpioClearOutput(NAND_NCE_GPIO_PIN); // Chip EN = 0
139 ptNandCmdSet(cmd);
140 hwGpioSetOutput(NAND_NCE_GPIO_PIN);
142 ptNandWaitRdy();
144 return (0);
145 }
147 /**
148 * @brief
149 * Read a single data byte
150 */
151 void ptNandReadDataByte(Uint8* puchValue)
152 {
153 // Set Data Bus direction as IN
154 hwGpioSetDataBusDirection(GPIO_IN);
156 hwGpioClearOutput(NAND_NRE_GPIO_PIN);
157 ndelay(TARGET_NAND_STD_DELAY);
159 *puchValue = hwGpioReadDataBus();
160 hwGpioSetOutput(NAND_NRE_GPIO_PIN);
161 ndelay(TARGET_NAND_STD_DELAY);
163 // Set Data Bus direction as OUT
164 hwGpioSetDataBusDirection(GPIO_OUT);
165 ndelay(TARGET_NAND_STD_DELAY);
166 }
168 /**
169 * @brief
170 * Read multiple bytes
171 */
172 Uint32 ptNandReadDataBytes(Uint32 numBytes, Uint8 *destAddr)
173 {
174 Uint32 i;
176 // 8-bit NAND
177 for (i = 0; i < numBytes; i++)
178 {
179 // NANDRead done directly without checking for nand width
180 ptNandReadDataByte((Uint8 *)destAddr);
181 destAddr++;
182 }
183 return SUCCESS;
184 }
186 /**
187 * @brief
188 * Swap the bytes in a 4 byte field
189 */
190 Uint32 swapBytes (Uint32 v)
191 {
192 Uint32 w;
194 w = (((v >> 24) & 0xff) << 0) |
195 (((v >> 16) & 0xff) << 8) |
196 (((v >> 8) & 0xff) << 16) |
197 (((v >> 0) & 0xff) << 24) ;
199 return (w);
201 }
204 /**
205 * @brief
206 * Read a complete page including the extra page bytes.
207 */
209 Int32 nandHwDriverReadBytes (Uint32 block, Uint32 page, Uint32 byte, Uint32 nbytes, Uint8 *data)
210 {
212 Uint32 addr;
214 if (data == NULL)
215 return (NAND_NULL_ARG);
217 if ( (block >= hwDevInfo->totalBlocks) ||
218 (page >= hwDevInfo->pagesPerBlock) )
219 return (NAND_INVALID_ADDR);
221 ndelay(TARGET_NAND_STD_DELAY*10);
223 hwGpioClearOutput(NAND_NCE_GPIO_PIN);
224 ndelay(TARGET_NAND_STD_DELAY*5);
226 ptNandCmdSet(hwDevInfo->readCommandPre); // First cycle send 0
228 // Send address of the block + page to be read
229 // Address cycles = 4, Block shift = 22, Page Shift = 16, Bigblock = 0
230 addr = (block << hwDevInfo->blockOffset) +
231 (page << hwDevInfo->pageOffset) +
232 (byte << hwDevInfo->columnOffset);
234 if (hwDevInfo->lsbFirst == FALSE)
235 addr = swapBytes (addr);
237 ptNandAleSet(addr & 0xFF); // BIT0-7 1rst Cycle
238 ndelay(TARGET_NAND_STD_DELAY);
240 if (hwDevInfo->addressBytes >= 2) {
241 ptNandAleSet((addr >> 8u) & 0x0F); // Bits8-11 2nd Cycle
242 ndelay(TARGET_NAND_STD_DELAY);
243 }
245 if (hwDevInfo->addressBytes >= 3) {
246 ptNandAleSet((addr >> 16u) & 0xFF); // Bits16-23
247 ndelay(TARGET_NAND_STD_DELAY);
248 }
250 if (hwDevInfo->addressBytes >= 4) {
251 ptNandAleSet((addr >> 24u) & 0xFF); // Bits24-31
252 ndelay(TARGET_NAND_STD_DELAY);
253 }
255 if (hwDevInfo->postCommand == TRUE)
256 ptNandCmdSet(hwDevInfo->readCommandPost);
258 // Wait for Ready Busy Pin to go HIGH
259 ptNandWaitRdy();
262 ptNandReadDataBytes(nbytes, data);
265 // Set Chip enable
266 hwGpioSetOutput(NAND_NCE_GPIO_PIN);
267 ndelay(TARGET_NAND_STD_DELAY*5);
269 return (0);
270 }
275 /**
276 * @brief
277 * Read a complete page including the extra page bytes
278 */
279 Int32 nandHwDriverReadPage(Uint32 block, Uint32 page, Uint8 *data)
280 {
281 Int32 ret;
282 Int32 i;
283 Int32 nblocks;
284 Uint8 *blockp;
285 Uint8 *eccp;
286 Uint8 eccCalc[3];
288 /* Read the page, including the extra bytes */
289 ret = nandHwDriverReadBytes (block, page, 0, hwDevInfo->pageSizeBytes + hwDevInfo->pageEccBytes, data);
290 if (ret < 0)
291 return (ret);
293 /* Perform ECC on 256 byte blocks. Three bytes of ecc per 512 byte block are used. The last
294 * 3 bytes are used for the last block, the previous three for the block before that, etc */
295 nblocks = hwDevInfo->pageSizeBytes >> 8;
297 for (i = 0; i < nblocks; i++) {
299 blockp = &data[i * 256];
300 eccp = &data[hwDevInfo->pageSizeBytes + hwDevInfo->pageEccBytes - ((nblocks - i) * 3)];
302 eccComputeECC (blockp, eccCalc);
304 if (eccCorrectData (blockp, eccp, eccCalc) != ECC_SUCCESS)
305 return (NAND_ECC_FAILURE);
307 }
309 return (0);
311 }
315 /**
316 * @brief
317 * Close the driver
318 */
319 int32 nandHwDriverClose (void)
320 {
321 return (0);
323 }