File indexing completed on 2025-05-11 08:23:58
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056 #include <rtems.h>
0057 #include <stdio.h>
0058 #include <inttypes.h>
0059
0060 #include <bsp/flashPgmPvt.h>
0061
0062 #define DEBUG 5
0063 #undef DEBUG
0064
0065 #ifdef DEBUG
0066 #define STATIC
0067 #else
0068 #define STATIC static
0069 #endif
0070
0071
0072 #define ERASE_TIMEOUT 4
0073 #define WRITE_TIMEOUT 1000
0074
0075
0076
0077 #ifdef __PPC__
0078 #define IOSYNC(mem) do { __asm__ volatile("eieio"); } while (0)
0079 #else
0080 #define IOSYNC(mem) do { } while (0)
0081 #endif
0082
0083
0084
0085 STATIC int
0086 flash_get_id_s160(struct bankdesc *, uint32_t , uint32_t *, uint32_t *);
0087
0088 STATIC void
0089 flash_unlock_block_s160(struct bankdesc *, uint32_t);
0090
0091 STATIC void
0092 flash_lock_block_s160(struct bankdesc *, uint32_t);
0093
0094 STATIC int
0095 flash_erase_block_s160(struct bankdesc *, uint32_t);
0096
0097 STATIC uint32_t
0098 flash_check_ready_s160(struct bankdesc *, uint32_t);
0099
0100 STATIC void
0101 flash_print_stat_s160(struct bankdesc *, uint32_t, int);
0102
0103 STATIC void
0104 flash_array_mode_s160(struct bankdesc *, uint32_t);
0105
0106 STATIC uint32_t
0107 flash_write_line_s160(struct bankdesc *, uint32_t, const char *, uint32_t);
0108
0109
0110
0111 static struct flash_bank_ops spansionOps = {
0112 get_id : flash_get_id_s160,
0113 unlock_block: flash_unlock_block_s160,
0114 lock_block : flash_lock_block_s160,
0115 erase_block : flash_erase_block_s160,
0116 check_ready : flash_check_ready_s160,
0117 print_stat : flash_print_stat_s160,
0118 array_mode : flash_array_mode_s160,
0119 write_line : flash_write_line_s160,
0120 };
0121
0122 static struct devdesc spansionDevs[] = {
0123 { 0x007e2101, "S29GL128N", 0x01000000, 32, 0x20000 },
0124 { 0x007e2201, "S29GL256N", 0x02000000, 32, 0x20000 },
0125 { 0x007e2301, "S29GL512N", 0x04000000, 32, 0x20000 },
0126 { 0, 0, 0, 0}
0127 };
0128
0129 struct vendesc BSP_flash_vendor_spansion[] = {
0130 { 0x01, "Spansion/AMD", spansionDevs, &spansionOps },
0131 { 0, 0}
0132 };
0133
0134
0135
0136 #define UNLK1_ADDR_16 0x555
0137 #define UNLK1_DATA 0xaa
0138 #define UNLK2_ADDR_16 0x2aa
0139 #define UNLK2_ADDR_8 0x555
0140 #define UNLK2_DATA 0x55
0141 #define ASEL_DATA 0x90
0142 #define VEND_ID_ADDR_16 0x000
0143 #define SPROT_ADDR_16 0x002
0144 #define DEV1_ID_ADDR_16 0x001
0145 #define DEV2_ID_ADDR_16 0x00e
0146 #define DEV3_ID_ADDR_16 0x00f
0147 #define ERASE_DATA 0x80
0148 #define SECT_ERASE_DATA 0x30
0149 #define DQ7_DATA 0x80
0150 #define RESET_DATA 0xf0
0151 #define WRBUF_DATA 0x25
0152 #define PGBUF_DATA 0x29
0153
0154 #define DQ7_POLL_ALL (-1)
0155
0156
0157
0158 union bconv {
0159 uint32_t u;
0160 uint16_t s[2];
0161 char c[4];
0162 };
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 #define ADDR32(b, a, o) ((a) + ((o)*FLASH_STRIDE(b)))
0174
0175 static inline uint32_t
0176 fl_rd32(struct bankdesc *b, uint32_t a, uint32_t off)
0177 {
0178 volatile union bconv *p;
0179 uint32_t rval;
0180
0181 if ( 1 == b->width )
0182 off <<= 1;
0183
0184 a = ADDR32(b, a, off);
0185
0186 p = (volatile union bconv *)a;
0187 if ( 4 == FLASH_STRIDE(b) ) {
0188 rval = p->u;
0189 IOSYNC(p->u);
0190 } else if ( 2 == FLASH_STRIDE(b) ) {
0191 rval = p->s[0];
0192 IOSYNC(p->s[0]);
0193 } else {
0194 rval = p->c[0];
0195 IOSYNC(p->c[0]);
0196 }
0197 return rval;
0198 }
0199
0200 static inline void
0201 fl_wr32(struct bankdesc *b, uint32_t a, uint32_t v)
0202 {
0203 volatile union bconv *p = (volatile union bconv*)a;
0204 if ( 4 == FLASH_STRIDE(b) ) {
0205 p->u = v;
0206 IOSYNC(p->u);
0207 } else if ( 2 == FLASH_STRIDE(b) ) {
0208 p->s[0] = v;
0209 IOSYNC(p->s[0]);
0210 } else {
0211 p->c[0] = v;
0212 IOSYNC(p->c[0]);
0213 }
0214 }
0215
0216 static inline uint32_t
0217 fl_splat32(struct bankdesc *b, uint32_t x)
0218 {
0219 if ( 4 == FLASH_STRIDE(b) ) {
0220 if ( 1 == b->width ) {
0221 x = (x << 8) | x;
0222 }
0223 x = (x<<16) | x;
0224 } else if ( 2 == FLASH_STRIDE(b) ) {
0225 if ( 1 == b->width )
0226 x = (x << 8) | x;
0227 }
0228 return x;
0229 }
0230
0231 static inline uint32_t
0232 fl_x32(struct bankdesc *b, union bconv *pv)
0233 {
0234 if ( 4 == FLASH_STRIDE(b) )
0235 return pv->u;
0236 else if ( 2 == FLASH_STRIDE(b) )
0237 return pv->s[0];
0238 else
0239 return pv->c[0];
0240 }
0241
0242 static inline void
0243 fl_wr32_cmd(struct bankdesc *b, uint32_t a, uint32_t off, uint32_t cmd)
0244 {
0245 if ( 1 == b->width ) {
0246 if ( off == UNLK2_ADDR_16 )
0247 off = UNLK2_ADDR_8;
0248 else
0249
0250 off <<= 1;
0251 }
0252 cmd = fl_splat32(b, cmd);
0253 a = ADDR32(b, a, off);
0254 fl_wr32(b, a, cmd);
0255 }
0256
0257
0258 static inline void unlk(struct bankdesc *b, uint32_t a)
0259 {
0260 a &= ~ ( ADDR32(b, 0,0x1000) - 1 );
0261 fl_wr32_cmd(b, a, UNLK1_ADDR_16, UNLK1_DATA);
0262 fl_wr32_cmd(b, a, UNLK2_ADDR_16, UNLK2_DATA);
0263 }
0264
0265
0266
0267 STATIC int
0268 sector_is_protected(struct bankdesc *b, uint32_t addr)
0269 {
0270 int rval;
0271 unlk(b, addr);
0272 fl_wr32_cmd(b, addr, UNLK1_ADDR_16, ASEL_DATA);
0273 rval = fl_rd32(b, addr, SPROT_ADDR_16);
0274 flash_array_mode_s160(b, addr);
0275 return rval;
0276 }
0277
0278 STATIC int fl_dq7_poll(struct bankdesc *b, uint32_t addr, uint32_t d7_val)
0279 {
0280 d7_val &= fl_splat32(b, DQ7_DATA);
0281 return ( (fl_rd32(b, addr, 0) & fl_splat32(b, DQ7_DATA)) == d7_val );
0282 }
0283
0284
0285
0286
0287 STATIC int
0288 flash_pend(struct bankdesc *b, uint32_t addr, uint32_t timeout_us, uint32_t d7_val)
0289 {
0290 uint32_t then = BSP_flashBspOps.read_us_timer();
0291 uint32_t now = then;
0292
0293 do {
0294 if ( fl_dq7_poll(b, addr, d7_val) ) {
0295 #if (DEBUG > 4)
0296 printf("Write buffer succeded after %"PRIi32"us\n", (now-then)*8/333);
0297 #endif
0298 return 0;
0299 }
0300 now = BSP_flashBspOps.read_us_timer();
0301 } while ( now - then < timeout_us );
0302
0303 return -1;
0304 }
0305
0306
0307
0308
0309 STATIC void
0310 flash_array_mode_s160(struct bankdesc *b, uint32_t addr)
0311 {
0312 fl_wr32_cmd(b, addr, 0, RESET_DATA);
0313 }
0314
0315 STATIC int
0316 flash_get_id_s160(struct bankdesc *b, uint32_t addr, uint32_t *pVendorId, uint32_t *pDeviceId)
0317 {
0318 uint32_t dev_id[3], x, i;
0319
0320 if ( 4 != FLASH_STRIDE(b) )
0321 fprintf(stderr,"Warning: strides other than 4 untested\n(%s at %d)\n",
0322 __FILE__,__LINE__);
0323
0324 if ( 2 != b->width )
0325 fprintf(stderr,"Warning: device width other than 2 untested\n(%s at %d)\n",
0326 __FILE__,__LINE__);
0327
0328 addr &= ~ (ADDR32(b, 0, 0x1000) - 1);
0329 unlk(b, addr);
0330 fl_wr32_cmd(b, addr, UNLK1_ADDR_16, ASEL_DATA);
0331 *pVendorId = fl_rd32(b, addr, VEND_ID_ADDR_16) & 0xff;
0332 dev_id [0] = fl_rd32(b, addr, DEV1_ID_ADDR_16);
0333 dev_id [1] = fl_rd32(b, addr, DEV2_ID_ADDR_16);
0334 dev_id [2] = fl_rd32(b, addr, DEV3_ID_ADDR_16);
0335
0336 #ifdef DEBUG
0337 printf("Vendor Id 0x%08"PRIx32", Dev Ids: 0x%08"PRIx32", 0x%08"PRIx32", 0x%08"PRIx32"\n",
0338 *pVendorId, dev_id[0], dev_id[1], dev_id[2]);
0339 #endif
0340
0341 flash_array_mode_s160(b, addr);
0342
0343 for ( x=0, i=0; i<3; i++ ) {
0344 x = (x<<8) | (dev_id[i] & 0xff);
0345 }
0346
0347 *pDeviceId = x;
0348
0349 return 0;
0350 }
0351
0352
0353 STATIC void
0354 flash_lock_block_s160(struct bankdesc *b, uint32_t addr)
0355 {
0356 }
0357
0358 STATIC void
0359 flash_unlock_block_s160(struct bankdesc *b, uint32_t addr)
0360 {
0361 }
0362
0363 STATIC uint32_t
0364 flash_check_ready_s160(struct bankdesc *b, uint32_t addr)
0365 {
0366 flash_array_mode_s160(b, addr);
0367 return 0;
0368 }
0369
0370
0371
0372
0373
0374
0375
0376
0377 STATIC int
0378 flash_erase_block_s160(struct bankdesc *b, uint32_t addr)
0379 {
0380 rtems_interval p,i;
0381
0382 addr &= ~ (b->fblksz-1);
0383
0384 if ( sector_is_protected(b, addr) ) {
0385 fprintf(stderr,"Sector at 0x%08"PRIx32" is protected\n", addr);
0386 return -10;
0387 }
0388
0389 unlk(b, addr);
0390 fl_wr32_cmd(b, addr, UNLK1_ADDR_16, ERASE_DATA);
0391 unlk(b, addr);
0392 fl_wr32_cmd(b, addr, 0, SECT_ERASE_DATA);
0393
0394 p = rtems_clock_get_ticks_per_second();
0395 p *= ERASE_TIMEOUT;
0396
0397 for ( i=p; i; i-- ) {
0398 rtems_task_wake_after(1);
0399 if ( fl_dq7_poll(b, addr, DQ7_POLL_ALL) ) {
0400 break;
0401 }
0402 }
0403 #ifdef DEBUG
0404 printf("ERASE polled for %"PRIi32" ticks\n", p-i);
0405 #endif
0406 flash_array_mode_s160(b, addr);
0407
0408 if ( i ) {
0409
0410 for ( i = 0; i < b->fblksz; i++ ) {
0411 if ( 0xff != ((char*)addr)[i] ) {
0412 fprintf(stderr,"ERROR: Erase verification failed at %p\n",
0413 ((char*)addr) + i);
0414 return -1;
0415 }
0416 }
0417 return 0;
0418 }
0419 return -1;
0420 }
0421
0422 STATIC void
0423 flash_print_stat_s160(struct bankdesc *b, uint32_t sta, int verbose)
0424 {
0425 fprintf(stderr,"Flash Spansion 160 error %"PRIi32"\n", sta);
0426 }
0427
0428 STATIC uint32_t
0429 flash_write_line_s160(struct bankdesc *b, uint32_t a, const char *s, uint32_t N)
0430 {
0431 uint32_t sta, nxt, j, v;
0432 union bconv buf;
0433
0434 if ( 0 == N )
0435 return -11;
0436
0437 if ( N & (FLASH_STRIDE(b) - 1) ) {
0438 fprintf(stderr,"flash_write_line_s160: invalid byte count (not multiple of stride\n");
0439 return -10;
0440 }
0441
0442 unlk(b, a);
0443
0444
0445 fl_wr32_cmd(b, a, 0, WRBUF_DATA);
0446
0447
0448 N /= FLASH_STRIDE(b);
0449
0450 fl_wr32_cmd(b, a, 0, N-1);
0451
0452
0453 v = 0;
0454
0455
0456 for (nxt = a; N>0; N--) {
0457 #if (DEBUG > 4)
0458 printf("Writing DAT *0x%08"PRIx32" = 0x%08"PRIx32"\n", nxt, *(uint32_t*)s);
0459 #endif
0460
0461 for ( j=0; j<FLASH_STRIDE(b); j++ ) {
0462 buf.c[j] = *s++;
0463 }
0464 v = fl_x32(b, &buf);
0465 fl_wr32(b, nxt, v);
0466 nxt += FLASH_STRIDE(b);
0467 }
0468
0469
0470 fl_wr32_cmd(b, a, 0, PGBUF_DATA);
0471
0472
0473
0474 sta = flash_pend(b, nxt - FLASH_STRIDE(b), WRITE_TIMEOUT, v);
0475
0476 return sta;
0477 }