]> rtime.felk.cvut.cz Git - arc.git/blob - arch/ppc/mpc55xx/drivers/flash_h7f_c90.c
Fixed a little bug in flash lock for mid address
[arc.git] / arch / ppc / mpc55xx / drivers / flash_h7f_c90.c
1 /* -------------------------------- Arctic Core ------------------------------
2  * Copyright (C) 2009-2011 ArcCore AB <contact@arccore.com>
3  * Licensed under ArcCore Embedded Software License Agreement.
4  * -------------------------------- Arctic Core ------------------------------*/
5
6 /*
7  * flash_h7f_c90.c
8  *
9  *  Created on: 29 aug 2011
10  *      Author: mahi
11  *
12  * Interface for the low level flash written by freescale (flash_ll_h7f_c90.c )
13  *
14  * This file aims to support support all mpc55xx as well as mpc56xx.
15  */
16
17 /* ----------------------------[includes]------------------------------------*/
18
19 #include <stdint.h>
20 #include <stdbool.h>
21 #include <string.h>
22 #include <assert.h>
23 #include "flash_ll_h7f_c90.h"
24 #include "typedefs.h"
25 #include "io.h"
26 //#include "flash_mpc5xxx.h"
27 #include "Fls_Cfg.h"
28
29 #define USE_DEBUG_PRINTF
30 #include "debug.h"
31
32 #define ASSERT(_x)  assert(_x)
33
34 /* ----------------------------[private define]------------------------------*/
35
36 #define PFLASH_CTRL_BASE        0xFFE8_8000
37 #define PFCR0                           (PFLASH_CTRL_BASE + 0x1c)
38 #define PFCR1                           (PFLASH_CTRL_BASE + 0x20)
39 #define PFAPR                           (PFLASH_CTRL_BASE + 0x24)
40
41 #define NVLML_LME                       (1<<31)
42
43
44 //#define FLASH_BANK_CNT                                3
45 #define PASSWORD_LOW_MID                        0xA1A11111UL
46 #define PASSWORD_HIGH                           0xB2B22222UL
47 #define PASSWORD_SECONDARY_LOW_MID      0xC3C33333UL
48
49 /* ----------------------------[private macro]-------------------------------*/
50
51 /* Check if two ranges overlap (_a0->_a1 is first range ) */
52 #define OVERLAP(_a0,_a1, _b0, _b1 ) ( ( ((_a0) <= (_b0)) && ((_b0) <= (_a1)) ) || \
53                                                                           ( ((_b0) <= (_a0)) && ((_a0) <= (_b1)) ) )
54
55 /* ----------------------------[private typedef]-----------------------------*/
56 /* ----------------------------[private function prototypes]-----------------*/
57 /* ----------------------------[private variables]---------------------------*/
58
59 /* ----------------------------[private functions]---------------------------*/
60 /* ----------------------------[public functions]----------------------------*/
61
62 /**
63  * Convert address to strange block format that freescale likes.
64  *
65  * @param addr
66  * @param size
67  * @param fb
68  * @return
69  */
70 static bool getAffectedBlocks( const FlashType *bPtr, uintptr_t addr, size_t size,      uint32_t (*fb)[ADDR_SPACE_CNT] ) {
71         uint16_t addrSpace;
72         bool anyAffected = false;
73
74
75         memset(fb, 0, sizeof(*fb) );
76
77         /* Check if sector range overlaps */
78         for (int sector = 0; sector < bPtr->sectCnt; sector++)
79         {
80                 if (OVERLAP( addr,addr+size-1,
81                                 bPtr->sectAddr[sector],bPtr->sectAddr[sector+1]-1))
82                 {
83                         addrSpace = bPtr->addrSpace[sector];
84                         (*fb)[ADDR_SPACE_GET(addrSpace)] |= (1 << ADDR_SPACE_GET_SECTOR(addrSpace));
85                         anyAffected = true;
86                 }
87         }
88         return anyAffected;
89 }
90
91
92 /**
93  * Setup the flash
94  */
95
96 void Flash_Init(void) {
97
98         /* TODO: Does freescale setup the platform flash controller with sane
99          * values, or not?
100          */
101 }
102
103 uint32_t Flash_Lock(const FlashType *fPtr, uint32_t op, uintptr_t from, uint32_t size) {
104         uint32_t flashBlocks[ADDR_SPACE_CNT];
105         int bank;
106         const FlashType *bPtr;
107         uint32_t regAddr;
108         uint32_t lock;
109
110         LDEBUG_PRINTF("Flash_lock from:%p size:%ul\n");
111
112         for (bank = 0; bank < FLASH_BANK_CNT; bank++) {
113                 bPtr = &fPtr[bank];
114
115                 getAffectedBlocks(bPtr, from, size, &flashBlocks);
116
117                 /* ---------- Low/Mid ---------- */
118             lock = (flashBlocks[ADDR_SPACE_MID]<<16) | flashBlocks[ADDR_SPACE_LOW];
119             if( lock != 0 ) {
120                         regAddr = bPtr->regBase + C90FL_LML;
121
122                         /* Unlock LML (enable LME bit) */
123                         if ( (READ32(regAddr) & NVLML_LME) == 0 ) {
124                                 WRITE32(regAddr,PASSWORD_LOW_MID);
125                         }
126                         /* lock/unlock */
127                         if( op & FLASH_OP_UNLOCK ) {
128                                 WRITE32(regAddr,(~lock) & READ32(regAddr) );
129                         } else {
130                                 WRITE32(regAddr,(lock) | READ32(regAddr) );
131                         }
132
133                         regAddr = bPtr->regBase + C90FL_SLL;
134                         /* Unlock secondary, SLL (enable LME bit) */
135                         if ( (READ32(regAddr) & NVLML_LME) == 0 ) {
136                                 WRITE32(regAddr,PASSWORD_SECONDARY_LOW_MID);
137                         }
138                         /* lock/unlock */
139                         if( op & FLASH_OP_UNLOCK ) {
140                                 WRITE32(regAddr,(~lock) & READ32(regAddr) );
141                         } else {
142                                 WRITE32(regAddr,(lock) | READ32(regAddr) );
143                         }
144
145             }
146
147                 /* ---------- high ----------*/
148             lock = flashBlocks[ADDR_SPACE_HIGH];
149             if( lock != 0 ) {
150                 regAddr = bPtr->regBase + C90FL_HBL;
151                 /* Unlock LML (enable LME bit) */
152                         if ( (READ32(regAddr) & NVLML_LME) == 0 ) {
153                                 WRITE32(regAddr,PASSWORD_HIGH);
154                         }
155
156                         /* lock/unlock */
157                         if( op & FLASH_OP_UNLOCK ) {
158                                 WRITE32(regAddr,(~lock) & READ32(regAddr) );
159                         } else {
160                                 WRITE32(regAddr,(lock) | READ32(regAddr) );
161                         }
162             }
163         }
164         return 0;
165 }
166
167 /**
168  *
169  * @param fPtr
170  * @param dest
171  * @param size
172  * @return
173  */
174 uint32_t Flash_Erase( const FlashType *fPtr, uintptr_t dest, uint32_t size, flashCbType cb) {
175         uint32_t rv;
176         uint32_t flashBlocks[ADDR_SPACE_CNT];
177         const FlashType *bPtr;
178         bool affected;
179
180         /* FSL functions are for each bank, so loop over banks */
181         for (int bank = 0; bank < FLASH_BANK_CNT; bank++) {
182                 bPtr = &fPtr[bank];
183
184                 affected = getAffectedBlocks(bPtr, dest, size, &flashBlocks);
185                 if( affected == false ) {
186                         continue;
187                 }
188
189                 rv = FSL_FlashEraseStart(bPtr->regBase, dest, flashBlocks[0],
190                                 flashBlocks[1], flashBlocks[2]);
191
192                 if (rv != EE_OK) {
193                         return EE_ERROR_PE_OPT;
194                 }
195
196                 /* Poll status */
197                 while ((rv = FSL_FlashCheckStatus(bPtr->regBase)) != EE_OK) {
198
199                         if (rv == EE_ERROR_PE_OPT) {
200                                 return rv;
201                         }
202
203                         if( cb != NULL ) {
204                                 cb();
205                         }
206
207                 }
208         }
209         return EE_OK;
210 }
211
212
213 #if 0
214 /**
215  *
216  * @param to
217  * @param from
218  * @param size
219  * @return
220  */
221 uint32_t Flash_ProgramStart( const FlashType *fPtr, uint32_t *to, uint32_t * from, uint32_t * size, flashCbType cb) {
222         uint32_t rv;
223         uint16_t fSize = size;
224         uint32_t fDest = (uint32_t) to;
225         uint32_t fSource = (uint32_t) from;
226         uint32_t flashBlocks[ADDR_SPACE_CNT];
227         uint32_t maxToProg;
228         const FlashType *bPtr;
229         bool affected;
230
231
232         /* Check double word alignment */
233         ASSERT((size % 8) == 0 );
234
235         /* FSL functions are for each bank, so loop over banks */
236         for (int bank = 0; bank < FLASH_BANK_CNT; bank++) {
237                 bPtr = &fPtr[bank];
238
239                 affected = getAffectedBlocks(bPtr, to, size, &flashBlocks);
240                 if( affected == false ) {
241                         /* This bank was not affected */
242                         continue;
243                 }
244
245                 /* Program to the end of bank */
246                 maxToProg =  MIN(fSize, (bPtr->sectAddr[0] + bPtr->bankSize - fDest));
247                 fSize -= maxToProg;
248
249                 while(maxToProg) {
250                         /* Program page */
251                         rv = FSL_FlashProgramStart(bPtr->regBase, &fDest, &maxToProg, &fSource);
252
253                         if (rv != EE_OK) {
254                                 return EE_ERROR_PE_OPT;
255                         }
256
257 #if 0
258                         /* Poll status */
259                         while ((rv = FSL_FlashCheckStatus(bPtr->regBase)) != EE_OK) {
260
261                                 if (rv == EE_ERROR_PE_OPT) {
262                                         return rv;
263                                 }
264
265                                 if( cb != NULL ) {
266                                         cb();
267                                 }
268                         }
269 #endif
270                 }
271         }
272         return EE_OK;
273 }
274 #endif
275
276
277 /**
278  *
279  * @param to
280  * @param from
281  * @param size
282  * @return
283  */
284 uint32_t Flash_ProgramPageStart( const FlashType *fPtr, uint32_t *to, uint32_t * from, uint32_t * size, flashCbType cb) {
285     uint32_t flashBlocks[ADDR_SPACE_CNT];
286     const FlashType *bPtr;
287     bool affected;
288
289
290     /* Check double word alignment */
291     ASSERT((*size % 8) == 0 );
292
293     /* FSL functions are for each bank, so loop over banks */
294     for (int bank = 0; bank < FLASH_BANK_CNT; bank++) {
295         bPtr = &fPtr[bank];
296
297         affected = getAffectedBlocks(bPtr, *to, *size, &flashBlocks);
298         if( affected == false ) {
299             /* This bank was not affected */
300             continue;
301         }
302
303         return FSL_FlashProgramStart(bPtr->regBase, to, size, from);
304     }
305
306     return EE_OK;
307 }
308 uint32_t Flash_CheckStatus( const FlashType *fPtr ) {
309         return FSL_FlashCheckStatus(fPtr->regBase);
310 }
311
312 uint32_t Flash_SectorAligned( const FlashType *fPtr, uintptr_t addr ) {
313     uint32_t rv = EE_ERROR_MISMATCH;
314     const FlashType *bPtr;
315
316     for (int bank = 0; bank < FLASH_BANK_CNT; bank++) {
317         bPtr = &fPtr[bank];
318
319         /* In range of bank */
320         if( (addr >= bPtr->sectAddr[0]) &&
321             (addr <= (bPtr->sectAddr[bPtr->sectCnt])) )
322         {
323             for (int sector = 0; sector < bPtr->sectCnt; sector++)
324             {
325                 if( addr == bPtr->sectAddr[sector] ) {
326                     rv = EE_OK;
327                     break;
328                 }
329             }
330             break;
331         }
332     }
333     return rv;
334 }
335
336