]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/flash/arm/mxc/v2_0/include/mxc_nfc_v2.h
Initial revision
[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 NFC_DEBUG_MIN   1
59 #define NFC_DEBUG_MED   2
60 #define NFC_DEBUG_MAX   3
61 #define NFC_DEBUG_DEF   NFC_DEBUG_MED
62
63 #define PG_2K_DATA_OP_MULTI_CYCLES()        false
64
65 typedef unsigned short u16;
66 typedef unsigned int u32;
67 typedef unsigned char u8;
68
69 #define ADDR_INPUT_SIZE                 8
70 //----------------------------------------------------------------------------
71 // Common device details.
72 #define FLASH_Read_ID                   (0x90)
73 #if CYGHWR_DEVS_FLASH_MXC_NAND_RESET_WORKAROUND
74 #define FLASH_Reset                     0xFFFF
75 #else
76 #define FLASH_Reset                     (0xFF)
77 #endif
78 #define FLASH_Read_Mode1                (0x00)
79 #define FLASH_Read_Mode1_2K             (0x30)
80 #define FLASH_Read_Mode2                (0x01)
81 #define FLASH_Read_Mode3                (0x50)
82 #define FLASH_Program                   (0x10)
83 #define FLASH_Send_Data                 (0x80)
84 #define FLASH_Status                    (0x70)
85 #define FLASH_Block_Erase               (0x60)
86 #define FLASH_Start_Erase               (0xD0)
87
88 #define NAND_MAIN_BUF0                  (NFC_BASE + 0x000)
89 #define NAND_MAIN_BUF1                  (NFC_BASE + 0x200)
90 #define NAND_MAIN_BUF2                  (NFC_BASE + 0x400)
91 #define NAND_MAIN_BUF3                  (NFC_BASE + 0x600)
92 #define NAND_SPAR_BUF0                  (NFC_BASE + 0x800)
93 #define NAND_SPAR_BUF1                  (NFC_BASE + 0x810)
94 #define NAND_SPAR_BUF2                  (NFC_BASE + 0x820)
95 #define NAND_SPAR_BUF3                  (NFC_BASE + 0x830)
96 #define NAND_RESERVED                   (NFC_BASE + 0x840)
97
98 #define NFC_BUFSIZE_REG                 (NAND_REG_BASE + 0x00)
99 #define RAM_BUFFER_ADDRESS_REG          (NAND_REG_BASE + 0x04)
100 #define NAND_FLASH_ADD_REG              (NAND_REG_BASE + 0x06)
101 #define NAND_FLASH_CMD_REG              (NAND_REG_BASE + 0x08)
102 #define NFC_CONFIGURATION_REG           (NAND_REG_BASE + 0x0A)
103 #define ECC_STATUS_RESULT_REG           (NAND_REG_BASE + 0x0C)
104 #define ECC_RSLT_MAIN_AREA_REG          (NAND_REG_BASE + 0x0E)
105 #define ECC_RSLT_SPARE_AREA_REG         (NAND_REG_BASE + 0x10)
106 #define NF_WR_PROT_REG                  (NAND_REG_BASE + 0x12)
107 #define UNLOCK_START_BLK_ADD_REG        (NAND_REG_BASE + 0x14)
108 #define UNLOCK_END_BLK_ADD_REG          (NAND_REG_BASE + 0x16)
109 #define NAND_FLASH_WR_PR_ST_REG         (NAND_REG_BASE + 0x18)
110 #define NAND_FLASH_CONFIG1_REG          (NAND_REG_BASE + 0x1A)
111 #define NAND_FLASH_CONFIG2_REG          (NAND_REG_BASE + 0x1C)
112
113 enum nfc_internal_buf {
114     RAM_BUF_0 = 0x0 << 4,
115     RAM_BUF_1 = 0x1 << 4,
116     RAM_BUF_2 = 0x2 << 4,
117     RAM_BUF_3 = 0x3 << 4,
118 };
119
120 enum nfc_output_mode {
121     FDO_PAGE_SPARE      = 0x0008,
122     FDO_SPARE_ONLY      = 0x1008,  // LSB has to be 0x08
123     FDO_FLASH_ID        = 0x0010,
124     FDO_FLASH_STATUS    = 0x0020,
125 };
126
127 /*!
128  * Defined the "complete" address input operations which may involve
129  * more than one cycle of single address input operation.
130  */
131 enum nfc_addr_ops {
132     ADDRESS_INPUT_READ_ID,
133     ADDRESS_INPUT_READ_PAGE,
134     ADDRESS_INPUT_PROGRAM_PAGE,
135     ADDRESS_INPUT_ERASE_BLOCK,
136 };
137
138 enum nfc_page_area {
139     NFC_SPARE_ONLY,
140     NFC_MAIN_ONLY,
141 };
142
143 enum {
144     MXC_NAND_8_BIT = 8,
145     MXC_NAND_16_BIT =  16,
146 };
147
148 enum {
149     NAND_SLC = 0,
150     NAND_MLC = 1,
151 };
152
153 // read column 464-465 byte but only 464 for bad block marker
154 #define BAD_BLK_MARKER_464          (NAND_MAIN_BUF3 + 464)
155 // read column 4-5 byte, but only 5 is used for swapped main area data
156 #define BAD_BLK_MARKER_SP_5         (NAND_SPAR_BUF3 + 4)
157
158 // Polls the NANDFC to wait for an operation to complete
159 #define wait_op_done()                                                              \
160     do {                                                                            \
161         volatile int mxc_nfc_wait_loop;                                                      \
162         while ((readl(NFC_IPC_REG) & NFC_IPC_INT) == 0)  \
163             {for (mxc_nfc_wait_loop = 0; mxc_nfc_wait_loop < 100; mxc_nfc_wait_loop++);} \
164         write_nfc_ip_reg(0, NFC_IPC_REG); \
165     } while (0)
166
167 int nfc_read_region(u32 la, u32 maddr, int len);
168 int nfc_program_region(u32 la, u32 maddr, int len);
169 int nfc_erase_region(u32 la, int len);
170
171 static void write_nfc_ip_reg(u32 val, u32 reg)
172 {
173     volatile int mxc_nfc_wait_loop;
174
175     writel(NFC_IPC_CREQ, NFC_IPC_REG);
176     for (mxc_nfc_wait_loop = 0; mxc_nfc_wait_loop < 100; mxc_nfc_wait_loop++);
177     
178     writel(val, reg);
179     writel(0, NFC_IPC_REG);
180 }
181
182 /*!
183  * NAND flash data output operation (reading data from NAND flash)
184  * @param buf_no    internal ram buffer number that will contain data
185  *                  to be outputted from the NAND flash after operation done
186  * @param mode      one of the mode defined in enum nfc_output_mode
187  * @param ecc_en    1 - ecc enabled; 0 - ecc disabled
188  */
189 static void NFC_DATA_OUTPUT(enum nfc_internal_buf buf_no, enum nfc_output_mode mode,
190                             int ecc_en)
191 {
192     u32 v = readl(NFC_FLASH_CONFIG2_REG);
193
194     if ((v & NFC_FLASH_CONFIG2_ECC_EN) != 0 && ecc_en == 0) {
195         write_nfc_ip_reg(v & ~NFC_FLASH_CONFIG2_ECC_EN, NFC_FLASH_CONFIG2_REG);
196     }
197     if ((v & NFC_FLASH_CONFIG2_ECC_EN) == 0 && ecc_en != 0) {
198         write_nfc_ip_reg(v | NFC_FLASH_CONFIG2_ECC_EN, NFC_FLASH_CONFIG2_REG);
199     }
200
201     v = readl(NAND_CONFIGURATION1_REG);
202
203     if (mode == FDO_SPARE_ONLY) {
204         v = (v & ~0x31) | buf_no | NAND_CONFIGURATION1_SP_EN;
205     } else {
206         v = (v & ~0x31) | buf_no;
207     }
208
209     writel(v, NAND_CONFIGURATION1_REG);
210     
211     writel(mode & 0xFF, NAND_LAUNCH_REG);
212     wait_op_done();
213 }
214
215 static void NFC_CMD_INPUT(u32 cmd)
216 {
217     writel(cmd & 0xFFFF, NAND_ADD_CMD_REG);
218     writel(NAND_LAUNCH_FCMD, NAND_LAUNCH_REG);
219     wait_op_done();
220 }
221
222 static u16 NFC_STATUS_READ(void)
223 {
224     u16 flash_status;
225     u16 saved = readw(NAND_MAIN_BUF0);
226
227     NFC_CMD_INPUT(FLASH_Status);
228     NFC_DATA_OUTPUT(RAM_BUF_0, FDO_FLASH_STATUS, 1);
229     flash_status = readw(NAND_MAIN_BUF0) & 0x00FF;
230
231     // restore
232     writew(saved, NAND_MAIN_BUF0); 
233
234     return flash_status;
235 }
236
237 /*!
238  * NAND flash data input operation (writing data to NAND flash)
239  * @param buf_no    internal ram buffer number containing data to be
240  *                  written into the NAND flash
241  * @param area      NFC_SPARE_ONLY or NFC_MAIN_ONLY,
242  * @param ecc_en    1 - ecc enabled; 0 - ecc disabled
243  */
244 static void NFC_DATA_INPUT(enum nfc_internal_buf buf_no, enum nfc_page_area area,
245                            int ecc_en)
246 {
247     u32 v = readl(NFC_FLASH_CONFIG2_REG);
248
249     // setup config2 register for ECC enable or not
250     if ((v & NFC_FLASH_CONFIG2_ECC_EN) != 0 && ecc_en == 0) {
251         write_nfc_ip_reg(v & ~NFC_FLASH_CONFIG2_ECC_EN, NFC_FLASH_CONFIG2_REG);
252     }
253     if ((v & NFC_FLASH_CONFIG2_ECC_EN) == 0 && ecc_en != 0) {
254         write_nfc_ip_reg(v | NFC_FLASH_CONFIG2_ECC_EN, NFC_FLASH_CONFIG2_REG);
255     }
256
257     // setup config1 register for ram buffer number, spare-only or not
258     v = readl(NAND_CONFIGURATION1_REG);
259
260     if (area == NFC_SPARE_ONLY) {
261         v = (v & ~0x31) | buf_no | NAND_CONFIGURATION1_SP_EN;
262     } else {
263         v = (v & ~0x31) | buf_no;
264     }
265
266     writel(v, NAND_CONFIGURATION1_REG);
267
268     // start operation
269     writel(NAND_LAUNCH_FDI, NAND_LAUNCH_REG);
270     wait_op_done();
271 }
272
273 static void NFC_DATA_INPUT_2k(enum nfc_internal_buf buf_no)
274 {
275     u32 v;
276
277     // setup config1 register for ram buffer number, spare-only or not
278     v = readl(NAND_CONFIGURATION1_REG);
279     v = (v & ~0x30) | buf_no;
280     writel(v, NAND_CONFIGURATION1_REG);
281
282     // start operation
283     writel(NAND_LAUNCH_FDI, NAND_LAUNCH_REG);
284     wait_op_done();
285 }
286
287 /*!
288  * The NFC has to be preset before performing any operation
289  */
290 static void NFC_PRESET(u32 max_block_count)
291 {
292     // not needed. It is done in plf_hardware_init()
293 }
294
295 /*!
296  * Issue the address input operation
297  * @param       addr    the address for the address input operation
298  */
299 static void NFC_ADDR_INPUT(u32 addr)
300 {
301     writel((addr & ((1 << ADDR_INPUT_SIZE) - 1)) << 16, NAND_ADD_CMD_REG);
302     writel(NAND_LAUNCH_FADD, NAND_LAUNCH_REG);
303     wait_op_done();
304 }
305
306 #endif // _MXC_NFC_V2_H_