unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / devs / flash / arm / mxc / v2_0 / include / mxc_nfc_v2.h
1 #ifndef _MXC_NFC_V2_H_
2 #define _MXC_NFC_V2_H_
3 //==========================================================================
4 //
5 //      mxc_nfc_v2.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:         2006-01-23
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
60 //----------------------------------------------------------------------------
61 // Common device details.
62 #define NAND_MAIN_BUF0                                  (NFC_BASE + 0x000)
63 #define NAND_MAIN_BUF1                                  (NFC_BASE + 0x200)
64 #define NAND_MAIN_BUF2                                  (NFC_BASE + 0x400)
65 #define NAND_MAIN_BUF3                                  (NFC_BASE + 0x600)
66 #if defined (NFC_V2_0)
67 #define NAND_SPAR_BUF0                                  (NFC_BASE + 0x800)
68 #define NAND_SPAR_BUF1                                  (NFC_BASE + 0x810)
69 #define NAND_SPAR_BUF2                                  (NFC_BASE + 0x820)
70 #define NAND_SPAR_BUF3                                  (NFC_BASE + 0x830)
71 #define NAND_RESERVED                                   (NFC_BASE + 0x840)
72 #define NFC_BUF_COUNT                                   4
73 #define NFC_SPARE_BUF_SZ                                16
74 #elif defined (NFC_V2_1)
75 #define NAND_MAIN_BUF4                                  (NFC_BASE + 0x800)
76 #define NAND_MAIN_BUF5                                  (NFC_BASE + 0xA00)
77 #define NAND_MAIN_BUF6                                  (NFC_BASE + 0xC00)
78 #define NAND_MAIN_BUF7                                  (NFC_BASE + 0xE00)
79 #define NAND_SPAR_BUF0                                  (NFC_BASE + 0x1000)
80 #define NAND_SPAR_BUF1                                  (NFC_BASE + 0x1040)
81 #define NAND_SPAR_BUF2                                  (NFC_BASE + 0x1080)
82 #define NAND_SPAR_BUF3                                  (NFC_BASE + 0x10C0)
83 #define NAND_SPAR_BUF4                                  (NFC_BASE + 0x1100)
84 #define NAND_SPAR_BUF5                                  (NFC_BASE + 0x1140)
85 #define NAND_SPAR_BUF6                                  (NFC_BASE + 0x1180)
86 #define NAND_SPAR_BUF7                                  (NFC_BASE + 0x11C0)
87 #define NFC_BUF_COUNT                                   8
88 #define NFC_SPARE_BUF_SZ                                64
89 #else
90 #error NOT supported
91 #endif
92
93 #define ECC_STATUS_RESULT_REG                   (NAND_REG_BASE + 0x08)
94 #define NUM_OF_CS_LINES                                 1
95 #define NFC_BUFSIZE                                             0
96
97 #define NFC_PPB_REG                                             NAND_CONFIGURATION2_REG
98 #define NFC_PPB_SHIFT                                   7
99 #define NFC_PPB_MASK                                    ~(3 << NFC_PPB_SHIFT)
100
101 enum nfc_internal_buf {
102         RAM_BUF_0 = 0x0 << 4,
103         RAM_BUF_1 = 0x1 << 4,
104         RAM_BUF_2 = 0x2 << 4,
105         RAM_BUF_3 = 0x3 << 4,
106         RAM_BUF_4 = 0x4 << 4,
107         RAM_BUF_5 = 0x5 << 4,
108         RAM_BUF_6 = 0x6 << 4,
109         RAM_BUF_7 = 0x7 << 4,
110         RAM_BUF_MASK = ~(0x7 << 4),
111 };
112
113 enum nfc_output_mode {
114         FDO_PAGE_SPARE      = 0x0008,
115         FDO_SPARE_ONLY      = 0x1008,  // LSB has to be 0x08
116         FDO_FLASH_ID        = 0x0010,
117         FDO_FLASH_STATUS    = 0x0020,
118 };
119
120 #define wait_for_auto_prog_done()
121
122 // Polls the NANDFC to wait for an operation to complete
123 #define wait_op_done() CYG_MACRO_START                          \
124         u32 __nfc_stat = nfc_reg_read(NFC_IPC_REG);             \
125         while (!(__nfc_stat & NFC_IPC_INT)) {                   \
126                 __nfc_stat = nfc_reg_read(NFC_IPC_REG);         \
127         }                                                                                               \
128         nfc_reg_write(__nfc_stat & ~NFC_IPC_INT, NFC_IPC_REG);  \
129 CYG_MACRO_END
130
131 #if 1
132 #define nfc_reg_write(v, r)             __nfc_reg_write(v, (void *)(r), #r, __FUNCTION__)
133 static inline void __nfc_reg_write(u32 val, void *addr,
134                                                                    const char *reg, const char *fn)
135 {
136         nfc_printf(NFC_DEBUG_MAX, "%s: Writing %08x to %s[%04lx]\n", fn, val, reg,
137                            (unsigned long)addr & 0x3fff);
138         writel(val, addr);
139 }
140
141 #define nfc_reg_read(r)         __nfc_reg_read((void *)(r), #r, __FUNCTION__)
142 static inline u32 __nfc_reg_read(void *addr,
143                                                                  const char *reg, const char *fn)
144 {
145         u32 val;
146         val = readl(addr);
147         nfc_printf(NFC_DEBUG_MAX, "%s: Read %08x from %s[%04lx]\n", fn, val, reg,
148                            (unsigned long)addr & 0x3fff);
149         return val;
150 }
151
152 #define write_nfc_ip_reg(v, r) CYG_MACRO_START                          \
153         nfc_reg_write(NFC_IPC_CREQ, NFC_IPC_REG);                               \
154         while (!(nfc_reg_read(NFC_IPC_REG) & NFC_IPC_CACK));    \
155         __nfc_reg_write(v, (void *)(r), #r, __FUNCTION__);              \
156         nfc_reg_write(0, NFC_IPC_REG);                                                  \
157 CYG_MACRO_END
158 #else
159 #define nfc_reg_read(r)                 readl(r)
160 #define nfc_reg_write(v, r)             writel(v, r)
161
162 static void write_nfc_ip_reg(u32 val, u32 reg)
163 {
164         nfc_reg_write(NFC_IPC_CREQ, NFC_IPC_REG);
165         while (!(nfc_reg_read(NFC_IPC_REG) & NFC_IPC_CACK));
166         nfc_reg_write(val, reg);
167         nfc_reg_write(0, NFC_IPC_REG);
168 }
169 #endif
170
171 /*!
172  * NAND flash data output operation (reading data from NAND flash)
173  * @param buf_no        internal ram buffer number that will contain data
174  *                                      to be outputted from the NAND flash after operation done
175  * @param mode          one of the mode defined in enum nfc_output_mode
176  * @param ecc_en        1 - ecc enabled; 0 - ecc disabled
177  */
178 static void NFC_DATA_OUTPUT(enum nfc_internal_buf buf_no, enum nfc_output_mode mode,
179                                                         int ecc_en)
180 {
181         u32 v = nfc_reg_read(NFC_FLASH_CONFIG2_REG);
182
183         if ((v & NFC_FLASH_CONFIG2_ECC_EN) != 0 && ecc_en == 0) {
184                 write_nfc_ip_reg(v & ~NFC_FLASH_CONFIG2_ECC_EN, NFC_FLASH_CONFIG2_REG);
185         }
186         if ((v & NFC_FLASH_CONFIG2_ECC_EN) == 0 && ecc_en != 0) {
187                 write_nfc_ip_reg(v | NFC_FLASH_CONFIG2_ECC_EN, NFC_FLASH_CONFIG2_REG);
188         }
189
190         v = (nfc_reg_read(NAND_CONFIGURATION1_REG) & RAM_BUF_MASK) | buf_no;
191         if (mode == FDO_SPARE_ONLY) {
192                 v |= NAND_CONFIGURATION1_SP_EN;
193         } else {
194                 v &= ~NAND_CONFIGURATION1_SP_EN;
195         }
196         nfc_reg_write(v, NAND_CONFIGURATION1_REG);
197
198         nfc_reg_write(mode & 0xFF, NAND_LAUNCH_REG);
199         wait_op_done();
200 }
201
202 static void NFC_CMD_INPUT(u32 cmd)
203 {
204         nfc_reg_write(cmd & 0xFFFF, NAND_ADD_CMD_REG);
205         nfc_reg_write(NAND_LAUNCH_FCMD, NAND_LAUNCH_REG);
206         wait_op_done();
207 }
208
209 static u16 NFC_STATUS_READ(void)
210 {
211         u16 flash_status;
212         u16 saved = readw(NAND_MAIN_BUF0);
213
214         NFC_CMD_INPUT(FLASH_Status);
215         NFC_DATA_OUTPUT(RAM_BUF_0, FDO_FLASH_STATUS, 1);
216         flash_status = readw(NAND_MAIN_BUF0) & 0x00FF;
217
218         // restore
219         writew(saved, NAND_MAIN_BUF0);
220
221         return flash_status;
222 }
223
224 /*!
225  * NAND flash data input operation (writing data to NAND flash)
226  * @param buf_no        internal ram buffer number containing data to be
227  *                                      written into the NAND flash
228  * @param area          NFC_SPARE_ONLY or NFC_MAIN_ONLY,
229  * @param ecc_en        1 - ecc enabled; 0 - ecc disabled
230  */
231 static void NFC_DATA_INPUT(enum nfc_internal_buf buf_no, enum nfc_page_area area,
232                            int ecc_en)
233 {
234         u32 v = nfc_reg_read(NFC_FLASH_CONFIG2_REG);
235
236         // setup config2 register for ECC enable or not
237         if ((v & NFC_FLASH_CONFIG2_ECC_EN) != 0 && ecc_en == 0) {
238                 write_nfc_ip_reg(v & ~NFC_FLASH_CONFIG2_ECC_EN, NFC_FLASH_CONFIG2_REG);
239         }
240         if ((v & NFC_FLASH_CONFIG2_ECC_EN) == 0 && ecc_en != 0) {
241                 write_nfc_ip_reg(v | NFC_FLASH_CONFIG2_ECC_EN, NFC_FLASH_CONFIG2_REG);
242         }
243
244         // setup config1 register for ram buffer number, spare-only or not
245         v = (nfc_reg_read(NAND_CONFIGURATION1_REG) & RAM_BUF_MASK) | buf_no;
246         if (area == NFC_SPARE_ONLY) {
247                 v |= NAND_CONFIGURATION1_SP_EN;
248         } else {
249                 v &= ~NAND_CONFIGURATION1_SP_EN;
250         }
251         nfc_reg_write(v, NAND_CONFIGURATION1_REG);
252
253         // start operation
254         nfc_reg_write(NAND_LAUNCH_FDI, NAND_LAUNCH_REG);
255         wait_op_done();
256 }
257
258 static void NFC_DATA_INPUT_2k(enum nfc_internal_buf buf_no)
259 {
260         u32 v;
261
262         // setup config1 register for ram buffer number, spare-only or not
263         v = (nfc_reg_read(NAND_CONFIGURATION1_REG) & RAM_BUF_MASK) | buf_no;
264         nfc_reg_write(v, NAND_CONFIGURATION1_REG);
265
266         // start operation
267         nfc_reg_write(NAND_LAUNCH_FDI, NAND_LAUNCH_REG);
268         wait_op_done();
269 }
270
271 /*!
272  * The NFC has to be preset before performing any operation
273  */
274 static void NFC_PRESET(u32 max_block_count)
275 {
276         // not needed. It is done in plf_hardware_init()
277 }
278
279 static void NFC_SET_NFC_ACTIVE_CS(u32 cs_line)
280 {
281         // not needed.
282 }
283
284 /*!
285  * Issue the address input operation
286  * @param               addr    the address for the address input operation
287  */
288 static void NFC_ADDR_INPUT(u32 addr)
289 {
290 #if 0
291         if (nfc_debug) {
292                 diag_printf("add = 0x%08x, at 0x%08lx\n",
293                                         (addr & 0xFF) << 16, NAND_ADD_CMD_REG);
294                 diag_printf("NAND_LAUNCH_FADD=%08x, NAND_LAUNCH_REG=%08lx\n",
295                                         NAND_LAUNCH_FADD, NAND_LAUNCH_REG);
296         }
297 #endif
298         nfc_reg_write((addr & 0xFF) << 16, NAND_ADD_CMD_REG);
299         nfc_reg_write(NAND_LAUNCH_FADD, NAND_LAUNCH_REG);
300         wait_op_done();
301 }
302
303 #define NFC_ARCH_INIT()
304 #define NAND_ADD0_REG                           0xDEADDAED
305 #define NAND_ADD8_REG                           0xDEADDAED
306 #define NAND_CMD_REG                            0xDEADDAED
307 #define NAND_LAUNCH_AUTO_PROG           0xDEADDAED
308 #define NAND_STATUS_SUM_REG                     0xDEADDAED
309 #define NAND_LAUNCH_AUTO_READ           0xDEADDAED
310 #define NAND_LAUNCH_AUTO_ERASE          0xDEADDAED
311 #endif // _MXC_NFC_V2_H_