]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/flash/arm/mxc/v2_0/include/mxc_nfc_v3.h
unified MX27, MX25, MX37 trees
[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
88 enum nfc_internal_buf {
89     RAM_BUF_0 = 0x0 << 4,
90     RAM_BUF_1 = 0x1 << 4,
91     RAM_BUF_2 = 0x2 << 4,
92     RAM_BUF_3 = 0x3 << 4,
93     RAM_BUF_4 = 0x4 << 4,
94     RAM_BUF_5 = 0x5 << 4,
95     RAM_BUF_6 = 0x6 << 4,
96     RAM_BUF_7 = 0x7 << 4,
97 };
98
99 enum nfc_output_mode {
100     FDO_PAGE_SPARE      = 0x0008,
101     FDO_SPARE_ONLY      = 0x1008,  // LSB has to be 0x08
102     FDO_FLASH_ID        = 0x0010,
103     FDO_FLASH_STATUS    = 0x0020,
104 };
105
106 #define wait_for_auto_prog_done()                                                                                                                       \
107         do {                                                                                                                                                                    \
108                 while ((nfc_reg_read(NFC_IPC_REG) & NFC_IPC_AUTO_DONE) == 0) {                                          \
109                 }                                                                                                                                                                       \
110                 write_nfc_ip_reg((nfc_reg_read(NFC_IPC_REG) & ~NFC_IPC_AUTO_DONE), NFC_IPC_REG);        \
111         } while (0)
112
113 // Polls the NANDFC to wait for an operation to complete
114 #define wait_op_done()                                                                                  \
115         do {                                                                                                            \
116                 while ((nfc_reg_read(NFC_IPC_REG) & NFC_IPC_INT) == 0)  \
117                         {}                                                                                                      \
118                 write_nfc_ip_reg(0, NFC_IPC_REG);                                               \
119         } while (0)
120
121 #if 0
122 #define nfc_reg_write(v, r)             __nfc_reg_write(v, (void *)(r), #r, __FUNCTION__)
123 static inline void __nfc_reg_write(u32 val, void *addr,
124                                                                    const char *reg, const char *fn)
125 {
126         diag_printf1("%s: Writing %08x to %s[%04lx]\n", fn, val, reg,
127                                  (unsigned long)addr & 0x1fff);
128         writel(val, addr);
129 }
130
131 #define nfc_reg_read(r)         __nfc_reg_read((void *)(r), #r, __FUNCTION__)
132 static inline u32 __nfc_reg_read(void *addr,
133                                                                  const char *reg, const char *fn)
134 {
135         u32 val;
136         val = readl(addr);
137         diag_printf1("%s: Read %08x from %s[%04lx]\n", fn, val, reg,
138                                  (unsigned long)addr & 0x1fff);
139         return val;
140 }
141 #else
142 #define nfc_reg_read(r)                 readl(r)
143 #define nfc_reg_write(v, r)             writel(v, r)
144 #endif
145
146 static void write_nfc_ip_reg(u32 val, u32 reg)
147 {
148     nfc_reg_write(NFC_IPC_CREQ, NFC_IPC_REG);
149     while((nfc_reg_read(NFC_IPC_REG) & NFC_IPC_CACK) == 0);
150
151     nfc_reg_write(val, reg);
152     nfc_reg_write((nfc_reg_read(NFC_IPC_REG) & ~NFC_IPC_CREQ), NFC_IPC_REG);
153 }
154
155 /*!
156  * NAND flash data output operation (reading data from NAND flash)
157  * @param buf_no    internal ram buffer number that will contain data
158  *                  to be outputted from the NAND flash after operation done
159  * @param mode      one of the mode defined in enum nfc_output_mode
160  * @param ecc_en    1 - ecc enabled; 0 - ecc disabled
161  */
162 static void NFC_DATA_OUTPUT(enum nfc_internal_buf buf_no, enum nfc_output_mode mode,
163                             int ecc_en)
164 {
165     u32 v = nfc_reg_read(NFC_FLASH_CONFIG2_REG);
166
167     if ((v & NFC_FLASH_CONFIG2_ECC_EN) != 0 && ecc_en == 0) {
168         write_nfc_ip_reg(v & ~NFC_FLASH_CONFIG2_ECC_EN, NFC_FLASH_CONFIG2_REG);
169     }
170     if ((v & NFC_FLASH_CONFIG2_ECC_EN) == 0 && ecc_en != 0) {
171         write_nfc_ip_reg(v | NFC_FLASH_CONFIG2_ECC_EN, NFC_FLASH_CONFIG2_REG);
172     }
173
174     v = nfc_reg_read(NAND_CONFIGURATION1_REG);
175
176     if (mode == FDO_SPARE_ONLY) {
177         v = (v & ~0x71) | buf_no | NAND_CONFIGURATION1_SP_EN;
178     } else {
179         v = (v & ~0x71) | buf_no;
180     }
181
182     nfc_reg_write(v, NAND_CONFIGURATION1_REG);
183
184     nfc_reg_write(mode & 0xFF, NAND_LAUNCH_REG);
185     wait_op_done();
186 }
187
188 static void NFC_CMD_INPUT(u32 cmd)
189 {
190     nfc_reg_write(cmd & 0xFFFF, NAND_CMD_REG);
191     nfc_reg_write(NAND_LAUNCH_FCMD, NAND_LAUNCH_REG);
192     wait_op_done();
193 }
194
195 static void NFC_SET_NFC_ACTIVE_CS(u32 cs_line)
196 {
197     u32 v;
198
199     v = nfc_reg_read(NAND_CONFIGURATION1_REG) & (~0x7071);
200     v |= (cs_line << 12);
201     nfc_reg_write(v, NAND_CONFIGURATION1_REG);
202 }
203
204 static u16 NFC_STATUS_READ(void)
205 {
206     u32 status;
207     u16 status_sum = 0;
208     int i;
209
210 #ifdef IMX51_TO_2
211     return nfc_reg_read(NAND_STATUS_SUM_REG);
212 #else
213     /* Cannot rely on STATUS_SUM register due to errata */
214     for (i = 0; i < num_of_nand_chips; i++) {
215         NFC_SET_NFC_ACTIVE_CS(i);
216         do {
217             nfc_reg_write(NAND_LAUNCH_AUTO_STAT, NAND_LAUNCH_REG);
218             status = (nfc_reg_read(NAND_CONFIGURATION1_REG) & 0x00FF0000) >> 16;
219         } while ((status & 0x40) == 0); // make sure I/O 6 == 1
220         /* Get Pass/Fail status */
221         status = (nfc_reg_read(NAND_CONFIGURATION1_REG) >> 16) & 0x1;
222         status_sum |= (status << i);
223     }
224     return status_sum;
225 #endif
226 }
227
228 /* This function uses a global variable for the page size. It shouldn't be a big
229  * problem since we don't expect mixed page size nand flash parts on the same IC.
230  * Note for address 0, it will always be correct regardless the page size. So for
231  * ID read, it doesn't need to have the correct page size global variable first.
232  */
233 static void start_nfc_addr_ops(u32 ops, u32 pg_no, u16 pg_off, u32 is_erase, u32 cs_line, u32 num_of_chips)
234 {
235     u32 add0, add8, page_number;
236     int num_of_bits[] = {0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4};
237
238     if (ops == FLASH_Read_ID) {
239         // issue addr cycle
240         nfc_reg_write(0x0, NAND_ADD0_REG + (4 * cs_line));
241         nfc_reg_write(NAND_LAUNCH_FADD, NAND_LAUNCH_REG);
242         wait_op_done();
243         return;
244     }
245
246     if (num_of_chips >  1) {
247         page_number = (pg_no << num_of_bits[num_of_chips]) | (cs_line & (num_of_chips - 1));
248     } else {
249         page_number = pg_no;
250     }
251     if (is_erase) {
252         add0 = page_number;
253         add8 = 0;
254     } else {
255         // for both read and write
256         if (g_is_2k_page || g_is_4k_page) {
257             // the first two addr cycles are for column addr. Page number starts
258             // from the 3rd addr cycle.
259             add0 = pg_off | (page_number << 16);
260             add8 = page_number >> 16;
261         } else {
262             diag_printf("too bad, die\n");
263             asm("1: b 1b");
264             // For 512B page, the first addr cycle is for column addr. Page number
265             // starts from the 2nd addr cycle.
266             add0 = (pg_off & 0xFF) | (page_number << 8);
267             add8 = page_number >> 24;
268         }
269     }
270     nfc_reg_write(add0, NAND_ADD0_REG);
271     nfc_reg_write(add8, NAND_ADD8_REG);
272 }
273
274 /*
275  * Do a page read at random address
276  *
277  * @param pg_no             page number offset from 0
278  * @param pg_off             byte offset within the page
279  * @param ecc_force        can force ecc to be off. Otherwise, by default it is on
280  *                                    unless the page offset is non-zero
281  * @param cs_line            indicates which NAND of interleaved NAND devices is used
282  *
283  * @return  0 if successful; non-zero otherwise
284  */
285 static int nfc_read_pg_random(u32 pg_no, u32 pg_off, u32 ecc_force, u32 cs_line, u32 num_of_chips)
286 {
287     u32 ecc = NFC_FLASH_CONFIG2_ECC_EN;
288     u32 v, res = 0;
289
290     // clear the NAND_STATUS_SUM_REG register
291     nfc_reg_write(0, NAND_STATUS_SUM_REG);
292
293     // the 2nd condition is to test for unaligned page address -- ecc has to be off.
294     if (ecc_force == ECC_FORCE_OFF || pg_off != 0 ) {
295         ecc = 0;
296     }
297
298     // Take care of config1 for RBA and SP_EN
299     v = nfc_reg_read(NAND_CONFIGURATION1_REG) & (~0x71);
300     nfc_reg_write(v, NAND_CONFIGURATION1_REG);
301
302     // For ECC
303     v = nfc_reg_read(NFC_FLASH_CONFIG2_REG) & (~NFC_FLASH_CONFIG2_ECC_EN);
304     // setup config2 register for ECC enable or not
305     write_nfc_ip_reg(v | ecc, NFC_FLASH_CONFIG2_REG);
306
307     start_nfc_addr_ops(FLASH_Read_Mode1, pg_no, pg_off, 0, cs_line, num_of_chips);
308
309     if (g_is_2k_page || g_is_4k_page) {
310         // combine the two commands for 2k/4k page read
311         nfc_reg_write((FLASH_Read_Mode1_LG << 8) | FLASH_Read_Mode1, NAND_CMD_REG);
312     } else {
313         // just one command is enough for 512 page
314         nfc_reg_write(FLASH_Read_Mode1, NAND_CMD_REG);
315     }
316
317     // start auto-read
318     nfc_reg_write(NAND_LAUNCH_AUTO_READ, NAND_LAUNCH_REG);
319     wait_op_done();
320
321     v = nfc_reg_read(NAND_STATUS_SUM_REG);
322     // test for CS0 ECC error from the STATUS_SUM register
323     if ((v & (0x0100 << cs_line)) != 0) {
324         // clear the status
325         nfc_reg_write((0x0100 << cs_line), NAND_STATUS_SUM_REG);
326         diag_printf("ECC error from NAND_STATUS_SUM_REG(0x%x) = 0x%x\n",
327                     NAND_STATUS_SUM_REG, v);
328         diag_printf("NAND_ECC_STATUS_RESULT_REG(0x%x) = 0x%x\n", NAND_ECC_STATUS_RESULT_REG,
329                     nfc_reg_read(NAND_ECC_STATUS_RESULT_REG));
330         res = -1;
331     }
332     return res;
333 }
334
335 /*!
336  * The NFC has to be preset before performing any operation
337  */
338 static void NFC_PRESET(u32 max_block_count)
339 {
340     // not needed. It is done in plf_hardware_init()
341 }
342
343 #endif // _MXC_NFC_V3_H_