TX51 pre-release
[karo-tx-redboot.git] / packages / devs / flash / arm / mxc / v2_0 / include / mxc_nfc_v3.h
1 #ifndef _MXC_NFC_V3_H_
2 #define _MXC_NFC_V3_H_
3 //==========================================================================
4 //
5 //      mxc_nfc_v3.h
6 //
7 //      Flash programming to support NAND flash on Freescale MXC platforms
8 //
9 //==========================================================================
10 //####ECOSGPLCOPYRIGHTBEGIN####
11 // -------------------------------------------
12 // This file is part of eCos, the Embedded Configurable Operating System.
13 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
14 //
15 // eCos is free software; you can redistribute it and/or modify it under
16 // the terms of the GNU General Public License as published by the Free
17 // Software Foundation; either version 2 or (at your option) any later version.
18 //
19 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
20 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
22 // for more details.
23 //
24 // You should have received a copy of the GNU General Public License along
25 // with eCos; if not, write to the Free Software Foundation, Inc.,
26 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 //
28 // As a special exception, if other files instantiate templates or use macros
29 // or inline functions from this file, or you compile this file and link it
30 // with other works to produce a work based on this file, this file does not
31 // by itself cause the resulting work to be covered by the GNU General Public
32 // License. However the source code for this file must still be made available
33 // in accordance with section (3) of the GNU General Public License.
34 //
35 // This exception does not invalidate any other reasons why a work based on
36 // this file might be covered by the GNU General Public License.
37 //
38 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
39 // at http://sources.redhat.com/ecos/ecos-license/
40 // -------------------------------------------
41 //####ECOSGPLCOPYRIGHTEND####
42 //==========================================================================
43 //#####DESCRIPTIONBEGIN####
44 //
45 // Author(s):    Kevin Zhang <k.zhang@freescale.com>
46 // Contributors: Kevin Zhang <k.zhang@freescale.com>
47 // Date:         2008-06-02
48 // Purpose:
49 // Description:
50 //
51 //####DESCRIPTIONEND####
52 //
53 //==========================================================================
54
55 #include <pkgconf/devs_flash_onmxc.h>
56 #include "mxc_nand_specifics.h"
57
58 #define PG_2K_DATA_OP_MULTI_CYCLES()    false
59 #define ADDR_INPUT_SIZE                                 8
60
61 #define NAND_MAIN_BUF0                                  (NFC_BASE + 0x000)
62 #define NAND_MAIN_BUF1                                  (NFC_BASE + 0x200)
63 #define NAND_MAIN_BUF2                                  (NFC_BASE + 0x400)
64 #define NAND_MAIN_BUF3                                  (NFC_BASE + 0x600)
65 #define NAND_MAIN_BUF4                                  (NFC_BASE + 0x800)
66 #define NAND_MAIN_BUF5                                  (NFC_BASE + 0xA00)
67 #define NAND_MAIN_BUF6                                  (NFC_BASE + 0xC00)
68 #define NAND_MAIN_BUF7                                  (NFC_BASE + 0xE00)
69 #define NAND_SPAR_BUF0                                  (NFC_BASE + 0x1000)
70 #define NAND_SPAR_BUF1                                  (NFC_BASE + 0x1040)
71 #define NAND_SPAR_BUF2                                  (NFC_BASE + 0x1080)
72 #define NAND_SPAR_BUF3                                  (NFC_BASE + 0x10C0)
73 #define NAND_SPAR_BUF4                                  (NFC_BASE + 0x1100)
74 #define NAND_SPAR_BUF5                                  (NFC_BASE + 0x1140)
75 #define NAND_SPAR_BUF6                                  (NFC_BASE + 0x1180)
76 #define NAND_SPAR_BUF7                                  (NFC_BASE + 0x11C0)
77
78 // The following defines are not used. Just for compilation purpose
79 #define ECC_STATUS_RESULT_REG                   0xDEADFFFF
80 #define NFC_DATA_INPUT(buf_no, earea, en)
81 #define NFC_DATA_INPUT_2k(buf_no)
82 // dummy function as it is not needed for automatic operations
83 #define NFC_ADDR_INPUT(addr)
84 #define NFC_ARCH_INIT()
85 #define NUM_OF_CS_LINES                                    8
86 #define NFC_BUFSIZE                                             4096
87 #define NFC_SPARE_BUF_SZ                                  64
88
89 enum nfc_internal_buf {
90         RAM_BUF_0 = 0x0 << 4,
91         RAM_BUF_1 = 0x1 << 4,
92         RAM_BUF_2 = 0x2 << 4,
93         RAM_BUF_3 = 0x3 << 4,
94         RAM_BUF_4 = 0x4 << 4,
95         RAM_BUF_5 = 0x5 << 4,
96         RAM_BUF_6 = 0x6 << 4,
97         RAM_BUF_7 = 0x7 << 4,
98 };
99
100 enum nfc_output_mode {
101         FDO_PAGE_SPARE          = 0x0008,
102         FDO_SPARE_ONLY          = 0x1008,  // LSB has to be 0x08
103         FDO_FLASH_ID            = 0x0010,
104         FDO_FLASH_STATUS        = 0x0020,
105 };
106
107 #if 1
108 #define MAX_LOOPS 10000
109 #define wait_for_auto_prog_done()                                                                               \
110         CYG_MACRO_START                                                                                                         \
111         int loops = MAX_LOOPS;                                                                                          \
112         static int max_loops = MAX_LOOPS;                                                                       \
113         while ((nfc_reg_read(NFC_IPC_REG) & NFC_IPC_AUTO_DONE) == 0) {          \
114                 HAL_DELAY_US(10);                                                                                               \
115                 if (loops-- < 0) {                                                                                              \
116                         diag_printf("%s: Timeout waiting for prog done\n", __FUNCTION__); \
117                         break;                                                                                                          \
118                 }                                                                                                                               \
119         }                                                                                                                                       \
120         if (loops < max_loops) {                                                                                        \
121                 diag_printf1("%s: auto_prog done after %u loops\n",                             \
122                                         __FUNCTION__, MAX_LOOPS - loops);                                       \
123                 max_loops = loops;                                                                                              \
124         }                                                                                                                                       \
125         nfc_reg_write((nfc_reg_read(NFC_IPC_REG) & ~NFC_IPC_AUTO_DONE),         \
126                                 NFC_IPC_REG);                                                                                   \
127         CYG_MACRO_END
128
129 // Polls the NANDFC to wait for an operation to complete
130 #define wait_op_done()                                                                                                  \
131         CYG_MACRO_START                                                                                                         \
132         int loops = MAX_LOOPS;                                                                                          \
133         static int max_loops = MAX_LOOPS;                                                                       \
134         while ((nfc_reg_read(NFC_IPC_REG) & NFC_IPC_INT) == 0) {                        \
135                 HAL_DELAY_US(10);                                                                                               \
136                 if (loops-- < 0) {                                                                                              \
137                         diag_printf("%s: Timeout waiting for NFC ready\n", __FUNCTION__); \
138                         break;                                                                                                          \
139                 }                                                                                                                               \
140         }                                                                                                                                       \
141         if (loops < max_loops) {                                                                                        \
142                 diag_printf1("%s: NFC ready after %u loops\n",                                  \
143                                         __FUNCTION__, MAX_LOOPS - loops);                                       \
144                 max_loops = loops;                                                                                              \
145         }                                                                                                                                       \
146         nfc_reg_write(0, NFC_IPC_REG);                                                                          \
147         CYG_MACRO_END
148 #else
149 #define wait_for_auto_prog_done()                                                                               \
150         CYG_MACRO_START                                                                                                         \
151         while ((nfc_reg_read(NFC_IPC_REG) & NFC_IPC_AUTO_DONE) == 0) {
152         }
153         nfc_reg_write((nfc_reg_read(NFC_IPC_REG) & ~NFC_IPC_AUTO_DONE),
154                                 NFC_IPC_REG);
155         CYG_MACRO_END
156
157 // Polls the NANDFC to wait for an operation to complete
158 #define wait_op_done()
159         CYG_MACRO_START
160         while ((nfc_reg_read(NFC_IPC_REG) & NFC_IPC_INT) == 0) {
161         }
162         nfc_reg_write(0, NFC_IPC_REG);
163         CYG_MACRO_END
164 #endif
165
166 #if 1
167 #include <cyg/hal/plf_mmap.h>
168 #define nfc_reg_write(v, r)             __nfc_reg_write(v, (void *)(r), #r, __FUNCTION__)
169 static inline void __nfc_reg_write(u32 val, void *addr,
170                                                                    const char *reg, const char *fn)
171 {
172         unsigned long pa;
173         HAL_VIRT_TO_PHYS_ADDRESS((unsigned long)addr, pa);
174         diag_printf1("%s: Writing %08x to %s[%04lx]\n", fn, val, reg, pa);
175         writel(val, addr);
176 }
177
178 #define nfc_reg_read(r)         __nfc_reg_read((void *)(r), #r, __FUNCTION__)
179 static inline u32 __nfc_reg_read(void *addr,
180                                                                  const char *reg, const char *fn)
181 {
182         u32 val;
183         unsigned long pa;
184
185         HAL_VIRT_TO_PHYS_ADDRESS((unsigned long)addr, pa);
186         val = readl(addr);
187         diag_printf1("%s: Read %08x from %s[%04lx]\n", fn, val, reg, pa);
188         return val;
189 }
190 #else
191 #define nfc_reg_read(r)                 readl(r)
192 #define nfc_reg_write(v, r)             writel(v, r)
193 #endif
194
195 static void write_nfc_ip_reg(u32 val, u32 reg)
196 {
197         unsigned int ipc = nfc_reg_read(NFC_IPC_REG);
198         int loops = MAX_LOOPS;
199         static int max_loops = MAX_LOOPS;
200
201         if (ipc & NFC_IPC_CACK) {
202                 diag_printf("%s: IPC ACK already set!\n", __FUNCTION__);
203         } else {
204                 nfc_reg_write(NFC_IPC_CREQ, NFC_IPC_REG);
205         }
206
207         while ((nfc_reg_read(NFC_IPC_REG) & NFC_IPC_CACK) == 0) {
208                 HAL_DELAY_US(1);
209                 if (loops-- < 0) {
210                         diag_printf("%s: Timeout waiting for IPC ready\n", __FUNCTION__);
211                         return;
212                 }
213         }
214         if (loops < max_loops) {
215                 diag_printf("%s: NFC ready after %u loops\n",
216                                         __FUNCTION__, MAX_LOOPS - loops);
217                 max_loops = loops;
218         }
219         nfc_reg_write(val, reg);
220         nfc_reg_write((nfc_reg_read(NFC_IPC_REG) & ~NFC_IPC_CREQ), NFC_IPC_REG);
221 }
222
223 /*!
224  * NAND flash data output operation (reading data from NAND flash)
225  * @param buf_no    internal ram buffer number that will contain data
226  *                  to be outputted from the NAND flash after operation done
227  * @param mode      one of the mode defined in enum nfc_output_mode
228  * @param ecc_en    1 - ecc enabled; 0 - ecc disabled
229  */
230 static void NFC_DATA_OUTPUT(enum nfc_internal_buf buf_no, enum nfc_output_mode mode,
231                                                         int ecc_en)
232 {
233         u32 v = nfc_reg_read(NFC_FLASH_CONFIG2_REG);
234
235         if ((v & NFC_FLASH_CONFIG2_ECC_EN) != 0 && ecc_en == 0) {
236                 write_nfc_ip_reg(v & ~NFC_FLASH_CONFIG2_ECC_EN, NFC_FLASH_CONFIG2_REG);
237         }
238         if ((v & NFC_FLASH_CONFIG2_ECC_EN) == 0 && ecc_en != 0) {
239                 write_nfc_ip_reg(v | NFC_FLASH_CONFIG2_ECC_EN, NFC_FLASH_CONFIG2_REG);
240         }
241
242         v = nfc_reg_read(NAND_CONFIGURATION1_REG);
243
244         if (mode == FDO_SPARE_ONLY) {
245                 v = (v & ~0x71) | buf_no | NAND_CONFIGURATION1_SP_EN;
246         } else {
247                 v = (v & ~0x71) | buf_no;
248         }
249
250         nfc_reg_write(v, NAND_CONFIGURATION1_REG);
251
252         nfc_reg_write(mode & 0xFF, NAND_LAUNCH_REG);
253         wait_op_done();
254 }
255
256 static void NFC_CMD_INPUT(u32 cmd)
257 {
258         nfc_reg_write(cmd & 0xFFFF, NAND_CMD_REG);
259         nfc_reg_write(NAND_LAUNCH_FCMD, NAND_LAUNCH_REG);
260         wait_op_done();
261 }
262
263 static void NFC_SET_NFC_ACTIVE_CS(u32 cs_line)
264 {
265         u32 v;
266
267         v = nfc_reg_read(NAND_CONFIGURATION1_REG) & ~0x7071;
268         v |= (cs_line << 12);
269         nfc_reg_write(v, NAND_CONFIGURATION1_REG);
270 }
271
272 #ifdef IMX51_TO_2
273 static inline u16 NFC_STATUS_READ(void)
274 {
275         u16 val = nfc_reg_read(NAND_STATUS_SUM_REG);
276
277         if (val != 0) {
278                 diag_printf("NFC STATUS: %04x\n", val);
279         }
280         return val;
281 }
282 #else
283 static inline u16 NFC_STATUS_READ(void)
284 {
285         u32 status;
286         int i;
287         u16 status_sum = 0;
288
289         /* Cannot rely on STATUS_SUM register due to errata */
290         for (i = 0; i < num_of_nand_chips; i++) {
291                 NFC_SET_NFC_ACTIVE_CS(i);
292                 do {
293                         nfc_reg_write(NAND_LAUNCH_AUTO_STAT, NAND_LAUNCH_REG);
294                         status = (nfc_reg_read(NAND_CONFIGURATION1_REG) & 0x00FF0000) >> 16;
295                 } while ((status & 0x40) == 0); // make sure I/O 6 == 1
296                 /* Get Pass/Fail status */
297                 status = (nfc_reg_read(NAND_CONFIGURATION1_REG) >> 16) & 0x1;
298                 status_sum |= (status << i);
299         }
300         diag_printf("NFC TO2 STATUS: %04x\n", status_sum);
301         return status_sum;
302 }
303 #endif
304
305 /* This function uses a global variable for the page size. It shouldn't be a big
306  * problem since we don't expect mixed page size nand flash parts on the same IC.
307  * Note for address 0, it will always be correct regardless the page size. So for
308  * ID read, it doesn't need to have the correct page size global variable first.
309  */
310 static void start_nfc_addr_ops(u32 ops, u32 pg_no, u16 pg_off, u32 is_erase, u32 cs_line, u32 num_of_chips)
311 {
312         u32 add0, add8, page_number;
313         int num_of_bits[] = {0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4};
314
315         if (ops == FLASH_Read_ID) {
316                 // issue addr cycle
317                 nfc_reg_write(0x0, NAND_ADD0_REG + (4 * cs_line));
318                 nfc_reg_write(NAND_LAUNCH_FADD, NAND_LAUNCH_REG);
319                 wait_op_done();
320                 return;
321         }
322
323         if (num_of_chips >  1) {
324                 page_number = (pg_no << num_of_bits[num_of_chips]) | (cs_line & (num_of_chips - 1));
325         } else {
326                 page_number = pg_no;
327         }
328         if (is_erase) {
329                 add0 = page_number;
330                 add8 = 0;
331         } else {
332                 // for both read and write
333                 if (g_is_2k_page || g_is_4k_page) {
334                         // the first two addr cycles are for column addr. Page number starts
335                         // from the 3rd addr cycle.
336                         add0 = pg_off | (page_number << 16);
337                         add8 = page_number >> 16;
338                 } else {
339                         // For 512B page, the first addr cycle is for column addr. Page number
340                         // starts from the 2nd addr cycle.
341                         add0 = (pg_off & 0xFF) | (page_number << 8);
342                         add8 = page_number >> 24;
343                 }
344         }
345         nfc_reg_write(add0, NAND_ADD0_REG);
346         nfc_reg_write(add8, NAND_ADD8_REG);
347 }
348
349 /*!
350  * The NFC has to be preset before performing any operation
351  */
352 static void NFC_PRESET(u32 max_block_count)
353 {
354         // not needed. It is done in plf_hardware_init()
355 }
356 #endif // _MXC_NFC_V3_H_