]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/flash/arm/am29/v2_0/src/am29.h
Initial revision
[karo-tx-redboot.git] / packages / devs / flash / arm / am29 / v2_0 / src / am29.h
1 //==========================================================================
2 //
3 //      am29.h
4 //
5 //      Flash programming for Freescale MX21 ADS board
6 //
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.
12 //
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.
16 //
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
20 // for more details.
21 //
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.
25 //
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.
32 //
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.
35 //
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 //===========================================================================
41
42 #include <cyg/infra/cyg_type.h>
43
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)
48
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 */
53 #else
54     #error MX1 or MX2?
55 #endif
56
57
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;
65 # else
66 #  error How many 16-bit flash devices?
67 # endif
68
69
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)))
73
74
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)
83
84
85 #define DRAIN_WRITE_BUFFER()     \
86 {                                                      \
87       asm volatile (                                                      \
88         "mov    r0, #0x0;"                                                    \
89         "mcr    p15,0,r0,c7,c10,4;" /* drain the write buffer */        \
90         :                                                               \
91         :                                                               \
92         : "r0" /* Clobber list */                                       \
93   );                        \
94 }                           
95
96 #define FLASH_RESET()                                   \
97 {                                                       \
98     *FLASH_P2V_MAPPED(FLASH_BASE, 0) = FLASHWORD(0xF0);             \
99 }
100
101 /* 
102  * This function does the "2 unlock cycle" commands.
103  */
104 #define FLASH_UNLOCK()                                  \
105 {                                                       \
106     *FLASH_P2V_MAPPED(FLASH_BASE, 0x555) = FLASHWORD(0xAA);         \
107     *FLASH_P2V_MAPPED(FLASH_BASE, 0x2AA) = FLASHWORD(0x55);         \
108 }
109
110 /*
111  * Setup the 3 cycle command for the autoselect commands based on 
112  * the address
113  */
114 #define FLASH_AUTO_SEL_SETUP(aSelAddr)                  \
115 {                                                       \
116     FLASH_RESET();                                      \
117     FLASH_UNLOCK();                                     \
118     *FLASH_P2V_MAPPED(aSelAddr, 0x555) = FLASHWORD(0x90);       \
119 }
120
121 /*
122  * The manufacturer's ID is in the passed in variable upon return
123  */
124 #define FLASH_GET_MANU_ID(aManuId)                   \
125 {                                                        \
126     FLASH_AUTO_SEL_SETUP(FLASH_BASE);                    \
127     aManuId = *FLASH_P2V_MAPPED(FLASH_BASE, 0);    \
128     FLASH_RESET();                                      \
129 }
130
131 /*
132  * The device IDs are in the variables upon return
133  */
134 #define FLASH_GET_DEV_ID(aDevId1, aDevId2, aDevId3)     \
135 {                                                                   \
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);              \
140     FLASH_RESET();                                      \
141 }
142
143 /*
144  * The sector lock status is in the variable upon return
145  */
146 #define FLASH_GET_SECTOR_LOCK_VERIFY(aSecAddr, aRtnLock)  \
147 {                                                             \
148     FLASH_AUTO_SEL_SETUP(aSecAddr);                           \
149     aRtnLock = *FLASH_P2V_MAPPED(aSecAddr, 0x02);     \
150 }
151
152 /*
153  * Write aProgData to address aProgAbsAddr as the absolute address 
154  * (not address offset)
155  * May require to call reset fucntion before start programming
156  */
157 #define FLASH_PROGRAM(aProgAddr, aProgData)             \
158 {                                                       \
159     FLASH_UNLOCK();                                     \
160     *FLASH_P2V_MAPPED(FLASH_BASE, 0x555) = FLASHWORD(0xA0);         \
161     *FLASH_P2V(aProgAddr) = aProgData;                  \
162      DRAIN_WRITE_BUFFER();                               \
163 }
164
165 #define FLASH_CHIP_ERASE()                              \
166 {                                                       \
167     FLASH_RESET();                                      \
168     DRAIN_WRITE_BUFFER();                               \
169     FLASH_UNLOCK();                                     \
170     DRAIN_WRITE_BUFFER();                               \
171     *FLASH_P2V_MAPPED(FLASH_BASE, 0x555) = FLASHWORD(0x80);         \
172     DRAIN_WRITE_BUFFER();                               \
173     FLASH_UNLOCK();                                     \
174     DRAIN_WRITE_BUFFER();                               \
175     *FLASH_P2V_MAPPED(FLASH_BASE, 0x555) = FLASHWORD(0x10);         \
176     DRAIN_WRITE_BUFFER();                               \
177     FLASH_RESET();                                      \
178     DRAIN_WRITE_BUFFER();                               \
179 }
180
181 #define FLASH_SECTOR_ERASE(aEraseSecAddr, aEraseStatus)     \
182     {                                                                           \
183     aEraseStatus = FLASH_ERR_OK;                            \
184     FLASH_RESET();                                      \
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)   \
199         {                                                   \
200         if(((*FLASH_P2V_MAPPED(aEraseSecAddr, 0x555)) & KBIT5) == KBIT5)  \
201             {                                               \
202             if(((*FLASH_P2V_MAPPED(aEraseSecAddr, 0x555)) & KBIT7) != KBIT7) \
203                 {                                               \
204                 aEraseStatus = FLASH_ERR_ERASE;                 \
205                 break;                                          \
206                 }                                               \
207             }                                               \
208         }                                                   \
209     FLASH_RESET();                                          \
210     DRAIN_WRITE_BUFFER();                      \
211     }
212
213 #define FLASH_ERASE_SUSPEND(aBankAddrSus)               \
214 {                                                       \
215     *FLASH_P2V(aBankAddrSus) = FLASHWORD(0xB0);         \
216     DRAIN_WRITE_BUFFER();                               \
217     FLASH_RESET();                                          \
218 }
219
220 #define FLASH_ERASE_RESUME(aBankAddrRes)                \
221 {                                                       \
222     *FLASH_P2V(aBankAddrRes) = FLASHWORD(0x30);         \
223     DRAIN_WRITE_BUFFER();                               \
224 }
225
226
227 /* 
228  * Call reset before doing this. When exiting the unlock bypass mode, 
229  * FLASH_UB_RESET() has to be called.
230  */
231 #define FLASH_UB_ENTRY()                                \
232 {                                                       \
233     FLASH_RESET();                                      \
234     DRAIN_WRITE_BUFFER();                               \
235     FLASH_UNLOCK();                                     \
236     DRAIN_WRITE_BUFFER();                               \
237     *FLASH_P2V_MAPPED(FLASH_BASE, 0x555) = FLASHWORD(0x20);         \
238      DRAIN_WRITE_BUFFER();                               \
239 }
240
241
242 #define FLASH_UB_PROGRAM(aUBProgAddr, aUBProgData)      \
243 {                                                       \
244     *FLASH_P2V_MAPPED(FLASH_BASE, 0) = FLASHWORD(0xA0); \
245      DRAIN_WRITE_BUFFER();                               \
246     *FLASH_P2V(aUBProgAddr) = aUBProgData;              \
247      DRAIN_WRITE_BUFFER();                               \
248 }
249
250 #define FLASH_UB_SECTOR_ERASE(aUBSecEraseAddr)          \
251 {                                                       \
252     *FLASH_P2V_MAPPED(FLASH_BASE, 0) = FLASHWORD(0x80);             \
253      DRAIN_WRITE_BUFFER();                               \
254     *FLASH_P2V(aUBSecEraseAddr) = FLASHWORD(0x30);      \
255      DRAIN_WRITE_BUFFER();                               \
256 }
257
258
259 #define FLASH_UB_ERASE()                                \
260 {                                                       \
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();                               \
265 }
266
267 #define FLASH_UB_RESET()                                \
268 {                                                       \
269     *FLASH_P2V_MAPPED(FLASH_BASE, 0) = FLASHWORD(0x90);             \
270     *FLASH_P2V_MAPPED(FLASH_BASE, 0) = FLASHWORD(0x00);             \
271 }
272
273
274 #define Get_PC(pcVal)                                   \
275 CYG_MACRO_START                                         \
276     register cyg_uint32 reg;                            \
277     asm volatile ("mov %0,pc"                           \
278                   : "=r"(reg)                           \
279                   :                                     \
280         );                                              \
281     pcVal = reg;                                        \
282 CYG_MACRO_END