1 //==========================================================================
5 // Flash programming for Freescale MX21 ADS board
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //===========================================================================
42 #include <cyg/infra/cyg_type.h>
44 #define CYGNUM_FLASH_INTERLEAVE (2)
45 #define FLASH_SECTOR_SIZE (0x10000*CYGNUM_FLASH_INTERLEAVE) //128KB with 64KB each chip
46 #define FLASH_SMALL_SECTOR_SIZE (0x2000*CYGNUM_FLASH_INTERLEAVE) //16KB with 8KB each chip
47 #define FLASH_SECTOR_NUM (256)
49 #if defined(CYGPKG_HAL_ARM_MDBMX1)
50 #define FLASH_BASE (0x10000000) /* CS0 for MX1 */
51 #elif defined(CYGPKG_HAL_ARM_MX21)
52 #define FLASH_BASE (0xC8000000) /* CS0 for MX2 */
58 # if 1 == CYGNUM_FLASH_INTERLEAVE
59 # define FLASHWORD( k ) (k)
60 typedef cyg_uint16 flash_data_t;
61 # elif 2 == CYGNUM_FLASH_INTERLEAVE
62 // 2 devices to make 32-bit
63 # define FLASHWORD( k ) ((k)+((k)<<16))
64 typedef cyg_uint32 flash_data_t;
66 # error How many 16-bit flash devices?
70 # define FLASH_P2V( _a_ ) ((volatile flash_data_t *)((CYG_ADDRWORD)(_a_)))
71 # define FLASH_P2V_MAPPED(base, offset ) \
72 ((volatile flash_data_t *)((CYG_ADDRWORD)(offset<<CYGNUM_FLASH_INTERLEAVE)+(CYG_ADDRWORD)(base)))
75 #define KBIT0 FLASHWORD(1<<0)
76 #define KBIT1 FLASHWORD(1<<1)
77 #define KBIT2 FLASHWORD(1<<2)
78 #define KBIT3 FLASHWORD(1<<3)
79 #define KBIT4 FLASHWORD(1<<4)
80 #define KBIT5 FLASHWORD(1<<5)
81 #define KBIT6 FLASHWORD(1<<6)
82 #define KBIT7 FLASHWORD(1<<7)
85 #define DRAIN_WRITE_BUFFER() \
89 "mcr p15,0,r0,c7,c10,4;" /* drain the write buffer */ \
92 : "r0" /* Clobber list */ \
96 #define FLASH_RESET() \
98 *FLASH_P2V_MAPPED(FLASH_BASE, 0) = FLASHWORD(0xF0); \
102 * This function does the "2 unlock cycle" commands.
104 #define FLASH_UNLOCK() \
106 *FLASH_P2V_MAPPED(FLASH_BASE, 0x555) = FLASHWORD(0xAA); \
107 *FLASH_P2V_MAPPED(FLASH_BASE, 0x2AA) = FLASHWORD(0x55); \
111 * Setup the 3 cycle command for the autoselect commands based on
114 #define FLASH_AUTO_SEL_SETUP(aSelAddr) \
118 *FLASH_P2V_MAPPED(aSelAddr, 0x555) = FLASHWORD(0x90); \
122 * The manufacturer's ID is in the passed in variable upon return
124 #define FLASH_GET_MANU_ID(aManuId) \
126 FLASH_AUTO_SEL_SETUP(FLASH_BASE); \
127 aManuId = *FLASH_P2V_MAPPED(FLASH_BASE, 0); \
132 * The device IDs are in the variables upon return
134 #define FLASH_GET_DEV_ID(aDevId1, aDevId2, aDevId3) \
136 FLASH_AUTO_SEL_SETUP(FLASH_BASE); \
137 aDevId1 = *FLASH_P2V_MAPPED(FLASH_BASE, 0x01); \
138 aDevId2 = *FLASH_P2V_MAPPED(FLASH_BASE, 0x0E); \
139 aDevId3 = *FLASH_P2V_MAPPED(FLASH_BASE, 0x0F); \
144 * The sector lock status is in the variable upon return
146 #define FLASH_GET_SECTOR_LOCK_VERIFY(aSecAddr, aRtnLock) \
148 FLASH_AUTO_SEL_SETUP(aSecAddr); \
149 aRtnLock = *FLASH_P2V_MAPPED(aSecAddr, 0x02); \
153 * Write aProgData to address aProgAbsAddr as the absolute address
154 * (not address offset)
155 * May require to call reset fucntion before start programming
157 #define FLASH_PROGRAM(aProgAddr, aProgData) \
160 *FLASH_P2V_MAPPED(FLASH_BASE, 0x555) = FLASHWORD(0xA0); \
161 *FLASH_P2V(aProgAddr) = aProgData; \
162 DRAIN_WRITE_BUFFER(); \
165 #define FLASH_CHIP_ERASE() \
168 DRAIN_WRITE_BUFFER(); \
170 DRAIN_WRITE_BUFFER(); \
171 *FLASH_P2V_MAPPED(FLASH_BASE, 0x555) = FLASHWORD(0x80); \
172 DRAIN_WRITE_BUFFER(); \
174 DRAIN_WRITE_BUFFER(); \
175 *FLASH_P2V_MAPPED(FLASH_BASE, 0x555) = FLASHWORD(0x10); \
176 DRAIN_WRITE_BUFFER(); \
178 DRAIN_WRITE_BUFFER(); \
181 #define FLASH_SECTOR_ERASE(aEraseSecAddr, aEraseStatus) \
183 aEraseStatus = FLASH_ERR_OK; \
185 DRAIN_WRITE_BUFFER(); \
186 *FLASH_P2V_MAPPED(FLASH_BASE, 0x555) = FLASHWORD(0xAA); \
187 DRAIN_WRITE_BUFFER(); \
188 *FLASH_P2V_MAPPED(FLASH_BASE, 0x2AA) = FLASHWORD(0x55); \
189 DRAIN_WRITE_BUFFER(); \
190 *FLASH_P2V_MAPPED(FLASH_BASE, 0x555) = FLASHWORD(0x80); \
191 DRAIN_WRITE_BUFFER(); \
192 *FLASH_P2V_MAPPED(FLASH_BASE, 0x555) = FLASHWORD(0xAA); \
193 DRAIN_WRITE_BUFFER(); \
194 *FLASH_P2V_MAPPED(FLASH_BASE, 0x2AA) = FLASHWORD(0x55); \
195 DRAIN_WRITE_BUFFER(); \
196 *FLASH_P2V_MAPPED(aEraseSecAddr, 0x555) = FLASHWORD(0x30); \
197 DRAIN_WRITE_BUFFER(); \
198 while(((*FLASH_P2V_MAPPED(aEraseSecAddr, 0x555)) & KBIT7) != KBIT7) \
200 if(((*FLASH_P2V_MAPPED(aEraseSecAddr, 0x555)) & KBIT5) == KBIT5) \
202 if(((*FLASH_P2V_MAPPED(aEraseSecAddr, 0x555)) & KBIT7) != KBIT7) \
204 aEraseStatus = FLASH_ERR_ERASE; \
210 DRAIN_WRITE_BUFFER(); \
213 #define FLASH_ERASE_SUSPEND(aBankAddrSus) \
215 *FLASH_P2V(aBankAddrSus) = FLASHWORD(0xB0); \
216 DRAIN_WRITE_BUFFER(); \
220 #define FLASH_ERASE_RESUME(aBankAddrRes) \
222 *FLASH_P2V(aBankAddrRes) = FLASHWORD(0x30); \
223 DRAIN_WRITE_BUFFER(); \
228 * Call reset before doing this. When exiting the unlock bypass mode,
229 * FLASH_UB_RESET() has to be called.
231 #define FLASH_UB_ENTRY() \
234 DRAIN_WRITE_BUFFER(); \
236 DRAIN_WRITE_BUFFER(); \
237 *FLASH_P2V_MAPPED(FLASH_BASE, 0x555) = FLASHWORD(0x20); \
238 DRAIN_WRITE_BUFFER(); \
242 #define FLASH_UB_PROGRAM(aUBProgAddr, aUBProgData) \
244 *FLASH_P2V_MAPPED(FLASH_BASE, 0) = FLASHWORD(0xA0); \
245 DRAIN_WRITE_BUFFER(); \
246 *FLASH_P2V(aUBProgAddr) = aUBProgData; \
247 DRAIN_WRITE_BUFFER(); \
250 #define FLASH_UB_SECTOR_ERASE(aUBSecEraseAddr) \
252 *FLASH_P2V_MAPPED(FLASH_BASE, 0) = FLASHWORD(0x80); \
253 DRAIN_WRITE_BUFFER(); \
254 *FLASH_P2V(aUBSecEraseAddr) = FLASHWORD(0x30); \
255 DRAIN_WRITE_BUFFER(); \
259 #define FLASH_UB_ERASE() \
261 *FLASH_P2V_MAPPED(FLASH_BASE, 0) = FLASHWORD(0x80); \
262 DRAIN_WRITE_BUFFER(); \
263 *FLASH_P2V_MAPPED(FLASH_BASE, 0) = FLASHWORD(0x10); \
264 DRAIN_WRITE_BUFFER(); \
267 #define FLASH_UB_RESET() \
269 *FLASH_P2V_MAPPED(FLASH_BASE, 0) = FLASHWORD(0x90); \
270 *FLASH_P2V_MAPPED(FLASH_BASE, 0) = FLASHWORD(0x00); \
274 #define Get_PC(pcVal) \
276 register cyg_uint32 reg; \
277 asm volatile ("mov %0,pc" \