1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14:
15: 16: 17: 18: 19:
20:
21: #include "flash.h"
22:
23: #ifndef SECSZ
24: #define SECSZ 0x20000
25: #endif
26:
27: #ifndef BSECSZ
28: #define BSECSZ 0x02000
29: #endif
30:
31: #define SECMSK (SECSZ - 1)
32:
33: #define MAX_RETRY (3)
34: #define WAIT_CNT 0x10000000
35:
36: #define WBSZ (16)
37:
38: EXPORT const UW FROM_SECSZ = SECSZ;
39:
40: 41: 42:
43: LOCAL const JEDEC_SPEC *checkFlashROM(_UH *rom)
44: {
45: const JEDEC_SPEC *spec;
46: UH man, dev;
47: W i;
48:
49:
50: rom[0] = 0x0090;
51: man = rom[0] & 0x00ff;
52: dev = rom[1] & 0x00ff;
53:
54:
55: for (i = 0; i < N_JedecSpec; ++i) {
56: spec = &JedecSpec[i];
57: if (spec->man != man || spec->dev != dev) continue;
58:
59: return spec;
60: }
61:
62: return NULL;
63: }
64:
65: 66: 67: 68: 69:
70: LOCAL ER writesec(_UH *rom, UH *data, const JEDEC_SPEC *spec)
71: {
72: _UH *rp, *xp;
73: UH *dp, *ep;
74: UH d;
75: UW n, mask, ptn;
76: W i;
77:
78: mask = (spec->size * (1024*1024) - 1) & ~SECMSK;
79: n = (UW)rom & mask;
80:
81:
82: ptn = ( n == 0 )? spec->bsec:
83: ( n == mask )? spec->tsec:
84: 0x8000;
85:
86:
87: mask = 0x10000;
88: for ( rp = rom; (ptn & (mask - 1)) != 0; rp += BSECSZ/sizeof(UH) ) {
89: if ( (ptn & (mask >>= 1)) == 0 ) continue;
90:
91:
92: *rp = 0x0070;
93: for (i = WAIT_CNT; --i >= 0 && (*rp & 0x0080) == 0; );
94: if (i < 0) return E_IO;
95:
96:
97: *rp = 0x0060;
98: *rp = 0x00D0;
99:
100:
101: *rp = 0x0070;
102: for (i = WAIT_CNT; --i >= 0 && (*rp & 0x0080) == 0; );
103: if (i < 0) return E_IO;
104:
105:
106: *rp = 0x0020;
107: *rp = 0x00D0;
108:
109:
110: for (i = WAIT_CNT; --i >= 0 && ((d = *rp) & 0x0080) == 0; );
111: if (i < 0 || (d & 0x003A) != 0) {
112: *rp = 0x0050;
113: return E_IO;
114: }
115: }
116:
117: if (data == NULL) return E_OK;
118:
119:
120: rp = rom;
121: ep = data + SECSZ / sizeof(UH);
122: for (dp = data; dp < ep; ) {
123: xp = rp;
124: for (i = WAIT_CNT; --i >= 0; ) {
125: *rp = 0x00E8;
126: if (*xp & 0x0080) break;
127: }
128: if (i < 0) goto abort;
129:
130: *rp = WBSZ - 1;
131: for (i = 0; i < WBSZ; i++) *rp++ = *dp++;
132: *xp = 0x00D0;
133:
134:
135:
136: for (i = WAIT_CNT; --i >= 0 && ((d = *xp) & 0x0080) == 0; );
137: if (i < 0 || (d & 0x001A) != 0) {
138: *xp = 0x0050;
139: goto abort;
140: }
141: }
142:
143: abort:
144:
145: *rom = 0x00FF;
146: if (dp < ep) return E_IO;
147:
148:
149: for (dp = data; dp < ep; ) {
150: if (*rom ++ != *dp++) return E_IO;
151: }
152:
153: return E_OK;
154: }
155:
156: 157: 158:
159: EXPORT ER flashwr(UW addr, void *data, W nsec, BOOL reset)
160: {
161: const JEDEC_SPEC *spec;
162: _UH *rom;
163: W sec, retry;
164: ER err;
165:
166:
167: rom = (_UH *)NOCACHE_ADDR(addr & ~SECMSK);
168:
169:
170: spec = checkFlashROM(rom);
171:
172:
173: *rom = 0x00FF;
174:
175:
176: if (spec == NULL) return E_IO;
177:
178:
179: for (sec = 0; sec < nsec; sec++) {
180: retry = MAX_RETRY;
181:
182: do {
183: err = writesec(rom, data, spec);
184: if (err >= E_OK) break;
185:
186:
187: *rom = 0x00FF;
188: } while (--retry > 0);
189:
190: if (err < E_OK) return err;
191:
192: rom = (_UH *)((B *)rom + SECSZ);
193: data = (B *)data + SECSZ;
194: }
195:
196: if (reset) flashwr_reset();
197:
198: return E_OK;
199: }