Compare commits
987 Commits
v0.4.0-rc2
...
v0.5.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fced63147 | ||
|
|
bbd84417f6 | ||
|
|
0d7a948c8d | ||
|
|
29f0ac0efd | ||
|
|
d02dfff48b | ||
|
|
69ac20a155 | ||
|
|
633b1a2b49 | ||
|
|
852289bc49 | ||
|
|
89f593d8cb | ||
|
|
c73342fbe7 | ||
|
|
b066a7db24 | ||
|
|
b5a324e63c | ||
|
|
1cfd3fdda9 | ||
|
|
ba4b8af4d7 | ||
|
|
577c3bc087 | ||
|
|
e872d2880e | ||
|
|
d6c42bf312 | ||
|
|
ffbb5cd85c | ||
|
|
5e7c8d074c | ||
|
|
e7269e32a7 | ||
|
|
f44bde23b9 | ||
|
|
0ea76bc778 | ||
|
|
b765688be6 | ||
|
|
b238735f89 | ||
|
|
107ddb38b7 | ||
|
|
898dd3af46 | ||
|
|
ac43d7a69f | ||
|
|
d4cd6f0320 | ||
|
|
89fa8ce2d8 | ||
|
|
bad3ee87ac | ||
|
|
f6026a8295 | ||
|
|
d567df02b9 | ||
|
|
2482244b07 | ||
|
|
e4c054cada | ||
|
|
ff640f197a | ||
|
|
e53f7e5fc0 | ||
|
|
45287bda76 | ||
|
|
5e2637a4e0 | ||
|
|
b851a4949b | ||
|
|
1aba820519 | ||
|
|
5141ab3e69 | ||
|
|
29f6f6ae5f | ||
|
|
379abb9167 | ||
|
|
b4bbe33d17 | ||
|
|
f279e54347 | ||
|
|
3c3f3c4247 | ||
|
|
03e4ae8481 | ||
|
|
37aaa28292 | ||
|
|
e7c611deea | ||
|
|
16cbe1216a | ||
|
|
9cac49caee | ||
|
|
3428035a7e | ||
|
|
37d5ac6378 | ||
|
|
9f40d41f68 | ||
|
|
523c172280 | ||
|
|
c8b5719802 | ||
|
|
1b0862c189 | ||
|
|
5227ae7162 | ||
|
|
47aa65b3e8 | ||
|
|
d343941386 | ||
|
|
cbe201fe6b | ||
|
|
7b0ead520d | ||
|
|
f4b9a2fc8b | ||
|
|
ca76e4a423 | ||
|
|
c4bcb0b95a | ||
|
|
d539fc856f | ||
|
|
f42353d821 | ||
|
|
f4a3db0d4a | ||
|
|
56d3927abf | ||
|
|
e899fcaca0 | ||
|
|
01c0ffe98f | ||
|
|
33f9bec9ec | ||
|
|
1cfb2287a6 | ||
|
|
5d9b7cdd2b | ||
|
|
c989de0cea | ||
|
|
d09bef2622 | ||
|
|
f499bab698 | ||
|
|
f6315d5e5b | ||
|
|
ae02a0e517 | ||
|
|
fa1f2682d4 | ||
|
|
796086cd49 | ||
|
|
524d79ebe7 | ||
|
|
4da551732e | ||
|
|
096fd6bcc0 | ||
|
|
875298bc53 | ||
|
|
ba576920cf | ||
|
|
9b4628ddab | ||
|
|
db91a36fdd | ||
|
|
acdf14eb43 | ||
|
|
73988aea1f | ||
|
|
212db44fcf | ||
|
|
a57daf23db | ||
|
|
6d6837f988 | ||
|
|
5d7d08a1f0 | ||
|
|
d16b0ea6d4 | ||
|
|
ef599aebfd | ||
|
|
ee124401a2 | ||
|
|
6d9f61fb65 | ||
|
|
129f099ef1 | ||
|
|
9d4aec6bda | ||
|
|
6349a47ebc | ||
|
|
53c0fb6ef5 | ||
|
|
289cecebf0 | ||
|
|
2889471b58 | ||
|
|
522d5b84e2 | ||
|
|
743fada06a | ||
|
|
7d8053e93f | ||
|
|
e3f3f60a02 | ||
|
|
5c739b148e | ||
|
|
d2911627d2 | ||
|
|
1e7e594452 | ||
|
|
5578935eff | ||
|
|
b778b36f29 | ||
|
|
36d60ee6c8 | ||
|
|
5bd1f0bad4 | ||
|
|
2e88162b00 | ||
|
|
5d987bca9c | ||
|
|
3c6af518b3 | ||
|
|
32ede8fa21 | ||
|
|
e105915a4a | ||
|
|
2ed19d3b9b | ||
|
|
e984dc1f16 | ||
|
|
b69119668e | ||
|
|
f9feeacb7f | ||
|
|
ecd5e5de7f | ||
|
|
81f238f522 | ||
|
|
041953f3b1 | ||
|
|
5cc83a880a | ||
|
|
08303f10aa | ||
|
|
28ddd16ddc | ||
|
|
a7844aa4e8 | ||
|
|
d6027ca6a8 | ||
|
|
ba71e8c521 | ||
|
|
28e6dcee85 | ||
|
|
22437fac28 | ||
|
|
5d538084be | ||
|
|
13cf987bb8 | ||
|
|
c7a17b8466 | ||
|
|
24943498e6 | ||
|
|
becfbeaacd | ||
|
|
5e86c5173c | ||
|
|
719f9ecde3 | ||
|
|
bc9afcd4d1 | ||
|
|
b125689459 | ||
|
|
3fea99097e | ||
|
|
a1d9f16320 | ||
|
|
930d70f1a3 | ||
|
|
3b7c9585db | ||
|
|
a0b83e82f7 | ||
|
|
977df18f50 | ||
|
|
364cfaac1d | ||
|
|
378567da4e | ||
|
|
2615bf4398 | ||
|
|
d76fd2aac7 | ||
|
|
1b9e80f7e6 | ||
|
|
0c1ebf2673 | ||
|
|
83ab5ad240 | ||
|
|
667c65552e | ||
|
|
e1f5055bb0 | ||
|
|
f169f86bd1 | ||
|
|
8d338f3296 | ||
|
|
b75bdb7b04 | ||
|
|
ac6f8f9616 | ||
|
|
3e83991560 | ||
|
|
56f705525c | ||
|
|
54ec0c4a8a | ||
|
|
be14e8cbb0 | ||
|
|
68bd107c6d | ||
|
|
dec80e1cff | ||
|
|
a843789ede | ||
|
|
fc574c64bb | ||
|
|
6c5e1781a1 | ||
|
|
ec2b8d71ac | ||
|
|
a343570195 | ||
|
|
17201b5847 | ||
|
|
558f760ff0 | ||
|
|
4332bc32e4 | ||
|
|
9f17b30f88 | ||
|
|
33a17fd359 | ||
|
|
582b4195a9 | ||
|
|
9b1d38707c | ||
|
|
9eeb02c165 | ||
|
|
2321bb3c42 | ||
|
|
4da640563b | ||
|
|
bb0d11cba9 | ||
|
|
689c244389 | ||
|
|
59a6380a17 | ||
|
|
cc9939879c | ||
|
|
8e85bb4eea | ||
|
|
2c4f7f1dd4 | ||
|
|
bce76b80cc | ||
|
|
952de89bfe | ||
|
|
0123985abc | ||
|
|
df500c5a04 | ||
|
|
a4bf71386b | ||
|
|
aebc0d5556 | ||
|
|
f6783d4465 | ||
|
|
26db0a6bef | ||
|
|
e941805713 | ||
|
|
0eed61b7c4 | ||
|
|
b992dd58f1 | ||
|
|
99cd373019 | ||
|
|
2ed3f55547 | ||
|
|
e5677ce9e5 | ||
|
|
95de667e24 | ||
|
|
c3c6a6e1d4 | ||
|
|
6ddcee7d20 | ||
|
|
47b5829db4 | ||
|
|
f26cd96740 | ||
|
|
05abfbadf1 | ||
|
|
403e239960 | ||
|
|
6ebac1b829 | ||
|
|
2bd6a4795a | ||
|
|
578294dbdd | ||
|
|
fa93174a56 | ||
|
|
01edbc2c3f | ||
|
|
b7163f534a | ||
|
|
0f863ecb01 | ||
|
|
3f4b9e334b | ||
|
|
fe0894015f | ||
|
|
aa9baf11a8 | ||
|
|
17a6ffa0c7 | ||
|
|
422e9f9b41 | ||
|
|
779005f43d | ||
|
|
bc404041c0 | ||
|
|
dcc9624b98 | ||
|
|
aaa52e16ce | ||
|
|
f609d03f1f | ||
|
|
28b953d0bd | ||
|
|
177fe9d762 | ||
|
|
05ab8bdb81 | ||
|
|
94e90cbf16 | ||
|
|
405b7a458d | ||
|
|
b21be6054a | ||
|
|
6684b35346 | ||
|
|
08bf273def | ||
|
|
d51b561b10 | ||
|
|
706284a8fd | ||
|
|
5ca7cbe2d2 | ||
|
|
75cdbff5aa | ||
|
|
b0bdc4e2f2 | ||
|
|
aaf145c422 | ||
|
|
efcea8306a | ||
|
|
859ccccd80 | ||
|
|
a0858bfed0 | ||
|
|
4592506b8e | ||
|
|
c34e69cb10 | ||
|
|
8e60d4955f | ||
|
|
aea22bdbd1 | ||
|
|
3fa99ed2bf | ||
|
|
827053c79d | ||
|
|
e26bda10bc | ||
|
|
6df10184f6 | ||
|
|
4df93cb95f | ||
|
|
9629adcbde | ||
|
|
5b34018ccd | ||
|
|
a727418184 | ||
|
|
4749a40821 | ||
|
|
5b1efd0176 | ||
|
|
11193c040c | ||
|
|
8eb92c7e99 | ||
|
|
8684bd1342 | ||
|
|
0535531d27 | ||
|
|
61e1e525c1 | ||
|
|
7ec55eb863 | ||
|
|
94fa8fd30a | ||
|
|
aa61a3b3d8 | ||
|
|
7351eecf6a | ||
|
|
6a1750e961 | ||
|
|
9f408db29d | ||
|
|
a665ef716a | ||
|
|
0cd84000da | ||
|
|
dc1c5a7500 | ||
|
|
e8eb5bbc04 | ||
|
|
c69553cbc5 | ||
|
|
1795239cfd | ||
|
|
09a0a69c09 | ||
|
|
d8ece229f9 | ||
|
|
d356034f03 | ||
|
|
18a5a46bd9 | ||
|
|
093ec6656a | ||
|
|
f49283a062 | ||
|
|
5e27647e22 | ||
|
|
457556b146 | ||
|
|
b7b9ad755e | ||
|
|
35c30e9ee7 | ||
|
|
3db34f8447 | ||
|
|
2e1f2b50fd | ||
|
|
5f3603b8ef | ||
|
|
21a1c6ec33 | ||
|
|
7bb79f0f51 | ||
|
|
52044a17ce | ||
|
|
b0759dfc53 | ||
|
|
0136977c40 | ||
|
|
50e79d60ce | ||
|
|
eea91f71f9 | ||
|
|
4f9a9b8eba | ||
|
|
8f93c0a3fe | ||
|
|
7cd2617384 | ||
|
|
4994c60083 | ||
|
|
56d9ee779d | ||
|
|
319555cd35 | ||
|
|
690e054a3d | ||
|
|
3d834bdab7 | ||
|
|
83e5aaf577 | ||
|
|
921f40f62a | ||
|
|
8b41812da3 | ||
|
|
e03f45f699 | ||
|
|
37f4978f95 | ||
|
|
07dcb5af12 | ||
|
|
29d2d15f3f | ||
|
|
d33f4a2ad5 | ||
|
|
9f18afc39e | ||
|
|
23bf724e04 | ||
|
|
6839618062 | ||
|
|
c9544e411d | ||
|
|
30da7c67ce | ||
|
|
af3f77a177 | ||
|
|
2eebdcf93e | ||
|
|
5787853bc1 | ||
|
|
969b1e66dd | ||
|
|
39dbb516a4 | ||
|
|
cbf48bed6a | ||
|
|
9a76c68563 | ||
|
|
c6e07051e6 | ||
|
|
ae68ddc25e | ||
|
|
26ba6ea511 | ||
|
|
fe4fe623d5 | ||
|
|
b4ee2864e4 | ||
|
|
6165f14ee2 | ||
|
|
b3052b614c | ||
|
|
b8c42b985d | ||
|
|
4bd2b30d5b | ||
|
|
fa46805481 | ||
|
|
740b9e25b4 | ||
|
|
5cd931ed1c | ||
|
|
6ef4e97779 | ||
|
|
2e7d51c96a | ||
|
|
81790fb56a | ||
|
|
bd9d2468cb | ||
|
|
f2a1b7f3af | ||
|
|
0ac6c0d1a8 | ||
|
|
7b2687b45b | ||
|
|
f0fac8a2cd | ||
|
|
c24087d33e | ||
|
|
a1ce28b118 | ||
|
|
778b789c8e | ||
|
|
40a93104d5 | ||
|
|
71031bcf7f | ||
|
|
1bd87f5dba | ||
|
|
6356604382 | ||
|
|
94e1445a86 | ||
|
|
a9d0b3de44 | ||
|
|
9a04974131 | ||
|
|
c606d858a9 | ||
|
|
1892a2b510 | ||
|
|
42082f7c23 | ||
|
|
4bbdf966d4 | ||
|
|
e6fc371e2e | ||
|
|
06b4903e3e | ||
|
|
8902789f0d | ||
|
|
17634b3760 | ||
|
|
6dbe9b7124 | ||
|
|
64751942a3 | ||
|
|
fcee511f4e | ||
|
|
c40571e6b9 | ||
|
|
8c0c259ed6 | ||
|
|
d80fca527a | ||
|
|
838cd58e24 | ||
|
|
ab263fafbb | ||
|
|
29d7031fe3 | ||
|
|
7bbd6c7683 | ||
|
|
d16dbaa0fc | ||
|
|
5d09972931 | ||
|
|
f1f8d9a6c9 | ||
|
|
f5ae179519 | ||
|
|
4cc3597944 | ||
|
|
fb7c709804 | ||
|
|
28bbe4e983 | ||
|
|
2b546fdc45 | ||
|
|
52558354e6 | ||
|
|
d213e1a12c | ||
|
|
c5414f95b6 | ||
|
|
49f42ab51d | ||
|
|
09c798a144 | ||
|
|
e7a8de1762 | ||
|
|
fdae51287c | ||
|
|
015bf55944 | ||
|
|
6287c23b32 | ||
|
|
c62fb3fa81 | ||
|
|
aa4c140a12 | ||
|
|
6c04f1e440 | ||
|
|
e7b2958229 | ||
|
|
4747af362d | ||
|
|
d220e22e63 | ||
|
|
fc4e001de3 | ||
|
|
6ef3d4ccfe | ||
|
|
49a231f38d | ||
|
|
e774df7f69 | ||
|
|
fc4cbc0f98 | ||
|
|
074498f836 | ||
|
|
8f1f8e7b96 | ||
|
|
d5b9c7998c | ||
|
|
1fa91f336a | ||
|
|
887cac65b0 | ||
|
|
0649fb2f6c | ||
|
|
9e3d43cfe7 | ||
|
|
70b1538996 | ||
|
|
d8464623bd | ||
|
|
559d08c19e | ||
|
|
4617cd0f91 | ||
|
|
1fafb669c9 | ||
|
|
53228fbc2e | ||
|
|
2ff1adfa79 | ||
|
|
f176278e98 | ||
|
|
e7d26173fc | ||
|
|
1ceb2c7e7a | ||
|
|
d4de14dafe | ||
|
|
ed44447e3d | ||
|
|
2ee47b22c6 | ||
|
|
e3773e3e3d | ||
|
|
3864da1ab8 | ||
|
|
6229e438dd | ||
|
|
ebe431879d | ||
|
|
7e4cf8db58 | ||
|
|
45de3b1fbe | ||
|
|
d543aa0148 | ||
|
|
96a56ba086 | ||
|
|
50d5441e2a | ||
|
|
6c137a2fc0 | ||
|
|
cb2dba2c12 | ||
|
|
5a41435e45 | ||
|
|
a60a57d8ed | ||
|
|
d623832685 | ||
|
|
fb7235f12a | ||
|
|
3931b99d14 | ||
|
|
3a693ef526 | ||
|
|
ecad76061f | ||
|
|
45e5d1d90a | ||
|
|
19167a7af6 | ||
|
|
3bb4a6ba14 | ||
|
|
6468c593c7 | ||
|
|
9f26aff39c | ||
|
|
cb0de21d0c | ||
|
|
22911a3aed | ||
|
|
9aafd42853 | ||
|
|
edefee9880 | ||
|
|
ea48794210 | ||
|
|
1abc26d7a2 | ||
|
|
6000411ddd | ||
|
|
241fd0b5a8 | ||
|
|
61780558e1 | ||
|
|
549d974814 | ||
|
|
f6a3fc818b | ||
|
|
32ab98c9e9 | ||
|
|
1dbb7ba472 | ||
|
|
f613011aa0 | ||
|
|
103c1f9525 | ||
|
|
ebfb2f4f37 | ||
|
|
7e888741d1 | ||
|
|
60501bb0fb | ||
|
|
c14852385f | ||
|
|
4a47d87e47 | ||
|
|
1b0f194d90 | ||
|
|
35691065f7 | ||
|
|
81e0d4438e | ||
|
|
8afd2309a4 | ||
|
|
73e5dffdfd | ||
|
|
505d4633cd | ||
|
|
ac86f4ccba | ||
|
|
8c21659d2a | ||
|
|
ef92da3315 | ||
|
|
e1c6f6783d | ||
|
|
a40f12d626 | ||
|
|
98a66c4809 | ||
|
|
35af12d3e7 | ||
|
|
ae80c3564a | ||
|
|
3c69eee9ef | ||
|
|
1ca286557a | ||
|
|
31b47688ca | ||
|
|
6f84198841 | ||
|
|
5c98e063b9 | ||
|
|
2c4ef30b11 | ||
|
|
962946ea89 | ||
|
|
66fb176766 | ||
|
|
70794664f1 | ||
|
|
c54c323cf3 | ||
|
|
d23428a47f | ||
|
|
c3d51bf0da | ||
|
|
bb88f3f470 | ||
|
|
36333f9ca8 | ||
|
|
f60a2390cc | ||
|
|
dce422516a | ||
|
|
52ba344a09 | ||
|
|
c3ee26d272 | ||
|
|
a72faf6405 | ||
|
|
07e0bd4685 | ||
|
|
14a25cd6de | ||
|
|
4ed89e4e42 | ||
|
|
98d2579c61 | ||
|
|
a8c8c238f2 | ||
|
|
8f779cf66b | ||
|
|
f1bd1274ee | ||
|
|
676f48d77d | ||
|
|
f941192723 | ||
|
|
ba951aede3 | ||
|
|
91305bfa7f | ||
|
|
3e71449ade | ||
|
|
1399e5f753 | ||
|
|
28ddefd065 | ||
|
|
7682877c8c | ||
|
|
bfa34f88f8 | ||
|
|
c49d4c9f7f | ||
|
|
4e27305ed5 | ||
|
|
d1638abd6a | ||
|
|
6ed9ab5b58 | ||
|
|
ab818f6898 | ||
|
|
803351ec59 | ||
|
|
630fc86ee3 | ||
|
|
8e9b12dc8a | ||
|
|
8772355bbd | ||
|
|
a84112f471 | ||
|
|
f4c1f08f16 | ||
|
|
a463670c31 | ||
|
|
51d9b56861 | ||
|
|
450aaad1e9 | ||
|
|
260eb4548b | ||
|
|
ee17d5c48e | ||
|
|
7176ed9afe | ||
|
|
f0c0256b1f | ||
|
|
1143bbc0c8 | ||
|
|
e0525cd182 | ||
|
|
a9761c9093 | ||
|
|
441ea95f69 | ||
|
|
4333840ee3 | ||
|
|
5164fe5563 | ||
|
|
b62c8d6009 | ||
|
|
a7315891ef | ||
|
|
7dcde11b45 | ||
|
|
e7a1ec64bf | ||
|
|
44ef0327dd | ||
|
|
6c573df11d | ||
|
|
6a237c23c1 | ||
|
|
70fee9207b | ||
|
|
612184176f | ||
|
|
8dbe367c53 | ||
|
|
4611f87f0a | ||
|
|
0345667642 | ||
|
|
8f5e84bf8d | ||
|
|
d249057adf | ||
|
|
20c1d4cc9a | ||
|
|
221ce7c89b | ||
|
|
8249261b88 | ||
|
|
a2d5b0ef77 | ||
|
|
ad02493cf2 | ||
|
|
19fc52f008 | ||
|
|
d10f0def80 | ||
|
|
b85dcae447 | ||
|
|
495ef923ef | ||
|
|
2fdc1db304 | ||
|
|
a4dace3122 | ||
|
|
b05ae41331 | ||
|
|
d16f9259c2 | ||
|
|
9cbf0723d5 | ||
|
|
01b2a3091a | ||
|
|
bb588bdaec | ||
|
|
0672a6497e | ||
|
|
1619facb5e | ||
|
|
f129ef67dc | ||
|
|
e521f6415b | ||
|
|
dc4df8bb97 | ||
|
|
1c79432061 | ||
|
|
e8445c9c9f | ||
|
|
ac5ad4ad8d | ||
|
|
daa02f7d84 | ||
|
|
ccaa9edf29 | ||
|
|
3099858c68 | ||
|
|
1e0f898415 | ||
|
|
db8b99aed6 | ||
|
|
93f2afa45f | ||
|
|
deb176d335 | ||
|
|
f97b6b59ab | ||
|
|
dd88b461da | ||
|
|
cd7f443103 | ||
|
|
2986320cde | ||
|
|
fb96b8607a | ||
|
|
e5d1befe43 | ||
|
|
6cb2d6dd7a | ||
|
|
4fa3cc7746 | ||
|
|
d236a48e8f | ||
|
|
33e7696cfa | ||
|
|
8b82171f75 | ||
|
|
f44eeba16f | ||
|
|
bf8d954352 | ||
|
|
bef497aeb0 | ||
|
|
fe1f7f63b6 | ||
|
|
9a8fe44c83 | ||
|
|
b50bb632ad | ||
|
|
4d238c7f91 | ||
|
|
59bf45be1f | ||
|
|
37cfbe4917 | ||
|
|
19925e4d7f | ||
|
|
f747b16e4e | ||
|
|
9b5572857a | ||
|
|
bc7fa896e6 | ||
|
|
190986eb8c | ||
|
|
ff1c09fbea | ||
|
|
decd417064 | ||
|
|
d26b5236ba | ||
|
|
3f59fcf77e | ||
|
|
b978dcbbee | ||
|
|
3cfbf70559 | ||
|
|
ec073e8943 | ||
|
|
2fbb0b5972 | ||
|
|
dcba070958 | ||
|
|
7013b960fe | ||
|
|
8d1dcb9bcd | ||
|
|
acee9d1c65 | ||
|
|
2a25c968bf | ||
|
|
b8f8d756a2 | ||
|
|
2319caff7d | ||
|
|
3f9d377ce7 | ||
|
|
127f9da4fe | ||
|
|
c3ee63be77 | ||
|
|
cebd817cee | ||
|
|
ada8f5963d | ||
|
|
3eaab9b55b | ||
|
|
647fe050db | ||
|
|
b1cd202f9a | ||
|
|
f2f798fdd3 | ||
|
|
d4e4da0fa1 | ||
|
|
8a2808681e | ||
|
|
80eb7e2a78 | ||
|
|
b89462d7dc | ||
|
|
984bf15821 | ||
|
|
814c2a8f9a | ||
|
|
818120d409 | ||
|
|
5104d56e5c | ||
|
|
cd9c61cc06 | ||
|
|
9bbbbdc0bd | ||
|
|
f4958d61ef | ||
|
|
94f373b404 | ||
|
|
6de2b2d14b | ||
|
|
72d227cd5e | ||
|
|
42c84c59b1 | ||
|
|
f9acaa894f | ||
|
|
f1ce4fe288 | ||
|
|
8022940c5c | ||
|
|
72eb87673c | ||
|
|
e538367186 | ||
|
|
0a837fc36b | ||
|
|
0365225c48 | ||
|
|
953d96f1e2 | ||
|
|
88aa5e31d1 | ||
|
|
90454525b6 | ||
|
|
4d0d649ef9 | ||
|
|
26a77f71e1 | ||
|
|
e85fe0a637 | ||
|
|
43a9282203 | ||
|
|
78b7a571e9 | ||
|
|
4bd415d01b | ||
|
|
8cfd25d29e | ||
|
|
97197c98eb | ||
|
|
da5979c38d | ||
|
|
ab6e62ab76 | ||
|
|
66f42b6f74 | ||
|
|
a09d6020e0 | ||
|
|
748863c2e2 | ||
|
|
64cf05f0c4 | ||
|
|
83ebddd519 | ||
|
|
9161b5fc5c | ||
|
|
395d3bff8c | ||
|
|
00017c90ae | ||
|
|
3c8a0e72f3 | ||
|
|
2eba49b8b1 | ||
|
|
c9e2d13cf9 | ||
|
|
bf3410fcc7 | ||
|
|
3e51d893ed | ||
|
|
9132f7083d | ||
|
|
b6a8254065 | ||
|
|
f3ae52cace | ||
|
|
18918a0423 | ||
|
|
aa2de47d3c | ||
|
|
bac52fbac8 | ||
|
|
9e62f86f24 | ||
|
|
ce58ab9a4e | ||
|
|
dcc7de4f9b | ||
|
|
20724e3325 | ||
|
|
4532dc7831 | ||
|
|
0538081246 | ||
|
|
ecc8041c0f | ||
|
|
73aaaf4830 | ||
|
|
9ab7636ce6 | ||
|
|
49e6c61bcc | ||
|
|
c634680384 | ||
|
|
f6236ade0e | ||
|
|
14c112e992 | ||
|
|
31bbb3cf0c | ||
|
|
54f3f8e4c1 | ||
|
|
00635e28ba | ||
|
|
a1cf1b5244 | ||
|
|
631514724d | ||
|
|
d944a0bed7 | ||
|
|
86e851e1e2 | ||
|
|
215353ef67 | ||
|
|
ee4106ee99 | ||
|
|
94dc7c0a93 | ||
|
|
5319ccd7eb | ||
|
|
ef72484b78 | ||
|
|
f1c1bed39a | ||
|
|
e2c9518eda | ||
|
|
9c3b4cfc5d | ||
|
|
0e4f4bacdc | ||
|
|
06df4664a9 | ||
|
|
2e1eaaae35 | ||
|
|
82ef8472bf | ||
|
|
c0cdb7c631 | ||
|
|
72ba8ec90e | ||
|
|
f40faeb349 | ||
|
|
8465e99442 | ||
|
|
b80d0501b6 | ||
|
|
c86d7bdad4 | ||
|
|
e804a34a63 | ||
|
|
e92b203a76 | ||
|
|
dc464ad88e | ||
|
|
fafed75d98 | ||
|
|
3ecc191b36 | ||
|
|
5fd1c2db9a | ||
|
|
76b81682ee | ||
|
|
602685e66f | ||
|
|
bc8be110ff | ||
|
|
24ebfffff5 | ||
|
|
feb95fbb7b | ||
|
|
ebdd3a1670 | ||
|
|
34f70956ed | ||
|
|
a69cbf0f74 | ||
|
|
61bb0d3d23 | ||
|
|
89747f81f2 | ||
|
|
c7b269ace1 | ||
|
|
b8c54b362b | ||
|
|
9597dcefaa | ||
|
|
dcca0b7694 | ||
|
|
0eb7fb59a0 | ||
|
|
215a5f7442 | ||
|
|
a7fb60dc7b | ||
|
|
7b36d2a229 | ||
|
|
7b76da57f4 | ||
|
|
b05f8171c9 | ||
|
|
6f03e92959 | ||
|
|
4e022886d6 | ||
|
|
4cf13101e5 | ||
|
|
3650981de7 | ||
|
|
2ae192699f | ||
|
|
bbc8f4e6ce | ||
|
|
cf811d8e6b | ||
|
|
f32492c74f | ||
|
|
737c9b6258 | ||
|
|
f7e0f3c285 | ||
|
|
3077f5845f | ||
|
|
2fba796e27 | ||
|
|
82ea640830 | ||
|
|
812e21ac39 | ||
|
|
31b050108a | ||
|
|
91b9f3de0b | ||
|
|
7e33f87b3d | ||
|
|
0d8f60e28f | ||
|
|
ca0f6a5c58 | ||
|
|
80660288e0 | ||
|
|
909130e16e | ||
|
|
282e89c878 | ||
|
|
70226c221f | ||
|
|
8865209545 | ||
|
|
32e647acf4 | ||
|
|
fe60480b7a | ||
|
|
14f4606dcb | ||
|
|
da9f72ca0a | ||
|
|
5e79f999bc | ||
|
|
78248f1df6 | ||
|
|
49b7905cae | ||
|
|
56a21c9cb1 | ||
|
|
e0285dbe73 | ||
|
|
4f1296d151 | ||
|
|
c6cd253ae1 | ||
|
|
48e282aa00 | ||
|
|
cc5f3c85de | ||
|
|
e4056cca2d | ||
|
|
ddf7aabc67 | ||
|
|
620310bcc6 | ||
|
|
b886049c74 | ||
|
|
c9e58238c3 | ||
|
|
ee13916411 | ||
|
|
d31bbc33fa | ||
|
|
decad30865 | ||
|
|
a8a9eddca0 | ||
|
|
41cb911853 | ||
|
|
f549dadb85 | ||
|
|
689fa8ad8c | ||
|
|
da741a51f2 | ||
|
|
f1be0e6af2 | ||
|
|
2ea78551ab | ||
|
|
4809dbb2d7 | ||
|
|
11fd673f0c | ||
|
|
b2495c0101 | ||
|
|
787a5067fb | ||
|
|
fdb9199001 | ||
|
|
d7246f452f | ||
|
|
c936cb334b | ||
|
|
5926b5a94f | ||
|
|
a6307fed91 | ||
|
|
617811ac66 | ||
|
|
aaf848596c | ||
|
|
9acd453d9f | ||
|
|
069f88cfac | ||
|
|
300f0f53c5 | ||
|
|
402d3292bb | ||
|
|
61c0635991 | ||
|
|
0c82bea44a | ||
|
|
c0b5ca6d17 | ||
|
|
b2468e3c4f | ||
|
|
4678108034 | ||
|
|
ec1c90e3cd | ||
|
|
8ffdefcc59 | ||
|
|
de27d28df9 | ||
|
|
8a871560f9 | ||
|
|
4a1bd5b806 | ||
|
|
0f3bbcf096 | ||
|
|
263b4b9057 | ||
|
|
3f0b17e48a | ||
|
|
321aa6aa8f | ||
|
|
81fab96c0d | ||
|
|
2a17fd9f9b | ||
|
|
876bf9bf4c | ||
|
|
88fcb5a9ef | ||
|
|
d37a10da52 | ||
|
|
33e5dd1272 | ||
|
|
d60ebc0ab5 | ||
|
|
a092e8d237 | ||
|
|
27b98c2fa5 | ||
|
|
ed81249129 | ||
|
|
ed6756fb23 | ||
|
|
010492a1ed | ||
|
|
e736468b0e | ||
|
|
4af724df23 | ||
|
|
ec28c674af | ||
|
|
d7dba8d346 | ||
|
|
1cda3e64e4 | ||
|
|
9f1d9499ce | ||
|
|
721502f1d3 | ||
|
|
4be9eded7f | ||
|
|
ccfaed8bc7 | ||
|
|
c2f714bd44 | ||
|
|
b7811b7679 | ||
|
|
5dcad2d34f | ||
|
|
96949890ee | ||
|
|
3b310dbac5 | ||
|
|
7373d1c342 | ||
|
|
03359b1680 | ||
|
|
7f6bab0c4c | ||
|
|
15ff2aeca9 | ||
|
|
1911c8ec8d | ||
|
|
7298452382 | ||
|
|
8ce828dd38 | ||
|
|
8d411d0d24 | ||
|
|
fc9de56a25 | ||
|
|
c09035ea2c | ||
|
|
52a788e008 | ||
|
|
ec108ff59e | ||
|
|
46f92878da | ||
|
|
d37ed9094a | ||
|
|
ae1c64706a | ||
|
|
b48a94f05d | ||
|
|
36df240cea | ||
|
|
fccdfc1cd7 | ||
|
|
0529431fe7 | ||
|
|
cc197c8086 | ||
|
|
bf71e34cbf | ||
|
|
099ffc754a | ||
|
|
3ad171cd53 | ||
|
|
e7e9bfde47 | ||
|
|
79ca05b106 | ||
|
|
051e2c99ab | ||
|
|
7e447043cd | ||
|
|
1d9fba8c14 | ||
|
|
6f8b8593d6 | ||
|
|
030ee192dd | ||
|
|
679f6602fd | ||
|
|
82f44a4708 | ||
|
|
ab5f98edcd | ||
|
|
f85ad1e52a | ||
|
|
a540033a71 | ||
|
|
1bd3ae3986 | ||
|
|
b559b273b5 | ||
|
|
96f9790279 | ||
|
|
4b964a81ca | ||
|
|
de761e350b | ||
|
|
c25fda2c95 | ||
|
|
c23d4596d2 | ||
|
|
763013f15e | ||
|
|
03a26d31e9 | ||
|
|
db464f3cd4 | ||
|
|
24e1e3dd26 | ||
|
|
591e0bbab9 | ||
|
|
edf52a6cc5 | ||
|
|
6030a5cb2a | ||
|
|
257a764582 | ||
|
|
f10ed95a5c | ||
|
|
d0a57c0f0c | ||
|
|
6344f2ab98 | ||
|
|
2946c895a1 | ||
|
|
17d437a7a1 | ||
|
|
c986cc200c | ||
|
|
fc1063a1b9 | ||
|
|
7a5c9c2f4a | ||
|
|
50dc56a488 | ||
|
|
57d7743639 | ||
|
|
e018c7c1d2 | ||
|
|
f7d1be714b | ||
|
|
c6e323b983 | ||
|
|
74113cf725 | ||
|
|
d33a81c549 | ||
|
|
57ebf6d3de | ||
|
|
45a528ff3c | ||
|
|
5e78ddcea0 | ||
|
|
5fdf9535ce | ||
|
|
99939c3c75 | ||
|
|
2119c0a764 | ||
|
|
381ce4308c | ||
|
|
61ee632dbc | ||
|
|
24b1426a72 | ||
|
|
db6c994642 | ||
|
|
d72e90ae4b | ||
|
|
53b3d4dd53 | ||
|
|
5b31186578 | ||
|
|
cb72b7a270 | ||
|
|
b1c00e5a4e | ||
|
|
27401e4c80 | ||
|
|
afbf927663 | ||
|
|
761d4555b8 | ||
|
|
409e23e39b | ||
|
|
57fc63f9f1 | ||
|
|
c9560ba190 | ||
|
|
73c1cff7c2 | ||
|
|
8d13a46626 | ||
|
|
9d6ede25dd | ||
|
|
550abe7396 | ||
|
|
4c9f29bd9c | ||
|
|
b8d8953ae9 | ||
|
|
a851ce0d6f | ||
|
|
0324eb2496 | ||
|
|
63763345d9 | ||
|
|
e4a40d257d | ||
|
|
e70d42a727 | ||
|
|
3ef9beb52c | ||
|
|
8c9b52e8b6 | ||
|
|
a3245bd7cd | ||
|
|
4a64820f23 | ||
|
|
79010bf3df | ||
|
|
7abe9f38b2 | ||
|
|
75067c4042 | ||
|
|
faef631a4d | ||
|
|
1f5883ea56 | ||
|
|
90efc404f3 | ||
|
|
c21c740a89 | ||
|
|
dc342f45f6 | ||
|
|
c8ea748dc2 | ||
|
|
3b68a708c2 | ||
|
|
ecff73043c | ||
|
|
39cfe62796 | ||
|
|
a97bb67543 | ||
|
|
249263d29d | ||
|
|
1aac72d243 | ||
|
|
a299371a9e | ||
|
|
27c068c1f8 | ||
|
|
ce1feaa732 | ||
|
|
b853b9dbc0 | ||
|
|
56e74908d1 | ||
|
|
4aa0a4d811 | ||
|
|
bb4cb7935e | ||
|
|
57d5673dea | ||
|
|
d2a2c14d20 | ||
|
|
3f30563c88 | ||
|
|
aa8db989b9 | ||
|
|
fa1cfc2d4d | ||
|
|
5869992314 | ||
|
|
52d4ba3467 | ||
|
|
a2ce3a51df | ||
|
|
4c4ec09110 |
17
.gitignore
vendored
17
.gitignore
vendored
@@ -14,6 +14,17 @@
|
|||||||
src/jtag/minidriver_imp.h
|
src/jtag/minidriver_imp.h
|
||||||
src/jtag/jtag_minidriver.h
|
src/jtag/jtag_minidriver.h
|
||||||
|
|
||||||
|
# OpenULINK driver files generated by SDCC
|
||||||
|
src/jtag/drivers/OpenULINK/*.rel
|
||||||
|
src/jtag/drivers/OpenULINK/*.asm
|
||||||
|
src/jtag/drivers/OpenULINK/*.lst
|
||||||
|
src/jtag/drivers/OpenULINK/*.sym
|
||||||
|
src/jtag/drivers/OpenULINK/*.map
|
||||||
|
src/jtag/drivers/OpenULINK/*.mem
|
||||||
|
src/jtag/drivers/OpenULINK/*.lnk
|
||||||
|
src/jtag/drivers/OpenULINK/*.ihx
|
||||||
|
src/jtag/drivers/OpenULINK/*.rst
|
||||||
|
|
||||||
# editor files
|
# editor files
|
||||||
*.swp
|
*.swp
|
||||||
|
|
||||||
@@ -73,3 +84,9 @@ patches
|
|||||||
.project
|
.project
|
||||||
.cproject
|
.cproject
|
||||||
.settings
|
.settings
|
||||||
|
|
||||||
|
# Emacs temp files
|
||||||
|
*~
|
||||||
|
|
||||||
|
# CScope database files
|
||||||
|
*cscope.out
|
||||||
|
|||||||
5
.gitmodules
vendored
5
.gitmodules
vendored
@@ -1,3 +1,6 @@
|
|||||||
[submodule "tools/git2cl"]
|
[submodule "tools/git2cl"]
|
||||||
path = tools/git2cl
|
path = tools/git2cl
|
||||||
url = git://repo.or.cz/git2cl.git
|
url = http://repo.or.cz/r/git2cl.git
|
||||||
|
[submodule "jimtcl"]
|
||||||
|
path = jimtcl
|
||||||
|
url = http://repo.or.cz/r/jimtcl.git
|
||||||
|
|||||||
56
HACKING
Normal file
56
HACKING
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
Submitting patches to the OpenOCD mailing list:
|
||||||
|
|
||||||
|
By the time you have read this, one supposes that
|
||||||
|
you have figured out how to clone the OpenOCD git
|
||||||
|
repository.
|
||||||
|
|
||||||
|
Below is a basic workflow and specific instructions
|
||||||
|
to get you going with git and patches.
|
||||||
|
|
||||||
|
0. Clone the git repository, rather than just
|
||||||
|
download the source.
|
||||||
|
|
||||||
|
git clone git://openocd.git.sourceforge.net/gitroot/openocd/openocd
|
||||||
|
|
||||||
|
or if you have problems with the "git:" protocol, use
|
||||||
|
the slower http protocol:
|
||||||
|
|
||||||
|
git clone http://repo.or.cz/r/openocd.git
|
||||||
|
|
||||||
|
1. Set up git with your name and email:
|
||||||
|
|
||||||
|
git config --global user.name "John Smith"
|
||||||
|
git config --global user.email "john@smith.org"
|
||||||
|
|
||||||
|
2. Work on your patches. Split the work into
|
||||||
|
multiple small patches that can be reviewed and
|
||||||
|
applied seperately and safely to the OpenOCD
|
||||||
|
repository.
|
||||||
|
|
||||||
|
while(!done) {
|
||||||
|
work - edit files using your favorite editor.
|
||||||
|
run "git commit -a" to commit all changes.
|
||||||
|
}
|
||||||
|
|
||||||
|
TIP! use "git add ." before commit to add new files.
|
||||||
|
|
||||||
|
--- example comment, notice the short first line w/topic ---
|
||||||
|
topic: short comment
|
||||||
|
<blank line>
|
||||||
|
longer comments over several
|
||||||
|
lines...
|
||||||
|
-----
|
||||||
|
|
||||||
|
3. Next you need to make sure that your patches
|
||||||
|
are on top of the latest stuff on the server and
|
||||||
|
that there are no conflicts.
|
||||||
|
|
||||||
|
git pull --rebase
|
||||||
|
|
||||||
|
4. Generate the patch files. This will generate
|
||||||
|
patches for all commits that are on top of
|
||||||
|
the latest stuff on the server:
|
||||||
|
|
||||||
|
git format-patch origin/master
|
||||||
|
|
||||||
|
5. Email the patches to openocd-development@lists.berlios.de
|
||||||
26
Makefile.am
26
Makefile.am
@@ -2,6 +2,9 @@
|
|||||||
# have all needed files, that a GNU package needs
|
# have all needed files, that a GNU package needs
|
||||||
AUTOMAKE_OPTIONS = gnu 1.6
|
AUTOMAKE_OPTIONS = gnu 1.6
|
||||||
|
|
||||||
|
# make sure we pass the correct jimtcl flags to distcheck
|
||||||
|
DISTCHECK_CONFIGURE_FLAGS = --with-jim-ext=nvp --disable-lineedit --disable-install-jim
|
||||||
|
|
||||||
nobase_dist_pkgdata_DATA = \
|
nobase_dist_pkgdata_DATA = \
|
||||||
contrib/libdcc/dcc_stdio.c \
|
contrib/libdcc/dcc_stdio.c \
|
||||||
contrib/libdcc/dcc_stdio.h \
|
contrib/libdcc/dcc_stdio.h \
|
||||||
@@ -9,11 +12,23 @@ nobase_dist_pkgdata_DATA = \
|
|||||||
contrib/libdcc/README \
|
contrib/libdcc/README \
|
||||||
contrib/openocd.udev
|
contrib/openocd.udev
|
||||||
|
|
||||||
SUBDIRS = src doc
|
if INTERNAL_JIMTCL
|
||||||
|
SUBDIRS = jimtcl
|
||||||
|
else
|
||||||
|
SUBDIRS =
|
||||||
|
endif
|
||||||
|
|
||||||
|
SUBDIRS += src doc
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
|
BUGS \
|
||||||
|
HACKING \
|
||||||
|
NEWTAPS \
|
||||||
|
PATCHES.txt \
|
||||||
|
README.Win32 \
|
||||||
Doxyfile.in \
|
Doxyfile.in \
|
||||||
tools/logger.pl
|
tools/logger.pl \
|
||||||
|
contrib/loaders
|
||||||
|
|
||||||
libtool: $(LIBTOOL_DEPS)
|
libtool: $(LIBTOOL_DEPS)
|
||||||
$(SHELL) ./config.status --recheck
|
$(SHELL) ./config.status --recheck
|
||||||
@@ -53,6 +68,9 @@ TCL_FILES = find $(srcdir)/$(TCL_PATH) -name '*.cfg' -o -name '*.tcl' | \
|
|||||||
sed -e 's,^$(srcdir)/$(TCL_PATH),,'
|
sed -e 's,^$(srcdir)/$(TCL_PATH),,'
|
||||||
|
|
||||||
dist-hook:
|
dist-hook:
|
||||||
|
if test -d $(srcdir)/.git -a \( ! -e $(distdir)/ChangeLog -o -w $(distdir)/ChangeLog \) ; then \
|
||||||
|
git --git-dir $(srcdir)/.git log | $(srcdir)/tools/git2cl/git2cl > $(distdir)/ChangeLog ; \
|
||||||
|
fi
|
||||||
for i in $$($(TCL_FILES)); do \
|
for i in $$($(TCL_FILES)); do \
|
||||||
j="$(distdir)/$(TCL_PATH)/$$i" && \
|
j="$(distdir)/$(TCL_PATH)/$$i" && \
|
||||||
mkdir -p "$$(dirname $$j)" && \
|
mkdir -p "$$(dirname $$j)" && \
|
||||||
@@ -69,10 +87,10 @@ install-data-hook:
|
|||||||
uninstall-hook:
|
uninstall-hook:
|
||||||
rm -rf $(DESTDIR)$(pkgdatadir)/scripts
|
rm -rf $(DESTDIR)$(pkgdatadir)/scripts
|
||||||
|
|
||||||
|
|
||||||
distclean-local:
|
distclean-local:
|
||||||
rm -rf Doxyfile doxygen
|
rm -rf Doxyfile doxygen
|
||||||
|
rm -f $(srcdir)/jimtcl/configure.gnu
|
||||||
|
|
||||||
DISTCLEANFILES = doxygen.log
|
DISTCLEANFILES = doxygen.log
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = \
|
MAINTAINERCLEANFILES = \
|
||||||
|
|||||||
110
NEWS
110
NEWS
@@ -1,88 +1,65 @@
|
|||||||
This file includes highlights of the changes made in the
|
This file includes highlights of the changes made in the
|
||||||
OpenOCD 0.4.0 source archive release. See the repository
|
OpenOCD 0.5.0 source archive release. See the repository
|
||||||
history for details about what changed, including bugfixes
|
history for details about what changed, including bugfixes
|
||||||
and other issues not mentioned here.
|
and other issues not mentioned here.
|
||||||
|
|
||||||
JTAG Layer:
|
JTAG Layer:
|
||||||
Support KT-Link JTAG adapter.
|
New driver for "Bus Pirate"
|
||||||
Support USB-JTAG, Altera USB-Blaster and compatibles.
|
Rename various commands so they're not JTAG-specific
|
||||||
|
There are migration procedures for most of these, but you should
|
||||||
|
convert your scripts to the new names, since those procedures
|
||||||
|
will not be around forever.
|
||||||
|
jtag jinterface ... is now adapter_name
|
||||||
|
jtag_khz ... is now adapter_khz
|
||||||
|
jtag_nsrst_delay ... is now adapter_nsrst_delay
|
||||||
|
jtag_nsrst_assert_width ... is now adapter_nsrst_assert_width
|
||||||
|
Support Voipac VPACLink JTAG Adapter.
|
||||||
|
|
||||||
Boundary Scan:
|
Boundary Scan:
|
||||||
|
|
||||||
|
Transport framework core ... supporting future work for SWD, SPI, and other
|
||||||
|
non-JTAG ways to debug targets or program flash.
|
||||||
|
|
||||||
Target Layer:
|
Target Layer:
|
||||||
General
|
ARM:
|
||||||
- new "reset-assert" event, for systems without SRST
|
- basic semihosting support for ARMv7M.
|
||||||
ARM
|
- renamed "armv7m" command prefix as "arm"
|
||||||
- supports "reset-assert" event (except on Cortex-M3)
|
MIPS:
|
||||||
- renamed "armv4_5" command prefix as "arm"
|
- "ejtag_srst" variant removed. The same functionality is
|
||||||
- recognize TrustZone "Secure Monitor" mode
|
obtained by using "reset_config none".
|
||||||
- "arm regs" command output changed
|
- added PIC32MX software reset support, this means srst is not
|
||||||
- register names use "sp" not "r13"
|
required to be connected anymore.
|
||||||
- add top-level "mcr" and "mrc" commands, replacing
|
OTHER:
|
||||||
various core-specific operations
|
- preliminary AVR32 AP7000 support.
|
||||||
- basic semihosting support (ARM7/ARM9 only, for now)
|
|
||||||
ARM11
|
|
||||||
- Should act much more like other ARM cores:
|
|
||||||
* Preliminary ETM and ETB hookup
|
|
||||||
* accelerated "flash erase_check"
|
|
||||||
* accelerated GDB memory checksum
|
|
||||||
* support "arm regs" command
|
|
||||||
* can access all core modes and registers
|
|
||||||
* watchpoint support
|
|
||||||
- Shares some core debug code with Cortex-A8
|
|
||||||
Cortex-A8
|
|
||||||
- Should act much more like other ARM cores:
|
|
||||||
* support "arm regs" command
|
|
||||||
* can access all core modes and registers
|
|
||||||
* watchpoint support
|
|
||||||
- Shares some core debug code with ARM11
|
|
||||||
Cortex-M3
|
|
||||||
- Exposed DWT registers like cycle counter
|
|
||||||
- vector_catch settings not clobbered by resets
|
|
||||||
- no longer interferes with firmware's fault handling
|
|
||||||
ETM, ETB
|
|
||||||
- "trigger_percent" command moved ETM --> ETB
|
|
||||||
- "etm trigger_debug" command added
|
|
||||||
MIPS
|
|
||||||
- use fastdata writes
|
|
||||||
Freescale DSP563xx cores (partial support)
|
|
||||||
|
|
||||||
Flash Layer:
|
Flash Layer:
|
||||||
'flash bank' and 'nand device' take <bank_name> as first argument.
|
New "stellaris recover" command, implements the procedure
|
||||||
With this, flash/NAND commands allow referencing banks by name:
|
to recover locked devices (restoring non-volatile
|
||||||
- <bank_name>: reference the bank with its defined name
|
state to the factory defaults, including erasing
|
||||||
- <driver_name>[.N]: reference the driver's Nth bank
|
the flash and its protection bits, and possibly
|
||||||
New 'nand verify' command to check bank against an image file.
|
re-enabling hardware debugging).
|
||||||
The "flash erase_address" command now rejects partial sectors;
|
PIC32MX now uses algorithm for flash programming, this
|
||||||
previously it would silently erase extra data. If you
|
has increased the performance by approx 96%.
|
||||||
want to erase the rest of the first and/or last sectors
|
New 'pic32mx unlock' cmd to remove readout protection.
|
||||||
instead of failing, you must pass an explicit "pad" flag.
|
New STM32 Value Line Support.
|
||||||
New at91sam9 NAND controller driver.
|
New 'virtual' flash driver, used to associate other addresses
|
||||||
New s3c64xx NAND controller driver.
|
with a flash bank. See pic32mx.cfg for usage.
|
||||||
|
New iMX27 NAND flash controller driver.
|
||||||
|
|
||||||
Board, Target, and Interface Configuration Scripts:
|
Board, Target, and Interface Configuration Scripts:
|
||||||
ARM9
|
Support IAR LPC1768 kickstart board (by Olimex)
|
||||||
- ETM and ETB hookup for iMX2* targets
|
Support Voipac PXA270/PXA270M module.
|
||||||
Add $HOME/.openocd to the search path.
|
New $PARPORTADDR tcl variable used to change default
|
||||||
Handle Rev C of LM3S811 eval boards.
|
parallel port address used.
|
||||||
- use "luminary-lm3s811.cfg" for older boards
|
Remove lm3s811.cfg; use "stellaris.cfg" instead
|
||||||
- use "luminary.cfg" for RevC and newer
|
|
||||||
|
|
||||||
Core Jim/TCL Scripting:
|
Core Jim/TCL Scripting:
|
||||||
New 'usage' command to provide terse command help.
|
New "add_script_search_dir" command, behaviour is the same
|
||||||
Improved command 'help' command output (sorted and indented).
|
as the "-s" cmd line option.
|
||||||
Improved command handling:
|
|
||||||
- Most boolean settings now accept any of the following:
|
|
||||||
on/off, enable/disable, true/false, yes/no, 1/0
|
|
||||||
- More error checking and reporting.
|
|
||||||
|
|
||||||
Documentation:
|
Documentation:
|
||||||
New built-in command development documentation and primer.
|
|
||||||
|
|
||||||
Build and Release:
|
Build and Release:
|
||||||
Use --enable-doxygen-pdf to build PDF developer documentation.
|
|
||||||
Consider upgrading to libftdi 0.17 if you use that library; it
|
|
||||||
includes bugfixes which improve FT2232H support.
|
|
||||||
|
|
||||||
For more details about what has changed since the last release,
|
For more details about what has changed since the last release,
|
||||||
see the git repository history. With gitweb, you can browse that
|
see the git repository history. With gitweb, you can browse that
|
||||||
@@ -94,3 +71,4 @@ For older NEWS, see the NEWS files associated with each release
|
|||||||
For more information about contributing test reports, bug fixes, or new
|
For more information about contributing test reports, bug fixes, or new
|
||||||
features and device support, please read the new Developer Manual (or
|
features and device support, please read the new Developer Manual (or
|
||||||
the BUGS and PATCHES.txt files in the source archive).
|
the BUGS and PATCHES.txt files in the source archive).
|
||||||
|
|
||||||
|
|||||||
98
NEWS-0.4.0
Normal file
98
NEWS-0.4.0
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
This file includes highlights of the changes made in the
|
||||||
|
OpenOCD 0.4.0 source archive release. See the repository
|
||||||
|
history for details about what changed, including bugfixes
|
||||||
|
and other issues not mentioned here.
|
||||||
|
|
||||||
|
JTAG Layer:
|
||||||
|
Support KT-Link JTAG adapter.
|
||||||
|
Support USB-JTAG, Altera USB-Blaster and compatibles.
|
||||||
|
|
||||||
|
Boundary Scan:
|
||||||
|
|
||||||
|
Target Layer:
|
||||||
|
General
|
||||||
|
- Removed commands which have been obsolete for at least
|
||||||
|
a year (from both documentation and, sometimes, code).
|
||||||
|
- new "reset-assert" event, for systems without SRST
|
||||||
|
ARM
|
||||||
|
- supports "reset-assert" event (except on Cortex-M3)
|
||||||
|
- renamed "armv4_5" command prefix as "arm"
|
||||||
|
- recognize TrustZone "Secure Monitor" mode
|
||||||
|
- "arm regs" command output changed
|
||||||
|
- register names use "sp" not "r13"
|
||||||
|
- add top-level "mcr" and "mrc" commands, replacing
|
||||||
|
various core-specific operations
|
||||||
|
- basic semihosting support (ARM7/ARM9 only, for now)
|
||||||
|
ARM11
|
||||||
|
- Should act much more like other ARM cores:
|
||||||
|
* Preliminary ETM and ETB hookup
|
||||||
|
* accelerated "flash erase_check"
|
||||||
|
* accelerated GDB memory checksum
|
||||||
|
* support "arm regs" command
|
||||||
|
* can access all core modes and registers
|
||||||
|
* watchpoint support
|
||||||
|
- Shares some core debug code with Cortex-A8
|
||||||
|
Cortex-A8
|
||||||
|
- Should act much more like other ARM cores:
|
||||||
|
* support "arm regs" command
|
||||||
|
* can access all core modes and registers
|
||||||
|
* watchpoint support
|
||||||
|
- Shares some core debug code with ARM11
|
||||||
|
Cortex-M3
|
||||||
|
- Exposed DWT registers like cycle counter
|
||||||
|
- vector_catch settings not clobbered by resets
|
||||||
|
- no longer interferes with firmware's fault handling
|
||||||
|
ETM, ETB
|
||||||
|
- "trigger_percent" command moved ETM --> ETB
|
||||||
|
- "etm trigger_debug" command added
|
||||||
|
MIPS
|
||||||
|
- use fastdata writes
|
||||||
|
Freescale DSP563xx cores (partial support)
|
||||||
|
|
||||||
|
Flash Layer:
|
||||||
|
'flash bank' and 'nand device' take <bank_name> as first argument.
|
||||||
|
With this, flash/NAND commands allow referencing banks by name:
|
||||||
|
- <bank_name>: reference the bank with its defined name
|
||||||
|
- <driver_name>[.N]: reference the driver's Nth bank
|
||||||
|
New 'nand verify' command to check bank against an image file.
|
||||||
|
The "flash erase_address" command now rejects partial sectors;
|
||||||
|
previously it would silently erase extra data. If you
|
||||||
|
want to erase the rest of the first and/or last sectors
|
||||||
|
instead of failing, you must pass an explicit "pad" flag.
|
||||||
|
New at91sam9 NAND controller driver.
|
||||||
|
New s3c64xx NAND controller driver.
|
||||||
|
|
||||||
|
Board, Target, and Interface Configuration Scripts:
|
||||||
|
ARM9
|
||||||
|
- ETM and ETB hookup for iMX2* targets
|
||||||
|
Add $HOME/.openocd to the search path.
|
||||||
|
Handle Rev C of LM3S811 eval boards.
|
||||||
|
- use "luminary-lm3s811.cfg" for older boards
|
||||||
|
- use "luminary.cfg" for RevC and newer
|
||||||
|
|
||||||
|
Core Jim/TCL Scripting:
|
||||||
|
New 'usage' command to provide terse command help.
|
||||||
|
Improved command 'help' command output (sorted and indented).
|
||||||
|
Improved command handling:
|
||||||
|
- Most boolean settings now accept any of the following:
|
||||||
|
on/off, enable/disable, true/false, yes/no, 1/0
|
||||||
|
- More error checking and reporting.
|
||||||
|
|
||||||
|
Documentation:
|
||||||
|
New built-in command development documentation and primer.
|
||||||
|
|
||||||
|
Build and Release:
|
||||||
|
Use --enable-doxygen-pdf to build PDF developer documentation.
|
||||||
|
Consider upgrading to libftdi 0.17 if you use that library; it
|
||||||
|
includes bugfixes which improve FT2232H support.
|
||||||
|
|
||||||
|
For more details about what has changed since the last release,
|
||||||
|
see the git repository history. With gitweb, you can browse that
|
||||||
|
in various levels of detail.
|
||||||
|
|
||||||
|
For older NEWS, see the NEWS files associated with each release
|
||||||
|
(i.e. NEWS-<version>).
|
||||||
|
|
||||||
|
For more information about contributing test reports, bug fixes, or new
|
||||||
|
features and device support, please read the new Developer Manual (or
|
||||||
|
the BUGS and PATCHES.txt files in the source archive).
|
||||||
10
README
10
README
@@ -64,8 +64,8 @@ you can build the in-tree documentation.
|
|||||||
Installing OpenOCD
|
Installing OpenOCD
|
||||||
==================
|
==================
|
||||||
|
|
||||||
On Linux, you may have permissions problems to address. The best
|
On Linux, you may have permissions problems to address. The best way
|
||||||
way to do this is to use the contrib/udev.rules file. It probably
|
to do this is to use the contrib/openocd.udev rules file. It probably
|
||||||
belongs somewhere in /etc/udev/rules.d, but consult your operating
|
belongs somewhere in /etc/udev/rules.d, but consult your operating
|
||||||
system documentation to be sure. In particular, make sure that it
|
system documentation to be sure. In particular, make sure that it
|
||||||
matches the syntax used by your operating system's version of udev.
|
matches the syntax used by your operating system's version of udev.
|
||||||
@@ -236,6 +236,8 @@ options may be available there:
|
|||||||
Programmer
|
Programmer
|
||||||
--enable-rlink Enable building support for the Raisonance RLink
|
--enable-rlink Enable building support for the Raisonance RLink
|
||||||
JTAG Programmer
|
JTAG Programmer
|
||||||
|
--enable-ulink Enable building support for the Keil ULINK JTAG
|
||||||
|
Programmer
|
||||||
--enable-usbprog Enable building support for the usbprog JTAG
|
--enable-usbprog Enable building support for the usbprog JTAG
|
||||||
Programmer
|
Programmer
|
||||||
--enable-vsllink Enable building support for the Versaloon-Link JTAG
|
--enable-vsllink Enable building support for the Versaloon-Link JTAG
|
||||||
@@ -255,8 +257,6 @@ options may be available there:
|
|||||||
|
|
||||||
--enable-ioutil Enable ioutil functions - useful for standalone
|
--enable-ioutil Enable ioutil functions - useful for standalone
|
||||||
OpenOCD implementations
|
OpenOCD implementations
|
||||||
--enable-httpd Enable builtin httpd server - useful for standalone
|
|
||||||
OpenOCD implementations
|
|
||||||
|
|
||||||
--disable-doxygen-html Disable building Doxygen manual as HTML.
|
--disable-doxygen-html Disable building Doxygen manual as HTML.
|
||||||
--enable-doxygen-pdf Enable building Doxygen manual as PDF.
|
--enable-doxygen-pdf Enable building Doxygen manual as PDF.
|
||||||
@@ -317,7 +317,7 @@ The libftdi source code can be download from the following website:
|
|||||||
|
|
||||||
For both Linux and Windows, both libusb and libftdi must be built and
|
For both Linux and Windows, both libusb and libftdi must be built and
|
||||||
installed. To use the newer FT2232H chips, supporting RTCK and USB high
|
installed. To use the newer FT2232H chips, supporting RTCK and USB high
|
||||||
speed (480 Mbps), you need libftdi version 0.16 or newer. Many Linux
|
speed (480 Mbps), use libftdi version 0.17 or newer. Many Linux
|
||||||
distributions provide suitable packages for these libraries.
|
distributions provide suitable packages for these libraries.
|
||||||
|
|
||||||
For Windows, libftdi is supported with versions 0.14 and later.
|
For Windows, libftdi is supported with versions 0.14 and later.
|
||||||
|
|||||||
36
bootstrap
36
bootstrap
@@ -1,16 +1,24 @@
|
|||||||
#!/bin/sh -e
|
#!/bin/sh
|
||||||
# Run the autotools bootstrap sequence to create the configure script
|
# Run the autotools bootstrap sequence to create the configure script
|
||||||
|
|
||||||
# Stop execution as soon as we have an unknown command
|
# Abort execution on error
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
if libtoolize --version >/dev/null 2>&1; then
|
if which libtoolize > /dev/null; then
|
||||||
libtoolize="libtoolize"
|
libtoolize="libtoolize"
|
||||||
elif glibtoolize --version >/dev/null 2>&1; then
|
elif which glibtoolize >/dev/null; then
|
||||||
libtoolize="glibtoolize"
|
libtoolize="glibtoolize"
|
||||||
else
|
else
|
||||||
echo "libtool is required" >&2
|
echo "$0: Error: libtool is required" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$1" = "nosubmodule" ]; then
|
||||||
|
SKIP_SUBMODULE=1
|
||||||
|
elif [ -n "$1" ]; then
|
||||||
|
echo "$0: Illegal argument $1"
|
||||||
|
echo "USAGE: $0 [nosubmodule]"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# bootstrap the autotools
|
# bootstrap the autotools
|
||||||
@@ -26,4 +34,14 @@ automake --gnu --add-missing --copy
|
|||||||
# AM_MAINTAINER_MODE requires --enable-maintainer-mode from everyone using
|
# AM_MAINTAINER_MODE requires --enable-maintainer-mode from everyone using
|
||||||
# current source snapshots (working from GIT, or some source snapshot, etc)
|
# current source snapshots (working from GIT, or some source snapshot, etc)
|
||||||
# otherwise the documentation will fail to build due to missing version.texi
|
# otherwise the documentation will fail to build due to missing version.texi
|
||||||
echo "Bootstrap complete; you can './configure --enable-maintainer-mode ....'"
|
|
||||||
|
if [ -n "$SKIP_SUBMODULE" ]; then
|
||||||
|
echo "Skipping submodule setup"
|
||||||
|
else
|
||||||
|
echo "Setting up submodules"
|
||||||
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Bootstrap complete. Quick build instructions:"
|
||||||
|
echo "./configure --enable-maintainer-mode ...."
|
||||||
|
|||||||
11
common.mk
Normal file
11
common.mk
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
# common flags used in openocd build
|
||||||
|
AM_CPPFLAGS = -I$(top_srcdir)/src \
|
||||||
|
-I$(top_builddir)/src \
|
||||||
|
-DPKGDATADIR=\"$(pkgdatadir)\" \
|
||||||
|
-DPKGLIBDIR=\"$(pkglibdir)\"
|
||||||
|
|
||||||
|
if INTERNAL_JIMTCL
|
||||||
|
AM_CPPFLAGS += -I$(top_srcdir)/jimtcl \
|
||||||
|
-I$(top_builddir)/jimtcl
|
||||||
|
endif
|
||||||
27
config_subdir.m4
Normal file
27
config_subdir.m4
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
dnl
|
||||||
|
dnl If needed, define the m4_ifblank and m4_ifnblank macros from autoconf 2.64
|
||||||
|
dnl This allows us to run with earlier Autoconfs as well.
|
||||||
|
ifdef([m4_ifblank],[],[
|
||||||
|
m4_define([m4_ifblank],
|
||||||
|
[m4_if(m4_translit([[$1]], [ ][ ][
|
||||||
|
]), [], [$2], [$3])])])
|
||||||
|
dnl
|
||||||
|
ifdef([m4_ifnblank],[],[
|
||||||
|
m4_define([m4_ifnblank],
|
||||||
|
[m4_if(m4_translit([[$1]], [ ][ ][
|
||||||
|
]), [], [$3], [$2])])])
|
||||||
|
dnl
|
||||||
|
|
||||||
|
dnl AC_CONFIG_SUBDIRS does not allow configure options to be passed
|
||||||
|
dnl to subdirs, this function allows that by creating a configure.gnu
|
||||||
|
dnl script that prepends configure options and then calls the real
|
||||||
|
dnl configure script
|
||||||
|
AC_DEFUN([AX_CONFIG_SUBDIR_OPTION],
|
||||||
|
[
|
||||||
|
AC_CONFIG_SUBDIRS([$1])
|
||||||
|
|
||||||
|
m4_ifblank([$2], [rm -f $srcdir/$1/configure.gnu],
|
||||||
|
[printf "#!/bin/sh
|
||||||
|
"\$"SHELL "../$srcdir/$1/configure" $2 \""\$"@"\" > "$srcdir/$1/configure.gnu"
|
||||||
|
])
|
||||||
|
])
|
||||||
133
configure.in
133
configure.in
@@ -1,8 +1,10 @@
|
|||||||
AC_PREREQ(2.60)
|
AC_PREREQ(2.60)
|
||||||
AC_INIT([openocd], [0.4.0-rc2],
|
AC_INIT([openocd], [0.5.0],
|
||||||
[OpenOCD Mailing List <openocd-development@lists.berlios.de>])
|
[OpenOCD Mailing List <openocd-development@lists.berlios.de>])
|
||||||
AC_CONFIG_SRCDIR([src/openocd.c])
|
AC_CONFIG_SRCDIR([src/openocd.c])
|
||||||
|
|
||||||
|
m4_include(config_subdir.m4)dnl
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([-Wall -Wno-portability dist-bzip2 dist-zip])
|
AM_INIT_AUTOMAKE([-Wall -Wno-portability dist-bzip2 dist-zip])
|
||||||
AM_MAINTAINER_MODE
|
AM_MAINTAINER_MODE
|
||||||
|
|
||||||
@@ -408,6 +410,10 @@ AC_ARG_ENABLE(ecosboard,
|
|||||||
AS_HELP_STRING([--enable-ecosboard], [Enable building support for eCos based JTAG debugger]),
|
AS_HELP_STRING([--enable-ecosboard], [Enable building support for eCos based JTAG debugger]),
|
||||||
[build_ecosboard=$enableval], [build_ecosboard=no])
|
[build_ecosboard=$enableval], [build_ecosboard=no])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(zy1000_master,
|
||||||
|
AS_HELP_STRING([--enable-zy1000-master], [Use ZY1000 JTAG master registers]),
|
||||||
|
[build_zy1000_master=$enableval], [build_zy1000_master=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(zy1000,
|
AC_ARG_ENABLE(zy1000,
|
||||||
AS_HELP_STRING([--enable-zy1000], [Enable ZY1000 interface]),
|
AS_HELP_STRING([--enable-zy1000], [Enable ZY1000 interface]),
|
||||||
[build_zy1000=$enableval], [build_zy1000=no])
|
[build_zy1000=$enableval], [build_zy1000=no])
|
||||||
@@ -416,10 +422,6 @@ AC_ARG_ENABLE(ioutil,
|
|||||||
AS_HELP_STRING([--enable-ioutil], [Enable ioutil functions - useful for standalone OpenOCD implementations]),
|
AS_HELP_STRING([--enable-ioutil], [Enable ioutil functions - useful for standalone OpenOCD implementations]),
|
||||||
[build_ioutil=$enableval], [build_ioutil=no])
|
[build_ioutil=$enableval], [build_ioutil=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(httpd,
|
|
||||||
AS_HELP_STRING([--enable-httpd], [Enable builtin httpd server - useful for standalone OpenOCD implementations]),
|
|
||||||
[build_httpd=$enableval], [build_httpd=no])
|
|
||||||
|
|
||||||
case "${host_cpu}" in
|
case "${host_cpu}" in
|
||||||
arm*)
|
arm*)
|
||||||
AC_ARG_ENABLE(ep93xx,
|
AC_ARG_ENABLE(ep93xx,
|
||||||
@@ -470,14 +472,25 @@ AC_ARG_ENABLE(rlink,
|
|||||||
AS_HELP_STRING([--enable-rlink], [Enable building support for the Raisonance RLink JTAG Programmer]),
|
AS_HELP_STRING([--enable-rlink], [Enable building support for the Raisonance RLink JTAG Programmer]),
|
||||||
[build_rlink=$enableval], [build_rlink=no])
|
[build_rlink=$enableval], [build_rlink=no])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(ulink,
|
||||||
|
AS_HELP_STRING([--enable-ulink], [Enable building support for the Keil ULINK JTAG Programmer]),
|
||||||
|
[build_ulink=$enableval], [build_ulink=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(arm-jtag-ew,
|
AC_ARG_ENABLE(arm-jtag-ew,
|
||||||
AS_HELP_STRING([--enable-arm-jtag-ew], [Enable building support for the Olimex ARM-JTAG-EW Programmer]),
|
AS_HELP_STRING([--enable-arm-jtag-ew], [Enable building support for the Olimex ARM-JTAG-EW Programmer]),
|
||||||
[build_armjtagew=$enableval], [build_armjtagew=no])
|
[build_armjtagew=$enableval], [build_armjtagew=no])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(buspirate,
|
||||||
|
AS_HELP_STRING([--enable-buspirate], [Enable building support for the Buspirate]),
|
||||||
|
[build_buspirate=$enableval], [build_buspirate=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(minidriver_dummy,
|
AC_ARG_ENABLE(minidriver_dummy,
|
||||||
AS_HELP_STRING([--enable-minidriver-dummy], [Enable the dummy minidriver.]),
|
AS_HELP_STRING([--enable-minidriver-dummy], [Enable the dummy minidriver.]),
|
||||||
[build_minidriver_dummy=$enableval], [build_minidriver_dummy=no])
|
[build_minidriver_dummy=$enableval], [build_minidriver_dummy=no])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(internal-jimtcl,
|
||||||
|
AS_HELP_STRING([--disable-internal-jimtcl], [Disable building internal jimtcl]),
|
||||||
|
[use_internal_jimtcl=$enableval], [use_internal_jimtcl=yes])
|
||||||
|
|
||||||
build_minidriver=no
|
build_minidriver=no
|
||||||
AC_MSG_CHECKING([whether to enable ZY1000 minidriver])
|
AC_MSG_CHECKING([whether to enable ZY1000 minidriver])
|
||||||
@@ -529,7 +542,7 @@ case $host in
|
|||||||
is_win32=yes
|
is_win32=yes
|
||||||
parport_use_ppdev=no
|
parport_use_ppdev=no
|
||||||
|
|
||||||
AC_COMPILE_IFELSE(AC_LANG_PROGRAM([],[return __MINGW32__;]),
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[return __MINGW32__;]])],
|
||||||
[is_mingw=yes],[is_mingw=no])
|
[is_mingw=yes],[is_mingw=no])
|
||||||
if test $is_mingw = yes; then
|
if test $is_mingw = yes; then
|
||||||
AC_DEFINE(IS_MINGW, 1, [1 if building for MinGW.])
|
AC_DEFINE(IS_MINGW, 1, [1 if building for MinGW.])
|
||||||
@@ -622,6 +635,12 @@ else
|
|||||||
AC_DEFINE(BUILD_ZY1000, 0, [0 if you don't want ZY1000.])
|
AC_DEFINE(BUILD_ZY1000, 0, [0 if you don't want ZY1000.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test $build_zy1000_master = yes; then
|
||||||
|
AC_DEFINE(BUILD_ZY1000_MASTER, 1, [1 if you want ZY1000 JTAG master registers.])
|
||||||
|
else
|
||||||
|
AC_DEFINE(BUILD_ZY1000_MASTER, 0, [0 if you don't want ZY1000 JTAG master registers.])
|
||||||
|
fi
|
||||||
|
|
||||||
if test $build_at91rm9200 = yes; then
|
if test $build_at91rm9200 = yes; then
|
||||||
build_bitbang=yes
|
build_bitbang=yes
|
||||||
AC_DEFINE(BUILD_AT91RM9200, 1, [1 if you want at91rm9200.])
|
AC_DEFINE(BUILD_AT91RM9200, 1, [1 if you want at91rm9200.])
|
||||||
@@ -735,12 +754,32 @@ else
|
|||||||
AC_DEFINE(BUILD_RLINK, 0, [0 if you don't want the RLink JTAG driver.])
|
AC_DEFINE(BUILD_RLINK, 0, [0 if you don't want the RLink JTAG driver.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test $build_ulink = yes; then
|
||||||
|
AC_DEFINE(BUILD_ULINK, 1, [1 if you want the ULINK JTAG driver.])
|
||||||
|
else
|
||||||
|
AC_DEFINE(BUILD_ULINK, 0, [0 if you don't want the ULINK JTAG driver.])
|
||||||
|
fi
|
||||||
|
|
||||||
if test $build_armjtagew = yes; then
|
if test $build_armjtagew = yes; then
|
||||||
AC_DEFINE(BUILD_ARMJTAGEW, 1, [1 if you want the ARM-JTAG-EW JTAG driver.])
|
AC_DEFINE(BUILD_ARMJTAGEW, 1, [1 if you want the ARM-JTAG-EW JTAG driver.])
|
||||||
else
|
else
|
||||||
AC_DEFINE(BUILD_ARMJTAGEW, 0, [0 if you don't want the ARM-JTAG-EW JTAG driver.])
|
AC_DEFINE(BUILD_ARMJTAGEW, 0, [0 if you don't want the ARM-JTAG-EW JTAG driver.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test $build_buspirate = yes; then
|
||||||
|
AC_DEFINE(BUILD_BUSPIRATE, 1, [1 if you want the Buspirate JTAG driver.])
|
||||||
|
else
|
||||||
|
AC_DEFINE(BUILD_BUSPIRATE, 0, [0 if you don't want the Buspirate JTAG driver.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$use_internal_jimtcl" = yes; then
|
||||||
|
if test -f "$srcdir/jimtcl/configure.ac"; then
|
||||||
|
AX_CONFIG_SUBDIR_OPTION([jimtcl], [--with-jim-ext=nvp --disable-lineedit --disable-install-jim])
|
||||||
|
else
|
||||||
|
AC_MSG_ERROR([jimtcl not found, run git submodule init and git submodule update.])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
#-- Deal with MingW/Cygwin FTD2XX issues
|
#-- Deal with MingW/Cygwin FTD2XX issues
|
||||||
|
|
||||||
if test $is_win32 = yes; then
|
if test $is_win32 = yes; then
|
||||||
@@ -834,14 +873,23 @@ if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes ; then
|
|||||||
AC_MSG_ERROR([Option: --with-ftd2xx-linux-tardir appears wrong, cannot find: ${FTD2XX_H}])
|
AC_MSG_ERROR([Option: --with-ftd2xx-linux-tardir appears wrong, cannot find: ${FTD2XX_H}])
|
||||||
fi
|
fi
|
||||||
CFLAGS="$CFLAGS -I$with_ftd2xx_linux_tardir"
|
CFLAGS="$CFLAGS -I$with_ftd2xx_linux_tardir"
|
||||||
FTD2XX_LDFLAGS="-L$with_ftd2xx_linux_tardir"
|
if test $with_ftd2xx_lib = shared; then
|
||||||
FTD2XX_LIB="-lftd2xx"
|
FTD2XX_LDFLAGS="-L$with_ftd2xx_linux_tardir"
|
||||||
if test $with_ftd2xx_lib != shared; then
|
FTD2XX_LIB="-lftd2xx"
|
||||||
# Test #1 - Future proof - if/when ftdichip fixes their distro.
|
else
|
||||||
# Try it with the simple ".a" suffix.
|
# Test #1 - v1.0.x
|
||||||
FTD2XX_LIB="$with_ftd2xx_linux_tardir/static_lib/libftd2xx.a"
|
case "$host_cpu" in
|
||||||
if test -f "${FTD2XX_LIB}"; then
|
i?86|x86_32)
|
||||||
FTD2XX_LDFLAGS="${FTD2XX_LDFLAGS}/static_lib"
|
dir=build/i386;;
|
||||||
|
amd64|x86_64)
|
||||||
|
dir=build/x86_64;;
|
||||||
|
*)
|
||||||
|
dir=none;;
|
||||||
|
esac
|
||||||
|
if test -f "$with_ftd2xx_linux_tardir/$dir/libftd2xx.a"; then
|
||||||
|
FTD2XX_LDFLAGS="-L$with_ftd2xx_linux_tardir/$dir"
|
||||||
|
# Also needs -lrt
|
||||||
|
FTD2XX_LIB="-lftd2xx -lrt"
|
||||||
else
|
else
|
||||||
# Test Number2.
|
# Test Number2.
|
||||||
# Grr.. perhaps it exists as a version number?
|
# Grr.. perhaps it exists as a version number?
|
||||||
@@ -889,22 +937,17 @@ _CFLAGS=`eval echo $CFLAGS`
|
|||||||
LDFLAGS=$_LDFLAGS
|
LDFLAGS=$_LDFLAGS
|
||||||
CFLAGS=$_CFLAGS
|
CFLAGS=$_CFLAGS
|
||||||
|
|
||||||
AC_RUN_IFELSE([
|
AC_RUN_IFELSE([AC_LANG_PROGRAM([[
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
#if IS_WIN32
|
#if IS_WIN32
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#endif
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ftd2xx.h>
|
#include <ftd2xx.h>
|
||||||
|
]], [[
|
||||||
int
|
|
||||||
main( int argc, char **argv )
|
|
||||||
{
|
|
||||||
DWORD x;
|
DWORD x;
|
||||||
FT_GetLibraryVersion( &x );
|
FT_GetLibraryVersion( &x );
|
||||||
return 0;
|
]])], [
|
||||||
}
|
|
||||||
], [
|
|
||||||
AC_MSG_RESULT([Success!])
|
AC_MSG_RESULT([Success!])
|
||||||
], [
|
], [
|
||||||
AC_MSG_ERROR([Cannot build & run test program using ftd2xx.lib])
|
AC_MSG_ERROR([Cannot build & run test program using ftd2xx.lib])
|
||||||
@@ -913,15 +956,16 @@ main( int argc, char **argv )
|
|||||||
])
|
])
|
||||||
|
|
||||||
AC_MSG_CHECKING([for ftd2xx highspeed device support])
|
AC_MSG_CHECKING([for ftd2xx highspeed device support])
|
||||||
AC_COMPILE_IFELSE([
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
#if IS_WIN32
|
#if IS_WIN32
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#endif
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ftd2xx.h>
|
#include <ftd2xx.h>
|
||||||
|
|
||||||
DWORD x = FT_DEVICE_4232H;
|
DWORD x = FT_DEVICE_4232H;
|
||||||
], [
|
]], [])], [
|
||||||
AC_DEFINE(BUILD_FT2232_HIGHSPEED, [1],
|
AC_DEFINE(BUILD_FT2232_HIGHSPEED, [1],
|
||||||
[Support FT2232H/FT4232HS with FTD2XX or libftdi.])
|
[Support FT2232H/FT4232HS with FTD2XX or libftdi.])
|
||||||
build_ft2232_highspeed=yes
|
build_ft2232_highspeed=yes
|
||||||
@@ -953,13 +997,10 @@ if test $build_ft2232_libftdi = yes ; then
|
|||||||
LDFLAGS=$_LDFLAGS
|
LDFLAGS=$_LDFLAGS
|
||||||
CFLAGS=$_CFLAGS
|
CFLAGS=$_CFLAGS
|
||||||
|
|
||||||
AC_RUN_IFELSE([
|
AC_RUN_IFELSE([AC_LANG_PROGRAM([[
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ftdi.h>
|
#include <ftdi.h>
|
||||||
|
]], [[
|
||||||
int
|
|
||||||
main( int argc, char **argv )
|
|
||||||
{
|
|
||||||
struct ftdi_context *p;
|
struct ftdi_context *p;
|
||||||
p = ftdi_new();
|
p = ftdi_new();
|
||||||
if( p != NULL ){
|
if( p != NULL ){
|
||||||
@@ -968,8 +1009,7 @@ main( int argc, char **argv )
|
|||||||
fprintf( stderr, "calling ftdi_new() failed\n");
|
fprintf( stderr, "calling ftdi_new() failed\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
]])], [
|
||||||
], [
|
|
||||||
AC_MSG_RESULT([Success])
|
AC_MSG_RESULT([Success])
|
||||||
], [
|
], [
|
||||||
AC_MSG_ERROR([Cannot build & run test program using libftdi])
|
AC_MSG_ERROR([Cannot build & run test program using libftdi])
|
||||||
@@ -978,11 +1018,12 @@ main( int argc, char **argv )
|
|||||||
])
|
])
|
||||||
|
|
||||||
AC_MSG_CHECKING([for libftdi highspeed device support])
|
AC_MSG_CHECKING([for libftdi highspeed device support])
|
||||||
AC_COMPILE_IFELSE([
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ftdi.h>
|
#include <ftdi.h>
|
||||||
|
]], [[
|
||||||
enum ftdi_chip_type x = TYPE_2232H;
|
enum ftdi_chip_type x = TYPE_2232H;
|
||||||
], [
|
]])], [
|
||||||
AC_DEFINE(BUILD_FT2232_HIGHSPEED, [1],
|
AC_DEFINE(BUILD_FT2232_HIGHSPEED, [1],
|
||||||
[Support FT2232H/FT4232HS with FTD2XX or libftdi.])
|
[Support FT2232H/FT4232HS with FTD2XX or libftdi.])
|
||||||
build_ft2232_highspeed=yes
|
build_ft2232_highspeed=yes
|
||||||
@@ -1003,7 +1044,7 @@ fi
|
|||||||
# check for usb.h when a driver will require it
|
# check for usb.h when a driver will require it
|
||||||
build_usb=no
|
build_usb=no
|
||||||
if test $build_jlink = yes -o $build_vsllink = yes -o $build_usbprog = yes -o \
|
if test $build_jlink = yes -o $build_vsllink = yes -o $build_usbprog = yes -o \
|
||||||
$build_rlink = yes -o $build_armjtagew = yes
|
$build_rlink = yes -o $build_ulink = yes -o $build_armjtagew = yes
|
||||||
then
|
then
|
||||||
AC_CHECK_HEADERS([usb.h],[],
|
AC_CHECK_HEADERS([usb.h],[],
|
||||||
[AC_MSG_ERROR([usb.h is required to build some OpenOCD driver(s)])])
|
[AC_MSG_ERROR([usb.h is required to build some OpenOCD driver(s)])])
|
||||||
@@ -1017,8 +1058,8 @@ AM_CONDITIONAL(GIVEIO, test x$parport_use_giveio = xyes)
|
|||||||
AM_CONDITIONAL(EP93XX, test $build_ep93xx = yes)
|
AM_CONDITIONAL(EP93XX, test $build_ep93xx = yes)
|
||||||
AM_CONDITIONAL(ECOSBOARD, test $build_ecosboard = yes)
|
AM_CONDITIONAL(ECOSBOARD, test $build_ecosboard = yes)
|
||||||
AM_CONDITIONAL(ZY1000, test $build_zy1000 = yes)
|
AM_CONDITIONAL(ZY1000, test $build_zy1000 = yes)
|
||||||
|
AM_CONDITIONAL(ZY1000_MASTER, test $build_zy1000_master = yes)
|
||||||
AM_CONDITIONAL(IOUTIL, test $build_ioutil = yes)
|
AM_CONDITIONAL(IOUTIL, test $build_ioutil = yes)
|
||||||
AM_CONDITIONAL(HTTPD, test $build_httpd = yes)
|
|
||||||
AM_CONDITIONAL(AT91RM9200, test $build_at91rm9200 = yes)
|
AM_CONDITIONAL(AT91RM9200, test $build_at91rm9200 = yes)
|
||||||
AM_CONDITIONAL(BITBANG, test $build_bitbang = yes)
|
AM_CONDITIONAL(BITBANG, test $build_bitbang = yes)
|
||||||
AM_CONDITIONAL(FT2232_LIBFTDI, test $build_ft2232_libftdi = yes)
|
AM_CONDITIONAL(FT2232_LIBFTDI, test $build_ft2232_libftdi = yes)
|
||||||
@@ -1034,7 +1075,9 @@ AM_CONDITIONAL(OOCD_TRACE, test $build_oocd_trace = yes)
|
|||||||
AM_CONDITIONAL(JLINK, test $build_jlink = yes)
|
AM_CONDITIONAL(JLINK, test $build_jlink = yes)
|
||||||
AM_CONDITIONAL(VSLLINK, test $build_vsllink = yes)
|
AM_CONDITIONAL(VSLLINK, test $build_vsllink = yes)
|
||||||
AM_CONDITIONAL(RLINK, test $build_rlink = yes)
|
AM_CONDITIONAL(RLINK, test $build_rlink = yes)
|
||||||
|
AM_CONDITIONAL(ULINK, test $build_ulink = yes)
|
||||||
AM_CONDITIONAL(ARMJTAGEW, test $build_armjtagew = yes)
|
AM_CONDITIONAL(ARMJTAGEW, test $build_armjtagew = yes)
|
||||||
|
AM_CONDITIONAL(BUSPIRATE, test $build_buspirate = yes)
|
||||||
AM_CONDITIONAL(USB, test $build_usb = yes)
|
AM_CONDITIONAL(USB, test $build_usb = yes)
|
||||||
AM_CONDITIONAL(IS_CYGWIN, test $is_cygwin = yes)
|
AM_CONDITIONAL(IS_CYGWIN, test $is_cygwin = yes)
|
||||||
AM_CONDITIONAL(IS_MINGW, test $is_mingw = yes)
|
AM_CONDITIONAL(IS_MINGW, test $is_mingw = yes)
|
||||||
@@ -1045,14 +1088,16 @@ AM_CONDITIONAL(BITQ, test $build_bitq = yes)
|
|||||||
AM_CONDITIONAL(MINIDRIVER, test $build_minidriver = yes)
|
AM_CONDITIONAL(MINIDRIVER, test $build_minidriver = yes)
|
||||||
AM_CONDITIONAL(MINIDRIVER_DUMMY, test $build_minidriver_dummy = yes)
|
AM_CONDITIONAL(MINIDRIVER_DUMMY, test $build_minidriver_dummy = yes)
|
||||||
|
|
||||||
|
AM_CONDITIONAL(INTERNAL_JIMTCL, test $use_internal_jimtcl = yes)
|
||||||
|
|
||||||
# Look for environ alternatives. Possibility #1: is environ in unistd.h or stdlib.h?
|
# Look for environ alternatives. Possibility #1: is environ in unistd.h or stdlib.h?
|
||||||
AC_MSG_CHECKING([for environ in unistd.h and stdlib.h])
|
AC_MSG_CHECKING([for environ in unistd.h and stdlib.h])
|
||||||
AC_COMPILE_IFELSE([
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
int main(int argc, char **argv) { char **ep = environ; }
|
]], [[char **ep = environ;]]
|
||||||
], [
|
)], [
|
||||||
AC_MSG_RESULT([yes])
|
AC_MSG_RESULT([yes])
|
||||||
has_environ=yes
|
has_environ=yes
|
||||||
], [
|
], [
|
||||||
@@ -1060,10 +1105,10 @@ int main(int argc, char **argv) { char **ep = environ; }
|
|||||||
|
|
||||||
# Possibility #2: can environ be found in an available library?
|
# Possibility #2: can environ be found in an available library?
|
||||||
AC_MSG_CHECKING([for extern environ])
|
AC_MSG_CHECKING([for extern environ])
|
||||||
AC_LINK_IFELSE([
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
int main(int argc, char **argv) { char **ep = environ; }
|
]], [[char **ep = environ;]]
|
||||||
], [
|
)], [
|
||||||
AC_DEFINE(NEED_ENVIRON_EXTERN, [1], [Must declare 'environ' to use it.])
|
AC_DEFINE(NEED_ENVIRON_EXTERN, [1], [Must declare 'environ' to use it.])
|
||||||
has_environ=yes
|
has_environ=yes
|
||||||
], [
|
], [
|
||||||
@@ -1079,7 +1124,7 @@ fi
|
|||||||
AC_DEFINE([_GNU_SOURCE],[1],[Use GNU C library extensions (e.g. stdndup).])
|
AC_DEFINE([_GNU_SOURCE],[1],[Use GNU C library extensions (e.g. stdndup).])
|
||||||
|
|
||||||
# set default gcc warnings
|
# set default gcc warnings
|
||||||
GCC_WARNINGS="-Wall -Wstrict-prototypes -Wformat-security"
|
GCC_WARNINGS="-Wall -Wstrict-prototypes -Wformat-security -Wshadow"
|
||||||
if test "${gcc_wextra}" = yes; then
|
if test "${gcc_wextra}" = yes; then
|
||||||
GCC_WARNINGS="${GCC_WARNINGS} -Wextra -Wno-unused-parameter"
|
GCC_WARNINGS="${GCC_WARNINGS} -Wextra -Wno-unused-parameter"
|
||||||
GCC_WARNINGS="${GCC_WARNINGS} -Wbad-function-cast"
|
GCC_WARNINGS="${GCC_WARNINGS} -Wbad-function-cast"
|
||||||
@@ -1142,9 +1187,11 @@ AC_OUTPUT(dnl
|
|||||||
src/helper/Makefile dnl
|
src/helper/Makefile dnl
|
||||||
src/jtag/Makefile dnl
|
src/jtag/Makefile dnl
|
||||||
src/jtag/drivers/Makefile dnl
|
src/jtag/drivers/Makefile dnl
|
||||||
|
src/transport/Makefile dnl
|
||||||
src/xsvf/Makefile dnl
|
src/xsvf/Makefile dnl
|
||||||
src/svf/Makefile dnl
|
src/svf/Makefile dnl
|
||||||
src/target/Makefile dnl
|
src/target/Makefile dnl
|
||||||
|
src/rtos/Makefile dnl
|
||||||
src/server/Makefile dnl
|
src/server/Makefile dnl
|
||||||
src/flash/Makefile dnl
|
src/flash/Makefile dnl
|
||||||
src/flash/nor/Makefile dnl
|
src/flash/nor/Makefile dnl
|
||||||
|
|||||||
68
contrib/coresight-trace.txt
Normal file
68
contrib/coresight-trace.txt
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
+OpenOCD and CoreSight Tracing
|
||||||
|
+
|
||||||
|
Many recent ARM chips (Using e..g. Cortex-M3 and
|
||||||
|
Cortex-M4 cores) support CoreSight debug/trace.
|
||||||
|
This note sketches an approach currently planned for those cores
|
||||||
|
with OpenOCD.
|
||||||
|
|
||||||
|
This tracing data can help debug and tune ARM software, but not
|
||||||
|
all cores support tracing. Some support more extensive tracing
|
||||||
|
other cores with trace support +should be able to use the same
|
||||||
|
approach and maybe some of the same analysis code.
|
||||||
|
|
||||||
|
+the Cortex-M3 is assumed here to be the
|
||||||
|
+core in use, for simplicity and to reflect current OpenOCD users.
|
||||||
|
|
||||||
|
|
||||||
|
This note summarizes a software model to generate, collect, and
|
||||||
|
analyze such trace data . That is not fully implemented as of early
|
||||||
|
January 2011, +and thus is not *yet* usable.
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+Some microcontroller cores support a low pin-count Single-wire trace,
|
||||||
|
with a mode where +trace data is emitted (usually to a UART. To use
|
||||||
|
this mode, +SWD must be in use.
|
||||||
|
+At this writing, OpenOCD SWD support is not yet complete either.
|
||||||
|
|
||||||
|
(There are also multi-wire trace ports requiring more complex debug
|
||||||
|
adapters than OpenOCD currently supports, and offering richer data.
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+* ENABLING involves activating SWD and (single wire) trace.
|
||||||
|
+
|
||||||
|
+current expectations are that OpenOCD itself will handle enabling;
|
||||||
|
activating single wire trace involves a debug adapter interaction, and
|
||||||
|
collecting that trace data requires particular (re)wiring.
|
||||||
|
+
|
||||||
|
+* CONFIGURATION involves setting up ITM and/or ETM modules to emit the
|
||||||
|
+desired data from the Cortex core. (This might include dumping
|
||||||
|
+event counters printf-style messages; code profiling; and more. Not all
|
||||||
|
+cores offer the same trace capabilities.
|
||||||
|
+
|
||||||
|
+current expectations are that Tcl scripts will be used to configure these
|
||||||
|
+modules for the desired tracing, by direct writes to registers. In some
|
||||||
|
+cases (as with RTOS event tracking and similar messaging, this might
|
||||||
|
+be augmented or replaced by user code running on the ARM core.
|
||||||
|
+
|
||||||
|
+COLLECTION involves reading that trace data, probably through UART, and
|
||||||
|
+saving it in a useful format to analyse For now, deferred analysis modes
|
||||||
|
are assumed, not than real-time or interactive ones.
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+current expectations are to to dump data in text using contrib/itmdump.c
|
||||||
|
+or derived tools, and to post-process it into reports. Such reports might
|
||||||
|
+include program messaging (such as application data streams via ITM, maybe
|
||||||
|
+using printf type messaging; code coverage analysis or so forth. Recent
|
||||||
|
+versions of CMSIS software reserve some ITM codespace for RTOS event
|
||||||
|
tracing and include ITM messaging support.
|
||||||
|
Clearly some of that data would be valuable for interactive debugging.
|
||||||
|
+
|
||||||
|
+Should someone get ambitious, GUI reports should be possible. GNU tools
|
||||||
|
+for simpler reports like gprof may be simpler to support at first.
|
||||||
|
+In any case, OpenOCD is not currently GUI-oriented. Accordingly, we now
|
||||||
|
+expect any such graphics to come from postprocessing.
|
||||||
|
|
||||||
|
measurments for RTOS event timings should also be easy to collect.
|
||||||
|
+Examples include context and message switch times, as well as times
|
||||||
|
for application interactions.
|
||||||
|
+
|
||||||
91
contrib/gen-stellaris-part-header.pl
Executable file
91
contrib/gen-stellaris-part-header.pl
Executable file
@@ -0,0 +1,91 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
# Automatically generates the StellarisParts struct in src/flash/nor/stellaris.c
|
||||||
|
# Uses the header files from TI/Luminary's StellarisWare complete Firmware Development Package
|
||||||
|
# available from: http://www.luminarymicro.com/products/software_updates.html
|
||||||
|
|
||||||
|
$comment = "// Autogenerated by contrib/gen-stellaris-part-header.pl
|
||||||
|
// From Stellaris Firmware Development Package revision";
|
||||||
|
|
||||||
|
$struct_header = "static struct {
|
||||||
|
uint32_t partno;
|
||||||
|
const char *partname;
|
||||||
|
} StellarisParts[] =
|
||||||
|
{
|
||||||
|
";
|
||||||
|
|
||||||
|
$struct_footer = "\t{0,\"Unknown part\"}\n};\n";
|
||||||
|
|
||||||
|
$#ARGV == 1 || die "Usage: $0 <inc directory> <output file>\n";
|
||||||
|
-d $ARGV[0] || die $ARGV[0]." is not a directory\n";
|
||||||
|
$dir = $ARGV[0];
|
||||||
|
-f $ARGV[1] || die $ARGV[1]." is not a file\n";
|
||||||
|
$file = $ARGV[1];
|
||||||
|
print STDERR "Scanning $dir, Updating $file\n";
|
||||||
|
|
||||||
|
opendir(DIR, $dir) || die "can't open $dir: $!";
|
||||||
|
@files = readdir(DIR);
|
||||||
|
closedir(DIR);
|
||||||
|
|
||||||
|
@short_files = sort(grep(/lm3s...\.h/, @files));
|
||||||
|
@long_files = sort(grep(/lm3s....\.h/, @files));
|
||||||
|
|
||||||
|
$ver = 0;
|
||||||
|
$new_struct = $struct_header;
|
||||||
|
process_file(@short_files);
|
||||||
|
process_file(@long_files);
|
||||||
|
$new_struct .= $struct_footer;
|
||||||
|
|
||||||
|
$dump = "$comment $ver\n$new_struct";
|
||||||
|
{
|
||||||
|
local($/, *INPUT);
|
||||||
|
open(INPUT, $file) || die "can't open $file: $!";
|
||||||
|
$contents = <INPUT>;
|
||||||
|
close(INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
$old_struct = qr/((^\/\/.*?\n)*)\Q$struct_header\E.*?$struct_footer/sm;
|
||||||
|
$contents =~ s/$old_struct/$dump/;
|
||||||
|
open(OUTPUT, ">$file") || die "can't open file $file for writing: $!";
|
||||||
|
print OUTPUT $contents;
|
||||||
|
close(OUTPUT);
|
||||||
|
|
||||||
|
sub process_file {
|
||||||
|
foreach $h_file (@_) {
|
||||||
|
($base) = ($h_file =~ m/lm3s(.{3,4})\.h/ig);
|
||||||
|
$base = uc($base);
|
||||||
|
local($/, *FILE);
|
||||||
|
open(FILE, "$dir/$h_file");
|
||||||
|
$content = <FILE>;
|
||||||
|
close(FILE);
|
||||||
|
$invalid = 0;
|
||||||
|
if ($content =~ /This is part of revision (\d+) of/) {
|
||||||
|
if ($ver != 0 and $ver != $1) {
|
||||||
|
print STDERR "File version mismatch: $ver != $1\n";
|
||||||
|
$ver = max($ver, $1);
|
||||||
|
} else {
|
||||||
|
$ver = $1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($content =~ /SYSCTL_DID1_VER_[^M]\s+0x(\S+)/) {
|
||||||
|
$did1_ver = hex($1);
|
||||||
|
} else {
|
||||||
|
print STDERR "$h_file is missing SYSCTL_DID1_VER\n";
|
||||||
|
$did1_ver = 255;
|
||||||
|
$invalid = 1;
|
||||||
|
}
|
||||||
|
if ($content =~ /SYSCTL_DID1_PRTNO_$base\s+0x(\S+)/) {
|
||||||
|
$prtno = hex($1);
|
||||||
|
} else {
|
||||||
|
print STDERR "$h_file is missing SYSCTL_DID1_PRTNO\n";
|
||||||
|
$prtno = 0;
|
||||||
|
$invalid = 1;
|
||||||
|
}
|
||||||
|
$id = ($did1_ver | $prtno) >> 16;
|
||||||
|
$new_member = sprintf "{0x%04X,\"LM3S%s\"},", $id, $base;
|
||||||
|
if ($invalid == 1) {
|
||||||
|
#$new_struct .= "\t//$new_member\t// Invalid\n";
|
||||||
|
} else {
|
||||||
|
$new_struct .= "\t$new_member\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
441
contrib/itmdump.c
Normal file
441
contrib/itmdump.c
Normal file
@@ -0,0 +1,441 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010 by David Brownell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simple utility to parse and dump ARM Cortex-M3 SWO trace output. Once the
|
||||||
|
* mechanisms work right, this information can be used for various purposes
|
||||||
|
* including profiling (particularly easy for flat PC-sample profiles) and
|
||||||
|
* for debugging.
|
||||||
|
*
|
||||||
|
* SWO is the Single Wire Output found on some ARM cores, most notably on the
|
||||||
|
* Cortex-M3. It combines data from several sources:
|
||||||
|
*
|
||||||
|
* - Software trace (ITM): so-called "printf-style" application messaging
|
||||||
|
* using "ITM stimulus ports"; and differential timestamps.
|
||||||
|
* - Hardware trace (DWT): for profiling counters and comparator matches.
|
||||||
|
* - TPIU may issue sync packets.
|
||||||
|
*
|
||||||
|
* The trace data format is defined in Appendix E, "Debug ITM and DWT packet
|
||||||
|
* protocol", of the ARMv7-M Architecture Reference Manual (DDI 0403C). It
|
||||||
|
* is a superset of the ITM data format from the Coresight TRM.
|
||||||
|
*
|
||||||
|
* The trace data has two encodings. The working assumption is that data
|
||||||
|
* gets into this program using the UART encoding.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Example ITM trace word (0xWWXXYYZZ) parsing for task events, sent
|
||||||
|
* on port 31 (Reserved for "the" RTOS in CMSIS v1.30)
|
||||||
|
* WWXX: event code (0..3 pre-assigned, 4..15 reserved)
|
||||||
|
* YY: task priority
|
||||||
|
* ZZ: task number
|
||||||
|
*
|
||||||
|
* NOTE that this specific encoding could be space-optimized; and that
|
||||||
|
* trace data streams could also be history-sensitive.
|
||||||
|
*/
|
||||||
|
static void show_task(int port, unsigned data)
|
||||||
|
{
|
||||||
|
unsigned code = data >> 16;
|
||||||
|
char buf[16];
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case 0:
|
||||||
|
strcpy(buf, "run");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
strcpy(buf, "block");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
strcpy(buf, "create");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
strcpy(buf, "destroy");
|
||||||
|
break;
|
||||||
|
/* 4..15 reserved for other infrastructure ops */
|
||||||
|
default:
|
||||||
|
sprintf(buf, "code %d", code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("TASK %d, pri %d: %s",
|
||||||
|
(data >> 0) & 0xff,
|
||||||
|
(data >> 8) & 0xff,
|
||||||
|
buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_reserved(FILE *f, char *label, int c)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
printf("%s - %#02x", label, c);
|
||||||
|
|
||||||
|
for (i = 0; (c & 0x80) && i < 4; i++) {
|
||||||
|
c = fgetc(f);
|
||||||
|
if (c == EOF) {
|
||||||
|
printf("(ERROR %d - %s) ", errno, strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf(" %#02x", c);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool read_varlen(FILE *f, int c, unsigned *value)
|
||||||
|
{
|
||||||
|
unsigned size;
|
||||||
|
unsigned char buf[4];
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
*value = 0;
|
||||||
|
|
||||||
|
switch (c & 3) {
|
||||||
|
case 3:
|
||||||
|
size = 4;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
size = 2;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
size = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("INVALID SIZE\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof buf);
|
||||||
|
if (fread(buf, 1, size, f) != size)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
*value = (buf[3] << 24)
|
||||||
|
+ (buf[2] << 16)
|
||||||
|
+ (buf[2] << 8)
|
||||||
|
+ (buf[0] << 0);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
err:
|
||||||
|
printf("(ERROR %d - %s)\n", errno, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_hard(FILE *f, int c)
|
||||||
|
{
|
||||||
|
unsigned type = c >> 3;
|
||||||
|
unsigned value;
|
||||||
|
unsigned size;
|
||||||
|
char *label;
|
||||||
|
|
||||||
|
printf("DWT - ", type);
|
||||||
|
|
||||||
|
if (!read_varlen(f, c, &value))
|
||||||
|
return;
|
||||||
|
printf("%#x", value);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 0: /* event counter wrapping */
|
||||||
|
printf("overflow %s%s%s%s%s%s",
|
||||||
|
(value & (1 << 5)) ? "cyc " : "",
|
||||||
|
(value & (1 << 4)) ? "fold " : "",
|
||||||
|
(value & (1 << 3)) ? "lsu " : "",
|
||||||
|
(value & (1 << 2)) ? "slp " : "",
|
||||||
|
(value & (1 << 1)) ? "exc " : "",
|
||||||
|
(value & (1 << 0)) ? "cpi " : "");
|
||||||
|
break;
|
||||||
|
case 1: /* exception tracing */
|
||||||
|
switch (value >> 12) {
|
||||||
|
case 1:
|
||||||
|
label = "entry to";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
label = "exit from";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
label = "return to";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
label = "?";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("%s exception %d", label, value & 0x1ff);
|
||||||
|
break;
|
||||||
|
case 2: /* PC sampling */
|
||||||
|
if (c == 0x15)
|
||||||
|
printf("PC - sleep");
|
||||||
|
else
|
||||||
|
printf("PC - %#08x", value);
|
||||||
|
break;
|
||||||
|
case 8: /* data tracing, pc value */
|
||||||
|
case 10:
|
||||||
|
case 12:
|
||||||
|
case 14:
|
||||||
|
printf("Data trace %d, PC %#08x", (c >> 4) & 3, value);
|
||||||
|
/* optionally followed by data value */
|
||||||
|
break;
|
||||||
|
case 9: /* data tracing, address offset */
|
||||||
|
case 11:
|
||||||
|
case 13:
|
||||||
|
case 15:
|
||||||
|
printf("Data trace %d, address offset %#04x",
|
||||||
|
(c >> 4) & 3, value);
|
||||||
|
/* always followed by data value */
|
||||||
|
break;
|
||||||
|
case 16 ... 23: /* data tracing, data value */
|
||||||
|
printf("Data trace %d, ", (c >> 4) & 3);
|
||||||
|
label = (c & 0x8) ? "write" : "read";
|
||||||
|
switch (c & 3) {
|
||||||
|
case 3:
|
||||||
|
printf("word %s, value %#08x", label, value);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
printf("halfword %s, value %#04x", label, value);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
printf("byte %s, value %#02x", label, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("UNDEFINED");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Table of SWIT (SoftWare InstrumentTation) message dump formats, for
|
||||||
|
* ITM port 0..31 application data.
|
||||||
|
*
|
||||||
|
* Eventually this should be customizable; all usage is application defined.
|
||||||
|
*
|
||||||
|
* REVISIT there can be up to 256 trace ports, via "ITM Extension" packets
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
int port;
|
||||||
|
void (*show)(int port, unsigned data);
|
||||||
|
} format[] = {
|
||||||
|
{ .port = 31, .show = show_task, },
|
||||||
|
};
|
||||||
|
|
||||||
|
static void show_swit(FILE *f, int c)
|
||||||
|
{
|
||||||
|
unsigned size;
|
||||||
|
unsigned port = c >> 3;
|
||||||
|
unsigned char buf[4];
|
||||||
|
unsigned value = 0;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
printf("SWIT %u - ", port);
|
||||||
|
|
||||||
|
if (!read_varlen(f, c, &value))
|
||||||
|
return;
|
||||||
|
printf("%#08x", value);
|
||||||
|
|
||||||
|
for (i = 0; i <= sizeof(format) / sizeof(format[0]); i++) {
|
||||||
|
if (format[i].port == port) {
|
||||||
|
printf(", ");
|
||||||
|
format[i].show(port, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
return;
|
||||||
|
|
||||||
|
err:
|
||||||
|
printf("(ERROR %d - %s)\n", errno, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_timestamp(FILE *f, int c)
|
||||||
|
{
|
||||||
|
unsigned counter = 0;
|
||||||
|
char *label = "";
|
||||||
|
bool delayed = false;
|
||||||
|
|
||||||
|
printf("TIMESTAMP - ");
|
||||||
|
|
||||||
|
/* Format 2: header only */
|
||||||
|
if (!(c & 0x80)) {
|
||||||
|
switch (c) {
|
||||||
|
case 0: /* sync packet -- coding error! */
|
||||||
|
case 0x70: /* overflow -- ditto! */
|
||||||
|
printf("ERROR - %#02x\n", c);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* synchronous to ITM */
|
||||||
|
counter = c >> 4;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Format 1: one to four bytes of data too */
|
||||||
|
switch (c) {
|
||||||
|
default:
|
||||||
|
label = ", reserved control\n";
|
||||||
|
break;
|
||||||
|
case 0xc:
|
||||||
|
/* synchronous to ITM */
|
||||||
|
break;
|
||||||
|
case 0xd:
|
||||||
|
label = ", timestamp delayed";
|
||||||
|
delayed = true;
|
||||||
|
break;
|
||||||
|
case 0xe:
|
||||||
|
label = ", packet delayed";
|
||||||
|
delayed = true;
|
||||||
|
break;
|
||||||
|
case 0xf:
|
||||||
|
label = ", packet and timetamp delayed";
|
||||||
|
delayed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = fgetc(f);
|
||||||
|
if (c == EOF)
|
||||||
|
goto err;
|
||||||
|
counter = c & 0x7f;
|
||||||
|
if (!(c & 0x80))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
c = fgetc(f);
|
||||||
|
if (c == EOF)
|
||||||
|
goto err;
|
||||||
|
counter |= (c & 0x7f) << 7;
|
||||||
|
if (!(c & 0x80))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
c = fgetc(f);
|
||||||
|
if (c == EOF)
|
||||||
|
goto err;
|
||||||
|
counter |= (c & 0x7f) << 14;
|
||||||
|
if (!(c & 0x80))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
c = fgetc(f);
|
||||||
|
if (c == EOF)
|
||||||
|
goto err;
|
||||||
|
counter |= (c & 0x7f) << 21;
|
||||||
|
|
||||||
|
done:
|
||||||
|
/* REVISIT should we try to convert from delta values? */
|
||||||
|
printf("+%u%s\n", counter, label);
|
||||||
|
return;
|
||||||
|
|
||||||
|
err:
|
||||||
|
printf("(ERROR %d - %s) ", errno, strerror(errno));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
FILE *f = stdin;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
/* parse arguments */
|
||||||
|
while ((c = getopt(argc, argv, "f:")) != EOF) {
|
||||||
|
switch (c) {
|
||||||
|
case 'f':
|
||||||
|
/* e.g. from UART connected to /dev/ttyUSB0 */
|
||||||
|
f = fopen(optarg, "r");
|
||||||
|
if (!f) {
|
||||||
|
perror(optarg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage:
|
||||||
|
fprintf(stderr, "usage: %s [-f input]",
|
||||||
|
basename(argv[0]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse data ... records have a header then data bytes.
|
||||||
|
* NOTE: we assume getc() deals in 8-bit bytes.
|
||||||
|
*/
|
||||||
|
bool overflow = false;
|
||||||
|
|
||||||
|
while ((c = getc(f)) != EOF) {
|
||||||
|
|
||||||
|
/* Sync packet ... 7 zeroes, 0x80 */
|
||||||
|
if (c == 0) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++) {
|
||||||
|
c = fgetc(f);
|
||||||
|
if (c == EOF)
|
||||||
|
break;
|
||||||
|
if (c != 0)
|
||||||
|
goto bad_sync;
|
||||||
|
}
|
||||||
|
c = fgetc(f);
|
||||||
|
if (c == 0x80) {
|
||||||
|
printf("SYNC\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bad_sync:
|
||||||
|
printf("BAD SYNC\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Overflow packet */
|
||||||
|
if (c == 0x70) {
|
||||||
|
/* REVISIT later, report just what overflowed!
|
||||||
|
* Timestamp and SWIT can happen. Non-ITM too?
|
||||||
|
*/
|
||||||
|
overflow = true;
|
||||||
|
printf("OVERFLOW ...\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
overflow = false;
|
||||||
|
|
||||||
|
switch (c & 0x0f) {
|
||||||
|
case 0x00: /* Timestamp */
|
||||||
|
show_timestamp(f, c);
|
||||||
|
break;
|
||||||
|
case 0x04: /* "Reserved" */
|
||||||
|
show_reserved(f, "RESERVED", c);
|
||||||
|
break;
|
||||||
|
case 0x08: /* ITM Extension */
|
||||||
|
/* FIXME someday, handle these ... */
|
||||||
|
show_reserved(f, "ITM EXT", c);
|
||||||
|
break;
|
||||||
|
case 0x0c: /* DWT Extension */
|
||||||
|
show_reserved(f, "DWT EXT", c);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (c & 4)
|
||||||
|
show_hard(f, c);
|
||||||
|
else
|
||||||
|
show_swit(f, c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
33
contrib/loaders/README
Normal file
33
contrib/loaders/README
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
Included in these directories are the src to the various ram loaders used
|
||||||
|
within openocd.
|
||||||
|
|
||||||
|
** target checksum loaders **
|
||||||
|
|
||||||
|
checksum/armv4_5_crc.s :
|
||||||
|
- ARMv4 and ARMv5 checksum loader : see target/arm_crc_code.c:arm_crc_code
|
||||||
|
|
||||||
|
checksum/armv7m_crc.s :
|
||||||
|
- ARMv7m checksum loader : see target/armv7m.c:cortex_m3_crc_code
|
||||||
|
|
||||||
|
checksum/mips32.s :
|
||||||
|
- MIPS32 checksum loader : see target/mips32.c:mips_crc_code
|
||||||
|
|
||||||
|
** target flash loaders **
|
||||||
|
|
||||||
|
flash/pic32mx.s :
|
||||||
|
- Microchip PIC32 flash loader : see flash/nor/pic32mx.c:pic32mx_flash_write_code
|
||||||
|
|
||||||
|
flash/stellaris.s :
|
||||||
|
- TI Stellaris flash loader : see flash/nor/stellaris.c:stellaris_write_code
|
||||||
|
|
||||||
|
flash/stm32x.s :
|
||||||
|
- ST STM32 flash loader : see flash/nor/stm32x.c:stm32x_flash_write_code
|
||||||
|
|
||||||
|
flash/str7x.s :
|
||||||
|
- ST STR7 flash loader : see flash/nor/str7x.c:str7x_flash_write_code
|
||||||
|
|
||||||
|
flash/str9x.s :
|
||||||
|
- ST STR9 flash loader : see flash/nor/str9x.c:str9x_flash_write_code
|
||||||
|
|
||||||
|
Spencer Oliver
|
||||||
|
spen@spen-soft.co.uk
|
||||||
58
contrib/loaders/checksum/armv4_5_crc.s
Normal file
58
contrib/loaders/checksum/armv4_5_crc.s
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010 by Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
r0 - address in - crc out
|
||||||
|
r1 - char count
|
||||||
|
*/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.arm
|
||||||
|
|
||||||
|
_start:
|
||||||
|
main:
|
||||||
|
mov r2, r0
|
||||||
|
mov r0, #0xffffffff /* crc */
|
||||||
|
mov r3, r1
|
||||||
|
mov r4, #0
|
||||||
|
b ncomp
|
||||||
|
nbyte:
|
||||||
|
ldrb r1, [r2, r4]
|
||||||
|
ldr r7, CRC32XOR
|
||||||
|
eor r0, r0, r1, asl #24
|
||||||
|
mov r5, #0
|
||||||
|
loop:
|
||||||
|
cmp r0, #0
|
||||||
|
mov r6, r0, asl #1
|
||||||
|
add r5, r5, #1
|
||||||
|
mov r0, r6
|
||||||
|
eorlt r0, r6, r7
|
||||||
|
cmp r5, #8
|
||||||
|
bne loop
|
||||||
|
add r4, r4, #1
|
||||||
|
ncomp:
|
||||||
|
cmp r4, r3
|
||||||
|
bne nbyte
|
||||||
|
end:
|
||||||
|
bkpt #0
|
||||||
|
|
||||||
|
CRC32XOR: .word 0x04c11db7
|
||||||
|
|
||||||
|
.end
|
||||||
66
contrib/loaders/checksum/armv7m_crc.s
Normal file
66
contrib/loaders/checksum/armv7m_crc.s
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010 by Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
parameters:
|
||||||
|
r0 - address in - crc out
|
||||||
|
r1 - char count
|
||||||
|
*/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.syntax unified
|
||||||
|
.arch armv7-m
|
||||||
|
.thumb
|
||||||
|
.thumb_func
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
_start:
|
||||||
|
main:
|
||||||
|
mov r2, r0
|
||||||
|
mov r0, #0xffffffff /* crc */
|
||||||
|
mov r3, r1
|
||||||
|
mov r4, #0
|
||||||
|
b ncomp
|
||||||
|
nbyte:
|
||||||
|
ldrb r1, [r2, r4]
|
||||||
|
|
||||||
|
ldr r7, CRC32XOR
|
||||||
|
eor r0, r0, r1, asl #24
|
||||||
|
mov r5, #0
|
||||||
|
loop:
|
||||||
|
cmp r0, #0
|
||||||
|
mov r6, r0, asl #1
|
||||||
|
add r5, r5, #1
|
||||||
|
mov r0, r6
|
||||||
|
it lt
|
||||||
|
eorlt r0, r6, r7
|
||||||
|
cmp r5, #8
|
||||||
|
bne loop
|
||||||
|
|
||||||
|
add r4, r4, #1
|
||||||
|
ncomp:
|
||||||
|
cmp r4, r3
|
||||||
|
bne nbyte
|
||||||
|
bkpt #0
|
||||||
|
|
||||||
|
CRC32XOR: .word 0x04c11db7
|
||||||
|
|
||||||
|
.end
|
||||||
72
contrib/loaders/checksum/mips32.s
Normal file
72
contrib/loaders/checksum/mips32.s
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010 by Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
.global main
|
||||||
|
.text
|
||||||
|
.set noreorder
|
||||||
|
|
||||||
|
/* params:
|
||||||
|
* $a0 address in
|
||||||
|
* $a1 byte count
|
||||||
|
* vars
|
||||||
|
* $a0 crc
|
||||||
|
* $a1 crc data byte
|
||||||
|
* temps:
|
||||||
|
* t3 v0 a3 a2 t0 v1
|
||||||
|
*/
|
||||||
|
|
||||||
|
.ent main
|
||||||
|
main:
|
||||||
|
addiu $t4, $a0, 0 /* address in */
|
||||||
|
addiu $t2, $a1, 0 /* count */
|
||||||
|
|
||||||
|
addiu $a0, $zero, 0xffffffff /* a0 crc - result */
|
||||||
|
|
||||||
|
beq $zero, $zero, ncomp
|
||||||
|
addiu $t3, $zero, 0 /* clear bytes read */
|
||||||
|
|
||||||
|
nbyte:
|
||||||
|
lb $a1, ($t4) /* load byte from source address */
|
||||||
|
addi $t4, $t4, 1 /* inc byte count */
|
||||||
|
|
||||||
|
crc:
|
||||||
|
sll $a1, $a1, 24
|
||||||
|
lui $v0, 0x04c1
|
||||||
|
xor $a0, $a0, $a1
|
||||||
|
ori $a3, $v0, 0x1db7
|
||||||
|
addu $a2, $zero, $zero /* clear bit count */
|
||||||
|
loop:
|
||||||
|
sll $t0, $a0, 1
|
||||||
|
addiu $a2, $a2, 1 /* inc bit count */
|
||||||
|
slti $a0, $a0, 0
|
||||||
|
xor $t1, $t0, $a3
|
||||||
|
movn $t0, $t1, $a0
|
||||||
|
slti $v1, $a2, 8 /* 8bits processed */
|
||||||
|
bne $v1, $zero, loop
|
||||||
|
addu $a0, $t0, $zero
|
||||||
|
|
||||||
|
ncomp:
|
||||||
|
bne $t2, $t3, nbyte /* all bytes processed */
|
||||||
|
addiu $t3, $t3, 1
|
||||||
|
|
||||||
|
wait:
|
||||||
|
sdbbp
|
||||||
|
|
||||||
|
.end main
|
||||||
57
contrib/loaders/flash/armv4_5_cfi_intel_16.s
Normal file
57
contrib/loaders/flash/armv4_5_cfi_intel_16.s
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2005, 2007 by Dominic Rath *
|
||||||
|
* Dominic.Rath@gmx.de *
|
||||||
|
* Copyright (C) 2010 Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.arm
|
||||||
|
.arch armv4
|
||||||
|
|
||||||
|
.section .init
|
||||||
|
|
||||||
|
/* algorithm register usage:
|
||||||
|
* r0: source address (in RAM)
|
||||||
|
* r1: target address (in Flash)
|
||||||
|
* r2: count
|
||||||
|
* r3: flash write command
|
||||||
|
* r4: status byte (returned to host)
|
||||||
|
* r5: busy test pattern
|
||||||
|
* r6: error test pattern
|
||||||
|
*/
|
||||||
|
|
||||||
|
loop:
|
||||||
|
ldrh r4, [r0], #2
|
||||||
|
strh r3, [r1]
|
||||||
|
strh r4, [r1]
|
||||||
|
busy:
|
||||||
|
ldrh r4, [r1]
|
||||||
|
and r7, r4, r5
|
||||||
|
cmp r7, r5
|
||||||
|
bne busy
|
||||||
|
tst r4, r6
|
||||||
|
bne done
|
||||||
|
subs r2, r2, #1
|
||||||
|
beq done
|
||||||
|
add r1, r1, #2
|
||||||
|
b loop
|
||||||
|
done:
|
||||||
|
b done
|
||||||
|
|
||||||
|
.end
|
||||||
57
contrib/loaders/flash/armv4_5_cfi_intel_32.s
Normal file
57
contrib/loaders/flash/armv4_5_cfi_intel_32.s
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2005, 2007 by Dominic Rath *
|
||||||
|
* Dominic.Rath@gmx.de *
|
||||||
|
* Copyright (C) 2010 Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.arm
|
||||||
|
.arch armv4
|
||||||
|
|
||||||
|
.section .init
|
||||||
|
|
||||||
|
/* algorithm register usage:
|
||||||
|
* r0: source address (in RAM)
|
||||||
|
* r1: target address (in Flash)
|
||||||
|
* r2: count
|
||||||
|
* r3: flash write command
|
||||||
|
* r4: status byte (returned to host)
|
||||||
|
* r5: busy test pattern
|
||||||
|
* r6: error test pattern
|
||||||
|
*/
|
||||||
|
|
||||||
|
loop:
|
||||||
|
ldr r4, [r0], #4
|
||||||
|
str r3, [r1]
|
||||||
|
str r4, [r1]
|
||||||
|
busy:
|
||||||
|
ldr r4, [r1]
|
||||||
|
and r7, r4, r5
|
||||||
|
cmp r7, r5
|
||||||
|
bne busy
|
||||||
|
tst r4, r6
|
||||||
|
bne done
|
||||||
|
subs r2, r2, #1
|
||||||
|
beq done
|
||||||
|
add r1, r1, #4
|
||||||
|
b loop
|
||||||
|
done:
|
||||||
|
b done
|
||||||
|
|
||||||
|
.end
|
||||||
57
contrib/loaders/flash/armv4_5_cfi_intel_8.s
Normal file
57
contrib/loaders/flash/armv4_5_cfi_intel_8.s
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2005, 2007 by Dominic Rath *
|
||||||
|
* Dominic.Rath@gmx.de *
|
||||||
|
* Copyright (C) 2010 Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.arm
|
||||||
|
.arch armv4
|
||||||
|
|
||||||
|
.section .init
|
||||||
|
|
||||||
|
/* algorithm register usage:
|
||||||
|
* r0: source address (in RAM)
|
||||||
|
* r1: target address (in Flash)
|
||||||
|
* r2: count
|
||||||
|
* r3: flash write command
|
||||||
|
* r4: status byte (returned to host)
|
||||||
|
* r5: busy test pattern
|
||||||
|
* r6: error test pattern
|
||||||
|
*/
|
||||||
|
|
||||||
|
loop:
|
||||||
|
ldrb r4, [r0], #1
|
||||||
|
strb r3, [r1]
|
||||||
|
strb r4, [r1]
|
||||||
|
busy:
|
||||||
|
ldrb r4, [r1]
|
||||||
|
and r7, r4, r5
|
||||||
|
cmp r7, r5
|
||||||
|
bne busy
|
||||||
|
tst r4, r6
|
||||||
|
bne done
|
||||||
|
subs r2, r2, #1
|
||||||
|
beq done
|
||||||
|
add r1, r1, #1
|
||||||
|
b loop
|
||||||
|
done:
|
||||||
|
b done
|
||||||
|
|
||||||
|
.end
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright (C) 2005 by Dominic Rath *
|
* Copyright (C) 2005, 2007 by Dominic Rath *
|
||||||
* Dominic.Rath@gmx.de *
|
* Dominic.Rath@gmx.de *
|
||||||
* *
|
* Copyright (C) 2010 Spencer Oliver *
|
||||||
* LPC1700 support Copyright (C) 2009 by Audrius Urmanavicius *
|
* spen@spen-soft.co.uk *
|
||||||
* didele.deze@gmail.com *
|
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published by *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
@@ -20,52 +19,57 @@
|
|||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#ifndef LPC2000_H
|
|
||||||
#define LPC2000_H
|
|
||||||
|
|
||||||
typedef enum
|
.text
|
||||||
{
|
.arm
|
||||||
lpc2000_v1,
|
.arch armv4
|
||||||
lpc2000_v2,
|
|
||||||
lpc1700
|
|
||||||
} lpc2000_variant;
|
|
||||||
|
|
||||||
struct lpc2000_flash_bank
|
.section .init
|
||||||
{
|
|
||||||
lpc2000_variant variant;
|
|
||||||
struct working_area *iap_working_area;
|
|
||||||
uint32_t cclk;
|
|
||||||
int cmd51_dst_boundary;
|
|
||||||
int cmd51_can_256b;
|
|
||||||
int cmd51_can_8192b;
|
|
||||||
int calc_checksum;
|
|
||||||
uint32_t cmd51_max_buffer;
|
|
||||||
int checksum_vector;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum lpc2000_status_codes
|
/* input parameters - */
|
||||||
{
|
/* R0 = source address */
|
||||||
LPC2000_CMD_SUCCESS = 0,
|
/* R1 = destination address */
|
||||||
LPC2000_INVALID_COMMAND = 1,
|
/* R2 = number of writes */
|
||||||
LPC2000_SRC_ADDR_ERROR = 2,
|
/* R3 = flash write command */
|
||||||
LPC2000_DST_ADDR_ERROR = 3,
|
/* R4 = constant to mask DQ7 bits (also used for Dq5 with shift) */
|
||||||
LPC2000_SRC_ADDR_NOT_MAPPED = 4,
|
/* output parameters - */
|
||||||
LPC2000_DST_ADDR_NOT_MAPPED = 5,
|
/* R5 = 0x80 ok 0x00 bad */
|
||||||
LPC2000_COUNT_ERROR = 6,
|
/* temp registers - */
|
||||||
LPC2000_INVALID_SECTOR = 7,
|
/* R6 = value read from flash to test status */
|
||||||
LPC2000_SECTOR_NOT_BLANK = 8,
|
/* R7 = holding register */
|
||||||
LPC2000_SECTOR_NOT_PREPARED = 9,
|
/* unlock registers - */
|
||||||
LPC2000_COMPARE_ERROR = 10,
|
/* R8 = unlock1_addr */
|
||||||
LPC2000_BUSY = 11,
|
/* R9 = unlock1_cmd */
|
||||||
LPC2000_PARAM_ERROR = 12,
|
/* R10 = unlock2_addr */
|
||||||
LPC2000_ADDR_ERROR = 13,
|
/* R11 = unlock2_cmd */
|
||||||
LPC2000_ADDR_NOT_MAPPED = 14,
|
|
||||||
LPC2000_CMD_NOT_LOCKED = 15,
|
|
||||||
LPC2000_INVALID_CODE = 16,
|
|
||||||
LPC2000_INVALID_BAUD_RATE = 17,
|
|
||||||
LPC2000_INVALID_STOP_BIT = 18,
|
|
||||||
LPC2000_CRP_ENABLED = 19
|
|
||||||
|
|
||||||
};
|
code:
|
||||||
|
ldrh r5, [r0], #2
|
||||||
|
strh r9, [r8]
|
||||||
|
strh r11, [r10]
|
||||||
|
strh r3, [r8]
|
||||||
|
strh r5, [r1]
|
||||||
|
nop
|
||||||
|
busy:
|
||||||
|
ldrh r6, [r1]
|
||||||
|
eor r7, r5, r6
|
||||||
|
ands r7, r4, r7
|
||||||
|
beq cont /* b if DQ7 == Data7 */
|
||||||
|
ands r6, r6, r4, lsr #2
|
||||||
|
beq busy /* b if DQ5 low */
|
||||||
|
ldrh r6, [r1]
|
||||||
|
eor r7, r5, r6
|
||||||
|
ands r7, r4, r7
|
||||||
|
beq cont /* b if DQ7 == Data7 */
|
||||||
|
mov r5, #0 /* 0x0 - return 0x00, error */
|
||||||
|
bne done
|
||||||
|
cont:
|
||||||
|
subs r2, r2, #1 /* 0x1 */
|
||||||
|
moveq r5, #128 /* 0x80 */
|
||||||
|
beq done
|
||||||
|
add r1, r1, #2 /* 0x2 */
|
||||||
|
b code
|
||||||
|
done:
|
||||||
|
b done
|
||||||
|
|
||||||
#endif /* LPC2000_H */
|
.end
|
||||||
66
contrib/loaders/flash/armv4_5_cfi_span_16_dq7.s
Normal file
66
contrib/loaders/flash/armv4_5_cfi_span_16_dq7.s
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2005, 2007 by Dominic Rath *
|
||||||
|
* Dominic.Rath@gmx.de *
|
||||||
|
* Copyright (C) 2010 Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.arm
|
||||||
|
.arch armv4
|
||||||
|
|
||||||
|
.section .init
|
||||||
|
|
||||||
|
/* input parameters - */
|
||||||
|
/* R0 = source address */
|
||||||
|
/* R1 = destination address */
|
||||||
|
/* R2 = number of writes */
|
||||||
|
/* R3 = flash write command */
|
||||||
|
/* R4 = constant to mask DQ7 bits (also used for Dq5 with shift) */
|
||||||
|
/* output parameters - */
|
||||||
|
/* R5 = 0x80 ok 0x00 bad */
|
||||||
|
/* temp registers - */
|
||||||
|
/* R6 = value read from flash to test status */
|
||||||
|
/* R7 = holding register */
|
||||||
|
/* unlock registers - */
|
||||||
|
/* R8 = unlock1_addr */
|
||||||
|
/* R9 = unlock1_cmd */
|
||||||
|
/* R10 = unlock2_addr */
|
||||||
|
/* R11 = unlock2_cmd */
|
||||||
|
|
||||||
|
code:
|
||||||
|
ldrh r5, [r0], #2
|
||||||
|
strh r9, [r8]
|
||||||
|
strh r11, [r10]
|
||||||
|
strh r3, [r8]
|
||||||
|
strh r5, [r1]
|
||||||
|
nop
|
||||||
|
busy:
|
||||||
|
ldrh r6, [r1]
|
||||||
|
eor r7, r5, r6
|
||||||
|
ands r7, #0x80
|
||||||
|
bne busy
|
||||||
|
subs r2, r2, #1 /* 0x1 */
|
||||||
|
moveq r5, #128 /* 0x80 */
|
||||||
|
beq done
|
||||||
|
add r1, r1, #2 /* 0x2 */
|
||||||
|
b code
|
||||||
|
done:
|
||||||
|
b done
|
||||||
|
|
||||||
|
.end
|
||||||
75
contrib/loaders/flash/armv4_5_cfi_span_32.s
Normal file
75
contrib/loaders/flash/armv4_5_cfi_span_32.s
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2005, 2007 by Dominic Rath *
|
||||||
|
* Dominic.Rath@gmx.de *
|
||||||
|
* Copyright (C) 2010 Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.arm
|
||||||
|
.arch armv4
|
||||||
|
|
||||||
|
.section .init
|
||||||
|
|
||||||
|
/* input parameters - */
|
||||||
|
/* R0 = source address */
|
||||||
|
/* R1 = destination address */
|
||||||
|
/* R2 = number of writes */
|
||||||
|
/* R3 = flash write command */
|
||||||
|
/* R4 = constant to mask DQ7 bits (also used for Dq5 with shift) */
|
||||||
|
/* output parameters - */
|
||||||
|
/* R5 = 0x80 ok 0x00 bad */
|
||||||
|
/* temp registers - */
|
||||||
|
/* R6 = value read from flash to test status */
|
||||||
|
/* R7 = holding register */
|
||||||
|
/* unlock registers - */
|
||||||
|
/* R8 = unlock1_addr */
|
||||||
|
/* R9 = unlock1_cmd */
|
||||||
|
/* R10 = unlock2_addr */
|
||||||
|
/* R11 = unlock2_cmd */
|
||||||
|
|
||||||
|
code:
|
||||||
|
ldr r5, [r0], #4
|
||||||
|
str r9, [r8]
|
||||||
|
str r11, [r10]
|
||||||
|
str r3, [r8]
|
||||||
|
str r5, [r1]
|
||||||
|
nop
|
||||||
|
busy:
|
||||||
|
ldr r6, [r1]
|
||||||
|
eor r7, r5, r6
|
||||||
|
ands r7, r4, r7
|
||||||
|
beq cont /* b if DQ7 == Data7 */
|
||||||
|
ands r6, r6, r4, lsr #2
|
||||||
|
beq busy /* b if DQ5 low */
|
||||||
|
ldr r6, [r1]
|
||||||
|
eor r7, r5, r6
|
||||||
|
ands r7, r4, r7
|
||||||
|
beq cont /* b if DQ7 == Data7 */
|
||||||
|
mov r5, #0 /* 0x0 - return 0x00, error */
|
||||||
|
bne done
|
||||||
|
cont:
|
||||||
|
subs r2, r2, #1 /* 0x1 */
|
||||||
|
moveq r5, #128 /* 0x80 */
|
||||||
|
beq done
|
||||||
|
add r1, r1, #4 /* 0x4 */
|
||||||
|
b code
|
||||||
|
done:
|
||||||
|
b done
|
||||||
|
|
||||||
|
.end
|
||||||
75
contrib/loaders/flash/armv4_5_cfi_span_8.s
Normal file
75
contrib/loaders/flash/armv4_5_cfi_span_8.s
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2005, 2007 by Dominic Rath *
|
||||||
|
* Dominic.Rath@gmx.de *
|
||||||
|
* Copyright (C) 2010 Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.arm
|
||||||
|
.arch armv4
|
||||||
|
|
||||||
|
.section .init
|
||||||
|
|
||||||
|
/* input parameters - */
|
||||||
|
/* R0 = source address */
|
||||||
|
/* R1 = destination address */
|
||||||
|
/* R2 = number of writes */
|
||||||
|
/* R3 = flash write command */
|
||||||
|
/* R4 = constant to mask DQ7 bits (also used for Dq5 with shift) */
|
||||||
|
/* output parameters - */
|
||||||
|
/* R5 = 0x80 ok 0x00 bad */
|
||||||
|
/* temp registers - */
|
||||||
|
/* R6 = value read from flash to test status */
|
||||||
|
/* R7 = holding register */
|
||||||
|
/* unlock registers - */
|
||||||
|
/* R8 = unlock1_addr */
|
||||||
|
/* R9 = unlock1_cmd */
|
||||||
|
/* R10 = unlock2_addr */
|
||||||
|
/* R11 = unlock2_cmd */
|
||||||
|
|
||||||
|
code:
|
||||||
|
ldrb r5, [r0], #1
|
||||||
|
strb r9, [r8]
|
||||||
|
strb r11, [r10]
|
||||||
|
strb r3, [r8]
|
||||||
|
strb r5, [r1]
|
||||||
|
nop
|
||||||
|
busy:
|
||||||
|
ldrb r6, [r1]
|
||||||
|
eor r7, r5, r6
|
||||||
|
ands r7, r4, r7
|
||||||
|
beq cont /* b if DQ7 == Data7 */
|
||||||
|
ands r6, r6, r4, lsr #2
|
||||||
|
beq busy /* b if DQ5 low */
|
||||||
|
ldrb r6, [r1]
|
||||||
|
eor r7, r5, r6
|
||||||
|
ands r7, r4, r7
|
||||||
|
beq cont /* b if DQ7 == Data7 */
|
||||||
|
mov r5, #0 /* 0x0 - return 0x00, error */
|
||||||
|
bne done
|
||||||
|
cont:
|
||||||
|
subs r2, r2, #1 /* 0x1 */
|
||||||
|
moveq r5, #128 /* 0x80 */
|
||||||
|
beq done
|
||||||
|
add r1, r1, #1 /* 0x1 */
|
||||||
|
b code
|
||||||
|
done:
|
||||||
|
b done
|
||||||
|
|
||||||
|
.end
|
||||||
81
contrib/loaders/flash/armv7m_cfi_span_16.s
Normal file
81
contrib/loaders/flash/armv7m_cfi_span_16.s
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2005, 2007 by Dominic Rath *
|
||||||
|
* Dominic.Rath@gmx.de *
|
||||||
|
* Copyright (C) 2010 Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.syntax unified
|
||||||
|
.arch armv7-m
|
||||||
|
.thumb
|
||||||
|
.thumb_func
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
/* input parameters - */
|
||||||
|
/* R0 = source address */
|
||||||
|
/* R1 = destination address */
|
||||||
|
/* R2 = number of writes */
|
||||||
|
/* R3 = flash write command */
|
||||||
|
/* R4 = constant to mask DQ7 bits (also used for Dq5 with shift) */
|
||||||
|
/* output parameters - */
|
||||||
|
/* R5 = 0x80 ok 0x00 bad */
|
||||||
|
/* temp registers - */
|
||||||
|
/* R6 = value read from flash to test status */
|
||||||
|
/* R7 = holding register */
|
||||||
|
/* unlock registers - */
|
||||||
|
/* R8 = unlock1_addr */
|
||||||
|
/* R9 = unlock1_cmd */
|
||||||
|
/* R10 = unlock2_addr */
|
||||||
|
/* R11 = unlock2_cmd */
|
||||||
|
|
||||||
|
code:
|
||||||
|
ldrh r5, [r0], #2
|
||||||
|
strh r9, [r8]
|
||||||
|
strh r11, [r10]
|
||||||
|
strh r3, [r8]
|
||||||
|
strh r5, [r1]
|
||||||
|
nop
|
||||||
|
busy:
|
||||||
|
ldrh r6, [r1]
|
||||||
|
eor r7, r5, r6
|
||||||
|
ands r7, r4, r7
|
||||||
|
beq cont /* b if DQ7 == Data7 */
|
||||||
|
ands r6, r6, r4, lsr #2
|
||||||
|
beq busy /* b if DQ5 low */
|
||||||
|
ldrh r6, [r1]
|
||||||
|
eor r7, r5, r6
|
||||||
|
ands r7, r4, r7
|
||||||
|
beq cont /* b if DQ7 == Data7 */
|
||||||
|
mov r5, #0 /* 0x0 - return 0x00, error */
|
||||||
|
bne done
|
||||||
|
cont:
|
||||||
|
subs r2, r2, #1 /* 0x1 */
|
||||||
|
beq success
|
||||||
|
add r1, r1, #2 /* 0x2 */
|
||||||
|
b code
|
||||||
|
|
||||||
|
success:
|
||||||
|
mov r5, #128 /* 0x80 */
|
||||||
|
b done
|
||||||
|
|
||||||
|
done:
|
||||||
|
bkpt #0
|
||||||
|
|
||||||
|
.end
|
||||||
132
contrib/loaders/flash/pic32mx.s
Normal file
132
contrib/loaders/flash/pic32mx.s
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010 by Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.arch m4k
|
||||||
|
.set noreorder
|
||||||
|
.set noat
|
||||||
|
|
||||||
|
/* params:
|
||||||
|
* $a0 src adr - ram + result
|
||||||
|
* $a1 dest adr - flash
|
||||||
|
* $a2 count (32bit words)
|
||||||
|
* vars
|
||||||
|
*
|
||||||
|
* temps:
|
||||||
|
* $t0, $t1, $t2, $t3, $t4, $t5
|
||||||
|
* $s0, $s1, $s3, $s4, $s5
|
||||||
|
*/
|
||||||
|
|
||||||
|
.type main, @function
|
||||||
|
.global main
|
||||||
|
|
||||||
|
.ent main
|
||||||
|
main:
|
||||||
|
/* setup constants */
|
||||||
|
lui $t0, 0xaa99
|
||||||
|
ori $t0, 0x6655 /* NVMKEY1 */
|
||||||
|
lui $t1, 0x5566
|
||||||
|
ori $t1, 0x99AA /* NVMKEY2 */
|
||||||
|
lui $t2, 0xBF80
|
||||||
|
ori $t2, 0xF400 /* NVMCON */
|
||||||
|
ori $t3, $zero, 0x4003 /* NVMCON row write cmd */
|
||||||
|
ori $t4, $zero, 0x8000 /* NVMCON start cmd */
|
||||||
|
|
||||||
|
write_row:
|
||||||
|
/* can we perform a row write: 128 32bit words */
|
||||||
|
sltiu $s3, $a2, 128
|
||||||
|
bne $s3, $zero, write_word
|
||||||
|
ori $t5, $zero, 0x4000 /* NVMCON clear cmd */
|
||||||
|
|
||||||
|
/* perform row write 512 bytes */
|
||||||
|
sw $a1, 32($t2) /* set NVMADDR with dest addr - real addr */
|
||||||
|
sw $a0, 64($t2) /* set NVMSRCADDR with src addr - real addr */
|
||||||
|
|
||||||
|
bal progflash
|
||||||
|
addiu $a0, $a0, 512
|
||||||
|
addiu $a1, $a1, 512
|
||||||
|
beq $zero, $zero, write_row
|
||||||
|
addiu $a2, $a2, -128
|
||||||
|
|
||||||
|
write_word:
|
||||||
|
/* write 32bit words */
|
||||||
|
lui $s5, 0xa000
|
||||||
|
ori $s5, 0x0000
|
||||||
|
or $a0, $a0, $s5 /* convert to virtual addr */
|
||||||
|
|
||||||
|
beq $zero, $zero, next_word
|
||||||
|
ori $t3, $zero, 0x4001 /* NVMCON word write cmd */
|
||||||
|
|
||||||
|
prog_word:
|
||||||
|
lw $s4, 0($a0) /* load data - from virtual addr */
|
||||||
|
sw $s4, 48($t2) /* set NVMDATA with data */
|
||||||
|
sw $a1, 32($t2) /* set NVMADDR with dest addr - real addr */
|
||||||
|
|
||||||
|
bal progflash
|
||||||
|
addiu $a0, $a0, 4
|
||||||
|
addiu $a1, $a1, 4
|
||||||
|
addiu $a2, $a2, -1
|
||||||
|
next_word:
|
||||||
|
bne $a2, $zero, prog_word
|
||||||
|
nop
|
||||||
|
|
||||||
|
done:
|
||||||
|
beq $zero, $zero, exit
|
||||||
|
addiu $a0, $zero, 0
|
||||||
|
|
||||||
|
error:
|
||||||
|
/* save result to $a0 */
|
||||||
|
addiu $a0, $s1, 0
|
||||||
|
|
||||||
|
exit:
|
||||||
|
sdbbp
|
||||||
|
.end main
|
||||||
|
|
||||||
|
.type progflash, @function
|
||||||
|
.global progflash
|
||||||
|
|
||||||
|
.ent progflash
|
||||||
|
progflash:
|
||||||
|
sw $t3, 0($t2) /* set NVMWREN */
|
||||||
|
sw $t0, 16($t2) /* write NVMKEY1 */
|
||||||
|
sw $t1, 16($t2) /* write NVMKEY2 */
|
||||||
|
sw $t4, 8($t2) /* start operation */
|
||||||
|
|
||||||
|
waitflash:
|
||||||
|
lw $s0, 0($t2)
|
||||||
|
and $s0, $s0, $t4
|
||||||
|
bne $s0, $zero, waitflash
|
||||||
|
nop
|
||||||
|
|
||||||
|
/* following is to comply with errata #34
|
||||||
|
* 500ns delay required */
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
/* check for errors */
|
||||||
|
lw $s1, 0($t2)
|
||||||
|
andi $s1, $zero, 0x3000
|
||||||
|
bne $s1, $zero, error
|
||||||
|
sw $t5, 4($t2) /* clear NVMWREN */
|
||||||
|
jr $ra
|
||||||
|
nop
|
||||||
|
|
||||||
|
.end progflash
|
||||||
66
contrib/loaders/flash/stellaris.s
Normal file
66
contrib/loaders/flash/stellaris.s
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2006 by Magnus Lundin *
|
||||||
|
* lundin@mlu.mine.nu *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2008 by Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.syntax unified
|
||||||
|
.cpu cortex-m3
|
||||||
|
.thumb
|
||||||
|
.thumb_func
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
Call with :
|
||||||
|
r0 = buffer address
|
||||||
|
r1 = destination address
|
||||||
|
r2 = bytecount (in) - endaddr (work)
|
||||||
|
|
||||||
|
Used registers:
|
||||||
|
r3 = pFLASH_CTRL_BASE
|
||||||
|
r4 = FLASHWRITECMD
|
||||||
|
r5 = #1
|
||||||
|
r6 = bytes written
|
||||||
|
r7 = temp reg
|
||||||
|
*/
|
||||||
|
|
||||||
|
write:
|
||||||
|
ldr r3,pFLASH_CTRL_BASE
|
||||||
|
ldr r4,FLASHWRITECMD
|
||||||
|
movs r5, 1
|
||||||
|
movs r6, #0
|
||||||
|
mainloop:
|
||||||
|
str r1, [r3, #0]
|
||||||
|
ldr r7, [r0, r6]
|
||||||
|
str r7, [r3, #4]
|
||||||
|
str r4, [r3, #8]
|
||||||
|
waitloop:
|
||||||
|
ldr r7, [r3, #8]
|
||||||
|
tst r7, r5
|
||||||
|
bne waitloop
|
||||||
|
adds r1, r1, #4
|
||||||
|
adds r6, r6, #4
|
||||||
|
cmp r6, r2
|
||||||
|
bne mainloop
|
||||||
|
bkpt #0
|
||||||
|
|
||||||
|
pFLASH_CTRL_BASE: .word 0x400FD000
|
||||||
|
FLASHWRITECMD: .word 0xA4420001
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright (C) 2005 by Dominic Rath *
|
* Copyright (C) 2010 by Spencer Oliver *
|
||||||
* Dominic.Rath@gmx.de *
|
|
||||||
* *
|
|
||||||
* Copyright (C) 2008 by Spencer Oliver *
|
|
||||||
* spen@spen-soft.co.uk *
|
* spen@spen-soft.co.uk *
|
||||||
* *
|
* *
|
||||||
|
* Copyright (C) 2011 Øyvind Harboe *
|
||||||
|
* oyvind.harboe@zylin.com *
|
||||||
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published by *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
@@ -20,58 +20,44 @@
|
|||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#ifndef STR9XPEC_H
|
|
||||||
#define STR9XPEC_H
|
|
||||||
|
|
||||||
|
|
||||||
struct str9xpec_flash_controller
|
// Build : arm-eabi-gcc -c stm32f2xxx.S
|
||||||
{
|
.text
|
||||||
struct jtag_tap *tap;
|
.syntax unified
|
||||||
uint32_t *sector_bits;
|
.cpu cortex-m3
|
||||||
int chain_pos;
|
.thumb
|
||||||
int isc_enable;
|
.thumb_func
|
||||||
uint8_t options[8];
|
.global write
|
||||||
};
|
|
||||||
|
|
||||||
enum str9xpec_status_codes
|
/*
|
||||||
{
|
r0 - source address
|
||||||
STR9XPEC_INVALID_COMMAND = 1,
|
r1 - target address
|
||||||
STR9XPEC_ISC_SUCCESS = 2,
|
r2 - count (halfword-16bit)
|
||||||
STR9XPEC_ISC_DISABLED = 3,
|
r3 - result out
|
||||||
STR9XPEC_ISC_INTFAIL = 32,
|
r4 - flash base
|
||||||
};
|
*/
|
||||||
|
|
||||||
/* ISC commands */
|
#define STM32_FLASH_CR_OFFSET 0x10 /* offset of CR register in FLASH struct */
|
||||||
|
#define STM32_FLASH_SR_OFFSET 0x0c /* offset of CR register in FLASH struct */
|
||||||
|
|
||||||
#define ISC_IDCODE 0xFE
|
write:
|
||||||
#define ISC_MFG_READ 0x4C
|
|
||||||
#define ISC_CONFIGURATION 0x07
|
|
||||||
#define ISC_ENABLE 0x0C
|
|
||||||
#define ISC_DISABLE 0x0F
|
|
||||||
#define ISC_NOOP 0x10
|
|
||||||
#define ISC_ADDRESS_SHIFT 0x11
|
|
||||||
#define ISC_CLR_STATUS 0x13
|
|
||||||
#define ISC_PROGRAM 0x20
|
|
||||||
#define ISC_PROGRAM_SECURITY 0x22
|
|
||||||
#define ISC_PROGRAM_UC 0x23
|
|
||||||
#define ISC_ERASE 0x30
|
|
||||||
#define ISC_READ 0x50
|
|
||||||
#define ISC_BLANK_CHECK 0x60
|
|
||||||
|
|
||||||
/* ISC_DEFAULT bit definitions */
|
write_half_word:
|
||||||
|
ldr r3, STM32_PROG16
|
||||||
|
str r3, [r4, #STM32_FLASH_CR_OFFSET]
|
||||||
|
ldrh r3, [r0], #0x02 /* read one half-word from src, increment ptr */
|
||||||
|
strh r3, [r1], #0x02 /* write one half-word from src, increment ptr */
|
||||||
|
busy:
|
||||||
|
ldr r3, [r4, #STM32_FLASH_SR_OFFSET]
|
||||||
|
tst r3, #0x10000 /* BSY (bit0) == 1 => operation in progress */
|
||||||
|
beq busy /* wait more... */
|
||||||
|
tst r3, #0xf0 /* PGSERR | PGPERR | PGAERR | WRPERR */
|
||||||
|
bne exit /* fail... */
|
||||||
|
subs r2, r2, #0x01 /* decrement counter */
|
||||||
|
bne write_half_word /* write next half-word if anything left */
|
||||||
|
exit:
|
||||||
|
bkpt #0x00
|
||||||
|
|
||||||
#define ISC_STATUS_SECURITY 0x40
|
|
||||||
#define ISC_STATUS_INT_ERROR 0x30
|
|
||||||
#define ISC_STATUS_MODE 0x08
|
|
||||||
#define ISC_STATUS_BUSY 0x04
|
|
||||||
#define ISC_STATUS_ERROR 0x03
|
|
||||||
|
|
||||||
/* Option bytes definitions */
|
STM32_PROG16: .word 0x101 /* PG | PSIZE_16*/
|
||||||
|
|
||||||
#define STR9XPEC_OPT_CSMAPBIT 48
|
|
||||||
#define STR9XPEC_OPT_LVDTHRESBIT 49
|
|
||||||
#define STR9XPEC_OPT_LVDSELBIT 50
|
|
||||||
#define STR9XPEC_OPT_LVDWARNBIT 51
|
|
||||||
#define STR9XPEC_OPT_OTPBIT 63
|
|
||||||
|
|
||||||
#endif /* STR9XPEC_H */
|
|
||||||
58
contrib/loaders/flash/stm32x.S
Normal file
58
contrib/loaders/flash/stm32x.S
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010 by Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.syntax unified
|
||||||
|
.cpu cortex-m3
|
||||||
|
.thumb
|
||||||
|
.thumb_func
|
||||||
|
.global write
|
||||||
|
|
||||||
|
/*
|
||||||
|
r0 - source address
|
||||||
|
r1 - target address
|
||||||
|
r2 - count (halfword-16bit)
|
||||||
|
r3 - sector offet in : result out
|
||||||
|
r4 - flash base
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define STM32_FLASH_CR_OFFSET 0x10 /* offset of CR register in FLASH struct */
|
||||||
|
#define STM32_FLASH_SR_OFFSET 0x0c /* offset of CR register in FLASH struct */
|
||||||
|
|
||||||
|
write:
|
||||||
|
ldr r4, STM32_FLASH_BASE
|
||||||
|
add r4, r3 /* add offset 0x00 for sector 0 : 0x40 for sector 1 */
|
||||||
|
write_half_word:
|
||||||
|
movs r3, #0x01
|
||||||
|
str r3, [r4, #STM32_FLASH_CR_OFFSET] /* PG (bit0) == 1 => flash programming enabled */
|
||||||
|
ldrh r3, [r0], #0x02 /* read one half-word from src, increment ptr */
|
||||||
|
strh r3, [r1], #0x02 /* write one half-word from src, increment ptr */
|
||||||
|
busy:
|
||||||
|
ldr r3, [r4, #STM32_FLASH_SR_OFFSET]
|
||||||
|
tst r3, #0x01 /* BSY (bit0) == 1 => operation in progress */
|
||||||
|
beq busy /* wait more... */
|
||||||
|
tst r3, #0x14 /* PGERR (bit2) == 1 or WRPRTERR (bit4) == 1 => error */
|
||||||
|
bne exit /* fail... */
|
||||||
|
subs r2, r2, #0x01 /* decrement counter */
|
||||||
|
bne write_half_word /* write next half-word if anything left */
|
||||||
|
exit:
|
||||||
|
bkpt #0x00
|
||||||
|
|
||||||
|
STM32_FLASH_BASE: .word 0x40022000 /* base address of FLASH struct */
|
||||||
59
contrib/loaders/flash/str7x.s
Normal file
59
contrib/loaders/flash/str7x.s
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010 by Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.arm
|
||||||
|
.arch armv4t
|
||||||
|
|
||||||
|
.section .init
|
||||||
|
/*
|
||||||
|
r0 source address
|
||||||
|
r1 address
|
||||||
|
r2 FLASH_CR0
|
||||||
|
r3 dword count
|
||||||
|
r4 result
|
||||||
|
r5 busy mask
|
||||||
|
*/
|
||||||
|
|
||||||
|
write:
|
||||||
|
mov r4, #0x10000000 /* set DWPG bit */
|
||||||
|
str r4, [r2, #0x0] /* FLASH_CR0 */
|
||||||
|
str r1, [r2, #0x10] /* FLASH_AR */
|
||||||
|
ldr r4, [r0], #4 /* load data */
|
||||||
|
str r4, [r2, #0x8] /* FLASH_DR0 */
|
||||||
|
ldr r4, [r0], #4 /* load data */
|
||||||
|
str r4, [r2, #0xc] /* FLASH_DR1 */
|
||||||
|
mov r4, #0x90000000 /* set DWPG and WMS bits */
|
||||||
|
str r4, [r2, #0x0] /* FLASH_CR0 */
|
||||||
|
busy:
|
||||||
|
ldr r4, [r2, #0x0] /* FLASH_CR0 */
|
||||||
|
tst r4, r5
|
||||||
|
bne busy
|
||||||
|
ldr r4, [r2, #0x14] /* FLASH_ER */
|
||||||
|
tst r4, #0xff /* do we have errors */
|
||||||
|
tsteq r4, #0x100 /* write protection set */
|
||||||
|
bne exit
|
||||||
|
add r1, r1, #0x8 /* next 8 bytes */
|
||||||
|
subs r3, r3, #1 /* decremment dword count */
|
||||||
|
bne write
|
||||||
|
exit:
|
||||||
|
b exit
|
||||||
|
|
||||||
|
.end
|
||||||
56
contrib/loaders/flash/str9x.s
Normal file
56
contrib/loaders/flash/str9x.s
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010 by Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.arm
|
||||||
|
.arch armv5t
|
||||||
|
|
||||||
|
.section .init
|
||||||
|
/*
|
||||||
|
r0 source address (in)
|
||||||
|
r1 target address (in)
|
||||||
|
r2 word count (in)
|
||||||
|
r3 result (out)
|
||||||
|
*/
|
||||||
|
|
||||||
|
write:
|
||||||
|
bic r4, r1, #3 /* word address */
|
||||||
|
mov r3, #0x40 /* write command */
|
||||||
|
strh r3, [r4, #0]
|
||||||
|
ldrh r3, [r0], #2 /* read data */
|
||||||
|
strh r3, [r1], #2 /* write data */
|
||||||
|
mov r3, #0x70 /* status command */
|
||||||
|
strh r3, [r4, #0]
|
||||||
|
busy:
|
||||||
|
ldrb r3, [r4, #0] /* status */
|
||||||
|
tst r3, #0x80
|
||||||
|
beq busy
|
||||||
|
mov r5, #0x50 /* clear status command */
|
||||||
|
strh r5, [r4, #0]
|
||||||
|
mov r5, #0xFF /* read array */
|
||||||
|
strh r5, [r4, #0]
|
||||||
|
tst r3, #0x12
|
||||||
|
bne exit
|
||||||
|
subs r2, r2, #1 /* decremment word count */
|
||||||
|
bne write
|
||||||
|
exit:
|
||||||
|
bkpt #0
|
||||||
|
|
||||||
|
.end
|
||||||
@@ -64,5 +64,8 @@ ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="664", GROUP="plugdev"
|
|||||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c140", MODE="664", GROUP="plugdev"
|
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c140", MODE="664", GROUP="plugdev"
|
||||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c141", MODE="664", GROUP="plugdev"
|
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c141", MODE="664", GROUP="plugdev"
|
||||||
|
|
||||||
|
# Hilscher NXHX Boards
|
||||||
|
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="0028", MODE="664", GROUP="plugdev"
|
||||||
|
|
||||||
LABEL="openocd_rules_end"
|
LABEL="openocd_rules_end"
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
info_TEXINFOS = openocd.texi
|
info_TEXINFOS = openocd.texi
|
||||||
openocd_TEXINFOS = fdl.texi
|
openocd_TEXINFOS = fdl.texi
|
||||||
man_MANS = openocd.1
|
man_MANS = openocd.1
|
||||||
EXTRA_DIST = openocd.1
|
EXTRA_DIST = openocd.1 \
|
||||||
|
INSTALL.txt
|
||||||
|
|
||||||
dist-hook:
|
dist-hook:
|
||||||
mkdir $(distdir)/manual
|
mkdir $(distdir)/manual
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ TMS which will select different shift registers.
|
|||||||
|
|
||||||
The first thing you need to do is reset the state machine, because when
|
The first thing you need to do is reset the state machine, because when
|
||||||
you connect to a chip you do not know what state the controller is in,you need
|
you connect to a chip you do not know what state the controller is in,you need
|
||||||
to clock TMS as 1, at least 7 times. This will put you into "Test Logic
|
to clock TMS as 1, at least 5 times. This will put you into "Test Logic
|
||||||
Reset" State. Knowing this, you can, once reset, then track what each
|
Reset" State. Knowing this, you can, once reset, then track what each
|
||||||
transition on TMS will do, and hence know what state the JTAG state
|
transition on TMS will do, and hence know what state the JTAG state
|
||||||
machine is in.
|
machine is in.
|
||||||
@@ -45,9 +45,9 @@ instruction register.
|
|||||||
|
|
||||||
For example, one of the data registers will be known as "bypass" this is
|
For example, one of the data registers will be known as "bypass" this is
|
||||||
(usually) a single bit which has no function and is used to bypass the
|
(usually) a single bit which has no function and is used to bypass the
|
||||||
chip. Assume we have 3 identical chips, wired up like the picture
|
chip. Assume we have 3 identical chips, wired up like the picture(wikipedia)
|
||||||
and each has a 3 bit instruction register, and there are 2 known
|
and each has a 3 bits instruction register, and there are 2 known
|
||||||
instructions (110 = bypass, 010 = some other function) if we want to use
|
instructions (110 = bypass, 010 = "some other function") if we want to use
|
||||||
"some other function", on the second chip in the line, and not change
|
"some other function", on the second chip in the line, and not change
|
||||||
the other chips we would do the following transitions.
|
the other chips we would do the following transitions.
|
||||||
|
|
||||||
@@ -66,13 +66,13 @@ each chip [110] [010] [110]
|
|||||||
The order is reversed, because we shift out the least significant bit
|
The order is reversed, because we shift out the least significant bit
|
||||||
first. Then we transition TMS:
|
first. Then we transition TMS:
|
||||||
|
|
||||||
1 1 1 1 0 0
|
1 1 1 0 0
|
||||||
|
|
||||||
which puts us in the "Shift DR state".
|
which puts us in the "Shift DR state".
|
||||||
|
|
||||||
Now when we clock data onto TDI (again while holding TMS to 0) , the
|
Now when we clock data onto TDI (again while holding TMS to 0) , the
|
||||||
data shifts through the data registers, and because of the instruction
|
data shifts through the data registers, and because of the instruction
|
||||||
registers we selected (some other function has 8 bits in its data
|
registers we selected ("some other function" has 8 bits in its data
|
||||||
register), our total data register in the chain looks like this:
|
register), our total data register in the chain looks like this:
|
||||||
|
|
||||||
0 00000000 0
|
0 00000000 0
|
||||||
@@ -107,10 +107,6 @@ gets interesting. But in and of itself, JTAG is actually very simple.
|
|||||||
|
|
||||||
@section primerjtag More Reading
|
@section primerjtag More Reading
|
||||||
|
|
||||||
The following link goes to an HTML (or PDF) introduction to JTAG,
|
|
||||||
written by one of the original members of the JTAG committee: @par
|
|
||||||
http://www.asset-intertech.com/products/boundscan.htm
|
|
||||||
|
|
||||||
A separate primer contains information about @subpage primerjtagbs for
|
A separate primer contains information about @subpage primerjtagbs for
|
||||||
developers that want to extend OpenOCD for such purposes.
|
developers that want to extend OpenOCD for such purposes.
|
||||||
|
|
||||||
|
|||||||
@@ -84,8 +84,8 @@ the minor version will @a also be zero (<code>y = 0, z = 0</code>).
|
|||||||
After these required numeric components, release version strings
|
After these required numeric components, release version strings
|
||||||
may contain tags such as as <em>-rc1</em> or <em>-rc2</em>.
|
may contain tags such as as <em>-rc1</em> or <em>-rc2</em>.
|
||||||
These 'rc' tags indicate "release candidate" versions of the package.
|
These 'rc' tags indicate "release candidate" versions of the package.
|
||||||
Like the major/minor/micro numbers, these tags will be manipulated
|
Like major/minor/micro numbers, these are updated
|
||||||
by the automated release process.
|
as part of the release process.
|
||||||
|
|
||||||
The release process includes version number manipulations to the tree
|
The release process includes version number manipulations to the tree
|
||||||
being released, ensuring that all numbers are incremented (or rolled
|
being released, ensuring that all numbers are incremented (or rolled
|
||||||
@@ -277,22 +277,34 @@ support; the Release Manager isn't the only participant.
|
|||||||
|
|
||||||
The following steps should be followed to produce each release:
|
The following steps should be followed to produce each release:
|
||||||
|
|
||||||
-# Produce final patches to mainline (or a release branch). Nobody
|
-# Produce final patches using a local clone of mainline. Nobody
|
||||||
except the RM should be committing anything.
|
except the RM should be committing anything. <em>Everyone with commit
|
||||||
-# Finalize @c NEWS file to describe the changes in the release
|
privileges needs to know and agree to this in advance!</em> Even the RM
|
||||||
|
only commits a handful of updates as part of the release process
|
||||||
|
itself ... to files which are part of the version identification scheme
|
||||||
|
or release process; and to create the version tag; and then to open the
|
||||||
|
merge window for the next release cycle.
|
||||||
|
-# Finalize @c the NEWS file to describe the changes in the release
|
||||||
- This file is used to automatically post "blurbs" about the project.
|
- This file is used to automatically post "blurbs" about the project.
|
||||||
- This material should be produced during the development cycle.
|
- This material should have been produced during the development cycle,
|
||||||
- Add a new item for each @c NEWS-worthy contribution, when committed.
|
by adding items for each @c NEWS-worthy contribution, when committed
|
||||||
|
during the merge window. (One part of closing the merge window, by
|
||||||
|
opening the RC phase of the release, is the commitment to hold all
|
||||||
|
further such contributions until the next merge window opens.)
|
||||||
|
- The RM should make sure nothing important was omitted, as part of
|
||||||
|
the RC1 cycle. From then on, no more updates to NEWS content should
|
||||||
|
be needed (except to seed the process for the next release, or maybe
|
||||||
|
if a significant and longstanding bug is fixed late in the RC phase).
|
||||||
-# Bump library version if our API changed (not yet required)
|
-# Bump library version if our API changed (not yet required)
|
||||||
-# Update and commit the final package version in @c configure.in:
|
-# Update and commit the final package version in @c configure.in:
|
||||||
<code>tools/release/version.sh</code> may help ensure the versions
|
(The <code>tools/release/version.sh</code> script might help ensure
|
||||||
are named consistently:
|
the versions are named properly.):
|
||||||
-# Remove @c -dev tag.
|
-# Remove @c -dev tag.
|
||||||
-# Update the @c -rc tag:
|
-# Update any @c -rc tag:
|
||||||
- If producing the final release from an -rc series, remove it
|
- If producing the final release from an -rc series, remove it
|
||||||
- If producing the first RC in a series, add rc1
|
- If producing the first RC in a series, add rc1
|
||||||
- If producing the next RC in a series, bump the rc number
|
- If producing the next RC in a series, bump the rc number
|
||||||
-# Commit that version change.
|
-# Commit that version change, with a good descriptive comment.
|
||||||
-# Create a git tag for the final commit, with a tag name matching
|
-# Create a git tag for the final commit, with a tag name matching
|
||||||
the version string in <code>configure.in</code> (including <em>-rcN</em>
|
the version string in <code>configure.in</code> (including <em>-rcN</em>
|
||||||
where relevant):
|
where relevant):
|
||||||
@@ -301,49 +313,92 @@ PACKAGE_VERSION="x.y.z"
|
|||||||
PACKAGE_TAG="v${PACKAGE_VERSION}"
|
PACKAGE_TAG="v${PACKAGE_VERSION}"
|
||||||
git tag -m "The openocd-${PACKAGE_VERSION} release." "${PACKAGE_TAG}"
|
git tag -m "The openocd-${PACKAGE_VERSION} release." "${PACKAGE_TAG}"
|
||||||
@endverbatim
|
@endverbatim
|
||||||
-# Prepare to resume normal development on mainline (major or minor release)
|
-# Do not push those changes to mainline yet; only builds using the
|
||||||
- Update the version label
|
source archives you will be creating should ever be labeled as
|
||||||
|
official releases (with no "-dev" suffix). Since mainline is a
|
||||||
|
development tree, these will be pushed later, as part of opening
|
||||||
|
the merge window for the next release cycle (restoring the "-dev"
|
||||||
|
suffix for that next release.) Those version and tag updates are
|
||||||
|
the last ones to be included in the release being made.
|
||||||
|
-# Produce the release files, using the local clone of the source
|
||||||
|
tree which holds the release's tag and updated version in
|
||||||
|
@c configure.in ... this is used only to produce the release, and
|
||||||
|
all files should already be properly checked out.
|
||||||
|
-# Run <code>tools/release.sh package</code> to produce the
|
||||||
|
source archives. This automatically bootstraps and
|
||||||
|
configures the process.
|
||||||
|
-# Run <code>tools/release.sh stage</code> to create an @c archives
|
||||||
|
directory with the release data, including MD5 and SHA1
|
||||||
|
checksum files (which are used with Berlios).
|
||||||
|
-# Sanity check at least one of those archives, by extracting and
|
||||||
|
configuring its contents, using them to build a copy of OpenOCD,
|
||||||
|
and verifying that the result prints the correct release version
|
||||||
|
in its startup banner. (For example,
|
||||||
|
"configure --enable-ft2232_libftdi --enable-parport"
|
||||||
|
then "make" and run "src/openocd -v" as a sanity check.)
|
||||||
|
-# Run <code>make docs</code> to create the
|
||||||
|
documentation which will be published.
|
||||||
|
-# Upload packages and post announcements of their availability:
|
||||||
|
-# Release packages into files section of project sites:
|
||||||
|
- SF.net:
|
||||||
|
-# Under "Project Admin", use the "File Manager"
|
||||||
|
-# Create a new folder under "openocd" named "${PACKAGE_VERSION}"
|
||||||
|
-# Upload the @c NEWS file and mark it as the release notes.
|
||||||
|
-# Upload the three source archive files, using the Web interface,
|
||||||
|
into that folder. Verify the upload worked OK by checking the
|
||||||
|
MD5 and SHA1 checksums computed by SourceForge against the
|
||||||
|
versions created as part of staging the release.
|
||||||
|
-# Also upload doc/openocd.pdf (the User's Guide) so the version
|
||||||
|
matching each release will be easily available.
|
||||||
|
-# Select each file in the release, and use the property panel
|
||||||
|
to set its type and select the right release notes.
|
||||||
|
- .tar.bz2: Linux, Mac
|
||||||
|
- .tar.gz: BSD, Solaris, Others
|
||||||
|
- .zip: Windows
|
||||||
|
- For openocd.pdf just associate it with the right release notes.
|
||||||
|
-# Create an SF.net project news update.
|
||||||
|
- Berlios:
|
||||||
|
-# Provide @c NEWS file, as requested.
|
||||||
|
-# Upload the release files via FTP to ftp://ftp.berlios.de/incoming/
|
||||||
|
-# Edit descriptions for each file (one at a time) Note that Berlios
|
||||||
|
does not automatically checksum files, and it uses a very old
|
||||||
|
version of the SourceForge code with user interface issues.
|
||||||
|
-# Click button to send E-mail Release Notice.
|
||||||
|
-# Depending on how paranoid you're feeling today, verify the images by
|
||||||
|
downloading them from the websites and making sure there are no
|
||||||
|
differences between the downloaded copies and your originals.
|
||||||
|
-# Publish User's and Developer's Guides to the project web sites:
|
||||||
|
-# Use SCP to update the SF.net web site with PDF and HTML for the
|
||||||
|
User's Guide, and HTML for the developer's guide ... you can
|
||||||
|
instantiate a shell.sourceforge.net instance and set up symlinks
|
||||||
|
from your home directory, to simplify this process.
|
||||||
|
-# (How to update the Berlios web site with the same data?)
|
||||||
|
-# Post announcement e-mail to the openocd-development list.
|
||||||
|
-# optionally:
|
||||||
|
-# Post an update on the Berlios blog (if it lets you)
|
||||||
|
-# Announce updates on freshmeat.net and other trackers.
|
||||||
|
-# Submit updates to news feeds (e.g. Digg, Reddit, etc.).
|
||||||
|
-# Resume normal development on mainline, by opening the merge window for
|
||||||
|
the next major or minor release cycle. (You might want to do this
|
||||||
|
before all the release bits are fully published.)
|
||||||
|
- Update the version label in the @c configure.in file:
|
||||||
- Restore @c -dev version tag.
|
- Restore @c -dev version tag.
|
||||||
- For a new minor release cycle, increment the release's minor number
|
- For a new minor release cycle, increment the release's minor number
|
||||||
- For a new major release cycle, increment the release's major number
|
- For a new major release cycle, increment the release's major number
|
||||||
and zero its minor number
|
and zero its minor number
|
||||||
- Archive @c NEWS file as "<code>doc/news/NEWS-${PACKAGE_VERSION}</code>".
|
- Archive @c NEWS file as "<code>doc/news/NEWS-${PACKAGE_VERSION}</code>".
|
||||||
- Create a new @c NEWS file for the next release
|
- Create a new @c NEWS file for the next release
|
||||||
- Commit those changes, and push the commit and the release tag
|
- Commit those changes.
|
||||||
to mainline.
|
- Push all the updates to mainline.
|
||||||
-# Produce the package source archives:
|
- Last updates for the release, including the release tag (you
|
||||||
-# <em>Start with a new clone of the source tree</em>, with the
|
will need to "git push --tags").
|
||||||
release's tag. This is used only for producing these packages.
|
- Updates opening the merge window
|
||||||
-# Checkout the appropriate tag:
|
- At this point, it's OK for commiters to start pushing changes
|
||||||
<code>git checkout "${PACKAGE_VERSION}"</code>
|
which have been held off until the next release. (Any bugfixes to
|
||||||
-# @c bootstrap, @c configure, and @c make the package.
|
this release will be against a bug-fix release branch starting from
|
||||||
-# Run <code>make distcheck</code> to produce the distribution archives.
|
the commit you tagged as this release, not mainline.)
|
||||||
-# Run <code>make maintainer-clean</code> verify the repository is empty.
|
- Announce to the openocd-development list. Ideally, you will also
|
||||||
-# Create signature files using @c md5sum, @c sha1sum, etc.
|
be able to say who is managing the next release cycle.
|
||||||
-# Publish documentation for the release:
|
|
||||||
- Allow users to access the documentation for each of our releases.
|
|
||||||
- Place static copies of the following files on the project website:
|
|
||||||
- @c NEWS: to provide a blurb for each release
|
|
||||||
- User's Guide, Developer Manual: to allow easy on-line viewing
|
|
||||||
-# Upload packages and post announcements of their availability:
|
|
||||||
-# Release packages into files section of project sites:
|
|
||||||
- SF.net:
|
|
||||||
-# Create a new folder named "${PACKAGE_VERSION}"
|
|
||||||
-# Select new folder as the target for uploads.
|
|
||||||
-# Upload files via Web interface into new
|
|
||||||
-# Set platform types for each archive:
|
|
||||||
- .tar.bz2: Linux, Mac
|
|
||||||
- .tar.gz: BSD, Solaris, Others
|
|
||||||
- .zip: Windows
|
|
||||||
- Berlios:
|
|
||||||
-# Create the new release for the new version.
|
|
||||||
-# Provide @c NEWS file, as requested.
|
|
||||||
-# Upload files via FTP to ftp://ftp.berlios.de/incoming/
|
|
||||||
-# Edit descriptions for each file.
|
|
||||||
-# Click button to send E-mail Release Notice.
|
|
||||||
-# Post announcement e-mail to the openocd-development list.
|
|
||||||
-# Announce updates on freshmeat.net and other trackers.
|
|
||||||
-# Submit big updates to news feeds (e.g. Digg, Reddit, etc.).
|
|
||||||
|
|
||||||
To start a bug-fix release branch:
|
To start a bug-fix release branch:
|
||||||
-# Create a new branch, starting from a major or
|
-# Create a new branch, starting from a major or
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ upon it, sometimes that is the only scheme available.
|
|||||||
|
|
||||||
As a small group of developers, supporting all the platforms and
|
As a small group of developers, supporting all the platforms and
|
||||||
targets in the debugger will be difficult, as there are enough problem
|
targets in the debugger will be difficult, as there are enough problem
|
||||||
with the plethora of Dongles, Chips, and different target boards.
|
with the plethora of Adapters, Chips, and different target boards.
|
||||||
Yes, the TCL interface might be suitable, but it has not received much
|
Yes, the TCL interface might be suitable, but it has not received much
|
||||||
love or attention. Perhaps it will after you read and understand this.
|
love or attention. Perhaps it will after you read and understand this.
|
||||||
|
|
||||||
@@ -235,7 +235,7 @@ different host-side GDB..
|
|||||||
Sure - a <em>man on a mission</em> can make that work. The GUI might be
|
Sure - a <em>man on a mission</em> can make that work. The GUI might be
|
||||||
libopenocd + Perl/TK, or maybe an Eclipse Plug-in.
|
libopenocd + Perl/TK, or maybe an Eclipse Plug-in.
|
||||||
That is a development support nightmare for reasons described
|
That is a development support nightmare for reasons described
|
||||||
above. We have enough support problems as it is with targets, dongles,
|
above. We have enough support problems as it is with targets, adapters,
|
||||||
etc.
|
etc.
|
||||||
|
|
||||||
@section serverdocshttpbg HTTP Server Background
|
@section serverdocshttpbg HTTP Server Background
|
||||||
@@ -270,8 +270,8 @@ every peripheral register on the target platform.
|
|||||||
|
|
||||||
That also is transportable, regardless of the OpenOCD host
|
That also is transportable, regardless of the OpenOCD host
|
||||||
platform: Linux/X86, Linux/ARM, FreeBSD, Cygwin, MingW, or MacOSX.
|
platform: Linux/X86, Linux/ARM, FreeBSD, Cygwin, MingW, or MacOSX.
|
||||||
You could even port OpenOCD to an Google Android and use it as a
|
You could even port OpenOCD to an Android system and use it as a
|
||||||
bit-bang dongle JTAG serving web pages.
|
bit-banging JTAG Adapter serving web pages.
|
||||||
|
|
||||||
@subsection serverdocshtmladv Advanced HTML Pages
|
@subsection serverdocshtmladv Advanced HTML Pages
|
||||||
|
|
||||||
@@ -309,17 +309,3 @@ This section needs to be expanded.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @page serverhttp OpenOCD HTTP Server API
|
|
||||||
|
|
||||||
|
|
||||||
Smoketest:
|
|
||||||
|
|
||||||
configure --enable-httpd --enable-dummy --enable-ioutil
|
|
||||||
|
|
||||||
openocd -s /usr/local/share/openocd -f httpd/httpd.tcl -f interface/dummy.cfg -f target/lpc2148.cfg
|
|
||||||
|
|
||||||
Navigate to: http://localhost:8888/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|||||||
807
doc/openocd.texi
807
doc/openocd.texi
File diff suppressed because it is too large
Load Diff
1
jimtcl
Submodule
1
jimtcl
Submodule
Submodule jimtcl added at 6233a6c5d3
@@ -1,12 +1,16 @@
|
|||||||
|
include $(top_srcdir)/common.mk
|
||||||
|
|
||||||
SUBDIRS = \
|
SUBDIRS = \
|
||||||
helper \
|
|
||||||
jtag \
|
jtag \
|
||||||
|
helper \
|
||||||
target \
|
target \
|
||||||
|
transport \
|
||||||
flash \
|
flash \
|
||||||
svf \
|
svf \
|
||||||
xsvf \
|
xsvf \
|
||||||
pld \
|
pld \
|
||||||
server
|
server \
|
||||||
|
rtos
|
||||||
|
|
||||||
lib_LTLIBRARIES = libopenocd.la
|
lib_LTLIBRARIES = libopenocd.la
|
||||||
bin_PROGRAMS = openocd
|
bin_PROGRAMS = openocd
|
||||||
@@ -20,6 +24,12 @@ endif
|
|||||||
openocd_SOURCES = $(MAINFILE)
|
openocd_SOURCES = $(MAINFILE)
|
||||||
openocd_LDADD = libopenocd.la
|
openocd_LDADD = libopenocd.la
|
||||||
|
|
||||||
|
if INTERNAL_JIMTCL
|
||||||
|
openocd_LDADD += $(top_builddir)/jimtcl/libjim.a
|
||||||
|
else
|
||||||
|
openocd_LDADD += -ljim
|
||||||
|
endif
|
||||||
|
|
||||||
libopenocd_la_SOURCES = \
|
libopenocd_la_SOURCES = \
|
||||||
hello.c \
|
hello.c \
|
||||||
openocd.c \
|
openocd.c \
|
||||||
@@ -29,20 +39,16 @@ noinst_HEADERS = \
|
|||||||
hello.h \
|
hello.h \
|
||||||
openocd.h
|
openocd.h
|
||||||
|
|
||||||
|
|
||||||
# set the include path found by configure
|
|
||||||
AM_CPPFLAGS = \
|
|
||||||
-I$(top_srcdir)/src \
|
|
||||||
-I$(top_builddir)/src
|
|
||||||
|
|
||||||
libopenocd_la_CPPFLAGS = -DPKGBLDDATE=\"`date +%F-%R`\"
|
libopenocd_la_CPPFLAGS = -DPKGBLDDATE=\"`date +%F-%R`\"
|
||||||
|
|
||||||
# banner output includes RELSTR appended to $VERSION from the configure script
|
# banner output includes RELSTR appended to $VERSION from the configure script
|
||||||
# guess-rev.sh returns either a repository version ID or "-snapshot"
|
# guess-rev.sh returns either a repository version ID or "-snapshot"
|
||||||
if RELEASE
|
if RELEASE
|
||||||
libopenocd_la_CPPFLAGS += -DRELSTR=\"\"
|
libopenocd_la_CPPFLAGS += -DRELSTR=\"\"
|
||||||
|
libopenocd_la_CPPFLAGS += -DGITVERSION=\"\"
|
||||||
else
|
else
|
||||||
libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\"
|
libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\"
|
||||||
|
libopenocd_la_CPPFLAGS += -DGITVERSION=\"`cd $(top_srcdir) && git describe`\"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# add default CPPFLAGS
|
# add default CPPFLAGS
|
||||||
@@ -80,6 +86,9 @@ else
|
|||||||
if RLINK
|
if RLINK
|
||||||
LIBUSB = -lusb
|
LIBUSB = -lusb
|
||||||
else
|
else
|
||||||
|
if ULINK
|
||||||
|
LIBUSB = -lusb
|
||||||
|
else
|
||||||
if VSLLINK
|
if VSLLINK
|
||||||
LIBUSB = -lusb
|
LIBUSB = -lusb
|
||||||
else
|
else
|
||||||
@@ -88,22 +97,21 @@ endif
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
libopenocd_la_LIBADD = \
|
libopenocd_la_LIBADD = \
|
||||||
$(top_builddir)/src/xsvf/libxsvf.la \
|
$(top_builddir)/src/xsvf/libxsvf.la \
|
||||||
$(top_builddir)/src/svf/libsvf.la \
|
$(top_builddir)/src/svf/libsvf.la \
|
||||||
$(top_builddir)/src/pld/libpld.la \
|
$(top_builddir)/src/pld/libpld.la \
|
||||||
$(top_builddir)/src/jtag/libjtag.la \
|
$(top_builddir)/src/jtag/libjtag.la \
|
||||||
|
$(top_builddir)/src/transport/libtransport.la \
|
||||||
$(top_builddir)/src/flash/libflash.la \
|
$(top_builddir)/src/flash/libflash.la \
|
||||||
$(top_builddir)/src/target/libtarget.la \
|
$(top_builddir)/src/target/libtarget.la \
|
||||||
$(top_builddir)/src/server/libserver.la \
|
$(top_builddir)/src/server/libserver.la \
|
||||||
|
$(top_builddir)/src/rtos/librtos.la \
|
||||||
$(top_builddir)/src/helper/libhelper.la \
|
$(top_builddir)/src/helper/libhelper.la \
|
||||||
$(FTDI2232LIB) $(MINGWLDADD) $(LIBUSB)
|
$(FTDI2232LIB) $(MINGWLDADD) $(LIBUSB)
|
||||||
|
|
||||||
if HTTPD
|
|
||||||
libopenocd_la_LIBADD += -lmicrohttpd
|
|
||||||
endif
|
|
||||||
|
|
||||||
STARTUP_TCL_SRCS = \
|
STARTUP_TCL_SRCS = \
|
||||||
$(srcdir)/helper/startup.tcl \
|
$(srcdir)/helper/startup.tcl \
|
||||||
$(srcdir)/jtag/startup.tcl \
|
$(srcdir)/jtag/startup.tcl \
|
||||||
@@ -127,7 +135,10 @@ startup_tcl.c: startup.tcl $(BIN2C)
|
|||||||
# add startup_tcl.c to make clean list
|
# add startup_tcl.c to make clean list
|
||||||
CLEANFILES = startup.tcl startup_tcl.c
|
CLEANFILES = startup.tcl startup_tcl.c
|
||||||
|
|
||||||
|
# we do not want generated file in the dist
|
||||||
|
dist-hook:
|
||||||
|
rm -f $(distdir)/startup_tcl.c
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||||
|
|
||||||
# The "quick" target builds executables & reinstalls the executables
|
# The "quick" target builds executables & reinstalls the executables
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright (C) 2007-2009 by Øyvind Harboe *
|
* Copyright (C) 2007-2010 by Øyvind Harboe *
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published by *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <helper/types.h>
|
#include <helper/types.h>
|
||||||
#include <jtag/jtag.h>
|
#include <jtag/jtag.h>
|
||||||
#include <helper/ioutil.h>
|
#include <helper/ioutil.h>
|
||||||
|
#include <helper/util.h>
|
||||||
#include <helper/configuration.h>
|
#include <helper/configuration.h>
|
||||||
|
|
||||||
#include <server/server.h>
|
#include <server/server.h>
|
||||||
@@ -99,10 +100,6 @@ static bool writeLog = true;
|
|||||||
|
|
||||||
char hwaddr[512];
|
char hwaddr[512];
|
||||||
|
|
||||||
|
|
||||||
extern struct flash_driver *flash_drivers[];
|
|
||||||
extern struct target_type *target_types[];
|
|
||||||
|
|
||||||
#ifdef CYGPKG_PROFILE_GPROF
|
#ifdef CYGPKG_PROFILE_GPROF
|
||||||
#include <cyg/profile/profile.h>
|
#include <cyg/profile/profile.h>
|
||||||
|
|
||||||
@@ -503,6 +500,10 @@ static void zylinjtag_startNetwork(void)
|
|||||||
|
|
||||||
cyg_httpd_init_tcl_interpreter();
|
cyg_httpd_init_tcl_interpreter();
|
||||||
|
|
||||||
|
// Kludge! Why can't I do this from httpd.c??? I get linker errors...
|
||||||
|
// some of that --start/end-group stuff?
|
||||||
|
Jim_InitStaticExtensions(httpstate.jim_interp);
|
||||||
|
|
||||||
Jim_CreateCommand(httpstate.jim_interp, "log", zylinjtag_Jim_Command_log,
|
Jim_CreateCommand(httpstate.jim_interp, "log", zylinjtag_Jim_Command_log,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
Jim_CreateCommand(httpstate.jim_interp, "zy1000_reboot",
|
Jim_CreateCommand(httpstate.jim_interp, "zy1000_reboot",
|
||||||
@@ -1093,6 +1094,9 @@ int main(int argc, char *argv[])
|
|||||||
command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
|
command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
|
||||||
command_context_mode(cmd_ctx, COMMAND_CONFIG);
|
command_context_mode(cmd_ctx, COMMAND_CONFIG);
|
||||||
|
|
||||||
|
if (util_init(cmd_ctx) != ERROR_OK)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
if (ioutil_init(cmd_ctx) != ERROR_OK)
|
if (ioutil_init(cmd_ctx) != ERROR_OK)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
@@ -1277,6 +1281,7 @@ struct Tftp
|
|||||||
cyg_uint8 *mem;
|
cyg_uint8 *mem;
|
||||||
int actual;
|
int actual;
|
||||||
char *server;
|
char *server;
|
||||||
|
int port;
|
||||||
char *file;
|
char *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1333,6 +1338,15 @@ static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
|
|||||||
strncpy(tftp->server, name, server - name);
|
strncpy(tftp->server, name, server - name);
|
||||||
tftp->server[server - name] = 0;
|
tftp->server[server - name] = 0;
|
||||||
|
|
||||||
|
tftp->port = 0; /* default port 69 */
|
||||||
|
char *port;
|
||||||
|
port = strchr(tftp->server, ':');
|
||||||
|
if (port != NULL)
|
||||||
|
{
|
||||||
|
tftp->port = atoi(port + 1);
|
||||||
|
*port = 0;
|
||||||
|
}
|
||||||
|
|
||||||
tftp->file = strdup(server + 1);
|
tftp->file = strdup(server + 1);
|
||||||
if (tftp->file == NULL)
|
if (tftp->file == NULL)
|
||||||
{
|
{
|
||||||
@@ -1350,7 +1364,7 @@ static int fetchTftp(struct Tftp *tftp)
|
|||||||
if (!tftp->readFile)
|
if (!tftp->readFile)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
tftp->actual = tftp_client_get(tftp->file, tftp->server, 0, tftp->mem,
|
tftp->actual = tftp_client_get(tftp->file, tftp->server, tftp->port, tftp->mem,
|
||||||
tftpMaxSize, TFTP_OCTET, &err);
|
tftpMaxSize, TFTP_OCTET, &err);
|
||||||
|
|
||||||
if (tftp->actual < 0)
|
if (tftp->actual < 0)
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
|
include $(top_srcdir)/common.mk
|
||||||
|
|
||||||
SUBDIRS = \
|
SUBDIRS = \
|
||||||
nor \
|
nor \
|
||||||
nand
|
nand
|
||||||
|
|
||||||
AM_CPPFLAGS = \
|
|
||||||
-I$(top_srcdir)/src \
|
|
||||||
-I$(top_builddir)/src
|
|
||||||
|
|
||||||
METASOURCES = AUTO
|
METASOURCES = AUTO
|
||||||
noinst_LTLIBRARIES = libflash.la
|
noinst_LTLIBRARIES = libflash.la
|
||||||
libflash_la_SOURCES = \
|
libflash_la_SOURCES = \
|
||||||
|
|||||||
@@ -25,13 +25,13 @@
|
|||||||
|
|
||||||
unsigned get_flash_name_index(const char *name)
|
unsigned get_flash_name_index(const char *name)
|
||||||
{
|
{
|
||||||
const char *index = strrchr(name, '.');
|
const char *name_index = strrchr(name, '.');
|
||||||
if (NULL == index)
|
if (NULL == name_index)
|
||||||
return 0;
|
return 0;
|
||||||
if (index[1] < '0' || index[1] > '9')
|
if (name_index[1] < '0' || name_index[1] > '9')
|
||||||
return ~0U;
|
return ~0U;
|
||||||
unsigned requested;
|
unsigned requested;
|
||||||
int retval = parse_uint(index + 1, &requested);
|
int retval = parse_uint(name_index + 1, &requested);
|
||||||
// detect parsing error by forcing past end of bank list
|
// detect parsing error by forcing past end of bank list
|
||||||
return (ERROR_OK == retval) ? requested : ~0U;
|
return (ERROR_OK == retval) ? requested : ~0U;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,9 @@
|
|||||||
* Parses the optional '.index' portion of a flash bank identifier.
|
* Parses the optional '.index' portion of a flash bank identifier.
|
||||||
* @param name The desired driver name, passed by the user.
|
* @param name The desired driver name, passed by the user.
|
||||||
* @returns The parsed index request, or 0 if not present. If the
|
* @returns The parsed index request, or 0 if not present. If the
|
||||||
* name provides a suffix but it does not parse as an unsigned integer,
|
* name provides a suffix but it does not parse as an unsigned integer,
|
||||||
* the routine returns ~0U. This will prevent further matching.
|
* the routine returns ~0U. This will prevent further matching.
|
||||||
*/
|
*/
|
||||||
unsigned get_flash_name_index(const char *name);
|
unsigned get_flash_name_index(const char *name);
|
||||||
/**
|
/**
|
||||||
* Attempt to match the @c expected name with the @c name of a driver.
|
* Attempt to match the @c expected name with the @c name of a driver.
|
||||||
@@ -36,13 +36,14 @@ unsigned get_flash_name_index(const char *name);
|
|||||||
*/
|
*/
|
||||||
bool flash_driver_name_matches(const char *name, const char *expected);
|
bool flash_driver_name_matches(const char *name, const char *expected);
|
||||||
|
|
||||||
#define ERROR_FLASH_BANK_INVALID -900
|
#define ERROR_FLASH_BANK_INVALID (-900)
|
||||||
#define ERROR_FLASH_SECTOR_INVALID -901
|
#define ERROR_FLASH_SECTOR_INVALID (-901)
|
||||||
#define ERROR_FLASH_OPERATION_FAILED -902
|
#define ERROR_FLASH_OPERATION_FAILED (-902)
|
||||||
#define ERROR_FLASH_DST_OUT_OF_BANK -903
|
#define ERROR_FLASH_DST_OUT_OF_BANK (-903)
|
||||||
#define ERROR_FLASH_DST_BREAKS_ALIGNMENT -904
|
#define ERROR_FLASH_DST_BREAKS_ALIGNMENT (-904)
|
||||||
#define ERROR_FLASH_BUSY -905
|
#define ERROR_FLASH_BUSY (-905)
|
||||||
#define ERROR_FLASH_SECTOR_NOT_ERASED -906
|
#define ERROR_FLASH_SECTOR_NOT_ERASED (-906)
|
||||||
#define ERROR_FLASH_BANK_NOT_PROBED -907
|
#define ERROR_FLASH_BANK_NOT_PROBED (-907)
|
||||||
|
#define ERROR_FLASH_OPER_UNSUPPORTED (-908)
|
||||||
|
|
||||||
#endif // FLASH_COMMON_H
|
#endif // FLASH_COMMON_H
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ static int mg_init_gpio (void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mg_dsk_wait(mg_io_type_wait wait, uint32_t time)
|
static int mg_dsk_wait(mg_io_type_wait wait_local, uint32_t time_var)
|
||||||
{
|
{
|
||||||
uint8_t status, error;
|
uint8_t status, error;
|
||||||
struct target *target = mflash_bank->target;
|
struct target *target = mflash_bank->target;
|
||||||
@@ -220,7 +220,7 @@ static int mg_dsk_wait(mg_io_type_wait wait, uint32_t time)
|
|||||||
struct duration bench;
|
struct duration bench;
|
||||||
duration_start(&bench);
|
duration_start(&bench);
|
||||||
|
|
||||||
while (time) {
|
while (time_var) {
|
||||||
|
|
||||||
ret = target_read_u8(target, mg_task_reg + MG_REG_STATUS, &status);
|
ret = target_read_u8(target, mg_task_reg + MG_REG_STATUS, &status);
|
||||||
if (ret != ERROR_OK)
|
if (ret != ERROR_OK)
|
||||||
@@ -228,10 +228,10 @@ static int mg_dsk_wait(mg_io_type_wait wait, uint32_t time)
|
|||||||
|
|
||||||
if (status & mg_io_rbit_status_busy)
|
if (status & mg_io_rbit_status_busy)
|
||||||
{
|
{
|
||||||
if (wait == mg_io_wait_bsy)
|
if (wait_local == mg_io_wait_bsy)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
} else {
|
} else {
|
||||||
switch (wait)
|
switch (wait_local)
|
||||||
{
|
{
|
||||||
case mg_io_wait_not_bsy:
|
case mg_io_wait_not_bsy:
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
@@ -259,7 +259,7 @@ static int mg_dsk_wait(mg_io_type_wait wait, uint32_t time)
|
|||||||
return ERROR_MG_IO;
|
return ERROR_MG_IO;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (wait)
|
switch (wait_local)
|
||||||
{
|
{
|
||||||
case mg_io_wait_rdy:
|
case mg_io_wait_rdy:
|
||||||
if (status & mg_io_rbit_status_ready)
|
if (status & mg_io_rbit_status_ready)
|
||||||
@@ -280,7 +280,7 @@ static int mg_dsk_wait(mg_io_type_wait wait, uint32_t time)
|
|||||||
else
|
else
|
||||||
LOG_ERROR("mflash: duration measurement failed: %d", ret);
|
LOG_ERROR("mflash: duration measurement failed: %d", ret);
|
||||||
|
|
||||||
if (t > time)
|
if (t > time_var)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -720,14 +720,20 @@ COMMAND_HANDLER(mg_write_cmd)
|
|||||||
if (ret != ERROR_OK)
|
if (ret != ERROR_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
int filesize;
|
||||||
buffer = malloc(MG_FILEIO_CHUNK);
|
buffer = malloc(MG_FILEIO_CHUNK);
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
fileio_close(&fileio);
|
fileio_close(&fileio);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
int retval = fileio_size(&fileio, &filesize);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
fileio_close(&fileio);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
cnt = fileio.size / MG_FILEIO_CHUNK;
|
cnt = filesize / MG_FILEIO_CHUNK;
|
||||||
res = fileio.size % MG_FILEIO_CHUNK;
|
res = filesize % MG_FILEIO_CHUNK;
|
||||||
|
|
||||||
struct duration bench;
|
struct duration bench;
|
||||||
duration_start(&bench);
|
duration_start(&bench);
|
||||||
@@ -752,8 +758,8 @@ COMMAND_HANDLER(mg_write_cmd)
|
|||||||
if (duration_measure(&bench) == ERROR_OK)
|
if (duration_measure(&bench) == ERROR_OK)
|
||||||
{
|
{
|
||||||
command_print(CMD_CTX, "wrote %ld bytes from file %s "
|
command_print(CMD_CTX, "wrote %ld bytes from file %s "
|
||||||
"in %fs (%0.3f kB/s)", (long)fileio.size, CMD_ARGV[1],
|
"in %fs (%0.3f kB/s)", (long)filesize, CMD_ARGV[1],
|
||||||
duration_elapsed(&bench), duration_kbps(&bench, fileio.size));
|
duration_elapsed(&bench), duration_kbps(&bench, filesize));
|
||||||
}
|
}
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
@@ -1121,7 +1127,7 @@ static int mg_storage_config(void)
|
|||||||
!= ERROR_OK)
|
!= ERROR_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
mg_gen_ataid((mg_io_type_drv_info *)buff);
|
mg_gen_ataid((mg_io_type_drv_info *)(void *)buff);
|
||||||
|
|
||||||
if ((ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_stgdrvinfo))
|
if ((ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_stgdrvinfo))
|
||||||
!= ERROR_OK)
|
!= ERROR_OK)
|
||||||
@@ -1149,7 +1155,7 @@ static int mg_boot_config(void)
|
|||||||
buff[0] = mg_op_mode_snd; /* operation mode */
|
buff[0] = mg_op_mode_snd; /* operation mode */
|
||||||
buff[1] = MG_UNLOCK_OTP_AREA;
|
buff[1] = MG_UNLOCK_OTP_AREA;
|
||||||
buff[2] = 4; /* boot size */
|
buff[2] = 4; /* boot size */
|
||||||
*((uint32_t *)(buff + 4)) = 0; /* XIP size */
|
*((uint32_t *)(void *)(buff + 4)) = 0; /* XIP size */
|
||||||
|
|
||||||
if ((ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_xipinfo))
|
if ((ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_xipinfo))
|
||||||
!= ERROR_OK)
|
!= ERROR_OK)
|
||||||
@@ -1302,7 +1308,7 @@ static const struct command_registration mflash_exec_command_handlers[] = {
|
|||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
int mflash_init_drivers(struct command_context *cmd_ctx)
|
static int mflash_init_drivers(struct command_context *cmd_ctx)
|
||||||
{
|
{
|
||||||
if (!mflash_bank)
|
if (!mflash_bank)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ struct mflash_gpio_num
|
|||||||
|
|
||||||
struct mflash_gpio_drv
|
struct mflash_gpio_drv
|
||||||
{
|
{
|
||||||
char *name;
|
const char *name;
|
||||||
int (*set_gpio_to_output) (struct mflash_gpio_num gpio);
|
int (*set_gpio_to_output) (struct mflash_gpio_num gpio);
|
||||||
int (*set_gpio_output_val) (struct mflash_gpio_num gpio, uint8_t val);
|
int (*set_gpio_output_val) (struct mflash_gpio_num gpio, uint8_t val);
|
||||||
};
|
};
|
||||||
@@ -142,7 +142,6 @@ struct mflash_bank
|
|||||||
};
|
};
|
||||||
|
|
||||||
int mflash_register_commands(struct command_context *cmd_ctx);
|
int mflash_register_commands(struct command_context *cmd_ctx);
|
||||||
int mflash_init_drivers(struct command_context *cmd_ctx);
|
|
||||||
|
|
||||||
#define MG_MFLASH_SECTOR_SIZE (0x200) /* 512Bytes = 2^9 */
|
#define MG_MFLASH_SECTOR_SIZE (0x200) /* 512Bytes = 2^9 */
|
||||||
#define MG_MFLASH_SECTOR_SIZE_MASK (0x200-1)
|
#define MG_MFLASH_SECTOR_SIZE_MASK (0x200-1)
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
AM_CPPFLAGS = \
|
include $(top_srcdir)/common.mk
|
||||||
-I$(top_srcdir)/src \
|
|
||||||
-I$(top_builddir)/src
|
|
||||||
|
|
||||||
noinst_LTLIBRARIES = libocdflashnand.la
|
noinst_LTLIBRARIES = libocdflashnand.la
|
||||||
|
|
||||||
@@ -18,6 +16,8 @@ NAND_DRIVERS = \
|
|||||||
nonce.c \
|
nonce.c \
|
||||||
davinci.c \
|
davinci.c \
|
||||||
lpc3180.c \
|
lpc3180.c \
|
||||||
|
lpc32xx.c \
|
||||||
|
mx2.c \
|
||||||
mx3.c \
|
mx3.c \
|
||||||
orion.c \
|
orion.c \
|
||||||
s3c24xx.c \
|
s3c24xx.c \
|
||||||
@@ -26,7 +26,8 @@ NAND_DRIVERS = \
|
|||||||
s3c2440.c \
|
s3c2440.c \
|
||||||
s3c2443.c \
|
s3c2443.c \
|
||||||
s3c6400.c \
|
s3c6400.c \
|
||||||
at91sam9.c
|
at91sam9.c \
|
||||||
|
nuc910.c
|
||||||
|
|
||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
arm_io.h \
|
arm_io.h \
|
||||||
@@ -35,8 +36,11 @@ noinst_HEADERS = \
|
|||||||
fileio.h \
|
fileio.h \
|
||||||
imp.h \
|
imp.h \
|
||||||
lpc3180.h \
|
lpc3180.h \
|
||||||
|
lpc32xx.h \
|
||||||
|
mx2.h \
|
||||||
mx3.h \
|
mx3.h \
|
||||||
s3c24xx.h \
|
s3c24xx.h \
|
||||||
s3c24xx_regs.h
|
s3c24xx_regs.h \
|
||||||
|
nuc910.h
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
* @param area Pointer to a pointer to a working area to copy code to
|
* @param area Pointer to a pointer to a working area to copy code to
|
||||||
* @return Success or failure of the operation
|
* @return Success or failure of the operation
|
||||||
*/
|
*/
|
||||||
int arm_code_to_working_area(struct target *target,
|
static int arm_code_to_working_area(struct target *target,
|
||||||
const uint32_t *code, unsigned code_size,
|
const uint32_t *code, unsigned code_size,
|
||||||
unsigned additional, struct working_area **area)
|
unsigned additional, struct working_area **area)
|
||||||
{
|
{
|
||||||
@@ -100,7 +100,7 @@ int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size)
|
|||||||
struct arm *armv4_5 = target->arch_info;
|
struct arm *armv4_5 = target->arch_info;
|
||||||
struct reg_param reg_params[3];
|
struct reg_param reg_params[3];
|
||||||
uint32_t target_buf;
|
uint32_t target_buf;
|
||||||
uint32_t exit = 0;
|
uint32_t exit_var = 0;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
/* Inputs:
|
/* Inputs:
|
||||||
@@ -153,11 +153,11 @@ int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size)
|
|||||||
|
|
||||||
/* armv4 must exit using a hardware breakpoint */
|
/* armv4 must exit using a hardware breakpoint */
|
||||||
if (armv4_5->is_armv4)
|
if (armv4_5->is_armv4)
|
||||||
exit = nand->copy_area->address + sizeof(code) - 4;
|
exit_var = nand->copy_area->address + sizeof(code) - 4;
|
||||||
|
|
||||||
/* use alg to write data from work area to NAND chip */
|
/* use alg to write data from work area to NAND chip */
|
||||||
retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
|
retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
|
||||||
nand->copy_area->address, exit, 1000, &algo);
|
nand->copy_area->address, exit_var, 1000, &algo);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
LOG_ERROR("error executing hosted NAND write");
|
LOG_ERROR("error executing hosted NAND write");
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size)
|
|||||||
struct arm *armv4_5 = target->arch_info;
|
struct arm *armv4_5 = target->arch_info;
|
||||||
struct reg_param reg_params[3];
|
struct reg_param reg_params[3];
|
||||||
uint32_t target_buf;
|
uint32_t target_buf;
|
||||||
uint32_t exit = 0;
|
uint32_t exit_var = 0;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
/* Inputs:
|
/* Inputs:
|
||||||
@@ -229,11 +229,11 @@ int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size)
|
|||||||
|
|
||||||
/* armv4 must exit using a hardware breakpoint */
|
/* armv4 must exit using a hardware breakpoint */
|
||||||
if (armv4_5->is_armv4)
|
if (armv4_5->is_armv4)
|
||||||
exit = nand->copy_area->address + sizeof(code) - 4;
|
exit_var = nand->copy_area->address + sizeof(code) - 4;
|
||||||
|
|
||||||
/* use alg to write data from NAND chip to work area */
|
/* use alg to write data from NAND chip to work area */
|
||||||
retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
|
retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
|
||||||
nand->copy_area->address, exit, 1000, &algo);
|
nand->copy_area->address, exit_var, 1000, &algo);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
LOG_ERROR("error executing hosted NAND read");
|
LOG_ERROR("error executing hosted NAND read");
|
||||||
|
|
||||||
|
|||||||
@@ -38,9 +38,6 @@
|
|||||||
* Representation of a pin on an AT91SAM9 chip.
|
* Representation of a pin on an AT91SAM9 chip.
|
||||||
*/
|
*/
|
||||||
struct at91sam9_pin {
|
struct at91sam9_pin {
|
||||||
/** Target this pin is on. */
|
|
||||||
struct target *target;
|
|
||||||
|
|
||||||
/** Address of the PIO controller. */
|
/** Address of the PIO controller. */
|
||||||
uint32_t pioc;
|
uint32_t pioc;
|
||||||
|
|
||||||
@@ -52,9 +49,6 @@ struct at91sam9_pin {
|
|||||||
* Private data for the controller that is stored in the NAND device structure.
|
* Private data for the controller that is stored in the NAND device structure.
|
||||||
*/
|
*/
|
||||||
struct at91sam9_nand {
|
struct at91sam9_nand {
|
||||||
/** Target the NAND is attached to. */
|
|
||||||
struct target *target;
|
|
||||||
|
|
||||||
/** Address of the ECC controller for NAND. */
|
/** Address of the ECC controller for NAND. */
|
||||||
uint32_t ecc;
|
uint32_t ecc;
|
||||||
|
|
||||||
@@ -101,8 +95,7 @@ static int at91sam9_halted(struct target *target, const char *label)
|
|||||||
*/
|
*/
|
||||||
static int at91sam9_init(struct nand_device *nand)
|
static int at91sam9_init(struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct at91sam9_nand *info = nand->controller_priv;
|
struct target *target = nand->target;
|
||||||
struct target *target = info->target;
|
|
||||||
|
|
||||||
if (!at91sam9_halted(target, "init")) {
|
if (!at91sam9_halted(target, "init")) {
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
@@ -117,9 +110,10 @@ static int at91sam9_init(struct nand_device *nand)
|
|||||||
* @param info NAND controller information for controlling NAND device.
|
* @param info NAND controller information for controlling NAND device.
|
||||||
* @return Success or failure of the enabling.
|
* @return Success or failure of the enabling.
|
||||||
*/
|
*/
|
||||||
static int at91sam9_enable(struct at91sam9_nand *info)
|
static int at91sam9_enable(struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct target *target = info->target;
|
struct at91sam9_nand *info = nand->controller_priv;
|
||||||
|
struct target *target = nand->target;
|
||||||
|
|
||||||
return target_write_u32(target, info->ce.pioc + AT91C_PIOx_CODR, 1 << info->ce.num);
|
return target_write_u32(target, info->ce.pioc + AT91C_PIOx_CODR, 1 << info->ce.num);
|
||||||
}
|
}
|
||||||
@@ -130,9 +124,10 @@ static int at91sam9_enable(struct at91sam9_nand *info)
|
|||||||
* @param info NAND controller information for controlling NAND device.
|
* @param info NAND controller information for controlling NAND device.
|
||||||
* @return Success or failure of the disabling.
|
* @return Success or failure of the disabling.
|
||||||
*/
|
*/
|
||||||
static int at91sam9_disable(struct at91sam9_nand *info)
|
static int at91sam9_disable(struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct target *target = info->target;
|
struct at91sam9_nand *info = nand->controller_priv;
|
||||||
|
struct target *target = nand->target;
|
||||||
|
|
||||||
return target_write_u32(target, info->ce.pioc + AT91C_PIOx_SODR, 1 << info->ce.num);
|
return target_write_u32(target, info->ce.pioc + AT91C_PIOx_SODR, 1 << info->ce.num);
|
||||||
}
|
}
|
||||||
@@ -147,13 +142,13 @@ static int at91sam9_disable(struct at91sam9_nand *info)
|
|||||||
static int at91sam9_command(struct nand_device *nand, uint8_t command)
|
static int at91sam9_command(struct nand_device *nand, uint8_t command)
|
||||||
{
|
{
|
||||||
struct at91sam9_nand *info = nand->controller_priv;
|
struct at91sam9_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (!at91sam9_halted(target, "command")) {
|
if (!at91sam9_halted(target, "command")) {
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
at91sam9_enable(info);
|
at91sam9_enable(nand);
|
||||||
|
|
||||||
return target_write_u8(target, info->cmd, command);
|
return target_write_u8(target, info->cmd, command);
|
||||||
}
|
}
|
||||||
@@ -166,13 +161,11 @@ static int at91sam9_command(struct nand_device *nand, uint8_t command)
|
|||||||
*/
|
*/
|
||||||
static int at91sam9_reset(struct nand_device *nand)
|
static int at91sam9_reset(struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct at91sam9_nand *info = nand->controller_priv;
|
if (!at91sam9_halted(nand->target, "reset")) {
|
||||||
|
|
||||||
if (!at91sam9_halted(info->target, "reset")) {
|
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return at91sam9_disable(info);
|
return at91sam9_disable(nand);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -185,9 +178,9 @@ static int at91sam9_reset(struct nand_device *nand)
|
|||||||
static int at91sam9_address(struct nand_device *nand, uint8_t address)
|
static int at91sam9_address(struct nand_device *nand, uint8_t address)
|
||||||
{
|
{
|
||||||
struct at91sam9_nand *info = nand->controller_priv;
|
struct at91sam9_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (!at91sam9_halted(info->target, "address")) {
|
if (!at91sam9_halted(nand->target, "address")) {
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,9 +198,9 @@ static int at91sam9_address(struct nand_device *nand, uint8_t address)
|
|||||||
static int at91sam9_read_data(struct nand_device *nand, void *data)
|
static int at91sam9_read_data(struct nand_device *nand, void *data)
|
||||||
{
|
{
|
||||||
struct at91sam9_nand *info = nand->controller_priv;
|
struct at91sam9_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (!at91sam9_halted(info->target, "read data")) {
|
if (!at91sam9_halted(nand->target, "read data")) {
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +218,7 @@ static int at91sam9_read_data(struct nand_device *nand, void *data)
|
|||||||
static int at91sam9_write_data(struct nand_device *nand, uint16_t data)
|
static int at91sam9_write_data(struct nand_device *nand, uint16_t data)
|
||||||
{
|
{
|
||||||
struct at91sam9_nand *info = nand->controller_priv;
|
struct at91sam9_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (!at91sam9_halted(target, "write data")) {
|
if (!at91sam9_halted(target, "write data")) {
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
@@ -244,7 +237,7 @@ static int at91sam9_write_data(struct nand_device *nand, uint16_t data)
|
|||||||
static int at91sam9_nand_ready(struct nand_device *nand, int timeout)
|
static int at91sam9_nand_ready(struct nand_device *nand, int timeout)
|
||||||
{
|
{
|
||||||
struct at91sam9_nand *info = nand->controller_priv;
|
struct at91sam9_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
|
|
||||||
if (!at91sam9_halted(target, "nand ready")) {
|
if (!at91sam9_halted(target, "nand ready")) {
|
||||||
@@ -279,7 +272,7 @@ static int at91sam9_read_block_data(struct nand_device *nand, uint8_t *data, int
|
|||||||
struct arm_nand_data *io = &info->io;
|
struct arm_nand_data *io = &info->io;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (!at91sam9_halted(info->target, "read block")) {
|
if (!at91sam9_halted(nand->target, "read block")) {
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +297,7 @@ static int at91sam9_write_block_data(struct nand_device *nand, uint8_t *data, in
|
|||||||
struct arm_nand_data *io = &info->io;
|
struct arm_nand_data *io = &info->io;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (!at91sam9_halted(info->target, "write block")) {
|
if (!at91sam9_halted(nand->target, "write block")) {
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,7 +374,7 @@ static int at91sam9_read_page(struct nand_device *nand, uint32_t page,
|
|||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
struct at91sam9_nand *info = nand->controller_priv;
|
struct at91sam9_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
uint8_t *oob_data;
|
uint8_t *oob_data;
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
|
|
||||||
@@ -458,7 +451,7 @@ static int at91sam9_write_page(struct nand_device *nand, uint32_t page,
|
|||||||
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
|
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
|
||||||
{
|
{
|
||||||
struct at91sam9_nand *info = nand->controller_priv;
|
struct at91sam9_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
int retval;
|
int retval;
|
||||||
uint8_t *oob_data = oob;
|
uint8_t *oob_data = oob;
|
||||||
uint32_t parity, nparity;
|
uint32_t parity, nparity;
|
||||||
@@ -517,23 +510,16 @@ static int at91sam9_write_page(struct nand_device *nand, uint32_t page,
|
|||||||
*/
|
*/
|
||||||
NAND_DEVICE_COMMAND_HANDLER(at91sam9_nand_device_command)
|
NAND_DEVICE_COMMAND_HANDLER(at91sam9_nand_device_command)
|
||||||
{
|
{
|
||||||
struct target *target = NULL;
|
|
||||||
unsigned long chip = 0, ecc = 0;
|
unsigned long chip = 0, ecc = 0;
|
||||||
struct at91sam9_nand *info = NULL;
|
struct at91sam9_nand *info = NULL;
|
||||||
|
|
||||||
LOG_DEBUG("AT91SAM9 NAND Device Command\n");
|
LOG_DEBUG("AT91SAM9 NAND Device Command");
|
||||||
|
|
||||||
if (CMD_ARGC < 3 || CMD_ARGC > 4) {
|
if (CMD_ARGC < 3 || CMD_ARGC > 4) {
|
||||||
LOG_ERROR("parameters: %s target chip_addr", CMD_ARGV[0]);
|
LOG_ERROR("parameters: %s target chip_addr", CMD_ARGV[0]);
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
target = get_target(CMD_ARGV[1]);
|
|
||||||
if (!target) {
|
|
||||||
LOG_ERROR("invalid target: %s", CMD_ARGV[1]);
|
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip);
|
COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip);
|
||||||
if (chip == 0) {
|
if (chip == 0) {
|
||||||
LOG_ERROR("invalid NAND chip address: %s", CMD_ARGV[2]);
|
LOG_ERROR("invalid NAND chip address: %s", CMD_ARGV[2]);
|
||||||
@@ -554,14 +540,13 @@ NAND_DEVICE_COMMAND_HANDLER(at91sam9_nand_device_command)
|
|||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->target = target;
|
|
||||||
info->data = chip;
|
info->data = chip;
|
||||||
info->cmd = chip | (1 << 22);
|
info->cmd = chip | (1 << 22);
|
||||||
info->addr = chip | (1 << 21);
|
info->addr = chip | (1 << 21);
|
||||||
info->ecc = ecc;
|
info->ecc = ecc;
|
||||||
|
|
||||||
nand->controller_priv = info;
|
nand->controller_priv = info;
|
||||||
info->io.target = target;
|
info->io.target = nand->target;
|
||||||
info->io.data = info->data;
|
info->io.data = info->data;
|
||||||
info->io.op = ARM_NAND_NONE;
|
info->io.op = ARM_NAND_NONE;
|
||||||
|
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ void nand_device_add(struct nand_device *c)
|
|||||||
|
|
||||||
/* Chip ID list
|
/* Chip ID list
|
||||||
*
|
*
|
||||||
* Name, ID code, pagesize, chipsize in MegaByte, eraseblock size,
|
* Manufacturer, ID code, pagesize, chipsize in MegaByte, eraseblock size,
|
||||||
* options
|
* options, name
|
||||||
*
|
*
|
||||||
* Pagesize; 0, 256, 512
|
* Pagesize; 0, 256, 512
|
||||||
* 0 get this information from the extended chip ID
|
* 0 get this information from the extended chip ID
|
||||||
@@ -52,80 +52,86 @@ void nand_device_add(struct nand_device *c)
|
|||||||
*/
|
*/
|
||||||
static struct nand_info nand_flash_ids[] =
|
static struct nand_info nand_flash_ids[] =
|
||||||
{
|
{
|
||||||
/* start "museum" IDs */
|
/* Vendor Specific Entries */
|
||||||
{"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0},
|
{ NAND_MFR_SAMSUNG, 0xD5, 8192, 2048, 0x100000, LP_OPTIONS, "K9GAG08 2GB NAND 3.3V x8 MLC 2b/cell"},
|
||||||
{"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0},
|
{ NAND_MFR_SAMSUNG, 0xD7, 8192, 4096, 0x100000, LP_OPTIONS, "K9LBG08 4GB NAND 3.3V x8 MLC 2b/cell"},
|
||||||
{"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0},
|
|
||||||
{"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0},
|
|
||||||
{"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0},
|
|
||||||
{"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0},
|
|
||||||
{"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0},
|
|
||||||
{"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0},
|
|
||||||
{"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0},
|
|
||||||
{"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0},
|
|
||||||
|
|
||||||
{"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0},
|
/* start "museum" IDs */
|
||||||
{"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0},
|
{ 0x0, 0x6e, 256, 1, 0x1000, 0, "NAND 1MiB 5V 8-bit"},
|
||||||
{"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
|
{ 0x0, 0x64, 256, 2, 0x1000, 0, "NAND 2MiB 5V 8-bit"},
|
||||||
{"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
|
{ 0x0, 0x6b, 512, 4, 0x2000, 0, "NAND 4MiB 5V 8-bit"},
|
||||||
|
{ 0x0, 0xe8, 256, 1, 0x1000, 0, "NAND 1MiB 3.3V 8-bit"},
|
||||||
|
{ 0x0, 0xec, 256, 1, 0x1000, 0, "NAND 1MiB 3.3V 8-bit"},
|
||||||
|
{ 0x0, 0xea, 256, 2, 0x1000, 0, "NAND 2MiB 3.3V 8-bit"},
|
||||||
|
{ 0x0, 0xd5, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"},
|
||||||
|
{ 0x0, 0xe3, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"},
|
||||||
|
{ 0x0, 0xe5, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"},
|
||||||
|
{ 0x0, 0xd6, 512, 8, 0x2000, 0, "NAND 8MiB 3.3V 8-bit"},
|
||||||
|
|
||||||
|
{ 0x0, 0x39, 512, 8, 0x2000, 0, "NAND 8MiB 1.8V 8-bit"},
|
||||||
|
{ 0x0, 0xe6, 512, 8, 0x2000, 0, "NAND 8MiB 3.3V 8-bit"},
|
||||||
|
{ 0x0, 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16, "NAND 8MiB 1.8V 16-bit"},
|
||||||
|
{ 0x0, 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16, "NAND 8MiB 3.3V 16-bit"},
|
||||||
/* end "museum" IDs */
|
/* end "museum" IDs */
|
||||||
|
|
||||||
{"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0},
|
{ 0x0, 0x33, 512, 16, 0x4000, 0, "NAND 16MiB 1.8V 8-bit"},
|
||||||
{"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0},
|
{ 0x0, 0x73, 512, 16, 0x4000, 0, "NAND 16MiB 3.3V 8-bit"},
|
||||||
{"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
|
{ 0x0, 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16,"NAND 16MiB 1.8V 16-bit"},
|
||||||
{"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
|
{ 0x0, 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16,"NAND 16MiB 3.3V 16-bit"},
|
||||||
|
|
||||||
{"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0},
|
{ 0x0, 0x35, 512, 32, 0x4000, 0, "NAND 32MiB 1.8V 8-bit"},
|
||||||
{"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0},
|
{ 0x0, 0x75, 512, 32, 0x4000, 0, "NAND 32MiB 3.3V 8-bit"},
|
||||||
{"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
|
{ 0x0, 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16,"NAND 32MiB 1.8V 16-bit"},
|
||||||
{"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
|
{ 0x0, 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16,"NAND 32MiB 3.3V 16-bit"},
|
||||||
|
|
||||||
{"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0},
|
{ 0x0, 0x36, 512, 64, 0x4000, 0, "NAND 64MiB 1.8V 8-bit"},
|
||||||
{"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0},
|
{ 0x0, 0x76, 512, 64, 0x4000, 0, "NAND 64MiB 3.3V 8-bit"},
|
||||||
{"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
|
{ 0x0, 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16,"NAND 64MiB 1.8V 16-bit"},
|
||||||
{"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
|
{ 0x0, 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16,"NAND 64MiB 3.3V 16-bit"},
|
||||||
|
|
||||||
{"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0},
|
{ 0x0, 0x78, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"},
|
||||||
{"NAND 128MiB 1,8V 8-bit", 0x39, 512, 128, 0x4000, 0},
|
{ 0x0, 0x39, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"},
|
||||||
{"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0},
|
{ 0x0, 0x79, 512, 128, 0x4000, 0, "NAND 128MiB 3.3V 8-bit"},
|
||||||
{"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
|
{ 0x0, 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 1.8V 16-bit"},
|
||||||
{"NAND 128MiB 1,8V 16-bit", 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16},
|
{ 0x0, 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 1.8V 16-bit"},
|
||||||
{"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
|
{ 0x0, 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 3.3V 16-bit"},
|
||||||
{"NAND 128MiB 3,3V 16-bit", 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16},
|
{ 0x0, 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 3.3V 16-bit"},
|
||||||
|
|
||||||
{"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0},
|
{ 0x0, 0x71, 512, 256, 0x4000, 0, "NAND 256MiB 3.3V 8-bit"},
|
||||||
|
|
||||||
{"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS},
|
{ 0x0, 0xA2, 0, 64, 0, LP_OPTIONS, "NAND 64MiB 1.8V 8-bit"},
|
||||||
{"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS},
|
{ 0x0, 0xF2, 0, 64, 0, LP_OPTIONS, "NAND 64MiB 3.3V 8-bit"},
|
||||||
{"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16},
|
{ 0x0, 0xB2, 0, 64, 0, LP_OPTIONS16, "NAND 64MiB 1.8V 16-bit"},
|
||||||
{"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16},
|
{ 0x0, 0xC2, 0, 64, 0, LP_OPTIONS16, "NAND 64MiB 3.3V 16-bit"},
|
||||||
|
|
||||||
{"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, LP_OPTIONS},
|
{ 0x0, 0xA1, 0, 128, 0, LP_OPTIONS, "NAND 128MiB 1.8V 8-bit"},
|
||||||
{"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, LP_OPTIONS},
|
{ 0x0, 0xF1, 0, 128, 0, LP_OPTIONS, "NAND 128MiB 3.3V 8-bit"},
|
||||||
{"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, LP_OPTIONS16},
|
{ 0x0, 0xB1, 0, 128, 0, LP_OPTIONS16, "NAND 128MiB 1.8V 16-bit"},
|
||||||
{"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, LP_OPTIONS16},
|
{ 0x0, 0xC1, 0, 128, 0, LP_OPTIONS16, "NAND 128MiB 3.3V 16-bit"},
|
||||||
|
|
||||||
{"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, LP_OPTIONS},
|
{ 0x0, 0xAA, 0, 256, 0, LP_OPTIONS, "NAND 256MiB 1.8V 8-bit"},
|
||||||
{"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, LP_OPTIONS},
|
{ 0x0, 0xDA, 0, 256, 0, LP_OPTIONS, "NAND 256MiB 3.3V 8-bit"},
|
||||||
{"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, LP_OPTIONS16},
|
{ 0x0, 0xBA, 0, 256, 0, LP_OPTIONS16, "NAND 256MiB 1.8V 16-bit"},
|
||||||
{"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, LP_OPTIONS16},
|
{ 0x0, 0xCA, 0, 256, 0, LP_OPTIONS16, "NAND 256MiB 3.3V 16-bit"},
|
||||||
|
|
||||||
{"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, LP_OPTIONS},
|
{ 0x0, 0xAC, 0, 512, 0, LP_OPTIONS, "NAND 512MiB 1.8V 8-bit"},
|
||||||
{"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, LP_OPTIONS},
|
{ 0x0, 0xDC, 0, 512, 0, LP_OPTIONS, "NAND 512MiB 3.3V 8-bit"},
|
||||||
{"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, LP_OPTIONS16},
|
{ 0x0, 0xBC, 0, 512, 0, LP_OPTIONS16, "NAND 512MiB 1.8V 16-bit"},
|
||||||
{"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, LP_OPTIONS16},
|
{ 0x0, 0xCC, 0, 512, 0, LP_OPTIONS16, "NAND 512MiB 3.3V 16-bit"},
|
||||||
|
|
||||||
{"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, LP_OPTIONS},
|
{ 0x0, 0xA3, 0, 1024, 0, LP_OPTIONS, "NAND 1GiB 1.8V 8-bit"},
|
||||||
{"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, LP_OPTIONS},
|
{ 0x0, 0xD3, 0, 1024, 0, LP_OPTIONS, "NAND 1GiB 3.3V 8-bit"},
|
||||||
{"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, LP_OPTIONS16},
|
{ 0x0, 0xB3, 0, 1024, 0, LP_OPTIONS16, "NAND 1GiB 1.8V 16-bit"},
|
||||||
{"NAND 1GiB 3,3V 16-bit", 0xC3, 0, 1024, 0, LP_OPTIONS16},
|
{ 0x0, 0xC3, 0, 1024, 0, LP_OPTIONS16, "NAND 1GiB 3.3V 16-bit"},
|
||||||
|
|
||||||
{"NAND 2GiB 1,8V 8-bit", 0xA5, 0, 2048, 0, LP_OPTIONS},
|
{ 0x0, 0xA5, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 1.8V 8-bit"},
|
||||||
{"NAND 2GiB 3,3V 8-bit", 0xD5, 0, 2048, 0, LP_OPTIONS},
|
{ 0x0, 0xD5, 0, 8192, 0, LP_OPTIONS, "NAND 2GiB 3.3V 8-bit"},
|
||||||
{"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, LP_OPTIONS16},
|
{ 0x0, 0xB5, 0, 2048, 0, LP_OPTIONS16, "NAND 2GiB 1.8V 16-bit"},
|
||||||
{"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16},
|
{ 0x0, 0xC5, 0, 2048, 0, LP_OPTIONS16, "NAND 2GiB 3.3V 16-bit"},
|
||||||
|
|
||||||
{NULL, 0, 0, 0, 0, 0 }
|
{ 0x0, 0x48, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 3.3V 8-bit"},
|
||||||
|
|
||||||
|
{0, 0, 0, 0, 0, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Manufacturer ID list
|
/* Manufacturer ID list
|
||||||
@@ -160,7 +166,14 @@ static struct nand_ecclayout nand_oob_8 = {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct nand_device *get_nand_device_by_name(const char *name)
|
/**
|
||||||
|
* Returns the flash bank specified by @a name, which matches the
|
||||||
|
* driver name and a suffix (option) specify the driver-specific
|
||||||
|
* bank number. The suffix consists of the '.' and the driver-specific
|
||||||
|
* bank number: when two davinci banks are defined, then 'davinci.1' refers
|
||||||
|
* to the second (e.g. DM355EVM).
|
||||||
|
*/
|
||||||
|
static struct nand_device *get_nand_device_by_name(const char *name)
|
||||||
{
|
{
|
||||||
unsigned requested = get_flash_name_index(name);
|
unsigned requested = get_flash_name_index(name);
|
||||||
unsigned found = 0;
|
unsigned found = 0;
|
||||||
@@ -215,9 +228,11 @@ COMMAND_HELPER(nand_command_get_device, unsigned name_index,
|
|||||||
|
|
||||||
int nand_build_bbt(struct nand_device *nand, int first, int last)
|
int nand_build_bbt(struct nand_device *nand, int first, int last)
|
||||||
{
|
{
|
||||||
uint32_t page = 0x0;
|
uint32_t page;
|
||||||
int i;
|
int i;
|
||||||
|
int pages_per_block = (nand->erase_size / nand->page_size);
|
||||||
uint8_t oob[6];
|
uint8_t oob[6];
|
||||||
|
int ret;
|
||||||
|
|
||||||
if ((first < 0) || (first >= nand->num_blocks))
|
if ((first < 0) || (first >= nand->num_blocks))
|
||||||
first = 0;
|
first = 0;
|
||||||
@@ -225,9 +240,12 @@ int nand_build_bbt(struct nand_device *nand, int first, int last)
|
|||||||
if ((last >= nand->num_blocks) || (last == -1))
|
if ((last >= nand->num_blocks) || (last == -1))
|
||||||
last = nand->num_blocks - 1;
|
last = nand->num_blocks - 1;
|
||||||
|
|
||||||
for (i = first; i < last; i++)
|
page = first * pages_per_block;
|
||||||
|
for (i = first; i <= last; i++)
|
||||||
{
|
{
|
||||||
nand_read_page(nand, page, NULL, 0, oob, 6);
|
ret = nand_read_page(nand, page, NULL, 0, oob, 6);
|
||||||
|
if (ret != ERROR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (((nand->device->options & NAND_BUSWIDTH_16) && ((oob[0] & oob[1]) != 0xff))
|
if (((nand->device->options & NAND_BUSWIDTH_16) && ((oob[0] & oob[1]) != 0xff))
|
||||||
|| (((nand->page_size == 512) && (oob[5] != 0xff)) ||
|
|| (((nand->page_size == 512) && (oob[5] != 0xff)) ||
|
||||||
@@ -241,7 +259,7 @@ int nand_build_bbt(struct nand_device *nand, int first, int last)
|
|||||||
nand->blocks[i].is_bad = 0;
|
nand->blocks[i].is_bad = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
page += (nand->erase_size / nand->page_size);
|
page += pages_per_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
@@ -349,7 +367,9 @@ int nand_probe(struct nand_device *nand)
|
|||||||
|
|
||||||
for (i = 0; nand_flash_ids[i].name; i++)
|
for (i = 0; nand_flash_ids[i].name; i++)
|
||||||
{
|
{
|
||||||
if (nand_flash_ids[i].id == device_id)
|
if (nand_flash_ids[i].id == device_id &&
|
||||||
|
(nand_flash_ids[i].mfr_id == manufacturer_id ||
|
||||||
|
nand_flash_ids[i].mfr_id == 0 ))
|
||||||
{
|
{
|
||||||
nand->device = &nand_flash_ids[i];
|
nand->device = &nand_flash_ids[i];
|
||||||
break;
|
break;
|
||||||
@@ -521,7 +541,7 @@ int nand_erase(struct nand_device *nand, int first_block, int last_block)
|
|||||||
if (!nand->device)
|
if (!nand->device)
|
||||||
return ERROR_NAND_DEVICE_NOT_PROBED;
|
return ERROR_NAND_DEVICE_NOT_PROBED;
|
||||||
|
|
||||||
if ((first_block < 0) || (last_block > nand->num_blocks))
|
if ((first_block < 0) || (last_block >= nand->num_blocks))
|
||||||
return ERROR_INVALID_ARGUMENTS;
|
return ERROR_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
/* make sure we know if a block is bad before erasing it */
|
/* make sure we know if a block is bad before erasing it */
|
||||||
@@ -764,6 +784,7 @@ int nand_page_command(struct nand_device *nand, uint32_t page,
|
|||||||
if (!nand->controller->nand_ready(nand, 100))
|
if (!nand->controller->nand_ready(nand, 100))
|
||||||
return ERROR_NAND_OPERATION_TIMEOUT;
|
return ERROR_NAND_OPERATION_TIMEOUT;
|
||||||
} else {
|
} else {
|
||||||
|
/* nand_poll_read() cannot be used during nand read */
|
||||||
alive_sleep(1);
|
alive_sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,8 @@ struct nand_ecclayout {
|
|||||||
|
|
||||||
struct nand_device
|
struct nand_device
|
||||||
{
|
{
|
||||||
char *name;
|
const char *name;
|
||||||
|
struct target *target;
|
||||||
struct nand_flash_controller *controller;
|
struct nand_flash_controller *controller;
|
||||||
void *controller_priv;
|
void *controller_priv;
|
||||||
struct nand_manufacturer *manufacturer;
|
struct nand_manufacturer *manufacturer;
|
||||||
@@ -91,17 +92,18 @@ enum
|
|||||||
struct nand_manufacturer
|
struct nand_manufacturer
|
||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
char *name;
|
const char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nand_info
|
struct nand_info
|
||||||
{
|
{
|
||||||
char *name;
|
int mfr_id;
|
||||||
int id;
|
int id;
|
||||||
int page_size;
|
int page_size;
|
||||||
int chip_size;
|
int chip_size;
|
||||||
int erase_size;
|
int erase_size;
|
||||||
int options;
|
int options;
|
||||||
|
const char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Option constants for bizarre disfunctionality and real features
|
/* Option constants for bizarre disfunctionality and real features
|
||||||
@@ -197,15 +199,6 @@ enum oob_formats
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the flash bank specified by @a name, which matches the
|
|
||||||
* driver name and a suffix (option) specify the driver-specific
|
|
||||||
* bank number. The suffix consists of the '.' and the driver-specific
|
|
||||||
* bank number: when two davinci banks are defined, then 'davinci.1' refers
|
|
||||||
* to the second (e.g. DM355EVM).
|
|
||||||
*/
|
|
||||||
struct nand_device *get_nand_device_by_name(const char *name);
|
|
||||||
|
|
||||||
struct nand_device *get_nand_device_by_num(int num);
|
struct nand_device *get_nand_device_by_num(int num);
|
||||||
|
|
||||||
int nand_page_command(struct nand_device *nand, uint32_t page,
|
int nand_page_command(struct nand_device *nand, uint32_t page,
|
||||||
@@ -230,7 +223,6 @@ int nand_calculate_ecc_kw(struct nand_device *nand,
|
|||||||
const uint8_t *dat, uint8_t *ecc_code);
|
const uint8_t *dat, uint8_t *ecc_code);
|
||||||
|
|
||||||
int nand_register_commands(struct command_context *cmd_ctx);
|
int nand_register_commands(struct command_context *cmd_ctx);
|
||||||
int nand_init(struct command_context *cmd_ctx);
|
|
||||||
|
|
||||||
/// helper for parsing a nand device command argument string
|
/// helper for parsing a nand device command argument string
|
||||||
COMMAND_HELPER(nand_command_get_device, unsigned name_index,
|
COMMAND_HELPER(nand_command_get_device, unsigned name_index,
|
||||||
|
|||||||
@@ -39,8 +39,6 @@ enum ecc {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct davinci_nand {
|
struct davinci_nand {
|
||||||
struct target *target;
|
|
||||||
|
|
||||||
uint8_t chipsel; /* chipselect 0..3 == CS2..CS5 */
|
uint8_t chipsel; /* chipselect 0..3 == CS2..CS5 */
|
||||||
uint8_t eccmode;
|
uint8_t eccmode;
|
||||||
|
|
||||||
@@ -82,7 +80,7 @@ static int halted(struct target *target, const char *label)
|
|||||||
static int davinci_init(struct nand_device *nand)
|
static int davinci_init(struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct davinci_nand *info = nand->controller_priv;
|
struct davinci_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
uint32_t nandfcr;
|
uint32_t nandfcr;
|
||||||
|
|
||||||
if (!halted(target, "init"))
|
if (!halted(target, "init"))
|
||||||
@@ -112,7 +110,7 @@ static int davinci_reset(struct nand_device *nand)
|
|||||||
static int davinci_nand_ready(struct nand_device *nand, int timeout)
|
static int davinci_nand_ready(struct nand_device *nand, int timeout)
|
||||||
{
|
{
|
||||||
struct davinci_nand *info = nand->controller_priv;
|
struct davinci_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
uint32_t nandfsr;
|
uint32_t nandfsr;
|
||||||
|
|
||||||
/* NOTE: return code is zero/error, else success; not ERROR_* */
|
/* NOTE: return code is zero/error, else success; not ERROR_* */
|
||||||
@@ -135,7 +133,7 @@ static int davinci_nand_ready(struct nand_device *nand, int timeout)
|
|||||||
static int davinci_command(struct nand_device *nand, uint8_t command)
|
static int davinci_command(struct nand_device *nand, uint8_t command)
|
||||||
{
|
{
|
||||||
struct davinci_nand *info = nand->controller_priv;
|
struct davinci_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (!halted(target, "command"))
|
if (!halted(target, "command"))
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
@@ -147,7 +145,7 @@ static int davinci_command(struct nand_device *nand, uint8_t command)
|
|||||||
static int davinci_address(struct nand_device *nand, uint8_t address)
|
static int davinci_address(struct nand_device *nand, uint8_t address)
|
||||||
{
|
{
|
||||||
struct davinci_nand *info = nand->controller_priv;
|
struct davinci_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (!halted(target, "address"))
|
if (!halted(target, "address"))
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
@@ -159,7 +157,7 @@ static int davinci_address(struct nand_device *nand, uint8_t address)
|
|||||||
static int davinci_write_data(struct nand_device *nand, uint16_t data)
|
static int davinci_write_data(struct nand_device *nand, uint16_t data)
|
||||||
{
|
{
|
||||||
struct davinci_nand *info = nand->controller_priv;
|
struct davinci_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (!halted(target, "write_data"))
|
if (!halted(target, "write_data"))
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
@@ -171,7 +169,7 @@ static int davinci_write_data(struct nand_device *nand, uint16_t data)
|
|||||||
static int davinci_read_data(struct nand_device *nand, void *data)
|
static int davinci_read_data(struct nand_device *nand, void *data)
|
||||||
{
|
{
|
||||||
struct davinci_nand *info = nand->controller_priv;
|
struct davinci_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (!halted(target, "read_data"))
|
if (!halted(target, "read_data"))
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
@@ -186,7 +184,7 @@ static int davinci_read_block_data(struct nand_device *nand,
|
|||||||
uint8_t *data, int data_size)
|
uint8_t *data, int data_size)
|
||||||
{
|
{
|
||||||
struct davinci_nand *info = nand->controller_priv;
|
struct davinci_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
uint32_t nfdata = info->data;
|
uint32_t nfdata = info->data;
|
||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
|
|
||||||
@@ -219,7 +217,7 @@ static int davinci_write_block_data(struct nand_device *nand,
|
|||||||
uint8_t *data, int data_size)
|
uint8_t *data, int data_size)
|
||||||
{
|
{
|
||||||
struct davinci_nand *info = nand->controller_priv;
|
struct davinci_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
uint32_t nfdata = info->data;
|
uint32_t nfdata = info->data;
|
||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
int status;
|
int status;
|
||||||
@@ -260,12 +258,12 @@ static int davinci_write_page(struct nand_device *nand, uint32_t page,
|
|||||||
|
|
||||||
if (!nand->device)
|
if (!nand->device)
|
||||||
return ERROR_NAND_DEVICE_NOT_PROBED;
|
return ERROR_NAND_DEVICE_NOT_PROBED;
|
||||||
if (!halted(info->target, "write_page"))
|
if (!halted(nand->target, "write_page"))
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
|
||||||
/* Always write both data and OOB ... we are not "raw" I/O! */
|
/* Always write both data and OOB ... we are not "raw" I/O! */
|
||||||
if (!data) {
|
if (!data) {
|
||||||
LOG_ERROR("Missing NAND data; try 'nand raw_access enable'\n");
|
LOG_ERROR("Missing NAND data; try 'nand raw_access enable'");
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +307,7 @@ static int davinci_read_page(struct nand_device *nand, uint32_t page,
|
|||||||
|
|
||||||
if (!nand->device)
|
if (!nand->device)
|
||||||
return ERROR_NAND_DEVICE_NOT_PROBED;
|
return ERROR_NAND_DEVICE_NOT_PROBED;
|
||||||
if (!halted(info->target, "read_page"))
|
if (!halted(nand->target, "read_page"))
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
|
||||||
return info->read_page(nand, page, data, data_size, oob, oob_size);
|
return info->read_page(nand, page, data, data_size, oob, oob_size);
|
||||||
@@ -318,7 +316,7 @@ static int davinci_read_page(struct nand_device *nand, uint32_t page,
|
|||||||
static void davinci_write_pagecmd(struct nand_device *nand, uint8_t cmd, uint32_t page)
|
static void davinci_write_pagecmd(struct nand_device *nand, uint8_t cmd, uint32_t page)
|
||||||
{
|
{
|
||||||
struct davinci_nand *info = nand->controller_priv;
|
struct davinci_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
int page3 = nand->address_cycles - (nand->page_size == 512);
|
int page3 = nand->address_cycles - (nand->page_size == 512);
|
||||||
|
|
||||||
/* write command ({page,otp}x{read,program} */
|
/* write command ({page,otp}x{read,program} */
|
||||||
@@ -338,11 +336,32 @@ static void davinci_write_pagecmd(struct nand_device *nand, uint8_t cmd, uint32_
|
|||||||
target_write_u8(target, info->addr, page >> 24);
|
target_write_u8(target, info->addr, page >> 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int davinci_seek_column(struct nand_device *nand, uint16_t column)
|
||||||
|
{
|
||||||
|
struct davinci_nand *info = nand->controller_priv;
|
||||||
|
struct target *target = nand->target;
|
||||||
|
|
||||||
|
/* Random read, we must have issued a page read already */
|
||||||
|
target_write_u8(target, info->cmd, NAND_CMD_RNDOUT);
|
||||||
|
|
||||||
|
target_write_u8(target, info->addr, column);
|
||||||
|
|
||||||
|
if (nand->page_size > 512) {
|
||||||
|
target_write_u8(target, info->addr, column >> 8);
|
||||||
|
target_write_u8(target, info->cmd, NAND_CMD_RNDOUTSTART);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!davinci_nand_ready(nand, 100))
|
||||||
|
return ERROR_NAND_OPERATION_TIMEOUT;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int davinci_writepage_tail(struct nand_device *nand,
|
static int davinci_writepage_tail(struct nand_device *nand,
|
||||||
uint8_t *oob, uint32_t oob_size)
|
uint8_t *oob, uint32_t oob_size)
|
||||||
{
|
{
|
||||||
struct davinci_nand *info = nand->controller_priv;
|
struct davinci_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
|
||||||
if (oob_size)
|
if (oob_size)
|
||||||
@@ -375,7 +394,7 @@ static int davinci_write_page_ecc1(struct nand_device *nand, uint32_t page,
|
|||||||
{
|
{
|
||||||
unsigned oob_offset;
|
unsigned oob_offset;
|
||||||
struct davinci_nand *info = nand->controller_priv;
|
struct davinci_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
const uint32_t fcr_addr = info->aemif + NANDFCR;
|
const uint32_t fcr_addr = info->aemif + NANDFCR;
|
||||||
const uint32_t ecc1_addr = info->aemif + NANDFECC + (4 * info->chipsel);
|
const uint32_t ecc1_addr = info->aemif + NANDFECC + (4 * info->chipsel);
|
||||||
uint32_t fcr, ecc1;
|
uint32_t fcr, ecc1;
|
||||||
@@ -463,7 +482,7 @@ static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page,
|
|||||||
|
|
||||||
struct davinci_nand *info = nand->controller_priv;
|
struct davinci_nand *info = nand->controller_priv;
|
||||||
const uint8_t *l;
|
const uint8_t *l;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
const uint32_t fcr_addr = info->aemif + NANDFCR;
|
const uint32_t fcr_addr = info->aemif + NANDFCR;
|
||||||
const uint32_t ecc4_addr = info->aemif + NAND4BITECC;
|
const uint32_t ecc4_addr = info->aemif + NAND4BITECC;
|
||||||
uint32_t fcr, ecc4;
|
uint32_t fcr, ecc4;
|
||||||
@@ -543,7 +562,7 @@ static int davinci_write_page_ecc4infix(struct nand_device *nand, uint32_t page,
|
|||||||
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
|
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
|
||||||
{
|
{
|
||||||
struct davinci_nand *info = nand->controller_priv;
|
struct davinci_nand *info = nand->controller_priv;
|
||||||
struct target *target = info->target;
|
struct target *target = nand->target;
|
||||||
const uint32_t fcr_addr = info->aemif + NANDFCR;
|
const uint32_t fcr_addr = info->aemif + NANDFCR;
|
||||||
const uint32_t ecc4_addr = info->aemif + NAND4BITECC;
|
const uint32_t ecc4_addr = info->aemif + NAND4BITECC;
|
||||||
uint32_t fcr, ecc4;
|
uint32_t fcr, ecc4;
|
||||||
@@ -599,6 +618,10 @@ static int davinci_write_page_ecc4infix(struct nand_device *nand, uint32_t page,
|
|||||||
static int davinci_read_page_ecc4infix(struct nand_device *nand, uint32_t page,
|
static int davinci_read_page_ecc4infix(struct nand_device *nand, uint32_t page,
|
||||||
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
|
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
|
||||||
{
|
{
|
||||||
|
int read_size;
|
||||||
|
int want_col, at_col;
|
||||||
|
int ret;
|
||||||
|
|
||||||
davinci_write_pagecmd(nand, NAND_CMD_READ0, page);
|
davinci_write_pagecmd(nand, NAND_CMD_READ0, page);
|
||||||
|
|
||||||
/* large page devices need a start command */
|
/* large page devices need a start command */
|
||||||
@@ -610,25 +633,49 @@ static int davinci_read_page_ecc4infix(struct nand_device *nand, uint32_t page,
|
|||||||
|
|
||||||
/* NOTE: not bothering to compute and use ECC data for now */
|
/* NOTE: not bothering to compute and use ECC data for now */
|
||||||
|
|
||||||
do {
|
want_col = 0;
|
||||||
/* write 512 bytes */
|
at_col = 0;
|
||||||
davinci_read_block_data(nand, data, 512);
|
while ((data && data_size) || (oob && oob_size)) {
|
||||||
data += 512;
|
|
||||||
data_size -= 512;
|
|
||||||
|
|
||||||
/* read this "out-of-band" data -- infix */
|
if (data && data_size) {
|
||||||
davinci_read_block_data(nand, oob, 16);
|
if (want_col != at_col) {
|
||||||
oob += 16;
|
/* Reads are slow, so seek past them when we can */
|
||||||
oob_size -= 16;
|
ret = davinci_seek_column(nand, want_col);
|
||||||
} while (data_size);
|
if (ret != ERROR_OK)
|
||||||
|
return ret;
|
||||||
|
at_col = want_col;
|
||||||
|
}
|
||||||
|
/* read 512 bytes or data_size, whichever is smaller*/
|
||||||
|
read_size = data_size > 512 ? 512 : data_size;
|
||||||
|
davinci_read_block_data(nand, data, read_size);
|
||||||
|
data += read_size;
|
||||||
|
data_size -= read_size;
|
||||||
|
at_col += read_size;
|
||||||
|
}
|
||||||
|
want_col += 512;
|
||||||
|
|
||||||
|
if (oob && oob_size) {
|
||||||
|
if (want_col != at_col) {
|
||||||
|
ret = davinci_seek_column(nand, want_col);
|
||||||
|
if (ret != ERROR_OK)
|
||||||
|
return ret;
|
||||||
|
at_col = want_col;
|
||||||
|
}
|
||||||
|
/* read this "out-of-band" data -- infix */
|
||||||
|
read_size = oob_size > 16 ? 16 : oob_size;
|
||||||
|
davinci_read_block_data(nand, oob, read_size);
|
||||||
|
oob += read_size;
|
||||||
|
oob_size -= read_size;
|
||||||
|
at_col += read_size;
|
||||||
|
}
|
||||||
|
want_col += 16;
|
||||||
|
}
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
|
NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
|
||||||
{
|
{
|
||||||
struct davinci_nand *info;
|
struct davinci_nand *info;
|
||||||
struct target *target;
|
|
||||||
unsigned long chip, aemif;
|
unsigned long chip, aemif;
|
||||||
enum ecc eccmode;
|
enum ecc eccmode;
|
||||||
int chipsel;
|
int chipsel;
|
||||||
@@ -648,12 +695,6 @@ NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
target = get_target(CMD_ARGV[1]);
|
|
||||||
if (!target) {
|
|
||||||
LOG_ERROR("invalid target %s", CMD_ARGV[1]);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip);
|
COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip);
|
||||||
if (chip == 0) {
|
if (chip == 0) {
|
||||||
LOG_ERROR("Invalid NAND chip address %s", CMD_ARGV[2]);
|
LOG_ERROR("Invalid NAND chip address %s", CMD_ARGV[2]);
|
||||||
@@ -699,7 +740,6 @@ NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
|
|||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
info->target = target;
|
|
||||||
info->eccmode = eccmode;
|
info->eccmode = eccmode;
|
||||||
info->chipsel = chipsel;
|
info->chipsel = chipsel;
|
||||||
info->aemif = aemif;
|
info->aemif = aemif;
|
||||||
@@ -709,7 +749,7 @@ NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
|
|||||||
|
|
||||||
nand->controller_priv = info;
|
nand->controller_priv = info;
|
||||||
|
|
||||||
info->io.target = target;
|
info->io.target = nand->target;
|
||||||
info->io.data = info->data;
|
info->io.data = info->data;
|
||||||
info->io.op = ARM_NAND_NONE;
|
info->io.op = ARM_NAND_NONE;
|
||||||
|
|
||||||
|
|||||||
@@ -31,14 +31,17 @@
|
|||||||
extern struct nand_flash_controller nonce_nand_controller;
|
extern struct nand_flash_controller nonce_nand_controller;
|
||||||
extern struct nand_flash_controller davinci_nand_controller;
|
extern struct nand_flash_controller davinci_nand_controller;
|
||||||
extern struct nand_flash_controller lpc3180_nand_controller;
|
extern struct nand_flash_controller lpc3180_nand_controller;
|
||||||
|
extern struct nand_flash_controller lpc32xx_nand_controller;
|
||||||
extern struct nand_flash_controller orion_nand_controller;
|
extern struct nand_flash_controller orion_nand_controller;
|
||||||
extern struct nand_flash_controller s3c2410_nand_controller;
|
extern struct nand_flash_controller s3c2410_nand_controller;
|
||||||
extern struct nand_flash_controller s3c2412_nand_controller;
|
extern struct nand_flash_controller s3c2412_nand_controller;
|
||||||
extern struct nand_flash_controller s3c2440_nand_controller;
|
extern struct nand_flash_controller s3c2440_nand_controller;
|
||||||
extern struct nand_flash_controller s3c2443_nand_controller;
|
extern struct nand_flash_controller s3c2443_nand_controller;
|
||||||
extern struct nand_flash_controller s3c6400_nand_controller;
|
extern struct nand_flash_controller s3c6400_nand_controller;
|
||||||
|
extern struct nand_flash_controller imx27_nand_flash_controller;
|
||||||
extern struct nand_flash_controller imx31_nand_flash_controller;
|
extern struct nand_flash_controller imx31_nand_flash_controller;
|
||||||
extern struct nand_flash_controller at91sam9_nand_controller;
|
extern struct nand_flash_controller at91sam9_nand_controller;
|
||||||
|
extern struct nand_flash_controller nuc910_nand_controller;
|
||||||
|
|
||||||
/* extern struct nand_flash_controller boundary_scan_nand_controller; */
|
/* extern struct nand_flash_controller boundary_scan_nand_controller; */
|
||||||
|
|
||||||
@@ -47,14 +50,17 @@ static struct nand_flash_controller *nand_flash_controllers[] =
|
|||||||
&nonce_nand_controller,
|
&nonce_nand_controller,
|
||||||
&davinci_nand_controller,
|
&davinci_nand_controller,
|
||||||
&lpc3180_nand_controller,
|
&lpc3180_nand_controller,
|
||||||
|
&lpc32xx_nand_controller,
|
||||||
&orion_nand_controller,
|
&orion_nand_controller,
|
||||||
&s3c2410_nand_controller,
|
&s3c2410_nand_controller,
|
||||||
&s3c2412_nand_controller,
|
&s3c2412_nand_controller,
|
||||||
&s3c2440_nand_controller,
|
&s3c2440_nand_controller,
|
||||||
&s3c2443_nand_controller,
|
&s3c2443_nand_controller,
|
||||||
&s3c6400_nand_controller,
|
&s3c6400_nand_controller,
|
||||||
|
&imx27_nand_flash_controller,
|
||||||
&imx31_nand_flash_controller,
|
&imx31_nand_flash_controller,
|
||||||
&at91sam9_nand_controller,
|
&at91sam9_nand_controller,
|
||||||
|
&nuc910_nand_controller,
|
||||||
/* &boundary_scan_nand_controller, */
|
/* &boundary_scan_nand_controller, */
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,16 +35,13 @@ struct nand_device;
|
|||||||
struct nand_flash_controller
|
struct nand_flash_controller
|
||||||
{
|
{
|
||||||
/** Driver name that is used to select it from configuration files. */
|
/** Driver name that is used to select it from configuration files. */
|
||||||
char *name;
|
const char *name;
|
||||||
|
|
||||||
const struct command_registration *commands;
|
const struct command_registration *commands;
|
||||||
|
|
||||||
/** NAND device command called when driver is instantiated during configuration. */
|
/** NAND device command called when driver is instantiated during configuration. */
|
||||||
__NAND_DEVICE_COMMAND((*nand_device_command));
|
__NAND_DEVICE_COMMAND((*nand_device_command));
|
||||||
|
|
||||||
/** Register controller specific commands as a TCL interface to the driver. */
|
|
||||||
int (*register_commands)(struct command_context *cmd_ctx);
|
|
||||||
|
|
||||||
/** Initialize the NAND device. */
|
/** Initialize the NAND device. */
|
||||||
int (*init)(struct nand_device *nand);
|
int (*init)(struct nand_device *nand);
|
||||||
|
|
||||||
@@ -75,9 +72,6 @@ struct nand_flash_controller
|
|||||||
/** Read a page from the NAND device. */
|
/** Read a page from the NAND device. */
|
||||||
int (*read_page)(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
|
int (*read_page)(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
|
||||||
|
|
||||||
/** Check if the controller is ready for more instructions with timeout. */
|
|
||||||
int (*controller_ready)(struct nand_device *nand, int timeout);
|
|
||||||
|
|
||||||
/** Check if the NAND device is ready for more instructions with timeout. */
|
/** Check if the NAND device is ready for more instructions with timeout. */
|
||||||
int (*nand_ready)(struct nand_device *nand, int timeout);
|
int (*nand_ready)(struct nand_device *nand, int timeout);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -120,3 +120,64 @@ int nand_calculate_ecc(struct nand_device *nand, const uint8_t *dat, uint8_t *ec
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int countbits(uint32_t b)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
for (;b; b >>= 1)
|
||||||
|
res += b & 0x01;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nand_correct_data - Detect and correct a 1 bit error for 256 byte block
|
||||||
|
*/
|
||||||
|
int nand_correct_data(struct nand_device *nand, u_char *dat,
|
||||||
|
u_char *read_ecc, u_char *calc_ecc)
|
||||||
|
{
|
||||||
|
uint8_t s0, s1, s2;
|
||||||
|
|
||||||
|
#ifdef NAND_ECC_SMC
|
||||||
|
s0 = calc_ecc[0] ^ read_ecc[0];
|
||||||
|
s1 = calc_ecc[1] ^ read_ecc[1];
|
||||||
|
s2 = calc_ecc[2] ^ read_ecc[2];
|
||||||
|
#else
|
||||||
|
s1 = calc_ecc[0] ^ read_ecc[0];
|
||||||
|
s0 = calc_ecc[1] ^ read_ecc[1];
|
||||||
|
s2 = calc_ecc[2] ^ read_ecc[2];
|
||||||
|
#endif
|
||||||
|
if ((s0 | s1 | s2) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Check for a single bit error */
|
||||||
|
if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
|
||||||
|
((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
|
||||||
|
((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
|
||||||
|
|
||||||
|
uint32_t byteoffs, bitnum;
|
||||||
|
|
||||||
|
byteoffs = (s1 << 0) & 0x80;
|
||||||
|
byteoffs |= (s1 << 1) & 0x40;
|
||||||
|
byteoffs |= (s1 << 2) & 0x20;
|
||||||
|
byteoffs |= (s1 << 3) & 0x10;
|
||||||
|
|
||||||
|
byteoffs |= (s0 >> 4) & 0x08;
|
||||||
|
byteoffs |= (s0 >> 3) & 0x04;
|
||||||
|
byteoffs |= (s0 >> 2) & 0x02;
|
||||||
|
byteoffs |= (s0 >> 1) & 0x01;
|
||||||
|
|
||||||
|
bitnum = (s2 >> 5) & 0x04;
|
||||||
|
bitnum |= (s2 >> 4) & 0x02;
|
||||||
|
bitnum |= (s2 >> 3) & 0x01;
|
||||||
|
|
||||||
|
dat[byteoffs] ^= (1 << bitnum);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -180,7 +180,13 @@ COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state,
|
|||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (!need_size)
|
if (!need_size)
|
||||||
state->size = state->fileio.size;
|
{
|
||||||
|
int filesize;
|
||||||
|
retval = fileio_size(&state->fileio, &filesize);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
state->size = filesize;
|
||||||
|
}
|
||||||
|
|
||||||
*dev = nand;
|
*dev = nand;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright (C) 2007 by Dominic Rath *
|
* Copyright (C) 2007 by Dominic Rath *
|
||||||
* Dominic.Rath@gmx.de *
|
* Dominic.Rath@gmx.de *
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 richard vegh <vegh.ricsi@gmail.com> *
|
||||||
|
* Copyright (C) 2010 Oyvind Harboe <oyvind.harboe@zylin.com> *
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published by *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
@@ -28,6 +31,13 @@
|
|||||||
|
|
||||||
static int lpc3180_reset(struct nand_device *nand);
|
static int lpc3180_reset(struct nand_device *nand);
|
||||||
static int lpc3180_controller_ready(struct nand_device *nand, int timeout);
|
static int lpc3180_controller_ready(struct nand_device *nand, int timeout);
|
||||||
|
static int lpc3180_tc_ready(struct nand_device *nand, int timeout);
|
||||||
|
|
||||||
|
|
||||||
|
#define ECC_OFFS 0x120
|
||||||
|
#define SPARE_OFFS 0x140
|
||||||
|
#define DATA_OFFS 0x200
|
||||||
|
|
||||||
|
|
||||||
/* nand device lpc3180 <target#> <oscillator_frequency>
|
/* nand device lpc3180 <target#> <oscillator_frequency>
|
||||||
*/
|
*/
|
||||||
@@ -39,13 +49,6 @@ NAND_DEVICE_COMMAND_HANDLER(lpc3180_nand_device_command)
|
|||||||
return ERROR_FLASH_BANK_INVALID;
|
return ERROR_FLASH_BANK_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct target *target = get_target(CMD_ARGV[1]);
|
|
||||||
if (NULL == target)
|
|
||||||
{
|
|
||||||
LOG_ERROR("target '%s' not defined", CMD_ARGV[1]);
|
|
||||||
return ERROR_NAND_DEVICE_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t osc_freq;
|
uint32_t osc_freq;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], osc_freq);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], osc_freq);
|
||||||
|
|
||||||
@@ -53,7 +56,6 @@ NAND_DEVICE_COMMAND_HANDLER(lpc3180_nand_device_command)
|
|||||||
lpc3180_info = malloc(sizeof(struct lpc3180_nand_controller));
|
lpc3180_info = malloc(sizeof(struct lpc3180_nand_controller));
|
||||||
nand->controller_priv = lpc3180_info;
|
nand->controller_priv = lpc3180_info;
|
||||||
|
|
||||||
lpc3180_info->target = target;
|
|
||||||
lpc3180_info->osc_freq = osc_freq;
|
lpc3180_info->osc_freq = osc_freq;
|
||||||
|
|
||||||
if ((lpc3180_info->osc_freq < 1000) || (lpc3180_info->osc_freq > 20000))
|
if ((lpc3180_info->osc_freq < 1000) || (lpc3180_info->osc_freq > 20000))
|
||||||
@@ -96,9 +98,10 @@ static int lpc3180_pll(int fclkin, uint32_t pll_ctrl)
|
|||||||
return (m / (2 * p)) * (fclkin / n);
|
return (m / (2 * p)) * (fclkin / n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static float lpc3180_cycle_time(struct lpc3180_nand_controller *lpc3180_info)
|
static float lpc3180_cycle_time(struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct target *target = lpc3180_info->target;
|
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
||||||
|
struct target *target = nand->target;
|
||||||
uint32_t sysclk_ctrl, pwr_ctrl, hclkdiv_ctrl, hclkpll_ctrl;
|
uint32_t sysclk_ctrl, pwr_ctrl, hclkdiv_ctrl, hclkpll_ctrl;
|
||||||
int sysclk;
|
int sysclk;
|
||||||
int hclk;
|
int hclk;
|
||||||
@@ -149,7 +152,7 @@ static float lpc3180_cycle_time(struct lpc3180_nand_controller *lpc3180_info)
|
|||||||
static int lpc3180_init(struct nand_device *nand)
|
static int lpc3180_init(struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
||||||
struct target *target = lpc3180_info->target;
|
struct target *target = nand->target;
|
||||||
int bus_width = nand->bus_width ? : 8;
|
int bus_width = nand->bus_width ? : 8;
|
||||||
int address_cycles = nand->address_cycles ? : 3;
|
int address_cycles = nand->address_cycles ? : 3;
|
||||||
int page_size = nand->page_size ? : 512;
|
int page_size = nand->page_size ? : 512;
|
||||||
@@ -224,7 +227,7 @@ static int lpc3180_init(struct nand_device *nand)
|
|||||||
target_write_u32(target, 0x200b8030, mlc_icr_value);
|
target_write_u32(target, 0x200b8030, mlc_icr_value);
|
||||||
|
|
||||||
/* calculate NAND controller timings */
|
/* calculate NAND controller timings */
|
||||||
cycle = lpc3180_cycle_time(lpc3180_info);
|
cycle = lpc3180_cycle_time(nand);
|
||||||
|
|
||||||
twp = ((40 / cycle) + 1);
|
twp = ((40 / cycle) + 1);
|
||||||
twh = ((20 / cycle) + 1);
|
twh = ((20 / cycle) + 1);
|
||||||
@@ -253,11 +256,24 @@ static int lpc3180_init(struct nand_device *nand)
|
|||||||
/* FLASHCLK_CTRL = 0x05 (enable clock for SLC flash controller) */
|
/* FLASHCLK_CTRL = 0x05 (enable clock for SLC flash controller) */
|
||||||
target_write_u32(target, 0x400040c8, 0x05);
|
target_write_u32(target, 0x400040c8, 0x05);
|
||||||
|
|
||||||
/* SLC_CFG = 0x (Force nCE assert, ECC enabled, WIDTH = bus_width) */
|
/* after reset set other registers of SLC so reset calling is here at the begining*/
|
||||||
target_write_u32(target, 0x20020014, 0x28 | (bus_width == 16) ? 1 : 0);
|
lpc3180_reset(nand);
|
||||||
|
|
||||||
|
/* SLC_CFG = 0x (Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst enabled, DMA read from SLC, WIDTH = bus_width) */
|
||||||
|
target_write_u32(target, 0x20020014, 0x3e | (bus_width == 16) ? 1 : 0);
|
||||||
|
|
||||||
|
/* SLC_IEN = 3 (INT_RDY_EN = 1) ,(INT_TC_STAT = 1) */
|
||||||
|
target_write_u32(target, 0x20020020, 0x03);
|
||||||
|
|
||||||
|
/* DMA configuration */
|
||||||
|
/* DMACLK_CTRL = 0x01 (enable clock for DMA controller) */
|
||||||
|
target_write_u32(target, 0x400040e8, 0x01);
|
||||||
|
/* DMACConfig = DMA enabled*/
|
||||||
|
target_write_u32(target, 0x31000030, 0x01);
|
||||||
|
|
||||||
|
|
||||||
/* calculate NAND controller timings */
|
/* calculate NAND controller timings */
|
||||||
cycle = lpc3180_cycle_time(lpc3180_info);
|
cycle = lpc3180_cycle_time(nand);
|
||||||
|
|
||||||
r_setup = w_setup = 0;
|
r_setup = w_setup = 0;
|
||||||
r_hold = w_hold = 10 / cycle;
|
r_hold = w_hold = 10 / cycle;
|
||||||
@@ -270,7 +286,6 @@ static int lpc3180_init(struct nand_device *nand)
|
|||||||
((r_width & 0xf) << 8) | ((r_rdy & 0xf) << 12) | ((w_setup & 0xf) << 16) |
|
((r_width & 0xf) << 8) | ((r_rdy & 0xf) << 12) | ((w_setup & 0xf) << 16) |
|
||||||
((w_hold & 0xf) << 20) | ((w_width & 0xf) << 24) | ((w_rdy & 0xf) << 28));
|
((w_hold & 0xf) << 20) | ((w_width & 0xf) << 24) | ((w_rdy & 0xf) << 28));
|
||||||
|
|
||||||
lpc3180_reset(nand);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
@@ -279,7 +294,7 @@ static int lpc3180_init(struct nand_device *nand)
|
|||||||
static int lpc3180_reset(struct nand_device *nand)
|
static int lpc3180_reset(struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
||||||
struct target *target = lpc3180_info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
{
|
||||||
@@ -321,7 +336,7 @@ static int lpc3180_reset(struct nand_device *nand)
|
|||||||
static int lpc3180_command(struct nand_device *nand, uint8_t command)
|
static int lpc3180_command(struct nand_device *nand, uint8_t command)
|
||||||
{
|
{
|
||||||
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
||||||
struct target *target = lpc3180_info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
{
|
||||||
@@ -351,7 +366,7 @@ static int lpc3180_command(struct nand_device *nand, uint8_t command)
|
|||||||
static int lpc3180_address(struct nand_device *nand, uint8_t address)
|
static int lpc3180_address(struct nand_device *nand, uint8_t address)
|
||||||
{
|
{
|
||||||
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
||||||
struct target *target = lpc3180_info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
{
|
||||||
@@ -381,7 +396,7 @@ static int lpc3180_address(struct nand_device *nand, uint8_t address)
|
|||||||
static int lpc3180_write_data(struct nand_device *nand, uint16_t data)
|
static int lpc3180_write_data(struct nand_device *nand, uint16_t data)
|
||||||
{
|
{
|
||||||
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
||||||
struct target *target = lpc3180_info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
{
|
||||||
@@ -411,7 +426,7 @@ static int lpc3180_write_data(struct nand_device *nand, uint16_t data)
|
|||||||
static int lpc3180_read_data(struct nand_device *nand, void *data)
|
static int lpc3180_read_data(struct nand_device *nand, void *data)
|
||||||
{
|
{
|
||||||
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
||||||
struct target *target = lpc3180_info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
{
|
||||||
@@ -473,9 +488,10 @@ static int lpc3180_read_data(struct nand_device *nand, void *data)
|
|||||||
static int lpc3180_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
|
static int lpc3180_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
|
||||||
{
|
{
|
||||||
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
||||||
struct target *target = lpc3180_info->target;
|
struct target *target = nand->target;
|
||||||
int retval;
|
int retval;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
uint8_t *page_buffer;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
{
|
||||||
@@ -490,7 +506,6 @@ static int lpc3180_write_page(struct nand_device *nand, uint32_t page, uint8_t *
|
|||||||
}
|
}
|
||||||
else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
|
else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
|
||||||
{
|
{
|
||||||
uint8_t *page_buffer;
|
|
||||||
uint8_t *oob_buffer;
|
uint8_t *oob_buffer;
|
||||||
int quarter, num_quarters;
|
int quarter, num_quarters;
|
||||||
|
|
||||||
@@ -606,8 +621,202 @@ static int lpc3180_write_page(struct nand_device *nand, uint32_t page, uint8_t *
|
|||||||
}
|
}
|
||||||
else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
|
else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Write both SLC NAND flash page main area and spare area.
|
||||||
|
* Small page -
|
||||||
|
* ------------------------------------------
|
||||||
|
* | 512 bytes main | 16 bytes spare |
|
||||||
|
* ------------------------------------------
|
||||||
|
* Large page -
|
||||||
|
* ------------------------------------------
|
||||||
|
* | 2048 bytes main | 64 bytes spare |
|
||||||
|
* ------------------------------------------
|
||||||
|
* If DMA & ECC enabled, then the ECC generated for the 1st 256-byte
|
||||||
|
* data is written to the 3rd word of the spare area. The ECC
|
||||||
|
* generated for the 2nd 256-byte data is written to the 4th word
|
||||||
|
* of the spare area. The ECC generated for the 3rd 256-byte data is
|
||||||
|
* written to the 7th word of the spare area. The ECC generated
|
||||||
|
* for the 4th 256-byte data is written to the 8th word of the
|
||||||
|
* spare area and so on.
|
||||||
|
*
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
int i=0,target_mem_base;
|
||||||
|
uint8_t *ecc_flash_buffer;
|
||||||
|
struct working_area *pworking_area;
|
||||||
|
|
||||||
|
|
||||||
|
if(lpc3180_info->is_bulk){
|
||||||
|
|
||||||
|
if (!data && oob){
|
||||||
|
/*if oob only mode is active original method is used as SLC controller hangs during DMA interworking. Anyway the code supports the oob only mode below. */
|
||||||
return nand_write_page_raw(nand, page, data, data_size, oob, oob_size);
|
return nand_write_page_raw(nand, page, data, data_size, oob, oob_size);
|
||||||
}
|
}
|
||||||
|
retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data);
|
||||||
|
if (ERROR_OK != retval)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* allocate a working area */
|
||||||
|
if (target->working_area_size < (uint32_t) nand->page_size + 0x200){
|
||||||
|
LOG_ERROR("Reserve at least 0x%x physical target working area",nand->page_size + 0x200);
|
||||||
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
if (target->working_area_phys%4){
|
||||||
|
LOG_ERROR("Reserve the physical target working area at word boundary");
|
||||||
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
if (target_alloc_working_area(target, target->working_area_size, &pworking_area) != ERROR_OK)
|
||||||
|
{
|
||||||
|
LOG_ERROR("no working area specified, can't read LPC internal flash");
|
||||||
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
target_mem_base = target->working_area_phys;
|
||||||
|
|
||||||
|
|
||||||
|
if (nand->page_size == 2048)
|
||||||
|
{
|
||||||
|
page_buffer = malloc(2048);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
page_buffer = malloc(512);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecc_flash_buffer = malloc(64);
|
||||||
|
|
||||||
|
/* SLC_CFG = 0x (Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst enabled, DMA write to SLC, WIDTH = bus_width) */
|
||||||
|
target_write_u32(target, 0x20020014, 0x3c);
|
||||||
|
|
||||||
|
if( data && !oob){
|
||||||
|
/* set DMA LLI-s in target memory and in DMA*/
|
||||||
|
for(i=0;i<nand->page_size/0x100;i++){
|
||||||
|
|
||||||
|
int tmp;
|
||||||
|
/* -------LLI for 256 byte block---------*/
|
||||||
|
/* DMACC0SrcAddr = SRAM */
|
||||||
|
target_write_u32(target,target_mem_base+0+i*32,target_mem_base+DATA_OFFS+i*256 );
|
||||||
|
if(i==0) target_write_u32(target,0x31000100,target_mem_base+DATA_OFFS );
|
||||||
|
/* DMACCxDestAddr = SLC_DMA_DATA */
|
||||||
|
target_write_u32(target,target_mem_base+4+i*32,0x20020038 );
|
||||||
|
if(i==0) target_write_u32(target,0x31000104,0x20020038 );
|
||||||
|
/* DMACCxLLI = next element */
|
||||||
|
tmp = (target_mem_base+(1+i*2)*16)&0xfffffffc;
|
||||||
|
target_write_u32(target,target_mem_base+8+i*32, tmp );
|
||||||
|
if(i==0) target_write_u32(target,0x31000108, tmp );
|
||||||
|
/* DMACCxControl = TransferSize =64, Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit,
|
||||||
|
Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 1,
|
||||||
|
Destination increment = 0, Terminal count interrupt enable bit = 0*/
|
||||||
|
target_write_u32(target,target_mem_base+12+i*32,0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27| 0<<31);
|
||||||
|
if(i==0) target_write_u32(target,0x3100010c,0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27| 0<<31);
|
||||||
|
|
||||||
|
/* -------LLI for 3 byte ECC---------*/
|
||||||
|
/* DMACC0SrcAddr = SLC_ECC*/
|
||||||
|
target_write_u32(target,target_mem_base+16+i*32,0x20020034 );
|
||||||
|
/* DMACCxDestAddr = SRAM */
|
||||||
|
target_write_u32(target,target_mem_base+20+i*32,target_mem_base+SPARE_OFFS+8+16*(i>>1)+(i%2)*4 );
|
||||||
|
/* DMACCxLLI = next element */
|
||||||
|
tmp = (target_mem_base+(2+i*2)*16)&0xfffffffc;
|
||||||
|
target_write_u32(target,target_mem_base+24+i*32, tmp );
|
||||||
|
/* DMACCxControl = TransferSize =1, Source burst size =4, Destination burst size = 4, Source transfer width = 32 bit,
|
||||||
|
Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 0,
|
||||||
|
Destination increment = 1, Terminal count interrupt enable bit = 0*/
|
||||||
|
target_write_u32(target,target_mem_base+28+i*32,0x01 | 1<<12 | 1<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27| 0<<31);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (data && oob){
|
||||||
|
/* -------LLI for 512 or 2048 bytes page---------*/
|
||||||
|
/* DMACC0SrcAddr = SRAM */
|
||||||
|
target_write_u32(target,target_mem_base,target_mem_base+DATA_OFFS );
|
||||||
|
target_write_u32(target,0x31000100,target_mem_base+DATA_OFFS );
|
||||||
|
/* DMACCxDestAddr = SLC_DMA_DATA */
|
||||||
|
target_write_u32(target,target_mem_base+4,0x20020038 );
|
||||||
|
target_write_u32(target,0x31000104,0x20020038 );
|
||||||
|
/* DMACCxLLI = next element */
|
||||||
|
target_write_u32(target,target_mem_base+8, (target_mem_base+32)&0xfffffffc );
|
||||||
|
target_write_u32(target,0x31000108, (target_mem_base+32)&0xfffffffc );
|
||||||
|
/* DMACCxControl = TransferSize =512 or 128, Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit,
|
||||||
|
Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 1,
|
||||||
|
Destination increment = 0, Terminal count interrupt enable bit = 0*/
|
||||||
|
target_write_u32(target,target_mem_base+12,(nand->page_size==2048?512:128) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27| 0<<31);
|
||||||
|
target_write_u32(target,0x3100010c,(nand->page_size==2048?512:128) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27| 0<<31);
|
||||||
|
i = 1;
|
||||||
|
}
|
||||||
|
else if (!data && oob){
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------LLI for spare area---------*/
|
||||||
|
/* DMACC0SrcAddr = SRAM*/
|
||||||
|
target_write_u32(target,target_mem_base+0+i*32,target_mem_base+SPARE_OFFS );
|
||||||
|
if(i==0) target_write_u32(target,0x31000100,target_mem_base+SPARE_OFFS );
|
||||||
|
/* DMACCxDestAddr = SLC_DMA_DATA */
|
||||||
|
target_write_u32(target,target_mem_base+4+i*32,0x20020038 );
|
||||||
|
if(i==0) target_write_u32(target,0x31000104,0x20020038 );
|
||||||
|
/* DMACCxLLI = next element = NULL */
|
||||||
|
target_write_u32(target,target_mem_base+8+i*32, 0 );
|
||||||
|
if(i==0) target_write_u32(target,0x31000108,0 );
|
||||||
|
/* DMACCxControl = TransferSize =16 for large page or 4 for small page, Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit,
|
||||||
|
Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 1,
|
||||||
|
Destination increment = 0, Terminal count interrupt enable bit = 0*/
|
||||||
|
target_write_u32(target,target_mem_base+12+i*32, (nand->page_size==2048?0x10:0x04) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27| 0<<31);
|
||||||
|
if(i==0) target_write_u32(target,0x3100010c,(nand->page_size==2048?0x10:0x04) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27| 0<<31 );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
memset(ecc_flash_buffer, 0xff, 64);
|
||||||
|
if( oob ){
|
||||||
|
memcpy(ecc_flash_buffer,oob, oob_size);
|
||||||
|
}
|
||||||
|
target_write_memory(target, target_mem_base+SPARE_OFFS, 4, 16, ecc_flash_buffer);
|
||||||
|
|
||||||
|
if (data){
|
||||||
|
memset(page_buffer, 0xff, nand->page_size == 2048?2048:512);
|
||||||
|
memcpy(page_buffer,data, data_size);
|
||||||
|
target_write_memory(target, target_mem_base+DATA_OFFS, 4, nand->page_size == 2048?512:128, page_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(page_buffer);
|
||||||
|
free(ecc_flash_buffer);
|
||||||
|
|
||||||
|
/* Enable DMA after channel set up !
|
||||||
|
LLI only works when DMA is the flow controller!
|
||||||
|
*/
|
||||||
|
/* DMACCxConfig= E=1, SrcPeripheral = 1 (SLC), DestPeripheral = 1 (SLC), FlowCntrl = 2 (Pher -> Mem, DMA), IE = 0, ITC = 0, L= 0, H=0*/
|
||||||
|
target_write_u32(target,0x31000110, 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14 | 0<<15 | 0<<16 | 0<<18);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* SLC_CTRL = 3 (START DMA), ECC_CLEAR */
|
||||||
|
target_write_u32(target, 0x20020010, 0x3);
|
||||||
|
|
||||||
|
/* SLC_ICR = 2, INT_TC_CLR, clear pending TC*/
|
||||||
|
target_write_u32(target, 0x20020028, 2);
|
||||||
|
|
||||||
|
/* SLC_TC */
|
||||||
|
if (!data && oob)
|
||||||
|
target_write_u32(target, 0x20020030, (nand->page_size==2048?0x10:0x04));
|
||||||
|
else
|
||||||
|
target_write_u32(target, 0x20020030, (nand->page_size==2048?0x840:0x210));
|
||||||
|
|
||||||
|
nand_write_finish(nand);
|
||||||
|
|
||||||
|
|
||||||
|
if (!lpc3180_tc_ready(nand, 1000))
|
||||||
|
{
|
||||||
|
LOG_ERROR("timeout while waiting for completion of DMA");
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_free_working_area(target,pworking_area);
|
||||||
|
|
||||||
|
LOG_INFO("Page = 0x%" PRIx32 " was written.",page);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return nand_write_page_raw(nand, page, data, data_size, oob, oob_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
@@ -615,7 +824,8 @@ static int lpc3180_write_page(struct nand_device *nand, uint32_t page, uint8_t *
|
|||||||
static int lpc3180_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
|
static int lpc3180_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
|
||||||
{
|
{
|
||||||
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
||||||
struct target *target = lpc3180_info->target;
|
struct target *target = nand->target;
|
||||||
|
uint8_t *page_buffer;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
{
|
||||||
@@ -630,7 +840,6 @@ static int lpc3180_read_page(struct nand_device *nand, uint32_t page, uint8_t *d
|
|||||||
}
|
}
|
||||||
else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
|
else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
|
||||||
{
|
{
|
||||||
uint8_t *page_buffer;
|
|
||||||
uint8_t *oob_buffer;
|
uint8_t *oob_buffer;
|
||||||
uint32_t page_bytes_done = 0;
|
uint32_t page_bytes_done = 0;
|
||||||
uint32_t oob_bytes_done = 0;
|
uint32_t oob_bytes_done = 0;
|
||||||
@@ -753,6 +962,174 @@ static int lpc3180_read_page(struct nand_device *nand, uint32_t page, uint8_t *d
|
|||||||
}
|
}
|
||||||
else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
|
else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Read both SLC NAND flash page main area and spare area.
|
||||||
|
* Small page -
|
||||||
|
* ------------------------------------------
|
||||||
|
* | 512 bytes main | 16 bytes spare |
|
||||||
|
* ------------------------------------------
|
||||||
|
* Large page -
|
||||||
|
* ------------------------------------------
|
||||||
|
* | 2048 bytes main | 64 bytes spare |
|
||||||
|
* ------------------------------------------
|
||||||
|
* If DMA & ECC enabled, then the ECC generated for the 1st 256-byte
|
||||||
|
* data is compared with the 3rd word of the spare area. The ECC
|
||||||
|
* generated for the 2nd 256-byte data is compared with the 4th word
|
||||||
|
* of the spare area. The ECC generated for the 3rd 256-byte data is
|
||||||
|
* compared with the 7th word of the spare area. The ECC generated
|
||||||
|
* for the 4th 256-byte data is compared with the 8th word of the
|
||||||
|
* spare area and so on.
|
||||||
|
*
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
int retval,i,target_mem_base;
|
||||||
|
uint8_t *ecc_hw_buffer;
|
||||||
|
uint8_t *ecc_flash_buffer;
|
||||||
|
struct working_area *pworking_area;
|
||||||
|
|
||||||
|
if(lpc3180_info->is_bulk){
|
||||||
|
|
||||||
|
/* read always the data and also oob areas*/
|
||||||
|
|
||||||
|
retval = nand_page_command(nand, page, NAND_CMD_READ0, 0);
|
||||||
|
if (ERROR_OK != retval)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* allocate a working area */
|
||||||
|
if (target->working_area_size < (uint32_t) nand->page_size + 0x200){
|
||||||
|
LOG_ERROR("Reserve at least 0x%x physical target working area",nand->page_size + 0x200);
|
||||||
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
if (target->working_area_phys%4){
|
||||||
|
LOG_ERROR("Reserve the physical target working area at word boundary");
|
||||||
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
if (target_alloc_working_area(target, target->working_area_size, &pworking_area) != ERROR_OK)
|
||||||
|
{
|
||||||
|
LOG_ERROR("no working area specified, can't read LPC internal flash");
|
||||||
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
target_mem_base = target->working_area_phys;
|
||||||
|
|
||||||
|
if (nand->page_size == 2048)
|
||||||
|
{
|
||||||
|
page_buffer = malloc(2048);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
page_buffer = malloc(512);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecc_hw_buffer = malloc(32);
|
||||||
|
ecc_flash_buffer = malloc(64);
|
||||||
|
|
||||||
|
/* SLC_CFG = 0x (Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst enabled, DMA read from SLC, WIDTH = bus_width) */
|
||||||
|
target_write_u32(target, 0x20020014, 0x3e);
|
||||||
|
|
||||||
|
/* set DMA LLI-s in target memory and in DMA*/
|
||||||
|
for(i=0;i<nand->page_size/0x100;i++){
|
||||||
|
int tmp;
|
||||||
|
/* -------LLI for 256 byte block---------*/
|
||||||
|
/* DMACC0SrcAddr = SLC_DMA_DATA*/
|
||||||
|
target_write_u32(target,target_mem_base+0+i*32,0x20020038 );
|
||||||
|
if(i==0) target_write_u32(target,0x31000100,0x20020038 );
|
||||||
|
/* DMACCxDestAddr = SRAM */
|
||||||
|
target_write_u32(target,target_mem_base+4+i*32,target_mem_base+DATA_OFFS+i*256 );
|
||||||
|
if(i==0) target_write_u32(target,0x31000104,target_mem_base+DATA_OFFS );
|
||||||
|
/* DMACCxLLI = next element */
|
||||||
|
tmp = (target_mem_base+(1+i*2)*16)&0xfffffffc;
|
||||||
|
target_write_u32(target,target_mem_base+8+i*32, tmp );
|
||||||
|
if(i==0) target_write_u32(target,0x31000108, tmp );
|
||||||
|
/* DMACCxControl = TransferSize =64, Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit,
|
||||||
|
Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 0,
|
||||||
|
Destination increment = 1, Terminal count interrupt enable bit = 0*/
|
||||||
|
target_write_u32(target,target_mem_base+12+i*32,0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27| 0<<31);
|
||||||
|
if(i==0) target_write_u32(target,0x3100010c,0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27| 0<<31);
|
||||||
|
|
||||||
|
/* -------LLI for 3 byte ECC---------*/
|
||||||
|
/* DMACC0SrcAddr = SLC_ECC*/
|
||||||
|
target_write_u32(target,target_mem_base+16+i*32,0x20020034 );
|
||||||
|
/* DMACCxDestAddr = SRAM */
|
||||||
|
target_write_u32(target,target_mem_base+20+i*32,target_mem_base+ECC_OFFS+i*4 );
|
||||||
|
/* DMACCxLLI = next element */
|
||||||
|
tmp = (target_mem_base+(2+i*2)*16)&0xfffffffc;
|
||||||
|
target_write_u32(target,target_mem_base+24+i*32, tmp );
|
||||||
|
/* DMACCxControl = TransferSize =1, Source burst size =4, Destination burst size = 4, Source transfer width = 32 bit,
|
||||||
|
Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 0,
|
||||||
|
Destination increment = 1, Terminal count interrupt enable bit = 0*/
|
||||||
|
target_write_u32(target,target_mem_base+28+i*32,0x01 | 1<<12 | 1<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27| 0<<31);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------LLI for spare area---------*/
|
||||||
|
/* DMACC0SrcAddr = SLC_DMA_DATA*/
|
||||||
|
target_write_u32(target,target_mem_base+0+i*32,0x20020038 );
|
||||||
|
/* DMACCxDestAddr = SRAM */
|
||||||
|
target_write_u32(target,target_mem_base+4+i*32,target_mem_base+SPARE_OFFS );
|
||||||
|
/* DMACCxLLI = next element = NULL */
|
||||||
|
target_write_u32(target,target_mem_base+8+i*32, 0 );
|
||||||
|
/* DMACCxControl = TransferSize =16 for large page or 4 for small page, Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit,
|
||||||
|
Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 0,
|
||||||
|
Destination increment = 1, Terminal count interrupt enable bit = 0*/
|
||||||
|
target_write_u32(target,target_mem_base+12+i*32, (nand->page_size==2048?0x10:0x04) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27| 0<<31);
|
||||||
|
|
||||||
|
/* Enable DMA after channel set up !
|
||||||
|
LLI only works when DMA is the flow controller!
|
||||||
|
*/
|
||||||
|
/* DMACCxConfig= E=1, SrcPeripheral = 1 (SLC), DestPeripheral = 1 (SLC), FlowCntrl = 2 (Pher-> Mem, DMA), IE = 0, ITC = 0, L= 0, H=0*/
|
||||||
|
target_write_u32(target,0x31000110, 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14 | 0<<15 | 0<<16 | 0<<18);
|
||||||
|
|
||||||
|
|
||||||
|
/* SLC_CTRL = 3 (START DMA), ECC_CLEAR */
|
||||||
|
target_write_u32(target, 0x20020010, 0x3);
|
||||||
|
|
||||||
|
/* SLC_ICR = 2, INT_TC_CLR, clear pending TC*/
|
||||||
|
target_write_u32(target, 0x20020028, 2);
|
||||||
|
|
||||||
|
/* SLC_TC */
|
||||||
|
target_write_u32(target, 0x20020030, (nand->page_size==2048?0x840:0x210));
|
||||||
|
|
||||||
|
if (!lpc3180_tc_ready(nand, 1000))
|
||||||
|
{
|
||||||
|
LOG_ERROR("timeout while waiting for completion of DMA");
|
||||||
|
free(page_buffer);
|
||||||
|
free(ecc_hw_buffer);
|
||||||
|
free(ecc_flash_buffer);
|
||||||
|
target_free_working_area(target,pworking_area);
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data){
|
||||||
|
target_read_memory(target, target_mem_base+DATA_OFFS, 4, nand->page_size == 2048?512:128, page_buffer);
|
||||||
|
memcpy(data, page_buffer, data_size);
|
||||||
|
|
||||||
|
LOG_INFO("Page = 0x%" PRIx32 " was read.",page);
|
||||||
|
|
||||||
|
/* check hw generated ECC for each 256 bytes block with the saved ECC in flash spare area*/
|
||||||
|
int idx = nand->page_size/0x200 ;
|
||||||
|
target_read_memory(target, target_mem_base+SPARE_OFFS, 4, 16, ecc_flash_buffer);
|
||||||
|
target_read_memory(target, target_mem_base+ECC_OFFS, 4, 8, ecc_hw_buffer);
|
||||||
|
for(i=0;i<idx;i++){
|
||||||
|
if( (0x00ffffff&*(uint32_t *)(void *)(ecc_hw_buffer+i*8)) != (0x00ffffff&*(uint32_t *)(void *)(ecc_flash_buffer+8+i*16)) )
|
||||||
|
LOG_WARNING("ECC mismatch at 256 bytes size block= %d at page= 0x%" PRIx32,i*2+1,page);
|
||||||
|
if( (0x00ffffff&*(uint32_t *)(void *)(ecc_hw_buffer+4+i*8)) != (0x00ffffff&*(uint32_t *)(void *)(ecc_flash_buffer+12+i*16)) )
|
||||||
|
LOG_WARNING("ECC mismatch at 256 bytes size block= %d at page= 0x%" PRIx32,i*2+2,page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oob)
|
||||||
|
memcpy(oob, ecc_flash_buffer, oob_size);
|
||||||
|
|
||||||
|
free(page_buffer);
|
||||||
|
free(ecc_hw_buffer);
|
||||||
|
free(ecc_flash_buffer);
|
||||||
|
|
||||||
|
target_free_working_area(target,pworking_area);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
return nand_read_page_raw(nand, page, data, data_size, oob, oob_size);
|
return nand_read_page_raw(nand, page, data, data_size, oob, oob_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -762,7 +1139,7 @@ static int lpc3180_read_page(struct nand_device *nand, uint32_t page, uint8_t *d
|
|||||||
static int lpc3180_controller_ready(struct nand_device *nand, int timeout)
|
static int lpc3180_controller_ready(struct nand_device *nand, int timeout)
|
||||||
{
|
{
|
||||||
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
||||||
struct target *target = lpc3180_info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
{
|
||||||
@@ -810,7 +1187,7 @@ static int lpc3180_controller_ready(struct nand_device *nand, int timeout)
|
|||||||
static int lpc3180_nand_ready(struct nand_device *nand, int timeout)
|
static int lpc3180_nand_ready(struct nand_device *nand, int timeout)
|
||||||
{
|
{
|
||||||
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
||||||
struct target *target = lpc3180_info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
{
|
||||||
@@ -855,6 +1232,42 @@ static int lpc3180_nand_ready(struct nand_device *nand, int timeout)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lpc3180_tc_ready(struct nand_device *nand, int timeout)
|
||||||
|
{
|
||||||
|
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
||||||
|
struct target *target = nand->target;
|
||||||
|
|
||||||
|
if (target->state != TARGET_HALTED)
|
||||||
|
{
|
||||||
|
LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG("lpc3180_tc_ready count start=%d",
|
||||||
|
timeout);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
|
||||||
|
{
|
||||||
|
uint32_t status = 0x0;
|
||||||
|
/* Read SLC_INT_STAT and check INT_TC_STAT bit */
|
||||||
|
target_read_u32(target, 0x2002001c, &status);
|
||||||
|
|
||||||
|
if (status & 2){
|
||||||
|
LOG_DEBUG("lpc3180_tc_ready count=%d",
|
||||||
|
timeout);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alive_sleep(1);
|
||||||
|
} while (timeout-- > 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_lpc3180_select_command)
|
COMMAND_HANDLER(handle_lpc3180_select_command)
|
||||||
{
|
{
|
||||||
struct lpc3180_nand_controller *lpc3180_info = NULL;
|
struct lpc3180_nand_controller *lpc3180_info = NULL;
|
||||||
@@ -863,7 +1276,7 @@ COMMAND_HANDLER(handle_lpc3180_select_command)
|
|||||||
"no", "mlc", "slc"
|
"no", "mlc", "slc"
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
|
if ((CMD_ARGC < 1) || (CMD_ARGC > 3))
|
||||||
{
|
{
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
@@ -879,7 +1292,7 @@ COMMAND_HANDLER(handle_lpc3180_select_command)
|
|||||||
|
|
||||||
lpc3180_info = nand->controller_priv;
|
lpc3180_info = nand->controller_priv;
|
||||||
|
|
||||||
if (CMD_ARGC == 2)
|
if (CMD_ARGC >= 2)
|
||||||
{
|
{
|
||||||
if (strcmp(CMD_ARGV[1], "mlc") == 0)
|
if (strcmp(CMD_ARGV[1], "mlc") == 0)
|
||||||
{
|
{
|
||||||
@@ -888,6 +1301,12 @@ COMMAND_HANDLER(handle_lpc3180_select_command)
|
|||||||
else if (strcmp(CMD_ARGV[1], "slc") == 0)
|
else if (strcmp(CMD_ARGV[1], "slc") == 0)
|
||||||
{
|
{
|
||||||
lpc3180_info->selected_controller = LPC3180_SLC_CONTROLLER;
|
lpc3180_info->selected_controller = LPC3180_SLC_CONTROLLER;
|
||||||
|
if (CMD_ARGC == 3 && strcmp(CMD_ARGV[2], "bulk") == 0){
|
||||||
|
lpc3180_info->is_bulk = 1;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
lpc3180_info->is_bulk = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -895,7 +1314,12 @@ COMMAND_HANDLER(handle_lpc3180_select_command)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
|
||||||
command_print(CMD_CTX, "%s controller selected", selected[lpc3180_info->selected_controller]);
|
command_print(CMD_CTX, "%s controller selected", selected[lpc3180_info->selected_controller]);
|
||||||
|
else{
|
||||||
|
command_print(CMD_CTX, lpc3180_info->is_bulk?"%s controller selected bulk mode is available":"%s controller selected bulk mode is not available", selected[lpc3180_info->selected_controller]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
@@ -905,8 +1329,8 @@ static const struct command_registration lpc3180_exec_command_handlers[] = {
|
|||||||
.name = "select",
|
.name = "select",
|
||||||
.handler = handle_lpc3180_select_command,
|
.handler = handle_lpc3180_select_command,
|
||||||
.mode = COMMAND_EXEC,
|
.mode = COMMAND_EXEC,
|
||||||
.help = "select MLC or SLC controller (default is MLC)",
|
.help = "select MLC or SLC controller (default is MLC), SLC can be set to bulk mode",
|
||||||
.usage = "bank_id ['mlc'|'slc']",
|
.usage = "bank_id ['mlc'|'slc' ['bulk'] ]",
|
||||||
},
|
},
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
@@ -932,6 +1356,5 @@ struct nand_flash_controller lpc3180_nand_controller = {
|
|||||||
.read_data = lpc3180_read_data,
|
.read_data = lpc3180_read_data,
|
||||||
.write_page = lpc3180_write_page,
|
.write_page = lpc3180_write_page,
|
||||||
.read_page = lpc3180_read_page,
|
.read_page = lpc3180_read_page,
|
||||||
.controller_ready = lpc3180_controller_ready,
|
|
||||||
.nand_ready = lpc3180_nand_ready,
|
.nand_ready = lpc3180_nand_ready,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ enum lpc3180_selected_controller
|
|||||||
|
|
||||||
struct lpc3180_nand_controller
|
struct lpc3180_nand_controller
|
||||||
{
|
{
|
||||||
struct target *target;
|
|
||||||
int osc_freq;
|
int osc_freq;
|
||||||
enum lpc3180_selected_controller selected_controller;
|
enum lpc3180_selected_controller selected_controller;
|
||||||
|
int is_bulk;
|
||||||
int sw_write_protection;
|
int sw_write_protection;
|
||||||
uint32_t sw_wp_lower_bound;
|
uint32_t sw_wp_lower_bound;
|
||||||
uint32_t sw_wp_upper_bound;
|
uint32_t sw_wp_upper_bound;
|
||||||
|
|||||||
1828
src/flash/nand/lpc32xx.c
Normal file
1828
src/flash/nand/lpc32xx.c
Normal file
File diff suppressed because it is too large
Load Diff
39
src/flash/nand/lpc32xx.h
Normal file
39
src/flash/nand/lpc32xx.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2007 by Dominic Rath *
|
||||||
|
* Dominic.Rath@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef LPC32xx_NAND_CONTROLLER_H
|
||||||
|
#define LPC32xx_NAND_CONTROLLER_H
|
||||||
|
|
||||||
|
enum lpc32xx_selected_controller
|
||||||
|
{
|
||||||
|
LPC32xx_NO_CONTROLLER,
|
||||||
|
LPC32xx_MLC_CONTROLLER,
|
||||||
|
LPC32xx_SLC_CONTROLLER,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lpc32xx_nand_controller
|
||||||
|
{
|
||||||
|
int osc_freq;
|
||||||
|
enum lpc32xx_selected_controller selected_controller;
|
||||||
|
int sw_write_protection;
|
||||||
|
uint32_t sw_wp_lower_bound;
|
||||||
|
uint32_t sw_wp_upper_bound;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /*LPC32xx_NAND_CONTROLLER_H */
|
||||||
761
src/flash/nand/mx2.c
Normal file
761
src/flash/nand/mx2.c
Normal file
@@ -0,0 +1,761 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2009 by Alexei Babich *
|
||||||
|
* Rezonans plc., Chelyabinsk, Russia *
|
||||||
|
* impatt@mail.ru *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2010 by Gaetan CARLIER *
|
||||||
|
* Trump s.a., Belgium *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Freescale iMX2* OpenOCD NAND Flash controller support.
|
||||||
|
* based on Freescale iMX3* OpenOCD NAND Flash controller support.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* driver tested with Samsung K9F2G08UXA and Numonyx/ST NAND02G-B2D @imx27
|
||||||
|
* tested "nand probe #", "nand erase # 0 #", "nand dump # file 0 #",
|
||||||
|
* "nand write # file 0", "nand verify"
|
||||||
|
*
|
||||||
|
* get_next_halfword_from_sram_buffer() not tested
|
||||||
|
* !! all function only tested with 2k page nand device; imx27_write_page
|
||||||
|
* writes the 4 MAIN_BUFFER's and is not compatible with < 2k page
|
||||||
|
* !! oob must be be used due to NFS bug
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "imp.h"
|
||||||
|
#include "mx2.h"
|
||||||
|
#include <target/target.h>
|
||||||
|
|
||||||
|
/* This permits to print (in LOG_INFO) how much bytes
|
||||||
|
* has been written after a page read or write.
|
||||||
|
* This is useful when OpenOCD is used with a graphical
|
||||||
|
* front-end to estimate progression of the global read/write
|
||||||
|
*/
|
||||||
|
#undef _MX2_PRINT_STAT
|
||||||
|
//#define _MX2_PRINT_STAT
|
||||||
|
|
||||||
|
static const char target_not_halted_err_msg[] =
|
||||||
|
"target must be halted to use mx2 NAND flash controller";
|
||||||
|
static const char data_block_size_err_msg[] =
|
||||||
|
"minimal granularity is one half-word, %" PRId32 " is incorrect";
|
||||||
|
static const char sram_buffer_bounds_err_msg[] =
|
||||||
|
"trying to access out of SRAM buffer bound (addr=0x%" PRIx32 ")";
|
||||||
|
static const char get_status_register_err_msg[] = "can't get NAND status";
|
||||||
|
static uint32_t in_sram_address;
|
||||||
|
static unsigned char sign_of_sequental_byte_read;
|
||||||
|
|
||||||
|
static int initialize_nf_controller(struct nand_device *nand);
|
||||||
|
static int get_next_byte_from_sram_buffer(struct target * target, uint8_t * value);
|
||||||
|
static int get_next_halfword_from_sram_buffer(struct target * target,
|
||||||
|
uint16_t * value);
|
||||||
|
static int poll_for_complete_op(struct target * target, const char *text);
|
||||||
|
static int validate_target_state(struct nand_device *nand);
|
||||||
|
static int do_data_output(struct nand_device *nand);
|
||||||
|
|
||||||
|
static int imx27_command(struct nand_device *nand, uint8_t command);
|
||||||
|
static int imx27_address(struct nand_device *nand, uint8_t address);
|
||||||
|
|
||||||
|
NAND_DEVICE_COMMAND_HANDLER(imx27_nand_device_command)
|
||||||
|
{
|
||||||
|
struct mx2_nf_controller *mx2_nf_info;
|
||||||
|
int hwecc_needed;
|
||||||
|
int x;
|
||||||
|
mx2_nf_info = malloc(sizeof(struct mx2_nf_controller));
|
||||||
|
if (mx2_nf_info == NULL) {
|
||||||
|
LOG_ERROR("no memory for nand controller");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nand->controller_priv = mx2_nf_info;
|
||||||
|
if (CMD_ARGC < 3) {
|
||||||
|
LOG_ERROR("use \"nand device imx27 target noecc|hwecc\"");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* check hwecc requirements
|
||||||
|
*/
|
||||||
|
|
||||||
|
hwecc_needed = strcmp(CMD_ARGV[2], "hwecc");
|
||||||
|
if (hwecc_needed == 0)
|
||||||
|
mx2_nf_info->flags.hw_ecc_enabled = 1;
|
||||||
|
else
|
||||||
|
mx2_nf_info->flags.hw_ecc_enabled = 0;
|
||||||
|
|
||||||
|
mx2_nf_info->optype = MX2_NF_DATAOUT_PAGE;
|
||||||
|
mx2_nf_info->fin = MX2_NF_FIN_NONE;
|
||||||
|
mx2_nf_info->flags.target_little_endian =
|
||||||
|
(nand->target->endianness == TARGET_LITTLE_ENDIAN);
|
||||||
|
/*
|
||||||
|
* testing host endianness
|
||||||
|
*/
|
||||||
|
x = 1;
|
||||||
|
if (*(char *) &x == 1)
|
||||||
|
mx2_nf_info->flags.host_little_endian = 1;
|
||||||
|
else
|
||||||
|
mx2_nf_info->flags.host_little_endian = 0;
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx27_init(struct nand_device *nand)
|
||||||
|
{
|
||||||
|
struct mx2_nf_controller *mx2_nf_info = nand->controller_priv;
|
||||||
|
struct target *target = nand->target;
|
||||||
|
|
||||||
|
int validate_target_result;
|
||||||
|
uint16_t buffsize_register_content;
|
||||||
|
uint32_t pcsr_register_content;
|
||||||
|
int retval;
|
||||||
|
uint16_t nand_status_content;
|
||||||
|
/*
|
||||||
|
* validate target state
|
||||||
|
*/
|
||||||
|
validate_target_result = validate_target_state(nand);
|
||||||
|
if (validate_target_result != ERROR_OK)
|
||||||
|
return validate_target_result;
|
||||||
|
|
||||||
|
target_read_u16(target, MX2_NF_BUFSIZ, &buffsize_register_content);
|
||||||
|
mx2_nf_info->flags.one_kb_sram = !(buffsize_register_content & 0x000f);
|
||||||
|
|
||||||
|
target_read_u32(target, MX2_FMCR, &pcsr_register_content);
|
||||||
|
if (!nand->bus_width) {
|
||||||
|
/* bus_width not yet defined. Read it from MX2_FMCR */
|
||||||
|
nand->bus_width =
|
||||||
|
(pcsr_register_content & MX2_FMCR_NF_16BIT_SEL) ? 16 : 8;
|
||||||
|
} else {
|
||||||
|
/* bus_width forced in soft. Sync it to MX2_FMCR */
|
||||||
|
pcsr_register_content |=
|
||||||
|
((nand->bus_width == 16) ? MX2_FMCR_NF_16BIT_SEL : 0x00000000);
|
||||||
|
target_write_u32(target, MX2_FMCR, pcsr_register_content);
|
||||||
|
}
|
||||||
|
if (nand->bus_width == 16)
|
||||||
|
LOG_DEBUG("MX2_NF : bus is 16-bit width");
|
||||||
|
else
|
||||||
|
LOG_DEBUG("MX2_NF : bus is 8-bit width");
|
||||||
|
|
||||||
|
if (!nand->page_size) {
|
||||||
|
nand->page_size =
|
||||||
|
(pcsr_register_content & MX2_FMCR_NF_FMS) ? 2048 : 512;
|
||||||
|
} else {
|
||||||
|
pcsr_register_content |=
|
||||||
|
((nand->page_size == 2048) ? MX2_FMCR_NF_FMS : 0x00000000);
|
||||||
|
target_write_u32(target, MX2_FMCR, pcsr_register_content);
|
||||||
|
}
|
||||||
|
if (mx2_nf_info->flags.one_kb_sram && (nand->page_size == 2048)) {
|
||||||
|
LOG_ERROR("NAND controller have only 1 kb SRAM, so "
|
||||||
|
"pagesize 2048 is incompatible with it");
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG("MX2_NF : NAND controller can handle pagesize of 2048");
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize_nf_controller(nand);
|
||||||
|
|
||||||
|
retval = ERROR_OK;
|
||||||
|
retval |= imx27_command(nand, NAND_CMD_STATUS);
|
||||||
|
retval |= imx27_address(nand, 0x00);
|
||||||
|
retval |= do_data_output(nand);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
LOG_ERROR(get_status_register_err_msg);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
target_read_u16(target, MX2_NF_MAIN_BUFFER0, &nand_status_content);
|
||||||
|
if (!(nand_status_content & 0x0080)) {
|
||||||
|
LOG_INFO("NAND read-only");
|
||||||
|
mx2_nf_info->flags.nand_readonly = 1;
|
||||||
|
} else {
|
||||||
|
mx2_nf_info->flags.nand_readonly = 0;
|
||||||
|
}
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx27_read_data(struct nand_device *nand, void *data)
|
||||||
|
{
|
||||||
|
struct target *target = nand->target;
|
||||||
|
int validate_target_result;
|
||||||
|
int try_data_output_from_nand_chip;
|
||||||
|
/*
|
||||||
|
* validate target state
|
||||||
|
*/
|
||||||
|
validate_target_result = validate_target_state(nand);
|
||||||
|
if (validate_target_result != ERROR_OK)
|
||||||
|
return validate_target_result;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get data from nand chip
|
||||||
|
*/
|
||||||
|
try_data_output_from_nand_chip = do_data_output(nand);
|
||||||
|
if (try_data_output_from_nand_chip != ERROR_OK) {
|
||||||
|
LOG_ERROR("imx27_read_data : read data failed : '%x'",
|
||||||
|
try_data_output_from_nand_chip);
|
||||||
|
return try_data_output_from_nand_chip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nand->bus_width == 16)
|
||||||
|
get_next_halfword_from_sram_buffer(target, data);
|
||||||
|
else
|
||||||
|
get_next_byte_from_sram_buffer(target, data);
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx27_write_data(struct nand_device *nand, uint16_t data)
|
||||||
|
{
|
||||||
|
LOG_ERROR("write_data() not implemented");
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx27_reset(struct nand_device *nand)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* validate target state
|
||||||
|
*/
|
||||||
|
int validate_target_result;
|
||||||
|
validate_target_result = validate_target_state(nand);
|
||||||
|
if (validate_target_result != ERROR_OK)
|
||||||
|
return validate_target_result;
|
||||||
|
initialize_nf_controller(nand);
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx27_command(struct nand_device *nand, uint8_t command)
|
||||||
|
{
|
||||||
|
struct mx2_nf_controller *mx2_nf_info = nand->controller_priv;
|
||||||
|
struct target *target = nand->target;
|
||||||
|
int validate_target_result;
|
||||||
|
int poll_result;
|
||||||
|
/*
|
||||||
|
* validate target state
|
||||||
|
*/
|
||||||
|
validate_target_result = validate_target_state(nand);
|
||||||
|
if (validate_target_result != ERROR_OK)
|
||||||
|
return validate_target_result;
|
||||||
|
|
||||||
|
switch(command) {
|
||||||
|
case NAND_CMD_READOOB:
|
||||||
|
command = NAND_CMD_READ0;
|
||||||
|
/* set read point for data_read() and read_block_data() to
|
||||||
|
* spare area in SRAM buffer
|
||||||
|
*/
|
||||||
|
in_sram_address = MX2_NF_SPARE_BUFFER0;
|
||||||
|
break;
|
||||||
|
case NAND_CMD_READ1:
|
||||||
|
command = NAND_CMD_READ0;
|
||||||
|
/*
|
||||||
|
* offset == one half of page size
|
||||||
|
*/
|
||||||
|
in_sram_address =
|
||||||
|
MX2_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
in_sram_address = MX2_NF_MAIN_BUFFER0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_write_u16(target, MX2_NF_FCMD, command);
|
||||||
|
/*
|
||||||
|
* start command input operation (set MX2_NF_BIT_OP_DONE==0)
|
||||||
|
*/
|
||||||
|
target_write_u16(target, MX2_NF_CFG2, MX2_NF_BIT_OP_FCI);
|
||||||
|
poll_result = poll_for_complete_op(target, "command");
|
||||||
|
if (poll_result != ERROR_OK)
|
||||||
|
return poll_result;
|
||||||
|
/*
|
||||||
|
* reset cursor to begin of the buffer
|
||||||
|
*/
|
||||||
|
sign_of_sequental_byte_read = 0;
|
||||||
|
/* Handle special read command and adjust NF_CFG2(FDO) */
|
||||||
|
switch(command) {
|
||||||
|
case NAND_CMD_READID:
|
||||||
|
mx2_nf_info->optype = MX2_NF_DATAOUT_NANDID;
|
||||||
|
mx2_nf_info->fin = MX2_NF_FIN_DATAOUT;
|
||||||
|
break;
|
||||||
|
case NAND_CMD_STATUS:
|
||||||
|
mx2_nf_info->optype = MX2_NF_DATAOUT_NANDSTATUS;
|
||||||
|
mx2_nf_info->fin = MX2_NF_FIN_DATAOUT;
|
||||||
|
target_write_u16 (target, MX2_NF_BUFADDR, 0);
|
||||||
|
in_sram_address = 0;
|
||||||
|
break;
|
||||||
|
case NAND_CMD_READ0:
|
||||||
|
mx2_nf_info->fin = MX2_NF_FIN_DATAOUT;
|
||||||
|
mx2_nf_info->optype = MX2_NF_DATAOUT_PAGE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Ohter command use the default 'One page data out' FDO */
|
||||||
|
mx2_nf_info->optype = MX2_NF_DATAOUT_PAGE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx27_address(struct nand_device *nand, uint8_t address)
|
||||||
|
{
|
||||||
|
struct target *target = nand->target;
|
||||||
|
int validate_target_result;
|
||||||
|
int poll_result;
|
||||||
|
/*
|
||||||
|
* validate target state
|
||||||
|
*/
|
||||||
|
validate_target_result = validate_target_state(nand);
|
||||||
|
if (validate_target_result != ERROR_OK)
|
||||||
|
return validate_target_result;
|
||||||
|
|
||||||
|
target_write_u16(target, MX2_NF_FADDR, address);
|
||||||
|
/*
|
||||||
|
* start address input operation (set MX2_NF_BIT_OP_DONE==0)
|
||||||
|
*/
|
||||||
|
target_write_u16(target, MX2_NF_CFG2, MX2_NF_BIT_OP_FAI);
|
||||||
|
poll_result = poll_for_complete_op(target, "address");
|
||||||
|
if (poll_result != ERROR_OK)
|
||||||
|
return poll_result;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx27_nand_ready(struct nand_device *nand, int tout)
|
||||||
|
{
|
||||||
|
uint16_t poll_complete_status;
|
||||||
|
struct target *target = nand->target;
|
||||||
|
int validate_target_result;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* validate target state
|
||||||
|
*/
|
||||||
|
validate_target_result = validate_target_state(nand);
|
||||||
|
if (validate_target_result != ERROR_OK)
|
||||||
|
return validate_target_result;
|
||||||
|
|
||||||
|
do {
|
||||||
|
target_read_u16(target, MX2_NF_CFG2, &poll_complete_status);
|
||||||
|
if (poll_complete_status & MX2_NF_BIT_OP_DONE)
|
||||||
|
return tout;
|
||||||
|
|
||||||
|
alive_sleep(1);
|
||||||
|
}
|
||||||
|
while (tout-- > 0);
|
||||||
|
return tout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx27_write_page(struct nand_device *nand, uint32_t page,
|
||||||
|
uint8_t * data, uint32_t data_size, uint8_t * oob,
|
||||||
|
uint32_t oob_size)
|
||||||
|
{
|
||||||
|
struct mx2_nf_controller *mx2_nf_info = nand->controller_priv;
|
||||||
|
struct target *target = nand->target;
|
||||||
|
int retval;
|
||||||
|
uint16_t nand_status_content;
|
||||||
|
uint16_t swap1, swap2, new_swap1;
|
||||||
|
int poll_result;
|
||||||
|
if (data_size % 2) {
|
||||||
|
LOG_ERROR(data_block_size_err_msg, data_size);
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
if (oob_size % 2) {
|
||||||
|
LOG_ERROR(data_block_size_err_msg, oob_size);
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
if (!data) {
|
||||||
|
LOG_ERROR("nothing to program");
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* validate target state
|
||||||
|
*/
|
||||||
|
retval = validate_target_state(nand);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
in_sram_address = MX2_NF_MAIN_BUFFER0;
|
||||||
|
sign_of_sequental_byte_read = 0;
|
||||||
|
retval = ERROR_OK;
|
||||||
|
retval |= imx27_command(nand, NAND_CMD_SEQIN);
|
||||||
|
retval |= imx27_address(nand, 0); //col
|
||||||
|
retval |= imx27_address(nand, 0); //col
|
||||||
|
retval |= imx27_address(nand, page & 0xff); //page address
|
||||||
|
retval |= imx27_address(nand, (page >> 8) & 0xff); //page address
|
||||||
|
retval |= imx27_address(nand, (page >> 16) & 0xff); //page address
|
||||||
|
|
||||||
|
target_write_buffer(target, MX2_NF_MAIN_BUFFER0, data_size, data);
|
||||||
|
if (oob) {
|
||||||
|
if (mx2_nf_info->flags.hw_ecc_enabled) {
|
||||||
|
/*
|
||||||
|
* part of spare block will be overrided by hardware
|
||||||
|
* ECC generator
|
||||||
|
*/
|
||||||
|
LOG_DEBUG("part of spare block will be overrided "
|
||||||
|
"by hardware ECC generator");
|
||||||
|
}
|
||||||
|
target_write_buffer(target, MX2_NF_SPARE_BUFFER0, oob_size,
|
||||||
|
oob);
|
||||||
|
}
|
||||||
|
//BI-swap - work-around of imx27 NFC for NAND device with page == 2kb
|
||||||
|
target_read_u16(target, MX2_NF_MAIN_BUFFER3 + 464, &swap1);
|
||||||
|
if (oob) {
|
||||||
|
LOG_ERROR("Due to NFC Bug, oob is not correctly implemented "
|
||||||
|
"in mx2 driver");
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
//target_read_u16 (target, MX2_NF_SPARE_BUFFER3 + 4, &swap2);
|
||||||
|
swap2 = 0xffff; //Spare buffer unused forced to 0xffff
|
||||||
|
new_swap1 = (swap1 & 0xFF00) | (swap2 >> 8);
|
||||||
|
swap2 = (swap1 << 8) | (swap2 & 0xFF);
|
||||||
|
|
||||||
|
target_write_u16(target, MX2_NF_MAIN_BUFFER3 + 464, new_swap1);
|
||||||
|
target_write_u16(target, MX2_NF_SPARE_BUFFER3 + 4, swap2);
|
||||||
|
/*
|
||||||
|
* start data input operation (set MX2_NF_BIT_OP_DONE==0)
|
||||||
|
*/
|
||||||
|
target_write_u16(target, MX2_NF_BUFADDR, 0);
|
||||||
|
target_write_u16(target, MX2_NF_CFG2, MX2_NF_BIT_OP_FDI);
|
||||||
|
poll_result = poll_for_complete_op(target, "data input");
|
||||||
|
if (poll_result != ERROR_OK)
|
||||||
|
return poll_result;
|
||||||
|
|
||||||
|
target_write_u16(target, MX2_NF_BUFADDR, 1);
|
||||||
|
target_write_u16(target, MX2_NF_CFG2, MX2_NF_BIT_OP_FDI);
|
||||||
|
poll_result = poll_for_complete_op(target, "data input");
|
||||||
|
if (poll_result != ERROR_OK)
|
||||||
|
return poll_result;
|
||||||
|
|
||||||
|
target_write_u16(target, MX2_NF_BUFADDR, 2);
|
||||||
|
target_write_u16(target, MX2_NF_CFG2, MX2_NF_BIT_OP_FDI);
|
||||||
|
poll_result = poll_for_complete_op(target, "data input");
|
||||||
|
if (poll_result != ERROR_OK)
|
||||||
|
return poll_result;
|
||||||
|
|
||||||
|
target_write_u16(target, MX2_NF_BUFADDR, 3);
|
||||||
|
target_write_u16(target, MX2_NF_CFG2, MX2_NF_BIT_OP_FDI);
|
||||||
|
poll_result = poll_for_complete_op(target, "data input");
|
||||||
|
if (poll_result != ERROR_OK)
|
||||||
|
return poll_result;
|
||||||
|
|
||||||
|
retval |= imx27_command(nand, NAND_CMD_PAGEPROG);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check status register
|
||||||
|
*/
|
||||||
|
retval = ERROR_OK;
|
||||||
|
retval |= imx27_command(nand, NAND_CMD_STATUS);
|
||||||
|
target_write_u16 (target, MX2_NF_BUFADDR, 0);
|
||||||
|
mx2_nf_info->optype = MX2_NF_DATAOUT_NANDSTATUS;
|
||||||
|
mx2_nf_info->fin = MX2_NF_FIN_DATAOUT;
|
||||||
|
retval |= do_data_output(nand);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
LOG_ERROR (get_status_register_err_msg);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
target_read_u16 (target, MX2_NF_MAIN_BUFFER0, &nand_status_content);
|
||||||
|
if (nand_status_content & 0x0001) {
|
||||||
|
/*
|
||||||
|
* page not correctly written
|
||||||
|
*/
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
#ifdef _MX2_PRINT_STAT
|
||||||
|
LOG_INFO("%d bytes newly written", data_size);
|
||||||
|
#endif
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx27_read_page(struct nand_device *nand, uint32_t page,
|
||||||
|
uint8_t * data, uint32_t data_size, uint8_t * oob,
|
||||||
|
uint32_t oob_size)
|
||||||
|
{
|
||||||
|
struct mx2_nf_controller *mx2_nf_info = nand->controller_priv;
|
||||||
|
struct target *target = nand->target;
|
||||||
|
int retval;
|
||||||
|
uint16_t swap1, swap2, new_swap1;
|
||||||
|
if (data_size % 2) {
|
||||||
|
LOG_ERROR(data_block_size_err_msg, data_size);
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
if (oob_size % 2) {
|
||||||
|
LOG_ERROR(data_block_size_err_msg, oob_size);
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* validate target state
|
||||||
|
*/
|
||||||
|
retval = validate_target_state(nand);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
/* Reset address_cycles before imx27_command ?? */
|
||||||
|
retval = ERROR_OK;
|
||||||
|
retval |= imx27_command(nand, NAND_CMD_READ0);
|
||||||
|
|
||||||
|
retval |= imx27_address(nand, 0); //col
|
||||||
|
retval |= imx27_address(nand, 0); //col
|
||||||
|
retval |= imx27_address(nand, page & 0xff); //page address
|
||||||
|
retval |= imx27_address(nand, (page >> 8) & 0xff); //page address
|
||||||
|
retval |= imx27_address(nand, (page >> 16) & 0xff); //page address
|
||||||
|
retval |= imx27_command(nand, NAND_CMD_READSTART);
|
||||||
|
|
||||||
|
target_write_u16(target, MX2_NF_BUFADDR, 0);
|
||||||
|
mx2_nf_info->fin = MX2_NF_FIN_DATAOUT;
|
||||||
|
retval = do_data_output(nand);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
LOG_ERROR("MX2_NF : Error reading page 0");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
//Test nand page size to know how much MAIN_BUFFER must be written
|
||||||
|
target_write_u16(target, MX2_NF_BUFADDR, 1);
|
||||||
|
mx2_nf_info->fin = MX2_NF_FIN_DATAOUT;
|
||||||
|
retval = do_data_output(nand);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
LOG_ERROR("MX2_NF : Error reading page 1");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
target_write_u16(target, MX2_NF_BUFADDR, 2);
|
||||||
|
mx2_nf_info->fin = MX2_NF_FIN_DATAOUT;
|
||||||
|
retval = do_data_output(nand);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
LOG_ERROR("MX2_NF : Error reading page 2");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
target_write_u16(target, MX2_NF_BUFADDR, 3);
|
||||||
|
mx2_nf_info->fin = MX2_NF_FIN_DATAOUT;
|
||||||
|
retval = do_data_output(nand);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
LOG_ERROR("MX2_NF : Error reading page 3");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
//BI-swap - work-around of imx27 NFC for NAND device with page == 2k
|
||||||
|
target_read_u16(target, MX2_NF_MAIN_BUFFER3 + 464, &swap1);
|
||||||
|
target_read_u16(target, MX2_NF_SPARE_BUFFER3 + 4, &swap2);
|
||||||
|
new_swap1 = (swap1 & 0xFF00) | (swap2 >> 8);
|
||||||
|
swap2 = (swap1 << 8) | (swap2 & 0xFF);
|
||||||
|
target_write_u16(target, MX2_NF_MAIN_BUFFER3 + 464, new_swap1);
|
||||||
|
target_write_u16(target, MX2_NF_SPARE_BUFFER3 + 4, swap2);
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
target_read_buffer(target, MX2_NF_MAIN_BUFFER0, data_size, data);
|
||||||
|
if (oob)
|
||||||
|
target_read_buffer(target, MX2_NF_SPARE_BUFFER0, oob_size,
|
||||||
|
oob);
|
||||||
|
#ifdef _MX2_PRINT_STAT
|
||||||
|
if (data_size > 0) {
|
||||||
|
/* When Operation Status is read (when page is erased),
|
||||||
|
* this function is used but data_size is null.
|
||||||
|
*/
|
||||||
|
LOG_INFO("%d bytes newly read", data_size);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int initialize_nf_controller(struct nand_device *nand)
|
||||||
|
{
|
||||||
|
struct mx2_nf_controller *mx2_nf_info = nand->controller_priv;
|
||||||
|
struct target *target = nand->target;
|
||||||
|
uint16_t work_mode;
|
||||||
|
uint16_t temp;
|
||||||
|
/*
|
||||||
|
* resets NAND flash controller in zero time ? I dont know.
|
||||||
|
*/
|
||||||
|
target_write_u16(target, MX2_NF_CFG1, MX2_NF_BIT_RESET_EN);
|
||||||
|
work_mode = MX2_NF_BIT_INT_DIS; /* disable interrupt */
|
||||||
|
if (target->endianness == TARGET_BIG_ENDIAN) {
|
||||||
|
LOG_DEBUG("MX2_NF : work in Big Endian mode");
|
||||||
|
work_mode |= MX2_NF_BIT_BE_EN;
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG("MX2_NF : work in Little Endian mode");
|
||||||
|
}
|
||||||
|
if (mx2_nf_info->flags.hw_ecc_enabled) {
|
||||||
|
LOG_DEBUG("MX2_NF : work with ECC mode");
|
||||||
|
work_mode |= MX2_NF_BIT_ECC_EN;
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG("MX2_NF : work without ECC mode");
|
||||||
|
}
|
||||||
|
target_write_u16(target, MX2_NF_CFG1, work_mode);
|
||||||
|
/*
|
||||||
|
* unlock SRAM buffer for write; 2 mean "Unlock", other values means "Lock"
|
||||||
|
*/
|
||||||
|
target_write_u16(target, MX2_NF_BUFCFG, 2);
|
||||||
|
target_read_u16(target, MX2_NF_FWP, &temp);
|
||||||
|
if ((temp & 0x0007) == 1) {
|
||||||
|
LOG_ERROR("NAND flash is tight-locked, reset needed");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unlock NAND flash for write
|
||||||
|
*/
|
||||||
|
target_write_u16(target, MX2_NF_FWP, 4);
|
||||||
|
target_write_u16(target, MX2_NF_LOCKSTART, 0x0000);
|
||||||
|
target_write_u16(target, MX2_NF_LOCKEND, 0xFFFF);
|
||||||
|
/*
|
||||||
|
* 0x0000 means that first SRAM buffer @0xD800_0000 will be used
|
||||||
|
*/
|
||||||
|
target_write_u16(target, MX2_NF_BUFADDR, 0x0000);
|
||||||
|
/*
|
||||||
|
* address of SRAM buffer
|
||||||
|
*/
|
||||||
|
in_sram_address = MX2_NF_MAIN_BUFFER0;
|
||||||
|
sign_of_sequental_byte_read = 0;
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_next_byte_from_sram_buffer(struct target * target, uint8_t * value)
|
||||||
|
{
|
||||||
|
static uint8_t even_byte = 0;
|
||||||
|
uint16_t temp;
|
||||||
|
/*
|
||||||
|
* host-big_endian ??
|
||||||
|
*/
|
||||||
|
if (sign_of_sequental_byte_read == 0)
|
||||||
|
even_byte = 0;
|
||||||
|
|
||||||
|
if (in_sram_address > MX2_NF_LAST_BUFFER_ADDR) {
|
||||||
|
LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
|
||||||
|
*value = 0;
|
||||||
|
sign_of_sequental_byte_read = 0;
|
||||||
|
even_byte = 0;
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
} else {
|
||||||
|
target_read_u16(target, in_sram_address, &temp);
|
||||||
|
if (even_byte) {
|
||||||
|
*value = temp >> 8;
|
||||||
|
even_byte = 0;
|
||||||
|
in_sram_address += 2;
|
||||||
|
} else {
|
||||||
|
*value = temp & 0xff;
|
||||||
|
even_byte = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sign_of_sequental_byte_read = 1;
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_next_halfword_from_sram_buffer(struct target * target,
|
||||||
|
uint16_t * value)
|
||||||
|
{
|
||||||
|
if (in_sram_address > MX2_NF_LAST_BUFFER_ADDR) {
|
||||||
|
LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
|
||||||
|
*value = 0;
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
} else {
|
||||||
|
target_read_u16(target, in_sram_address, value);
|
||||||
|
in_sram_address += 2;
|
||||||
|
}
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int poll_for_complete_op(struct target * target, const char *text)
|
||||||
|
{
|
||||||
|
uint16_t poll_complete_status;
|
||||||
|
for (int poll_cycle_count = 0; poll_cycle_count < 100; poll_cycle_count++) {
|
||||||
|
target_read_u16(target, MX2_NF_CFG2, &poll_complete_status);
|
||||||
|
if (poll_complete_status & MX2_NF_BIT_OP_DONE)
|
||||||
|
break;
|
||||||
|
|
||||||
|
usleep(10);
|
||||||
|
}
|
||||||
|
if (!(poll_complete_status & MX2_NF_BIT_OP_DONE)) {
|
||||||
|
LOG_ERROR("%s sending timeout", text);
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int validate_target_state(struct nand_device *nand)
|
||||||
|
{
|
||||||
|
struct mx2_nf_controller *mx2_nf_info = nand->controller_priv;
|
||||||
|
struct target *target = nand->target;
|
||||||
|
|
||||||
|
if (target->state != TARGET_HALTED) {
|
||||||
|
LOG_ERROR(target_not_halted_err_msg);
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mx2_nf_info->flags.target_little_endian !=
|
||||||
|
(target->endianness == TARGET_LITTLE_ENDIAN)) {
|
||||||
|
/*
|
||||||
|
* endianness changed after NAND controller probed
|
||||||
|
*/
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_data_output(struct nand_device *nand)
|
||||||
|
{
|
||||||
|
struct mx2_nf_controller *mx2_nf_info = nand->controller_priv;
|
||||||
|
struct target *target = nand->target;
|
||||||
|
int poll_result;
|
||||||
|
uint16_t ecc_status;
|
||||||
|
switch(mx2_nf_info->fin) {
|
||||||
|
case MX2_NF_FIN_DATAOUT:
|
||||||
|
/*
|
||||||
|
* start data output operation (set MX2_NF_BIT_OP_DONE==0)
|
||||||
|
*/
|
||||||
|
target_write_u16(target, MX2_NF_CFG2, MX2_NF_BIT_DATAOUT_TYPE(mx2_nf_info->optype));
|
||||||
|
poll_result = poll_for_complete_op(target, "data output");
|
||||||
|
if (poll_result != ERROR_OK)
|
||||||
|
return poll_result;
|
||||||
|
|
||||||
|
mx2_nf_info->fin = MX2_NF_FIN_NONE;
|
||||||
|
/*
|
||||||
|
* ECC stuff
|
||||||
|
*/
|
||||||
|
if ((mx2_nf_info->optype == MX2_NF_DATAOUT_PAGE) && mx2_nf_info->flags.hw_ecc_enabled) {
|
||||||
|
target_read_u16(target, MX2_NF_ECCSTATUS, &ecc_status);
|
||||||
|
switch(ecc_status & 0x000c) {
|
||||||
|
case 1 << 2:
|
||||||
|
LOG_INFO("main area readed with 1 (correctable) error");
|
||||||
|
break;
|
||||||
|
case 2 << 2:
|
||||||
|
LOG_INFO("main area readed with more than 1 (incorrectable) error");
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch(ecc_status & 0x0003) {
|
||||||
|
case 1:
|
||||||
|
LOG_INFO("spare area readed with 1 (correctable) error");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
LOG_INFO("main area readed with more than 1 (incorrectable) error");
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MX2_NF_FIN_NONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct nand_flash_controller imx27_nand_flash_controller = {
|
||||||
|
.name = "imx27",
|
||||||
|
.nand_device_command = &imx27_nand_device_command,
|
||||||
|
.init = &imx27_init,
|
||||||
|
.reset = &imx27_reset,
|
||||||
|
.command = &imx27_command,
|
||||||
|
.address = &imx27_address,
|
||||||
|
.write_data = &imx27_write_data,
|
||||||
|
.read_data = &imx27_read_data,
|
||||||
|
.write_page = &imx27_write_page,
|
||||||
|
.read_page = &imx27_read_page,
|
||||||
|
.nand_ready = &imx27_nand_ready,
|
||||||
|
};
|
||||||
119
src/flash/nand/mx2.h
Normal file
119
src/flash/nand/mx2.h
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2009 by Alexei Babich *
|
||||||
|
* Rezonans plc., Chelyabinsk, Russia *
|
||||||
|
* impatt@mail.ru *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Freescale iMX2* OpenOCD NAND Flash controller support.
|
||||||
|
* based on Freescale iMX3* OpenOCD NAND Flash controller support.
|
||||||
|
*
|
||||||
|
* Many thanks to Ben Dooks for writing s3c24xx driver.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MX2_NF_BASE_ADDR 0xd8000000
|
||||||
|
#define MX2_NF_BUFSIZ (MX2_NF_BASE_ADDR + 0xe00)
|
||||||
|
#define MX2_NF_BUFADDR (MX2_NF_BASE_ADDR + 0xe04)
|
||||||
|
#define MX2_NF_FADDR (MX2_NF_BASE_ADDR + 0xe06)
|
||||||
|
#define MX2_NF_FCMD (MX2_NF_BASE_ADDR + 0xe08)
|
||||||
|
#define MX2_NF_BUFCFG (MX2_NF_BASE_ADDR + 0xe0a)
|
||||||
|
#define MX2_NF_ECCSTATUS (MX2_NF_BASE_ADDR + 0xe0c)
|
||||||
|
#define MX2_NF_ECCMAINPOS (MX2_NF_BASE_ADDR + 0xe0e)
|
||||||
|
#define MX2_NF_ECCSPAREPOS (MX2_NF_BASE_ADDR + 0xe10)
|
||||||
|
#define MX2_NF_FWP (MX2_NF_BASE_ADDR + 0xe12)
|
||||||
|
#define MX2_NF_LOCKSTART (MX2_NF_BASE_ADDR + 0xe14)
|
||||||
|
#define MX2_NF_LOCKEND (MX2_NF_BASE_ADDR + 0xe16)
|
||||||
|
#define MX2_NF_FWPSTATUS (MX2_NF_BASE_ADDR + 0xe18)
|
||||||
|
/*
|
||||||
|
* all bits not marked as self-clearing bit
|
||||||
|
*/
|
||||||
|
#define MX2_NF_CFG1 (MX2_NF_BASE_ADDR + 0xe1a)
|
||||||
|
#define MX2_NF_CFG2 (MX2_NF_BASE_ADDR + 0xe1c)
|
||||||
|
|
||||||
|
#define MX2_NF_MAIN_BUFFER0 (MX2_NF_BASE_ADDR + 0x0000)
|
||||||
|
#define MX2_NF_MAIN_BUFFER1 (MX2_NF_BASE_ADDR + 0x0200)
|
||||||
|
#define MX2_NF_MAIN_BUFFER2 (MX2_NF_BASE_ADDR + 0x0400)
|
||||||
|
#define MX2_NF_MAIN_BUFFER3 (MX2_NF_BASE_ADDR + 0x0600)
|
||||||
|
#define MX2_NF_SPARE_BUFFER0 (MX2_NF_BASE_ADDR + 0x0800)
|
||||||
|
#define MX2_NF_SPARE_BUFFER1 (MX2_NF_BASE_ADDR + 0x0810)
|
||||||
|
#define MX2_NF_SPARE_BUFFER2 (MX2_NF_BASE_ADDR + 0x0820)
|
||||||
|
#define MX2_NF_SPARE_BUFFER3 (MX2_NF_BASE_ADDR + 0x0830)
|
||||||
|
#define MX2_NF_MAIN_BUFFER_LEN 512
|
||||||
|
#define MX2_NF_SPARE_BUFFER_LEN 16
|
||||||
|
#define MX2_NF_LAST_BUFFER_ADDR ((MX2_NF_SPARE_BUFFER3) + MX2_NF_SPARE_BUFFER_LEN - 2)
|
||||||
|
|
||||||
|
/* bits in MX2_NF_CFG1 register */
|
||||||
|
#define MX2_NF_BIT_SPARE_ONLY_EN (1<<2)
|
||||||
|
#define MX2_NF_BIT_ECC_EN (1<<3)
|
||||||
|
#define MX2_NF_BIT_INT_DIS (1<<4)
|
||||||
|
#define MX2_NF_BIT_BE_EN (1<<5)
|
||||||
|
#define MX2_NF_BIT_RESET_EN (1<<6)
|
||||||
|
#define MX2_NF_BIT_FORCE_CE (1<<7)
|
||||||
|
|
||||||
|
/* bits in MX2_NF_CFG2 register */
|
||||||
|
|
||||||
|
/*Flash Command Input*/
|
||||||
|
#define MX2_NF_BIT_OP_FCI (1<<0)
|
||||||
|
/*
|
||||||
|
* Flash Address Input
|
||||||
|
*/
|
||||||
|
#define MX2_NF_BIT_OP_FAI (1<<1)
|
||||||
|
/*
|
||||||
|
* Flash Data Input
|
||||||
|
*/
|
||||||
|
#define MX2_NF_BIT_OP_FDI (1<<2)
|
||||||
|
|
||||||
|
/* see "enum mx_dataout_type" below */
|
||||||
|
#define MX2_NF_BIT_DATAOUT_TYPE(x) ((x)<<3)
|
||||||
|
#define MX2_NF_BIT_OP_DONE (1<<15)
|
||||||
|
|
||||||
|
#define MX2_CCM_CGR2 0x53f80028
|
||||||
|
#define MX2_GPR 0x43fac008
|
||||||
|
//#define MX2_PCSR 0x53f8000c
|
||||||
|
#define MX2_FMCR 0x10027814
|
||||||
|
#define MX2_FMCR_NF_16BIT_SEL (1<<4)
|
||||||
|
#define MX2_FMCR_NF_FMS (1<<5)
|
||||||
|
|
||||||
|
enum mx_dataout_type
|
||||||
|
{
|
||||||
|
MX2_NF_DATAOUT_PAGE = 1,
|
||||||
|
MX2_NF_DATAOUT_NANDID = 2,
|
||||||
|
MX2_NF_DATAOUT_NANDSTATUS = 4,
|
||||||
|
};
|
||||||
|
enum mx_nf_finalize_action
|
||||||
|
{
|
||||||
|
MX2_NF_FIN_NONE,
|
||||||
|
MX2_NF_FIN_DATAOUT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mx2_nf_flags
|
||||||
|
{
|
||||||
|
unsigned host_little_endian:1;
|
||||||
|
unsigned target_little_endian:1;
|
||||||
|
unsigned nand_readonly:1;
|
||||||
|
unsigned one_kb_sram:1;
|
||||||
|
unsigned hw_ecc_enabled:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mx2_nf_controller
|
||||||
|
{
|
||||||
|
enum mx_dataout_type optype;
|
||||||
|
enum mx_nf_finalize_action fin;
|
||||||
|
struct mx2_nf_flags flags;
|
||||||
|
};
|
||||||
@@ -47,7 +47,7 @@ static const char sram_buffer_bounds_err_msg[] =
|
|||||||
"trying to access out of SRAM buffer bound (addr=0x%" PRIx32 ")";
|
"trying to access out of SRAM buffer bound (addr=0x%" PRIx32 ")";
|
||||||
static const char get_status_register_err_msg[] = "can't get NAND status";
|
static const char get_status_register_err_msg[] = "can't get NAND status";
|
||||||
static uint32_t in_sram_address;
|
static uint32_t in_sram_address;
|
||||||
unsigned char sign_of_sequental_byte_read;
|
static unsigned char sign_of_sequental_byte_read;
|
||||||
|
|
||||||
static int test_iomux_settings (struct target * target, uint32_t value,
|
static int test_iomux_settings (struct target * target, uint32_t value,
|
||||||
uint32_t mask, const char *text);
|
uint32_t mask, const char *text);
|
||||||
@@ -61,7 +61,6 @@ static int do_data_output (struct nand_device *nand);
|
|||||||
|
|
||||||
static int imx31_command (struct nand_device *nand, uint8_t command);
|
static int imx31_command (struct nand_device *nand, uint8_t command);
|
||||||
static int imx31_address (struct nand_device *nand, uint8_t address);
|
static int imx31_address (struct nand_device *nand, uint8_t address);
|
||||||
static int imx31_controller_ready (struct nand_device *nand, int tout);
|
|
||||||
|
|
||||||
NAND_DEVICE_COMMAND_HANDLER(imx31_nand_device_command)
|
NAND_DEVICE_COMMAND_HANDLER(imx31_nand_device_command)
|
||||||
{
|
{
|
||||||
@@ -75,12 +74,6 @@ NAND_DEVICE_COMMAND_HANDLER(imx31_nand_device_command)
|
|||||||
|
|
||||||
nand->controller_priv = mx3_nf_info;
|
nand->controller_priv = mx3_nf_info;
|
||||||
|
|
||||||
mx3_nf_info->target = get_target (CMD_ARGV[1]);
|
|
||||||
if (mx3_nf_info->target == NULL)
|
|
||||||
{
|
|
||||||
LOG_ERROR ("target '%s' not defined", CMD_ARGV[1]);
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
if (CMD_ARGC < 3)
|
if (CMD_ARGC < 3)
|
||||||
{
|
{
|
||||||
LOG_ERROR ("use \"nand device imx31 target noecc|hwecc\"");
|
LOG_ERROR ("use \"nand device imx31 target noecc|hwecc\"");
|
||||||
@@ -105,9 +98,9 @@ NAND_DEVICE_COMMAND_HANDLER(imx31_nand_device_command)
|
|||||||
mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
|
mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
|
||||||
mx3_nf_info->fin = MX3_NF_FIN_NONE;
|
mx3_nf_info->fin = MX3_NF_FIN_NONE;
|
||||||
mx3_nf_info->flags.target_little_endian =
|
mx3_nf_info->flags.target_little_endian =
|
||||||
(mx3_nf_info->target->endianness == TARGET_LITTLE_ENDIAN);
|
(nand->target->endianness == TARGET_LITTLE_ENDIAN);
|
||||||
/*
|
/*
|
||||||
* testing host endianess
|
* testing host endianness
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
int x = 1;
|
int x = 1;
|
||||||
@@ -126,7 +119,7 @@ NAND_DEVICE_COMMAND_HANDLER(imx31_nand_device_command)
|
|||||||
static int imx31_init (struct nand_device *nand)
|
static int imx31_init (struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
||||||
struct target *target = mx3_nf_info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -268,8 +261,7 @@ static int imx31_init (struct nand_device *nand)
|
|||||||
|
|
||||||
static int imx31_read_data (struct nand_device *nand, void *data)
|
static int imx31_read_data (struct nand_device *nand, void *data)
|
||||||
{
|
{
|
||||||
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
struct target *target = nand->target;
|
||||||
struct target *target = mx3_nf_info->target;
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* validate target state
|
* validate target state
|
||||||
@@ -312,11 +304,6 @@ static int imx31_write_data (struct nand_device *nand, uint16_t data)
|
|||||||
return ERROR_NAND_OPERATION_FAILED;
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int imx31_nand_ready (struct nand_device *nand, int timeout)
|
|
||||||
{
|
|
||||||
return imx31_controller_ready (nand, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int imx31_reset (struct nand_device *nand)
|
static int imx31_reset (struct nand_device *nand)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -335,7 +322,7 @@ static int imx31_reset (struct nand_device *nand)
|
|||||||
static int imx31_command (struct nand_device *nand, uint8_t command)
|
static int imx31_command (struct nand_device *nand, uint8_t command)
|
||||||
{
|
{
|
||||||
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
||||||
struct target *target = mx3_nf_info->target;
|
struct target *target = nand->target;
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* validate target state
|
* validate target state
|
||||||
@@ -408,8 +395,7 @@ static int imx31_command (struct nand_device *nand, uint8_t command)
|
|||||||
|
|
||||||
static int imx31_address (struct nand_device *nand, uint8_t address)
|
static int imx31_address (struct nand_device *nand, uint8_t address)
|
||||||
{
|
{
|
||||||
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
struct target *target = nand->target;
|
||||||
struct target *target = mx3_nf_info->target;
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* validate target state
|
* validate target state
|
||||||
@@ -438,11 +424,10 @@ static int imx31_address (struct nand_device *nand, uint8_t address)
|
|||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int imx31_controller_ready (struct nand_device *nand, int tout)
|
static int imx31_nand_ready (struct nand_device *nand, int tout)
|
||||||
{
|
{
|
||||||
uint16_t poll_complete_status;
|
uint16_t poll_complete_status;
|
||||||
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
struct target *target = nand->target;
|
||||||
struct target *target = mx3_nf_info->target;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -474,7 +459,7 @@ static int imx31_write_page (struct nand_device *nand, uint32_t page,
|
|||||||
uint32_t oob_size)
|
uint32_t oob_size)
|
||||||
{
|
{
|
||||||
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
||||||
struct target *target = mx3_nf_info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (data_size % 2)
|
if (data_size % 2)
|
||||||
{
|
{
|
||||||
@@ -580,8 +565,7 @@ static int imx31_read_page (struct nand_device *nand, uint32_t page,
|
|||||||
uint8_t * data, uint32_t data_size, uint8_t * oob,
|
uint8_t * data, uint32_t data_size, uint8_t * oob,
|
||||||
uint32_t oob_size)
|
uint32_t oob_size)
|
||||||
{
|
{
|
||||||
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
struct target *target = nand->target;
|
||||||
struct target *target = mx3_nf_info->target;
|
|
||||||
|
|
||||||
if (data_size % 2)
|
if (data_size % 2)
|
||||||
{
|
{
|
||||||
@@ -656,7 +640,7 @@ static int test_iomux_settings (struct target * target, uint32_t address,
|
|||||||
static int initialize_nf_controller (struct nand_device *nand)
|
static int initialize_nf_controller (struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
||||||
struct target *target = mx3_nf_info->target;
|
struct target *target = nand->target;
|
||||||
/*
|
/*
|
||||||
* resets NAND flash controller in zero time ? I dont know.
|
* resets NAND flash controller in zero time ? I dont know.
|
||||||
*/
|
*/
|
||||||
@@ -784,7 +768,7 @@ static int poll_for_complete_op (struct target * target, const char *text)
|
|||||||
static int validate_target_state (struct nand_device *nand)
|
static int validate_target_state (struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
||||||
struct target *target = mx3_nf_info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
{
|
{
|
||||||
@@ -806,7 +790,7 @@ static int validate_target_state (struct nand_device *nand)
|
|||||||
static int do_data_output (struct nand_device *nand)
|
static int do_data_output (struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
|
||||||
struct target *target = mx3_nf_info->target;
|
struct target *target = nand->target;
|
||||||
switch (mx3_nf_info->fin)
|
switch (mx3_nf_info->fin)
|
||||||
{
|
{
|
||||||
case MX3_NF_FIN_DATAOUT:
|
case MX3_NF_FIN_DATAOUT:
|
||||||
@@ -876,6 +860,5 @@ struct nand_flash_controller imx31_nand_flash_controller = {
|
|||||||
.read_data = &imx31_read_data,
|
.read_data = &imx31_read_data,
|
||||||
.write_page = &imx31_write_page,
|
.write_page = &imx31_write_page,
|
||||||
.read_page = &imx31_read_page,
|
.read_page = &imx31_read_page,
|
||||||
.controller_ready = &imx31_controller_ready,
|
|
||||||
.nand_ready = &imx31_nand_ready,
|
.nand_ready = &imx31_nand_ready,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -109,7 +109,6 @@ struct mx3_nf_flags
|
|||||||
|
|
||||||
struct mx3_nf_controller
|
struct mx3_nf_controller
|
||||||
{
|
{
|
||||||
struct target *target;
|
|
||||||
enum mx_dataout_type optype;
|
enum mx_dataout_type optype;
|
||||||
enum mx_nf_finalize_action fin;
|
enum mx_nf_finalize_action fin;
|
||||||
struct mx3_nf_flags flags;
|
struct mx3_nf_flags flags;
|
||||||
|
|||||||
@@ -52,11 +52,6 @@ static int nonce_nand_reset(struct nand_device *nand)
|
|||||||
return nonce_nand_command(nand, NAND_CMD_RESET);
|
return nonce_nand_command(nand, NAND_CMD_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nonce_nand_controller_ready(struct nand_device *nand, int timeout)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
NAND_DEVICE_COMMAND_HANDLER(nonce_nand_device_command)
|
NAND_DEVICE_COMMAND_HANDLER(nonce_nand_device_command)
|
||||||
{
|
{
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
@@ -79,5 +74,4 @@ struct nand_flash_controller nonce_nand_controller =
|
|||||||
.read_data = &nonce_nand_read,
|
.read_data = &nonce_nand_read,
|
||||||
.write_data = &nonce_nand_write,
|
.write_data = &nonce_nand_write,
|
||||||
.write_block_data = &nonce_nand_fast_block_write,
|
.write_block_data = &nonce_nand_fast_block_write,
|
||||||
.controller_ready = &nonce_nand_controller_ready,
|
|
||||||
};
|
};
|
||||||
|
|||||||
226
src/flash/nand/nuc910.c
Normal file
226
src/flash/nand/nuc910.c
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010 by Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NAND controller interface for Nuvoton NUC910
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "imp.h"
|
||||||
|
#include "nuc910.h"
|
||||||
|
#include "arm_io.h"
|
||||||
|
#include <target/arm.h>
|
||||||
|
|
||||||
|
struct nuc910_nand_controller
|
||||||
|
{
|
||||||
|
struct arm_nand_data io;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int validate_target_state(struct nand_device *nand)
|
||||||
|
{
|
||||||
|
struct target *target = nand->target;
|
||||||
|
|
||||||
|
if (target->state != TARGET_HALTED) {
|
||||||
|
LOG_ERROR("Target not halted");
|
||||||
|
return ERROR_NAND_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nuc910_nand_command(struct nand_device *nand, uint8_t command)
|
||||||
|
{
|
||||||
|
struct target *target = nand->target;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if ((result = validate_target_state(nand)) != ERROR_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
target_write_u8(target, NUC910_SMCMD, command);
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nuc910_nand_address(struct nand_device *nand, uint8_t address)
|
||||||
|
{
|
||||||
|
struct target *target = nand->target;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if ((result = validate_target_state(nand)) != ERROR_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
target_write_u32(target, NUC910_SMADDR, ((address & 0xff) | NUC910_SMADDR_EOA));
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nuc910_nand_read(struct nand_device *nand, void *data)
|
||||||
|
{
|
||||||
|
struct target *target = nand->target;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if ((result = validate_target_state(nand)) != ERROR_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
target_read_u8(target, NUC910_SMDATA, data);
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nuc910_nand_write(struct nand_device *nand, uint16_t data)
|
||||||
|
{
|
||||||
|
struct target *target = nand->target;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if ((result = validate_target_state(nand)) != ERROR_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
target_write_u8(target, NUC910_SMDATA, data);
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nuc910_nand_read_block_data(struct nand_device *nand,
|
||||||
|
uint8_t *data, int data_size)
|
||||||
|
{
|
||||||
|
struct nuc910_nand_controller *nuc910_nand = nand->controller_priv;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if ((result = validate_target_state(nand)) != ERROR_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
nuc910_nand->io.chunk_size = nand->page_size;
|
||||||
|
|
||||||
|
/* try the fast way first */
|
||||||
|
result = arm_nandread(&nuc910_nand->io, data, data_size);
|
||||||
|
if (result != ERROR_NAND_NO_BUFFER)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* else do it slowly */
|
||||||
|
while (data_size--)
|
||||||
|
nuc910_nand_read(nand, data++);
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nuc910_nand_write_block_data(struct nand_device *nand,
|
||||||
|
uint8_t *data, int data_size)
|
||||||
|
{
|
||||||
|
struct nuc910_nand_controller *nuc910_nand = nand->controller_priv;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if ((result = validate_target_state(nand)) != ERROR_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
nuc910_nand->io.chunk_size = nand->page_size;
|
||||||
|
|
||||||
|
/* try the fast way first */
|
||||||
|
result = arm_nandwrite(&nuc910_nand->io, data, data_size);
|
||||||
|
if (result != ERROR_NAND_NO_BUFFER)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* else do it slowly */
|
||||||
|
while (data_size--)
|
||||||
|
nuc910_nand_write(nand, *data++);
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nuc910_nand_reset(struct nand_device *nand)
|
||||||
|
{
|
||||||
|
return nuc910_nand_command(nand, NAND_CMD_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nuc910_nand_ready(struct nand_device *nand, int timeout)
|
||||||
|
{
|
||||||
|
struct target *target = nand->target;
|
||||||
|
uint32_t status;
|
||||||
|
|
||||||
|
do {
|
||||||
|
target_read_u32(target, NUC910_SMISR, &status);
|
||||||
|
if (status & NUC910_SMISR_RB_) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
alive_sleep(1);
|
||||||
|
} while (timeout-- > 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NAND_DEVICE_COMMAND_HANDLER(nuc910_nand_device_command)
|
||||||
|
{
|
||||||
|
struct nuc910_nand_controller *nuc910_nand;
|
||||||
|
|
||||||
|
nuc910_nand = calloc(1, sizeof(struct nuc910_nand_controller));
|
||||||
|
if (!nuc910_nand) {
|
||||||
|
LOG_ERROR("no memory for nand controller");
|
||||||
|
return ERROR_NAND_DEVICE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
nand->controller_priv = nuc910_nand;
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nuc910_nand_init(struct nand_device *nand)
|
||||||
|
{
|
||||||
|
struct nuc910_nand_controller *nuc910_nand = nand->controller_priv;
|
||||||
|
struct target *target = nand->target;
|
||||||
|
int bus_width = nand->bus_width ? : 8;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if ((result = validate_target_state(nand)) != ERROR_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* nuc910 only supports 8bit */
|
||||||
|
if (bus_width != 8)
|
||||||
|
{
|
||||||
|
LOG_ERROR("nuc910 only supports 8 bit bus width, not %i", bus_width);
|
||||||
|
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* inform calling code about selected bus width */
|
||||||
|
nand->bus_width = bus_width;
|
||||||
|
|
||||||
|
nuc910_nand->io.target = target;
|
||||||
|
nuc910_nand->io.data = NUC910_SMDATA;
|
||||||
|
nuc910_nand->io.op = ARM_NAND_NONE;
|
||||||
|
|
||||||
|
/* configure nand controller */
|
||||||
|
target_write_u32(target, NUC910_FMICSR, NUC910_FMICSR_SM_EN);
|
||||||
|
target_write_u32(target, NUC910_SMCSR, 0x010000a8); /* 2048 page size */
|
||||||
|
target_write_u32(target, NUC910_SMTCR, 0x00010204);
|
||||||
|
target_write_u32(target, NUC910_SMIER, 0x00000000);
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct nand_flash_controller nuc910_nand_controller =
|
||||||
|
{
|
||||||
|
.name = "nuc910",
|
||||||
|
.command = nuc910_nand_command,
|
||||||
|
.address = nuc910_nand_address,
|
||||||
|
.read_data = nuc910_nand_read,
|
||||||
|
.write_data = nuc910_nand_write,
|
||||||
|
.write_block_data = nuc910_nand_write_block_data,
|
||||||
|
.read_block_data = nuc910_nand_read_block_data,
|
||||||
|
.nand_ready = nuc910_nand_ready,
|
||||||
|
.reset = nuc910_nand_reset,
|
||||||
|
.nand_device_command = nuc910_nand_device_command,
|
||||||
|
.init = nuc910_nand_init,
|
||||||
|
};
|
||||||
60
src/flash/nand/nuc910.h
Normal file
60
src/flash/nand/nuc910.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010 by Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NAND controller interface for Nuvoton NUC910
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NUC910_H
|
||||||
|
#define NUC910_H
|
||||||
|
|
||||||
|
#define NUC910_FMICSR 0xB000D000
|
||||||
|
#define NUC910_SMCSR 0xB000D0A0
|
||||||
|
#define NUC910_SMTCR 0xB000D0A4
|
||||||
|
#define NUC910_SMIER 0xB000D0A8
|
||||||
|
#define NUC910_SMISR 0xB000D0AC
|
||||||
|
#define NUC910_SMCMD 0xB000D0B0
|
||||||
|
#define NUC910_SMADDR 0xB000D0B4
|
||||||
|
#define NUC910_SMDATA 0xB000D0B8
|
||||||
|
|
||||||
|
#define NUC910_SMECC0 0xB000D0BC
|
||||||
|
#define NUC910_SMECC1 0xB000D0C0
|
||||||
|
#define NUC910_SMECC2 0xB000D0C4
|
||||||
|
#define NUC910_SMECC3 0xB000D0C8
|
||||||
|
#define NUC910_ECC4ST 0xB000D114
|
||||||
|
|
||||||
|
/* Global Control and Status Register (FMICSR) */
|
||||||
|
#define NUC910_FMICSR_SM_EN (1<<3)
|
||||||
|
|
||||||
|
/* NAND Flash Address Port Register (SMADDR) */
|
||||||
|
#define NUC910_SMADDR_EOA (1<<31)
|
||||||
|
|
||||||
|
/* NAND Flash Control and Status Register (SMCSR) */
|
||||||
|
#define NUC910_SMCSR_PSIZE (1<<3)
|
||||||
|
#define NUC910_SMCSR_DBW (1<<4)
|
||||||
|
|
||||||
|
/* NAND Flash Interrupt Status Register (SMISR) */
|
||||||
|
#define NUC910_SMISR_ECC_IF (1<<2)
|
||||||
|
#define NUC910_SMISR_RB_ (1<<18)
|
||||||
|
|
||||||
|
/* ECC4 Correction Status (ECC4ST) */
|
||||||
|
|
||||||
|
#endif /* NUC910_H */
|
||||||
|
|
||||||
@@ -33,8 +33,6 @@
|
|||||||
|
|
||||||
struct orion_nand_controller
|
struct orion_nand_controller
|
||||||
{
|
{
|
||||||
struct target *target;
|
|
||||||
|
|
||||||
struct arm_nand_data io;
|
struct arm_nand_data io;
|
||||||
|
|
||||||
uint32_t cmd;
|
uint32_t cmd;
|
||||||
@@ -53,7 +51,7 @@ struct orion_nand_controller
|
|||||||
static int orion_nand_command(struct nand_device *nand, uint8_t command)
|
static int orion_nand_command(struct nand_device *nand, uint8_t command)
|
||||||
{
|
{
|
||||||
struct orion_nand_controller *hw = nand->controller_priv;
|
struct orion_nand_controller *hw = nand->controller_priv;
|
||||||
struct target *target = hw->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
CHECK_HALTED;
|
CHECK_HALTED;
|
||||||
target_write_u8(target, hw->cmd, command);
|
target_write_u8(target, hw->cmd, command);
|
||||||
@@ -63,7 +61,7 @@ static int orion_nand_command(struct nand_device *nand, uint8_t command)
|
|||||||
static int orion_nand_address(struct nand_device *nand, uint8_t address)
|
static int orion_nand_address(struct nand_device *nand, uint8_t address)
|
||||||
{
|
{
|
||||||
struct orion_nand_controller *hw = nand->controller_priv;
|
struct orion_nand_controller *hw = nand->controller_priv;
|
||||||
struct target *target = hw->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
CHECK_HALTED;
|
CHECK_HALTED;
|
||||||
target_write_u8(target, hw->addr, address);
|
target_write_u8(target, hw->addr, address);
|
||||||
@@ -73,7 +71,7 @@ static int orion_nand_address(struct nand_device *nand, uint8_t address)
|
|||||||
static int orion_nand_read(struct nand_device *nand, void *data)
|
static int orion_nand_read(struct nand_device *nand, void *data)
|
||||||
{
|
{
|
||||||
struct orion_nand_controller *hw = nand->controller_priv;
|
struct orion_nand_controller *hw = nand->controller_priv;
|
||||||
struct target *target = hw->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
CHECK_HALTED;
|
CHECK_HALTED;
|
||||||
target_read_u8(target, hw->data, data);
|
target_read_u8(target, hw->data, data);
|
||||||
@@ -83,7 +81,7 @@ static int orion_nand_read(struct nand_device *nand, void *data)
|
|||||||
static int orion_nand_write(struct nand_device *nand, uint16_t data)
|
static int orion_nand_write(struct nand_device *nand, uint16_t data)
|
||||||
{
|
{
|
||||||
struct orion_nand_controller *hw = nand->controller_priv;
|
struct orion_nand_controller *hw = nand->controller_priv;
|
||||||
struct target *target = hw->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
CHECK_HALTED;
|
CHECK_HALTED;
|
||||||
target_write_u8(target, hw->data, data);
|
target_write_u8(target, hw->data, data);
|
||||||
@@ -116,11 +114,6 @@ static int orion_nand_reset(struct nand_device *nand)
|
|||||||
return orion_nand_command(nand, NAND_CMD_RESET);
|
return orion_nand_command(nand, NAND_CMD_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int orion_nand_controller_ready(struct nand_device *nand, int timeout)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
NAND_DEVICE_COMMAND_HANDLER(orion_nand_device_command)
|
NAND_DEVICE_COMMAND_HANDLER(orion_nand_device_command)
|
||||||
{
|
{
|
||||||
struct orion_nand_controller *hw;
|
struct orion_nand_controller *hw;
|
||||||
@@ -128,23 +121,17 @@ NAND_DEVICE_COMMAND_HANDLER(orion_nand_device_command)
|
|||||||
uint8_t ale, cle;
|
uint8_t ale, cle;
|
||||||
|
|
||||||
if (CMD_ARGC != 3) {
|
if (CMD_ARGC != 3) {
|
||||||
LOG_ERROR("arguments must be: <target_id> <NAND_address>\n");
|
LOG_ERROR("arguments must be: <target_id> <NAND_address>");
|
||||||
return ERROR_NAND_DEVICE_INVALID;
|
return ERROR_NAND_DEVICE_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
hw = calloc(1, sizeof(*hw));
|
hw = calloc(1, sizeof(*hw));
|
||||||
if (!hw) {
|
if (!hw) {
|
||||||
LOG_ERROR("no memory for nand controller\n");
|
LOG_ERROR("no memory for nand controller");
|
||||||
return ERROR_NAND_DEVICE_INVALID;
|
return ERROR_NAND_DEVICE_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
nand->controller_priv = hw;
|
nand->controller_priv = hw;
|
||||||
hw->target = get_target(CMD_ARGV[1]);
|
|
||||||
if (!hw->target) {
|
|
||||||
LOG_ERROR("target '%s' not defined", CMD_ARGV[1]);
|
|
||||||
free(hw);
|
|
||||||
return ERROR_NAND_DEVICE_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], base);
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], base);
|
||||||
cle = 0;
|
cle = 0;
|
||||||
@@ -154,7 +141,7 @@ NAND_DEVICE_COMMAND_HANDLER(orion_nand_device_command)
|
|||||||
hw->cmd = base + (1 << cle);
|
hw->cmd = base + (1 << cle);
|
||||||
hw->addr = base + (1 << ale);
|
hw->addr = base + (1 << ale);
|
||||||
|
|
||||||
hw->io.target = hw->target;
|
hw->io.target = nand->target;
|
||||||
hw->io.data = hw->data;
|
hw->io.data = hw->data;
|
||||||
hw->io.op = ARM_NAND_NONE;
|
hw->io.op = ARM_NAND_NONE;
|
||||||
|
|
||||||
@@ -175,7 +162,6 @@ struct nand_flash_controller orion_nand_controller =
|
|||||||
.write_data = orion_nand_write,
|
.write_data = orion_nand_write,
|
||||||
.write_block_data = orion_nand_fast_block_write,
|
.write_block_data = orion_nand_fast_block_write,
|
||||||
.reset = orion_nand_reset,
|
.reset = orion_nand_reset,
|
||||||
.controller_ready = orion_nand_controller_ready,
|
|
||||||
.nand_device_command = orion_nand_device_command,
|
.nand_device_command = orion_nand_device_command,
|
||||||
.init = orion_nand_init,
|
.init = orion_nand_init,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,8 +46,7 @@ NAND_DEVICE_COMMAND_HANDLER(s3c2410_nand_device_command)
|
|||||||
|
|
||||||
static int s3c2410_init(struct nand_device *nand)
|
static int s3c2410_init(struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct target *target = nand->target;
|
||||||
struct target *target = s3c24xx_info->target;
|
|
||||||
|
|
||||||
target_write_u32(target, S3C2410_NFCONF,
|
target_write_u32(target, S3C2410_NFCONF,
|
||||||
S3C2410_NFCONF_EN | S3C2410_NFCONF_TACLS(3) |
|
S3C2410_NFCONF_EN | S3C2410_NFCONF_TACLS(3) |
|
||||||
@@ -58,8 +57,7 @@ static int s3c2410_init(struct nand_device *nand)
|
|||||||
|
|
||||||
static int s3c2410_write_data(struct nand_device *nand, uint16_t data)
|
static int s3c2410_write_data(struct nand_device *nand, uint16_t data)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct target *target = nand->target;
|
||||||
struct target *target = s3c24xx_info->target;
|
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
||||||
@@ -72,8 +70,7 @@ static int s3c2410_write_data(struct nand_device *nand, uint16_t data)
|
|||||||
|
|
||||||
static int s3c2410_read_data(struct nand_device *nand, void *data)
|
static int s3c2410_read_data(struct nand_device *nand, void *data)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct target *target = nand->target;
|
||||||
struct target *target = s3c24xx_info->target;
|
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
||||||
@@ -86,8 +83,7 @@ static int s3c2410_read_data(struct nand_device *nand, void *data)
|
|||||||
|
|
||||||
static int s3c2410_nand_ready(struct nand_device *nand, int timeout)
|
static int s3c2410_nand_ready(struct nand_device *nand, int timeout)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct target *target = nand->target;
|
||||||
struct target *target = s3c24xx_info->target;
|
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
@@ -118,6 +114,5 @@ struct nand_flash_controller s3c2410_nand_controller = {
|
|||||||
.read_data = &s3c2410_read_data,
|
.read_data = &s3c2410_read_data,
|
||||||
.write_page = s3c24xx_write_page,
|
.write_page = s3c24xx_write_page,
|
||||||
.read_page = s3c24xx_read_page,
|
.read_page = s3c24xx_read_page,
|
||||||
.controller_ready = &s3c24xx_controller_ready,
|
|
||||||
.nand_ready = &s3c2410_nand_ready,
|
.nand_ready = &s3c2410_nand_ready,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,8 +46,7 @@ NAND_DEVICE_COMMAND_HANDLER(s3c2412_nand_device_command)
|
|||||||
|
|
||||||
static int s3c2412_init(struct nand_device *nand)
|
static int s3c2412_init(struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct target *target = nand->target;
|
||||||
struct target *target = s3c24xx_info->target;
|
|
||||||
|
|
||||||
target_write_u32(target, S3C2410_NFCONF,
|
target_write_u32(target, S3C2410_NFCONF,
|
||||||
S3C2440_NFCONF_TACLS(3) |
|
S3C2440_NFCONF_TACLS(3) |
|
||||||
@@ -74,6 +73,5 @@ struct nand_flash_controller s3c2412_nand_controller = {
|
|||||||
.read_page = s3c24xx_read_page,
|
.read_page = s3c24xx_read_page,
|
||||||
.write_block_data = &s3c2440_write_block_data,
|
.write_block_data = &s3c2440_write_block_data,
|
||||||
.read_block_data = &s3c2440_read_block_data,
|
.read_block_data = &s3c2440_read_block_data,
|
||||||
.controller_ready = &s3c24xx_controller_ready,
|
|
||||||
.nand_ready = &s3c2440_nand_ready,
|
.nand_ready = &s3c2440_nand_ready,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -47,8 +47,7 @@ NAND_DEVICE_COMMAND_HANDLER(s3c2440_nand_device_command)
|
|||||||
|
|
||||||
static int s3c2440_init(struct nand_device *nand)
|
static int s3c2440_init(struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct target *target = nand->target;
|
||||||
struct target *target = s3c24xx_info->target;
|
|
||||||
|
|
||||||
target_write_u32(target, S3C2410_NFCONF,
|
target_write_u32(target, S3C2410_NFCONF,
|
||||||
S3C2440_NFCONF_TACLS(3) |
|
S3C2440_NFCONF_TACLS(3) |
|
||||||
@@ -64,7 +63,7 @@ static int s3c2440_init(struct nand_device *nand)
|
|||||||
int s3c2440_nand_ready(struct nand_device *nand, int timeout)
|
int s3c2440_nand_ready(struct nand_device *nand, int timeout)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
||||||
struct target *target = s3c24xx_info->target;
|
struct target *target = nand->target;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
@@ -90,11 +89,11 @@ int s3c2440_nand_ready(struct nand_device *nand, int timeout)
|
|||||||
int s3c2440_read_block_data(struct nand_device *nand, uint8_t *data, int data_size)
|
int s3c2440_read_block_data(struct nand_device *nand, uint8_t *data, int data_size)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
||||||
struct target *target = s3c24xx_info->target;
|
struct target *target = nand->target;
|
||||||
uint32_t nfdata = s3c24xx_info->data;
|
uint32_t nfdata = s3c24xx_info->data;
|
||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
|
|
||||||
LOG_INFO("%s: reading data: %p, %p, %d\n", __func__, nand, data, data_size);
|
LOG_INFO("%s: reading data: %p, %p, %d", __func__, nand, data, data_size);
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
||||||
@@ -126,7 +125,7 @@ int s3c2440_read_block_data(struct nand_device *nand, uint8_t *data, int data_si
|
|||||||
int s3c2440_write_block_data(struct nand_device *nand, uint8_t *data, int data_size)
|
int s3c2440_write_block_data(struct nand_device *nand, uint8_t *data, int data_size)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
||||||
struct target *target = s3c24xx_info->target;
|
struct target *target = nand->target;
|
||||||
uint32_t nfdata = s3c24xx_info->data;
|
uint32_t nfdata = s3c24xx_info->data;
|
||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
|
|
||||||
@@ -166,6 +165,5 @@ struct nand_flash_controller s3c2440_nand_controller = {
|
|||||||
.read_page = s3c24xx_read_page,
|
.read_page = s3c24xx_read_page,
|
||||||
.write_block_data = &s3c2440_write_block_data,
|
.write_block_data = &s3c2440_write_block_data,
|
||||||
.read_block_data = &s3c2440_read_block_data,
|
.read_block_data = &s3c2440_read_block_data,
|
||||||
.controller_ready = &s3c24xx_controller_ready,
|
|
||||||
.nand_ready = &s3c2440_nand_ready,
|
.nand_ready = &s3c2440_nand_ready,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -47,8 +47,7 @@ NAND_DEVICE_COMMAND_HANDLER(s3c2443_nand_device_command)
|
|||||||
|
|
||||||
static int s3c2443_init(struct nand_device *nand)
|
static int s3c2443_init(struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct target *target = nand->target;
|
||||||
struct target *target = s3c24xx_info->target;
|
|
||||||
|
|
||||||
target_write_u32(target, S3C2410_NFCONF,
|
target_write_u32(target, S3C2410_NFCONF,
|
||||||
S3C2440_NFCONF_TACLS(3) |
|
S3C2440_NFCONF_TACLS(3) |
|
||||||
@@ -75,6 +74,5 @@ struct nand_flash_controller s3c2443_nand_controller = {
|
|||||||
.read_page = s3c24xx_read_page,
|
.read_page = s3c24xx_read_page,
|
||||||
.write_block_data = &s3c2440_write_block_data,
|
.write_block_data = &s3c2440_write_block_data,
|
||||||
.read_block_data = &s3c2440_read_block_data,
|
.read_block_data = &s3c2440_read_block_data,
|
||||||
.controller_ready = &s3c24xx_controller_ready,
|
|
||||||
.nand_ready = &s3c2440_nand_ready,
|
.nand_ready = &s3c2440_nand_ready,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -38,18 +38,11 @@ S3C24XX_DEVICE_COMMAND()
|
|||||||
struct s3c24xx_nand_controller *s3c24xx_info;
|
struct s3c24xx_nand_controller *s3c24xx_info;
|
||||||
s3c24xx_info = malloc(sizeof(struct s3c24xx_nand_controller));
|
s3c24xx_info = malloc(sizeof(struct s3c24xx_nand_controller));
|
||||||
if (s3c24xx_info == NULL) {
|
if (s3c24xx_info == NULL) {
|
||||||
LOG_ERROR("no memory for nand controller\n");
|
LOG_ERROR("no memory for nand controller");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
nand->controller_priv = s3c24xx_info;
|
nand->controller_priv = s3c24xx_info;
|
||||||
|
|
||||||
s3c24xx_info->target = get_target(CMD_ARGV[1]);
|
|
||||||
if (s3c24xx_info->target == NULL) {
|
|
||||||
LOG_ERROR("target '%s' not defined", CMD_ARGV[1]);
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
*info = s3c24xx_info;
|
*info = s3c24xx_info;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
@@ -58,7 +51,7 @@ S3C24XX_DEVICE_COMMAND()
|
|||||||
int s3c24xx_reset(struct nand_device *nand)
|
int s3c24xx_reset(struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
||||||
struct target *target = s3c24xx_info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
||||||
@@ -73,7 +66,7 @@ int s3c24xx_reset(struct nand_device *nand)
|
|||||||
int s3c24xx_command(struct nand_device *nand, uint8_t command)
|
int s3c24xx_command(struct nand_device *nand, uint8_t command)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
||||||
struct target *target = s3c24xx_info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
||||||
@@ -88,7 +81,7 @@ int s3c24xx_command(struct nand_device *nand, uint8_t command)
|
|||||||
int s3c24xx_address(struct nand_device *nand, uint8_t address)
|
int s3c24xx_address(struct nand_device *nand, uint8_t address)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
||||||
struct target *target = s3c24xx_info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
||||||
@@ -102,7 +95,7 @@ int s3c24xx_address(struct nand_device *nand, uint8_t address)
|
|||||||
int s3c24xx_write_data(struct nand_device *nand, uint16_t data)
|
int s3c24xx_write_data(struct nand_device *nand, uint16_t data)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
||||||
struct target *target = s3c24xx_info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
||||||
@@ -116,7 +109,7 @@ int s3c24xx_write_data(struct nand_device *nand, uint16_t data)
|
|||||||
int s3c24xx_read_data(struct nand_device *nand, void *data)
|
int s3c24xx_read_data(struct nand_device *nand, void *data)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
||||||
struct target *target = s3c24xx_info->target;
|
struct target *target = nand->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
|
||||||
@@ -126,8 +119,3 @@ int s3c24xx_read_data(struct nand_device *nand, void *data)
|
|||||||
target_read_u8(target, s3c24xx_info->data, data);
|
target_read_u8(target, s3c24xx_info->data, data);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int s3c24xx_controller_ready(struct nand_device *nand, int timeout)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -33,8 +33,6 @@
|
|||||||
|
|
||||||
struct s3c24xx_nand_controller
|
struct s3c24xx_nand_controller
|
||||||
{
|
{
|
||||||
struct target *target;
|
|
||||||
|
|
||||||
/* register addresses */
|
/* register addresses */
|
||||||
uint32_t cmd;
|
uint32_t cmd;
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
@@ -68,8 +66,6 @@ int s3c24xx_address(struct nand_device *nand, uint8_t address);
|
|||||||
int s3c24xx_write_data(struct nand_device *nand, uint16_t data);
|
int s3c24xx_write_data(struct nand_device *nand, uint16_t data);
|
||||||
int s3c24xx_read_data(struct nand_device *nand, void *data);
|
int s3c24xx_read_data(struct nand_device *nand, void *data);
|
||||||
|
|
||||||
int s3c24xx_controller_ready(struct nand_device *nand, int tout);
|
|
||||||
|
|
||||||
#define s3c24xx_write_page NULL
|
#define s3c24xx_write_page NULL
|
||||||
#define s3c24xx_read_page NULL
|
#define s3c24xx_read_page NULL
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,7 @@ NAND_DEVICE_COMMAND_HANDLER(s3c6400_nand_device_command)
|
|||||||
|
|
||||||
static int s3c6400_init(struct nand_device *nand)
|
static int s3c6400_init(struct nand_device *nand)
|
||||||
{
|
{
|
||||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
struct target *target = nand->target;
|
||||||
struct target *target = s3c24xx_info->target;
|
|
||||||
|
|
||||||
target_write_u32(target, S3C2410_NFCONF,
|
target_write_u32(target, S3C2410_NFCONF,
|
||||||
S3C2440_NFCONF_TACLS(3) |
|
S3C2440_NFCONF_TACLS(3) |
|
||||||
@@ -71,6 +70,5 @@ struct nand_flash_controller s3c6400_nand_controller = {
|
|||||||
.read_page = s3c24xx_read_page,
|
.read_page = s3c24xx_read_page,
|
||||||
.write_block_data = &s3c2440_write_block_data,
|
.write_block_data = &s3c2440_write_block_data,
|
||||||
.read_block_data = &s3c2440_read_block_data,
|
.read_block_data = &s3c2440_read_block_data,
|
||||||
.controller_ready = &s3c24xx_controller_ready,
|
|
||||||
.nand_ready = &s3c2440_nand_ready,
|
.nand_ready = &s3c2440_nand_ready,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "imp.h"
|
#include "imp.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
|
#include <target/target.h>
|
||||||
|
|
||||||
// to be removed
|
// to be removed
|
||||||
extern struct nand_device *nand_devices;
|
extern struct nand_device *nand_devices;
|
||||||
@@ -147,18 +148,11 @@ COMMAND_HANDLER(handle_nand_probe_command)
|
|||||||
|
|
||||||
if ((retval = nand_probe(p)) == ERROR_OK)
|
if ((retval = nand_probe(p)) == ERROR_OK)
|
||||||
{
|
{
|
||||||
command_print(CMD_CTX, "NAND flash device '%s' found", p->device->name);
|
command_print(CMD_CTX, "NAND flash device '%s (%s)' found",
|
||||||
}
|
p->device->name, p->manufacturer->name);
|
||||||
else if (retval == ERROR_NAND_OPERATION_FAILED)
|
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "probing failed for NAND flash device");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "unknown error when probing NAND flash device");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_nand_erase_command)
|
COMMAND_HANDLER(handle_nand_erase_command)
|
||||||
@@ -205,16 +199,8 @@ COMMAND_HANDLER(handle_nand_erase_command)
|
|||||||
offset, offset + length,
|
offset, offset + length,
|
||||||
CMD_ARGV[0], p->device->name);
|
CMD_ARGV[0], p->device->name);
|
||||||
}
|
}
|
||||||
else if (retval == ERROR_NAND_OPERATION_FAILED)
|
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "erase failed");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "unknown error when erasing NAND flash device");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
|
COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
|
||||||
@@ -260,18 +246,8 @@ COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
|
|||||||
command_print(CMD_CTX, "checked NAND flash device for bad blocks, "
|
command_print(CMD_CTX, "checked NAND flash device for bad blocks, "
|
||||||
"use \"nand info\" command to list blocks");
|
"use \"nand info\" command to list blocks");
|
||||||
}
|
}
|
||||||
else if (retval == ERROR_NAND_OPERATION_FAILED)
|
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "error when checking for bad blocks on "
|
|
||||||
"NAND flash device");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
command_print(CMD_CTX, "unknown error when checking for bad "
|
|
||||||
"blocks on NAND flash device");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_nand_write_command)
|
COMMAND_HANDLER(handle_nand_write_command)
|
||||||
@@ -309,7 +285,7 @@ COMMAND_HANDLER(handle_nand_write_command)
|
|||||||
if (nand_fileio_finish(&s))
|
if (nand_fileio_finish(&s))
|
||||||
{
|
{
|
||||||
command_print(CMD_CTX, "wrote file %s to NAND flash %s up to "
|
command_print(CMD_CTX, "wrote file %s to NAND flash %s up to "
|
||||||
"offset 0x%8.8" PRIx32 " in %fs (%0.3f kb/s)",
|
"offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
|
||||||
CMD_ARGV[1], CMD_ARGV[0], s.address, duration_elapsed(&s.bench),
|
CMD_ARGV[1], CMD_ARGV[0], s.address, duration_elapsed(&s.bench),
|
||||||
duration_kbps(&s.bench, total_bytes));
|
duration_kbps(&s.bench, total_bytes));
|
||||||
}
|
}
|
||||||
@@ -336,13 +312,14 @@ COMMAND_HANDLER(handle_nand_verify_command)
|
|||||||
|
|
||||||
while (file.size > 0)
|
while (file.size > 0)
|
||||||
{
|
{
|
||||||
int retval = nand_read_page(nand, dev.address / dev.page_size,
|
retval = nand_read_page(nand, dev.address / dev.page_size,
|
||||||
dev.page, dev.page_size, dev.oob, dev.oob_size);
|
dev.page, dev.page_size, dev.oob, dev.oob_size);
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
{
|
{
|
||||||
command_print(CMD_CTX, "reading NAND flash page failed");
|
command_print(CMD_CTX, "reading NAND flash page failed");
|
||||||
nand_fileio_cleanup(&dev);
|
nand_fileio_cleanup(&dev);
|
||||||
return nand_fileio_cleanup(&file);
|
nand_fileio_cleanup(&file);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bytes_read = nand_fileio_read(nand, &file);
|
int bytes_read = nand_fileio_read(nand, &file);
|
||||||
@@ -350,7 +327,8 @@ COMMAND_HANDLER(handle_nand_verify_command)
|
|||||||
{
|
{
|
||||||
command_print(CMD_CTX, "error while reading file");
|
command_print(CMD_CTX, "error while reading file");
|
||||||
nand_fileio_cleanup(&dev);
|
nand_fileio_cleanup(&dev);
|
||||||
return nand_fileio_cleanup(&file);
|
nand_fileio_cleanup(&file);
|
||||||
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dev.page && memcmp(dev.page, file.page, dev.page_size)) ||
|
if ((dev.page && memcmp(dev.page, file.page, dev.page_size)) ||
|
||||||
@@ -359,7 +337,8 @@ COMMAND_HANDLER(handle_nand_verify_command)
|
|||||||
command_print(CMD_CTX, "NAND flash contents differ "
|
command_print(CMD_CTX, "NAND flash contents differ "
|
||||||
"at 0x%8.8" PRIx32, dev.address);
|
"at 0x%8.8" PRIx32, dev.address);
|
||||||
nand_fileio_cleanup(&dev);
|
nand_fileio_cleanup(&dev);
|
||||||
return nand_fileio_cleanup(&file);
|
nand_fileio_cleanup(&file);
|
||||||
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
file.size -= bytes_read;
|
file.size -= bytes_read;
|
||||||
@@ -369,7 +348,7 @@ COMMAND_HANDLER(handle_nand_verify_command)
|
|||||||
if (nand_fileio_finish(&file) == ERROR_OK)
|
if (nand_fileio_finish(&file) == ERROR_OK)
|
||||||
{
|
{
|
||||||
command_print(CMD_CTX, "verified file %s in NAND flash %s "
|
command_print(CMD_CTX, "verified file %s in NAND flash %s "
|
||||||
"up to offset 0x%8.8" PRIx32 " in %fs (%0.3f kb/s)",
|
"up to offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
|
||||||
CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench),
|
CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench),
|
||||||
duration_kbps(&file.bench, dev.size));
|
duration_kbps(&file.bench, dev.size));
|
||||||
}
|
}
|
||||||
@@ -379,6 +358,7 @@ COMMAND_HANDLER(handle_nand_verify_command)
|
|||||||
|
|
||||||
COMMAND_HANDLER(handle_nand_dump_command)
|
COMMAND_HANDLER(handle_nand_dump_command)
|
||||||
{
|
{
|
||||||
|
int filesize;
|
||||||
struct nand_device *nand = NULL;
|
struct nand_device *nand = NULL;
|
||||||
struct nand_fileio_state s;
|
struct nand_fileio_state s;
|
||||||
int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
|
int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
|
||||||
@@ -389,12 +369,13 @@ COMMAND_HANDLER(handle_nand_dump_command)
|
|||||||
while (s.size > 0)
|
while (s.size > 0)
|
||||||
{
|
{
|
||||||
size_t size_written;
|
size_t size_written;
|
||||||
int retval = nand_read_page(nand, s.address / nand->page_size,
|
retval = nand_read_page(nand, s.address / nand->page_size,
|
||||||
s.page, s.page_size, s.oob, s.oob_size);
|
s.page, s.page_size, s.oob, s.oob_size);
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
{
|
{
|
||||||
command_print(CMD_CTX, "reading NAND flash page failed");
|
command_print(CMD_CTX, "reading NAND flash page failed");
|
||||||
return nand_fileio_cleanup(&s);
|
nand_fileio_cleanup(&s);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL != s.page)
|
if (NULL != s.page)
|
||||||
@@ -407,11 +388,15 @@ COMMAND_HANDLER(handle_nand_dump_command)
|
|||||||
s.address += nand->page_size;
|
s.address += nand->page_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retval = fileio_size(&s.fileio, &filesize);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
if (nand_fileio_finish(&s) == ERROR_OK)
|
if (nand_fileio_finish(&s) == ERROR_OK)
|
||||||
{
|
{
|
||||||
command_print(CMD_CTX, "dumped %ld bytes in %fs (%0.3f kb/s)",
|
command_print(CMD_CTX, "dumped %ld bytes in %fs (%0.3f KiB/s)",
|
||||||
(long)s.fileio.size, duration_elapsed(&s.bench),
|
(long)filesize, duration_elapsed(&s.bench),
|
||||||
duration_kbps(&s.bench, s.fileio.size));
|
duration_kbps(&s.bench, filesize));
|
||||||
}
|
}
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
@@ -512,7 +497,7 @@ static const struct command_registration nand_exec_command_handlers[] = {
|
|||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
int nand_init(struct command_context *cmd_ctx)
|
static int nand_init(struct command_context *cmd_ctx)
|
||||||
{
|
{
|
||||||
if (!nand_devices)
|
if (!nand_devices)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
@@ -536,12 +521,14 @@ COMMAND_HANDLER(handle_nand_init_command)
|
|||||||
LOG_DEBUG("Initializing NAND devices...");
|
LOG_DEBUG("Initializing NAND devices...");
|
||||||
return nand_init(CMD_CTX);
|
return nand_init(CMD_CTX);
|
||||||
}
|
}
|
||||||
int nand_list_walker(struct nand_flash_controller *c, void *x)
|
|
||||||
|
static int nand_list_walker(struct nand_flash_controller *c, void *x)
|
||||||
{
|
{
|
||||||
struct command_context *cmd_ctx = (struct command_context *)x;
|
struct command_context *cmd_ctx = (struct command_context *)x;
|
||||||
command_print(cmd_ctx, " %s", c->name);
|
command_print(cmd_ctx, " %s", c->name);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_nand_list_drivers)
|
COMMAND_HANDLER(handle_nand_list_drivers)
|
||||||
{
|
{
|
||||||
command_print(CMD_CTX, "Available NAND flash controller drivers:");
|
command_print(CMD_CTX, "Available NAND flash controller drivers:");
|
||||||
@@ -551,16 +538,37 @@ COMMAND_HANDLER(handle_nand_list_drivers)
|
|||||||
static COMMAND_HELPER(create_nand_device, const char *bank_name,
|
static COMMAND_HELPER(create_nand_device, const char *bank_name,
|
||||||
struct nand_flash_controller *controller)
|
struct nand_flash_controller *controller)
|
||||||
{
|
{
|
||||||
|
struct nand_device *c;
|
||||||
|
struct target *target;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
if (CMD_ARGC < 2)
|
||||||
|
{
|
||||||
|
LOG_ERROR("missing target");
|
||||||
|
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||||
|
}
|
||||||
|
target = get_target(CMD_ARGV[1]);
|
||||||
|
if (!target) {
|
||||||
|
LOG_ERROR("invalid target %s", CMD_ARGV[1]);
|
||||||
|
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
if (NULL != controller->commands)
|
if (NULL != controller->commands)
|
||||||
{
|
{
|
||||||
int retval = register_commands(CMD_CTX, NULL,
|
retval = register_commands(CMD_CTX, NULL,
|
||||||
controller->commands);
|
controller->commands);
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
struct nand_device *c = malloc(sizeof(struct nand_device));
|
c = malloc(sizeof(struct nand_device));
|
||||||
|
if (c == NULL)
|
||||||
|
{
|
||||||
|
LOG_ERROR("End of memory");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
c->name = strdup(bank_name);
|
c->name = strdup(bank_name);
|
||||||
|
c->target = target;
|
||||||
c->controller = controller;
|
c->controller = controller;
|
||||||
c->controller_priv = NULL;
|
c->controller_priv = NULL;
|
||||||
c->manufacturer = NULL;
|
c->manufacturer = NULL;
|
||||||
@@ -571,7 +579,7 @@ static COMMAND_HELPER(create_nand_device, const char *bank_name,
|
|||||||
c->use_raw = 0;
|
c->use_raw = 0;
|
||||||
c->next = NULL;
|
c->next = NULL;
|
||||||
|
|
||||||
int retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
|
retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
{
|
{
|
||||||
LOG_ERROR("'%s' driver rejected nand flash", controller->name);
|
LOG_ERROR("'%s' driver rejected nand flash", controller->name);
|
||||||
@@ -586,7 +594,7 @@ static COMMAND_HELPER(create_nand_device, const char *bank_name,
|
|||||||
|
|
||||||
COMMAND_HANDLER(handle_nand_device_command)
|
COMMAND_HANDLER(handle_nand_device_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC < 1)
|
if (CMD_ARGC < 2)
|
||||||
{
|
{
|
||||||
LOG_ERROR("incomplete nand device configuration");
|
LOG_ERROR("incomplete nand device configuration");
|
||||||
return ERROR_FLASH_BANK_INVALID;
|
return ERROR_FLASH_BANK_INVALID;
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
AM_CPPFLAGS = \
|
include $(top_srcdir)/common.mk
|
||||||
-I$(top_srcdir)/src \
|
|
||||||
-I$(top_builddir)/src
|
|
||||||
|
|
||||||
noinst_LTLIBRARIES = libocdflashnor.la
|
noinst_LTLIBRARIES = libocdflashnor.la
|
||||||
libocdflashnor_la_SOURCES = \
|
libocdflashnor_la_SOURCES = \
|
||||||
@@ -16,6 +14,7 @@ NOR_DRIVERS = \
|
|||||||
avrf.c \
|
avrf.c \
|
||||||
cfi.c \
|
cfi.c \
|
||||||
ecos.c \
|
ecos.c \
|
||||||
|
em357.c \
|
||||||
faux.c \
|
faux.c \
|
||||||
lpc2000.c \
|
lpc2000.c \
|
||||||
lpc288x.c \
|
lpc288x.c \
|
||||||
@@ -23,31 +22,26 @@ NOR_DRIVERS = \
|
|||||||
non_cfi.c \
|
non_cfi.c \
|
||||||
ocl.c \
|
ocl.c \
|
||||||
pic32mx.c \
|
pic32mx.c \
|
||||||
|
stmsmi.c \
|
||||||
stellaris.c \
|
stellaris.c \
|
||||||
stm32x.c \
|
stm32f1x.c \
|
||||||
|
stm32f2x.c \
|
||||||
str7x.c \
|
str7x.c \
|
||||||
str9x.c \
|
str9x.c \
|
||||||
str9xpec.c \
|
str9xpec.c \
|
||||||
tms470.c
|
tms470.c \
|
||||||
|
virtual.c \
|
||||||
|
fm3.c
|
||||||
|
|
||||||
|
# Disabled for now, it generates warnings
|
||||||
|
# dsp5680xx_flash.c
|
||||||
|
|
||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
at91sam7.h \
|
|
||||||
at91sam3.h \
|
|
||||||
avrf.h \
|
|
||||||
core.h \
|
core.h \
|
||||||
cfi.h \
|
cfi.h \
|
||||||
driver.h \
|
driver.h \
|
||||||
imp.h \
|
imp.h \
|
||||||
lpc2000.h \
|
|
||||||
lpc288x.h \
|
|
||||||
non_cfi.h \
|
non_cfi.h \
|
||||||
ocl.h \
|
ocl.h
|
||||||
pic32mx.h \
|
|
||||||
stellaris.h \
|
|
||||||
stm32x.h \
|
|
||||||
str7x.h \
|
|
||||||
str9x.h \
|
|
||||||
str9xpec.h \
|
|
||||||
tms470.h
|
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||||
|
|||||||
@@ -105,19 +105,19 @@ static int aduc702x_erase(struct flash_bank *bank, int first, int last)
|
|||||||
|
|
||||||
/* mass erase */
|
/* mass erase */
|
||||||
if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) {
|
if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) {
|
||||||
LOG_DEBUG("performing mass erase.\n");
|
LOG_DEBUG("performing mass erase.");
|
||||||
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, 0x3cff);
|
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, 0x3cff);
|
||||||
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, 0xffc3);
|
target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, 0xffc3);
|
||||||
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x06);
|
target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x06);
|
||||||
|
|
||||||
if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK)
|
if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK)
|
||||||
{
|
{
|
||||||
LOG_ERROR("mass erase failed\n");
|
LOG_ERROR("mass erase failed");
|
||||||
aduc702x_set_write_enable(target, 0);
|
aduc702x_set_write_enable(target, 0);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("mass erase successful.\n");
|
LOG_DEBUG("mass erase successful.");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
} else {
|
} else {
|
||||||
unsigned long adr;
|
unsigned long adr;
|
||||||
@@ -132,12 +132,12 @@ static int aduc702x_erase(struct flash_bank *bank, int first, int last)
|
|||||||
|
|
||||||
if (aduc702x_check_flash_completion(target, 50) != ERROR_OK)
|
if (aduc702x_check_flash_completion(target, 50) != ERROR_OK)
|
||||||
{
|
{
|
||||||
LOG_ERROR("failed to erase sector at address 0x%08lX\n", adr);
|
LOG_ERROR("failed to erase sector at address 0x%08lX", adr);
|
||||||
aduc702x_set_write_enable(target, 0);
|
aduc702x_set_write_enable(target, 0);
|
||||||
return ERROR_FLASH_SECTOR_NOT_ERASED;
|
return ERROR_FLASH_SECTOR_NOT_ERASED;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("erased sector at address 0x%08lX\n", adr);
|
LOG_DEBUG("erased sector at address 0x%08lX", adr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32
|
|||||||
r6 - set to 2, used to write flash command
|
r6 - set to 2, used to write flash command
|
||||||
|
|
||||||
*/
|
*/
|
||||||
uint32_t aduc702x_flash_write_code[] = {
|
static const uint32_t aduc702x_flash_write_code[] = {
|
||||||
//<_start>:
|
//<_start>:
|
||||||
0xe3a05008, // mov r5, #8 ; 0x8
|
0xe3a05008, // mov r5, #8 ; 0x8
|
||||||
0xe5845004, // str r5, [r4, #4]
|
0xe5845004, // str r5, [r4, #4]
|
||||||
@@ -227,7 +227,7 @@ static int aduc702x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* memory buffer */
|
/* memory buffer */
|
||||||
while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
|
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
|
||||||
{
|
{
|
||||||
buffer_size /= 2;
|
buffer_size /= 2;
|
||||||
if (buffer_size <= 256)
|
if (buffer_size <= 256)
|
||||||
@@ -330,20 +330,20 @@ static int aduc702x_write_single(struct flash_bank *bank, uint8_t *buffer, uint3
|
|||||||
|
|
||||||
if (aduc702x_check_flash_completion(target, 1) != ERROR_OK)
|
if (aduc702x_check_flash_completion(target, 1) != ERROR_OK)
|
||||||
{
|
{
|
||||||
LOG_ERROR("single write failed for address 0x%08lX\n", (unsigned long)(offset + x));
|
LOG_ERROR("single write failed for address 0x%08lX", (unsigned long)(offset + x));
|
||||||
aduc702x_set_write_enable(target, 0);
|
aduc702x_set_write_enable(target, 0);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
LOG_DEBUG("wrote %d bytes at address 0x%08lX\n", (int)count, (unsigned long)(offset + x));
|
LOG_DEBUG("wrote %d bytes at address 0x%08lX", (int)count, (unsigned long)(offset + x));
|
||||||
|
|
||||||
aduc702x_set_write_enable(target, 0);
|
aduc702x_set_write_enable(target, 0);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int aduc702x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
|
static int aduc702x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
@@ -417,6 +417,7 @@ struct flash_driver aduc702x_flash = {
|
|||||||
.erase = aduc702x_erase,
|
.erase = aduc702x_erase,
|
||||||
.protect = aduc702x_protect,
|
.protect = aduc702x_protect,
|
||||||
.write = aduc702x_write,
|
.write = aduc702x_write,
|
||||||
|
.read = default_flash_read,
|
||||||
.probe = aduc702x_probe,
|
.probe = aduc702x_probe,
|
||||||
.auto_probe = aduc702x_probe,
|
.auto_probe = aduc702x_probe,
|
||||||
.erase_check = default_flash_blank_check,
|
.erase_check = default_flash_blank_check,
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
* Copyright (C) 2009 by Duane Ellis *
|
* Copyright (C) 2009 by Duane Ellis *
|
||||||
* openocd@duaneellis.com *
|
* openocd@duaneellis.com *
|
||||||
* *
|
* *
|
||||||
|
* Copyright (C) 2010 by Olaf Lüke (at91sam3s* support) *
|
||||||
|
* olaf@uni-paderborn.de *
|
||||||
|
* *
|
||||||
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General public License as published by *
|
* it under the terms of the GNU General public License as published by *
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
@@ -58,15 +62,16 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "imp.h"
|
#include "imp.h"
|
||||||
#include "at91sam3.h"
|
|
||||||
#include <helper/membuf.h>
|
|
||||||
#include <helper/time_support.h>
|
#include <helper/time_support.h>
|
||||||
|
|
||||||
#define REG_NAME_WIDTH (12)
|
#define REG_NAME_WIDTH (12)
|
||||||
|
|
||||||
|
// at91sam3u series (has one or two flash banks)
|
||||||
|
#define FLASH_BANK0_BASE_U 0x00080000
|
||||||
|
#define FLASH_BANK1_BASE_U 0x00100000
|
||||||
|
|
||||||
#define FLASH_BANK0_BASE 0x00080000
|
// at91sam3s series (has always one flash bank)
|
||||||
#define FLASH_BANK1_BASE 0x00100000
|
#define FLASH_BANK_BASE_S 0x00400000
|
||||||
|
|
||||||
#define AT91C_EFC_FCMD_GETD (0x0) // (EFC) Get Flash Descriptor
|
#define AT91C_EFC_FCMD_GETD (0x0) // (EFC) Get Flash Descriptor
|
||||||
#define AT91C_EFC_FCMD_WP (0x1) // (EFC) Write Page
|
#define AT91C_EFC_FCMD_WP (0x1) // (EFC) Write Page
|
||||||
@@ -93,6 +98,8 @@
|
|||||||
#define offset_EFC_FRR 12
|
#define offset_EFC_FRR 12
|
||||||
|
|
||||||
|
|
||||||
|
extern struct flash_driver at91sam3_flash;
|
||||||
|
|
||||||
static float
|
static float
|
||||||
_tomhz(uint32_t freq_hz)
|
_tomhz(uint32_t freq_hz)
|
||||||
{
|
{
|
||||||
@@ -211,8 +218,6 @@ struct sam3_chip {
|
|||||||
struct sam3_chip_details details;
|
struct sam3_chip_details details;
|
||||||
struct target *target;
|
struct target *target;
|
||||||
struct sam3_cfg cfg;
|
struct sam3_cfg cfg;
|
||||||
|
|
||||||
struct membuf *mbuf;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -257,6 +262,7 @@ get_current_sam3(struct command_context *cmd_ctx)
|
|||||||
|
|
||||||
// these are used to *initialize* the "pChip->details" structure.
|
// these are used to *initialize* the "pChip->details" structure.
|
||||||
static const struct sam3_chip_details all_sam3_details[] = {
|
static const struct sam3_chip_details all_sam3_details[] = {
|
||||||
|
// Start at91sam3u* series
|
||||||
{
|
{
|
||||||
.chipid_cidr = 0x28100960,
|
.chipid_cidr = 0x28100960,
|
||||||
.name = "at91sam3u4e",
|
.name = "at91sam3u4e",
|
||||||
@@ -287,7 +293,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
|
|||||||
.pChip = NULL,
|
.pChip = NULL,
|
||||||
.pBank = NULL,
|
.pBank = NULL,
|
||||||
.bank_number = 0,
|
.bank_number = 0,
|
||||||
.base_address = FLASH_BANK0_BASE,
|
.base_address = FLASH_BANK0_BASE_U,
|
||||||
.controller_address = 0x400e0800,
|
.controller_address = 0x400e0800,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 128 * 1024,
|
.size_bytes = 128 * 1024,
|
||||||
@@ -302,7 +308,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
|
|||||||
.pChip = NULL,
|
.pChip = NULL,
|
||||||
.pBank = NULL,
|
.pBank = NULL,
|
||||||
.bank_number = 1,
|
.bank_number = 1,
|
||||||
.base_address = FLASH_BANK1_BASE,
|
.base_address = FLASH_BANK1_BASE_U,
|
||||||
.controller_address = 0x400e0a00,
|
.controller_address = 0x400e0a00,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 128 * 1024,
|
.size_bytes = 128 * 1024,
|
||||||
@@ -336,7 +342,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
|
|||||||
.pChip = NULL,
|
.pChip = NULL,
|
||||||
.pBank = NULL,
|
.pBank = NULL,
|
||||||
.bank_number = 0,
|
.bank_number = 0,
|
||||||
.base_address = FLASH_BANK0_BASE,
|
.base_address = FLASH_BANK0_BASE_U,
|
||||||
.controller_address = 0x400e0800,
|
.controller_address = 0x400e0800,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 128 * 1024,
|
.size_bytes = 128 * 1024,
|
||||||
@@ -377,7 +383,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
|
|||||||
.pChip = NULL,
|
.pChip = NULL,
|
||||||
.pBank = NULL,
|
.pBank = NULL,
|
||||||
.bank_number = 0,
|
.bank_number = 0,
|
||||||
.base_address = FLASH_BANK0_BASE,
|
.base_address = FLASH_BANK0_BASE_U,
|
||||||
.controller_address = 0x400e0800,
|
.controller_address = 0x400e0800,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 64 * 1024,
|
.size_bytes = 64 * 1024,
|
||||||
@@ -425,7 +431,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
|
|||||||
.pChip = NULL,
|
.pChip = NULL,
|
||||||
.pBank = NULL,
|
.pBank = NULL,
|
||||||
.bank_number = 0,
|
.bank_number = 0,
|
||||||
.base_address = FLASH_BANK0_BASE,
|
.base_address = FLASH_BANK0_BASE_U,
|
||||||
.controller_address = 0x400e0800,
|
.controller_address = 0x400e0800,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 128 * 1024,
|
.size_bytes = 128 * 1024,
|
||||||
@@ -439,7 +445,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
|
|||||||
.pChip = NULL,
|
.pChip = NULL,
|
||||||
.pBank = NULL,
|
.pBank = NULL,
|
||||||
.bank_number = 1,
|
.bank_number = 1,
|
||||||
.base_address = FLASH_BANK1_BASE,
|
.base_address = FLASH_BANK1_BASE_U,
|
||||||
.controller_address = 0x400e0a00,
|
.controller_address = 0x400e0a00,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 128 * 1024,
|
.size_bytes = 128 * 1024,
|
||||||
@@ -473,7 +479,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
|
|||||||
.pChip = NULL,
|
.pChip = NULL,
|
||||||
.pBank = NULL,
|
.pBank = NULL,
|
||||||
.bank_number = 0,
|
.bank_number = 0,
|
||||||
.base_address = FLASH_BANK0_BASE,
|
.base_address = FLASH_BANK0_BASE_U,
|
||||||
.controller_address = 0x400e0800,
|
.controller_address = 0x400e0800,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 128 * 1024,
|
.size_bytes = 128 * 1024,
|
||||||
@@ -514,7 +520,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
|
|||||||
.pChip = NULL,
|
.pChip = NULL,
|
||||||
.pBank = NULL,
|
.pBank = NULL,
|
||||||
.bank_number = 0,
|
.bank_number = 0,
|
||||||
.base_address = FLASH_BANK0_BASE,
|
.base_address = FLASH_BANK0_BASE_U,
|
||||||
.controller_address = 0x400e0800,
|
.controller_address = 0x400e0800,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 64 * 1024,
|
.size_bytes = 64 * 1024,
|
||||||
@@ -532,6 +538,300 @@ static const struct sam3_chip_details all_sam3_details[] = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Start at91sam3s* series
|
||||||
|
|
||||||
|
// Note: The preliminary at91sam3s datasheet says on page 302
|
||||||
|
// that the flash controller is at address 0x400E0800.
|
||||||
|
// This is _not_ the case, the controller resides at address 0x400e0a0.
|
||||||
|
{
|
||||||
|
.chipid_cidr = 0x28A00960,
|
||||||
|
.name = "at91sam3s4c",
|
||||||
|
.total_flash_size = 256 * 1024,
|
||||||
|
.total_sram_size = 48 * 1024,
|
||||||
|
.n_gpnvms = 2,
|
||||||
|
.n_banks = 1,
|
||||||
|
{
|
||||||
|
// .bank[0] = {
|
||||||
|
{
|
||||||
|
.probed = 0,
|
||||||
|
.pChip = NULL,
|
||||||
|
.pBank = NULL,
|
||||||
|
.bank_number = 0,
|
||||||
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
|
|
||||||
|
.controller_address = 0x400e0a00,
|
||||||
|
.present = 1,
|
||||||
|
.size_bytes = 256 * 1024,
|
||||||
|
.nsectors = 32,
|
||||||
|
.sector_size = 8192,
|
||||||
|
.page_size = 256,
|
||||||
|
},
|
||||||
|
// .bank[1] = {
|
||||||
|
{
|
||||||
|
.present = 0,
|
||||||
|
.probed = 0,
|
||||||
|
.bank_number = 1,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
.chipid_cidr = 0x28900960,
|
||||||
|
.name = "at91sam3s4b",
|
||||||
|
.total_flash_size = 256 * 1024,
|
||||||
|
.total_sram_size = 48 * 1024,
|
||||||
|
.n_gpnvms = 2,
|
||||||
|
.n_banks = 1,
|
||||||
|
{
|
||||||
|
// .bank[0] = {
|
||||||
|
{
|
||||||
|
.probed = 0,
|
||||||
|
.pChip = NULL,
|
||||||
|
.pBank = NULL,
|
||||||
|
.bank_number = 0,
|
||||||
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
|
|
||||||
|
.controller_address = 0x400e0a00,
|
||||||
|
.present = 1,
|
||||||
|
.size_bytes = 256 * 1024,
|
||||||
|
.nsectors = 32,
|
||||||
|
.sector_size = 8192,
|
||||||
|
.page_size = 256,
|
||||||
|
},
|
||||||
|
// .bank[1] = {
|
||||||
|
{
|
||||||
|
.present = 0,
|
||||||
|
.probed = 0,
|
||||||
|
.bank_number = 1,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.chipid_cidr = 0x28800960,
|
||||||
|
.name = "at91sam3s4a",
|
||||||
|
.total_flash_size = 256 * 1024,
|
||||||
|
.total_sram_size = 48 * 1024,
|
||||||
|
.n_gpnvms = 2,
|
||||||
|
.n_banks = 1,
|
||||||
|
{
|
||||||
|
// .bank[0] = {
|
||||||
|
{
|
||||||
|
.probed = 0,
|
||||||
|
.pChip = NULL,
|
||||||
|
.pBank = NULL,
|
||||||
|
.bank_number = 0,
|
||||||
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
|
|
||||||
|
.controller_address = 0x400e0a00,
|
||||||
|
.present = 1,
|
||||||
|
.size_bytes = 256 * 1024,
|
||||||
|
.nsectors = 32,
|
||||||
|
.sector_size = 8192,
|
||||||
|
.page_size = 256,
|
||||||
|
},
|
||||||
|
// .bank[1] = {
|
||||||
|
{
|
||||||
|
.present = 0,
|
||||||
|
.probed = 0,
|
||||||
|
.bank_number = 1,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.chipid_cidr = 0x28AA0760,
|
||||||
|
.name = "at91sam3s2c",
|
||||||
|
.total_flash_size = 128 * 1024,
|
||||||
|
.total_sram_size = 32 * 1024,
|
||||||
|
.n_gpnvms = 2,
|
||||||
|
.n_banks = 1,
|
||||||
|
{
|
||||||
|
// .bank[0] = {
|
||||||
|
{
|
||||||
|
.probed = 0,
|
||||||
|
.pChip = NULL,
|
||||||
|
.pBank = NULL,
|
||||||
|
.bank_number = 0,
|
||||||
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
|
|
||||||
|
.controller_address = 0x400e0a00,
|
||||||
|
.present = 1,
|
||||||
|
.size_bytes = 128 * 1024,
|
||||||
|
.nsectors = 16,
|
||||||
|
.sector_size = 8192,
|
||||||
|
.page_size = 256,
|
||||||
|
},
|
||||||
|
// .bank[1] = {
|
||||||
|
{
|
||||||
|
.present = 0,
|
||||||
|
.probed = 0,
|
||||||
|
.bank_number = 1,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.chipid_cidr = 0x289A0760,
|
||||||
|
.name = "at91sam3s2b",
|
||||||
|
.total_flash_size = 128 * 1024,
|
||||||
|
.total_sram_size = 32 * 1024,
|
||||||
|
.n_gpnvms = 2,
|
||||||
|
.n_banks = 1,
|
||||||
|
{
|
||||||
|
// .bank[0] = {
|
||||||
|
{
|
||||||
|
.probed = 0,
|
||||||
|
.pChip = NULL,
|
||||||
|
.pBank = NULL,
|
||||||
|
.bank_number = 0,
|
||||||
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
|
|
||||||
|
.controller_address = 0x400e0a00,
|
||||||
|
.present = 1,
|
||||||
|
.size_bytes = 128 * 1024,
|
||||||
|
.nsectors = 16,
|
||||||
|
.sector_size = 8192,
|
||||||
|
.page_size = 256,
|
||||||
|
},
|
||||||
|
// .bank[1] = {
|
||||||
|
{
|
||||||
|
.present = 0,
|
||||||
|
.probed = 0,
|
||||||
|
.bank_number = 1,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.chipid_cidr = 0x288A0760,
|
||||||
|
.name = "at91sam3s2a",
|
||||||
|
.total_flash_size = 128 * 1024,
|
||||||
|
.total_sram_size = 32 * 1024,
|
||||||
|
.n_gpnvms = 2,
|
||||||
|
.n_banks = 1,
|
||||||
|
{
|
||||||
|
// .bank[0] = {
|
||||||
|
{
|
||||||
|
.probed = 0,
|
||||||
|
.pChip = NULL,
|
||||||
|
.pBank = NULL,
|
||||||
|
.bank_number = 0,
|
||||||
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
|
|
||||||
|
.controller_address = 0x400e0a00,
|
||||||
|
.present = 1,
|
||||||
|
.size_bytes = 128 * 1024,
|
||||||
|
.nsectors = 16,
|
||||||
|
.sector_size = 8192,
|
||||||
|
.page_size = 256,
|
||||||
|
},
|
||||||
|
// .bank[1] = {
|
||||||
|
{
|
||||||
|
.present = 0,
|
||||||
|
.probed = 0,
|
||||||
|
.bank_number = 1,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.chipid_cidr = 0x28A90560,
|
||||||
|
.name = "at91sam3s1c",
|
||||||
|
.total_flash_size = 64 * 1024,
|
||||||
|
.total_sram_size = 16 * 1024,
|
||||||
|
.n_gpnvms = 2,
|
||||||
|
.n_banks = 1,
|
||||||
|
{
|
||||||
|
// .bank[0] = {
|
||||||
|
{
|
||||||
|
.probed = 0,
|
||||||
|
.pChip = NULL,
|
||||||
|
.pBank = NULL,
|
||||||
|
.bank_number = 0,
|
||||||
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
|
|
||||||
|
.controller_address = 0x400e0a00,
|
||||||
|
.present = 1,
|
||||||
|
.size_bytes = 64 * 1024,
|
||||||
|
.nsectors = 8,
|
||||||
|
.sector_size = 8192,
|
||||||
|
.page_size = 256,
|
||||||
|
},
|
||||||
|
// .bank[1] = {
|
||||||
|
{
|
||||||
|
.present = 0,
|
||||||
|
.probed = 0,
|
||||||
|
.bank_number = 1,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.chipid_cidr = 0x28990560,
|
||||||
|
.name = "at91sam3s1b",
|
||||||
|
.total_flash_size = 64 * 1024,
|
||||||
|
.total_sram_size = 16 * 1024,
|
||||||
|
.n_gpnvms = 2,
|
||||||
|
.n_banks = 1,
|
||||||
|
{
|
||||||
|
// .bank[0] = {
|
||||||
|
{
|
||||||
|
.probed = 0,
|
||||||
|
.pChip = NULL,
|
||||||
|
.pBank = NULL,
|
||||||
|
.bank_number = 0,
|
||||||
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
|
|
||||||
|
.controller_address = 0x400e0a00,
|
||||||
|
.present = 1,
|
||||||
|
.size_bytes = 64 * 1024,
|
||||||
|
.nsectors = 8,
|
||||||
|
.sector_size = 8192,
|
||||||
|
.page_size = 256,
|
||||||
|
},
|
||||||
|
// .bank[1] = {
|
||||||
|
{
|
||||||
|
.present = 0,
|
||||||
|
.probed = 0,
|
||||||
|
.bank_number = 1,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.chipid_cidr = 0x28890560,
|
||||||
|
.name = "at91sam3s1a",
|
||||||
|
.total_flash_size = 64 * 1024,
|
||||||
|
.total_sram_size = 16 * 1024,
|
||||||
|
.n_gpnvms = 2,
|
||||||
|
.n_banks = 1,
|
||||||
|
{
|
||||||
|
// .bank[0] = {
|
||||||
|
{
|
||||||
|
.probed = 0,
|
||||||
|
.pChip = NULL,
|
||||||
|
.pBank = NULL,
|
||||||
|
.bank_number = 0,
|
||||||
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
|
|
||||||
|
.controller_address = 0x400e0a00,
|
||||||
|
.present = 1,
|
||||||
|
.size_bytes = 64 * 1024,
|
||||||
|
.nsectors = 8,
|
||||||
|
.sector_size = 8192,
|
||||||
|
.page_size = 256,
|
||||||
|
},
|
||||||
|
// .bank[1] = {
|
||||||
|
{
|
||||||
|
.present = 0,
|
||||||
|
.probed = 0,
|
||||||
|
.bank_number = 1,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
// terminate
|
// terminate
|
||||||
{
|
{
|
||||||
.chipid_cidr = 0,
|
.chipid_cidr = 0,
|
||||||
@@ -1000,20 +1300,6 @@ FLASHD_Lock(struct sam3_bank_private *pPrivate,
|
|||||||
/****** END SAM3 CODE ********/
|
/****** END SAM3 CODE ********/
|
||||||
|
|
||||||
/* begin helpful debug code */
|
/* begin helpful debug code */
|
||||||
|
|
||||||
static void
|
|
||||||
sam3_sprintf(struct sam3_chip *pChip , const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap,fmt);
|
|
||||||
if (pChip->mbuf == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
membuf_vsprintf(pChip->mbuf, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
// print the fieldname, the field value, in dec & hex, and return field value
|
// print the fieldname, the field value, in dec & hex, and return field value
|
||||||
static uint32_t
|
static uint32_t
|
||||||
sam3_reg_fieldname(struct sam3_chip *pChip,
|
sam3_reg_fieldname(struct sam3_chip *pChip,
|
||||||
@@ -1038,7 +1324,7 @@ sam3_reg_fieldname(struct sam3_chip *pChip,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// show the basics
|
// show the basics
|
||||||
sam3_sprintf(pChip, "\t%*s: %*d [0x%0*x] ",
|
LOG_USER_N("\t%*s: %*d [0x%0*x] ",
|
||||||
REG_NAME_WIDTH, regname,
|
REG_NAME_WIDTH, regname,
|
||||||
dwidth, v,
|
dwidth, v,
|
||||||
hwidth, v);
|
hwidth, v);
|
||||||
@@ -1173,16 +1459,16 @@ sam3_explain_ckgr_mor(struct sam3_chip *pChip)
|
|||||||
uint32_t rcen;
|
uint32_t rcen;
|
||||||
|
|
||||||
v = sam3_reg_fieldname(pChip, "MOSCXTEN", pChip->cfg.CKGR_MOR, 0, 1);
|
v = sam3_reg_fieldname(pChip, "MOSCXTEN", pChip->cfg.CKGR_MOR, 0, 1);
|
||||||
sam3_sprintf(pChip, "(main xtal enabled: %s)\n",
|
LOG_USER("(main xtal enabled: %s)",
|
||||||
_yes_or_no(v));
|
_yes_or_no(v));
|
||||||
v = sam3_reg_fieldname(pChip, "MOSCXTBY", pChip->cfg.CKGR_MOR, 1, 1);
|
v = sam3_reg_fieldname(pChip, "MOSCXTBY", pChip->cfg.CKGR_MOR, 1, 1);
|
||||||
sam3_sprintf(pChip, "(main osc bypass: %s)\n",
|
LOG_USER("(main osc bypass: %s)",
|
||||||
_yes_or_no(v));
|
_yes_or_no(v));
|
||||||
rcen = sam3_reg_fieldname(pChip, "MOSCRCEN", pChip->cfg.CKGR_MOR, 2, 1);
|
rcen = sam3_reg_fieldname(pChip, "MOSCRCEN", pChip->cfg.CKGR_MOR, 3, 1);
|
||||||
sam3_sprintf(pChip, "(onchip RC-OSC enabled: %s)\n",
|
LOG_USER("(onchip RC-OSC enabled: %s)",
|
||||||
_yes_or_no(rcen));
|
_yes_or_no(rcen));
|
||||||
v = sam3_reg_fieldname(pChip, "MOSCRCF", pChip->cfg.CKGR_MOR, 4, 3);
|
v = sam3_reg_fieldname(pChip, "MOSCRCF", pChip->cfg.CKGR_MOR, 4, 3);
|
||||||
sam3_sprintf(pChip, "(onchip RC-OSC freq: %s)\n",
|
LOG_USER("(onchip RC-OSC freq: %s)",
|
||||||
_rc_freq[v]);
|
_rc_freq[v]);
|
||||||
|
|
||||||
pChip->cfg.rc_freq = 0;
|
pChip->cfg.rc_freq = 0;
|
||||||
@@ -1190,6 +1476,7 @@ sam3_explain_ckgr_mor(struct sam3_chip *pChip)
|
|||||||
switch (v) {
|
switch (v) {
|
||||||
default:
|
default:
|
||||||
pChip->cfg.rc_freq = 0;
|
pChip->cfg.rc_freq = 0;
|
||||||
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
pChip->cfg.rc_freq = 4 * 1000 * 1000;
|
pChip->cfg.rc_freq = 4 * 1000 * 1000;
|
||||||
break;
|
break;
|
||||||
@@ -1203,14 +1490,14 @@ sam3_explain_ckgr_mor(struct sam3_chip *pChip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
v = sam3_reg_fieldname(pChip,"MOSCXTST", pChip->cfg.CKGR_MOR, 8, 8);
|
v = sam3_reg_fieldname(pChip,"MOSCXTST", pChip->cfg.CKGR_MOR, 8, 8);
|
||||||
sam3_sprintf(pChip, "(startup clks, time= %f uSecs)\n",
|
LOG_USER("(startup clks, time= %f uSecs)",
|
||||||
((float)(v * 1000000)) / ((float)(pChip->cfg.slow_freq)));
|
((float)(v * 1000000)) / ((float)(pChip->cfg.slow_freq)));
|
||||||
v = sam3_reg_fieldname(pChip, "MOSCSEL", pChip->cfg.CKGR_MOR, 24, 1);
|
v = sam3_reg_fieldname(pChip, "MOSCSEL", pChip->cfg.CKGR_MOR, 24, 1);
|
||||||
sam3_sprintf(pChip, "(mainosc source: %s)\n",
|
LOG_USER("(mainosc source: %s)",
|
||||||
v ? "external xtal" : "internal RC");
|
v ? "external xtal" : "internal RC");
|
||||||
|
|
||||||
v = sam3_reg_fieldname(pChip,"CFDEN", pChip->cfg.CKGR_MOR, 25, 1);
|
v = sam3_reg_fieldname(pChip,"CFDEN", pChip->cfg.CKGR_MOR, 25, 1);
|
||||||
sam3_sprintf(pChip, "(clock failure enabled: %s)\n",
|
LOG_USER("(clock failure enabled: %s)",
|
||||||
_yes_or_no(v));
|
_yes_or_no(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1224,19 +1511,19 @@ sam3_explain_chipid_cidr(struct sam3_chip *pChip)
|
|||||||
const char *cp;
|
const char *cp;
|
||||||
|
|
||||||
sam3_reg_fieldname(pChip, "Version", pChip->cfg.CHIPID_CIDR, 0, 5);
|
sam3_reg_fieldname(pChip, "Version", pChip->cfg.CHIPID_CIDR, 0, 5);
|
||||||
sam3_sprintf(pChip,"\n");
|
LOG_USER_N("\n");
|
||||||
|
|
||||||
v = sam3_reg_fieldname(pChip, "EPROC", pChip->cfg.CHIPID_CIDR, 5, 3);
|
v = sam3_reg_fieldname(pChip, "EPROC", pChip->cfg.CHIPID_CIDR, 5, 3);
|
||||||
sam3_sprintf(pChip, "%s\n", eproc_names[v]);
|
LOG_USER("%s", eproc_names[v]);
|
||||||
|
|
||||||
v = sam3_reg_fieldname(pChip, "NVPSIZE", pChip->cfg.CHIPID_CIDR, 8, 4);
|
v = sam3_reg_fieldname(pChip, "NVPSIZE", pChip->cfg.CHIPID_CIDR, 8, 4);
|
||||||
sam3_sprintf(pChip, "%s\n", nvpsize[v]);
|
LOG_USER("%s", nvpsize[v]);
|
||||||
|
|
||||||
v = sam3_reg_fieldname(pChip, "NVPSIZE2", pChip->cfg.CHIPID_CIDR, 12, 4);
|
v = sam3_reg_fieldname(pChip, "NVPSIZE2", pChip->cfg.CHIPID_CIDR, 12, 4);
|
||||||
sam3_sprintf(pChip, "%s\n", nvpsize2[v]);
|
LOG_USER("%s", nvpsize2[v]);
|
||||||
|
|
||||||
v = sam3_reg_fieldname(pChip, "SRAMSIZE", pChip->cfg.CHIPID_CIDR, 16,4);
|
v = sam3_reg_fieldname(pChip, "SRAMSIZE", pChip->cfg.CHIPID_CIDR, 16,4);
|
||||||
sam3_sprintf(pChip, "%s\n", sramsize[ v ]);
|
LOG_USER("%s", sramsize[ v ]);
|
||||||
|
|
||||||
v = sam3_reg_fieldname(pChip, "ARCH", pChip->cfg.CHIPID_CIDR, 20, 8);
|
v = sam3_reg_fieldname(pChip, "ARCH", pChip->cfg.CHIPID_CIDR, 20, 8);
|
||||||
cp = _unknown;
|
cp = _unknown;
|
||||||
@@ -1247,13 +1534,13 @@ sam3_explain_chipid_cidr(struct sam3_chip *pChip)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sam3_sprintf(pChip, "%s\n", cp);
|
LOG_USER("%s", cp);
|
||||||
|
|
||||||
v = sam3_reg_fieldname(pChip, "NVPTYP", pChip->cfg.CHIPID_CIDR, 28, 3);
|
v = sam3_reg_fieldname(pChip, "NVPTYP", pChip->cfg.CHIPID_CIDR, 28, 3);
|
||||||
sam3_sprintf(pChip, "%s\n", nvptype[ v ]);
|
LOG_USER("%s", nvptype[ v ]);
|
||||||
|
|
||||||
v = sam3_reg_fieldname(pChip, "EXTID", pChip->cfg.CHIPID_CIDR, 31, 1);
|
v = sam3_reg_fieldname(pChip, "EXTID", pChip->cfg.CHIPID_CIDR, 31, 1);
|
||||||
sam3_sprintf(pChip, "(exists: %s)\n", _yes_or_no(v));
|
LOG_USER("(exists: %s)", _yes_or_no(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1263,14 +1550,14 @@ sam3_explain_ckgr_mcfr(struct sam3_chip *pChip)
|
|||||||
|
|
||||||
|
|
||||||
v = sam3_reg_fieldname(pChip, "MAINFRDY", pChip->cfg.CKGR_MCFR, 16, 1);
|
v = sam3_reg_fieldname(pChip, "MAINFRDY", pChip->cfg.CKGR_MCFR, 16, 1);
|
||||||
sam3_sprintf(pChip, "(main ready: %s)\n", _yes_or_no(v));
|
LOG_USER("(main ready: %s)", _yes_or_no(v));
|
||||||
|
|
||||||
v = sam3_reg_fieldname(pChip, "MAINF", pChip->cfg.CKGR_MCFR, 0, 16);
|
v = sam3_reg_fieldname(pChip, "MAINF", pChip->cfg.CKGR_MCFR, 0, 16);
|
||||||
|
|
||||||
v = (v * pChip->cfg.slow_freq) / 16;
|
v = (v * pChip->cfg.slow_freq) / 16;
|
||||||
pChip->cfg.mainosc_freq = v;
|
pChip->cfg.mainosc_freq = v;
|
||||||
|
|
||||||
sam3_sprintf(pChip, "(%3.03f Mhz (%d.%03dkhz slowclk)\n",
|
LOG_USER("(%3.03f Mhz (%d.%03dkhz slowclk)",
|
||||||
_tomhz(v),
|
_tomhz(v),
|
||||||
pChip->cfg.slow_freq / 1000,
|
pChip->cfg.slow_freq / 1000,
|
||||||
pChip->cfg.slow_freq % 1000);
|
pChip->cfg.slow_freq % 1000);
|
||||||
@@ -1283,17 +1570,17 @@ sam3_explain_ckgr_plla(struct sam3_chip *pChip)
|
|||||||
uint32_t mula,diva;
|
uint32_t mula,diva;
|
||||||
|
|
||||||
diva = sam3_reg_fieldname(pChip, "DIVA", pChip->cfg.CKGR_PLLAR, 0, 8);
|
diva = sam3_reg_fieldname(pChip, "DIVA", pChip->cfg.CKGR_PLLAR, 0, 8);
|
||||||
sam3_sprintf(pChip,"\n");
|
LOG_USER_N("\n");
|
||||||
mula = sam3_reg_fieldname(pChip, "MULA", pChip->cfg.CKGR_PLLAR, 16, 11);
|
mula = sam3_reg_fieldname(pChip, "MULA", pChip->cfg.CKGR_PLLAR, 16, 11);
|
||||||
sam3_sprintf(pChip,"\n");
|
LOG_USER_N("\n");
|
||||||
pChip->cfg.plla_freq = 0;
|
pChip->cfg.plla_freq = 0;
|
||||||
if (mula == 0) {
|
if (mula == 0) {
|
||||||
sam3_sprintf(pChip,"\tPLLA Freq: (Disabled,mula = 0)\n");
|
LOG_USER("\tPLLA Freq: (Disabled,mula = 0)");
|
||||||
} else if (diva == 0) {
|
} else if (diva == 0) {
|
||||||
sam3_sprintf(pChip,"\tPLLA Freq: (Disabled,diva = 0)\n");
|
LOG_USER("\tPLLA Freq: (Disabled,diva = 0)");
|
||||||
} else if (diva == 1) {
|
} else if (diva == 1) {
|
||||||
pChip->cfg.plla_freq = (pChip->cfg.mainosc_freq * (mula + 1));
|
pChip->cfg.plla_freq = (pChip->cfg.mainosc_freq * (mula + 1));
|
||||||
sam3_sprintf(pChip,"\tPLLA Freq: %3.03f MHz\n",
|
LOG_USER("\tPLLA Freq: %3.03f MHz",
|
||||||
_tomhz(pChip->cfg.plla_freq));
|
_tomhz(pChip->cfg.plla_freq));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1334,7 +1621,7 @@ sam3_explain_mckr(struct sam3_chip *pChip)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sam3_sprintf(pChip, "%s (%3.03f Mhz)\n",
|
LOG_USER("%s (%3.03f Mhz)",
|
||||||
cp,
|
cp,
|
||||||
_tomhz(fin));
|
_tomhz(fin));
|
||||||
pres = sam3_reg_fieldname(pChip, "PRES", pChip->cfg.PMC_MCKR, 4, 3);
|
pres = sam3_reg_fieldname(pChip, "PRES", pChip->cfg.PMC_MCKR, 4, 3);
|
||||||
@@ -1342,6 +1629,7 @@ sam3_explain_mckr(struct sam3_chip *pChip)
|
|||||||
case 0:
|
case 0:
|
||||||
pdiv = 1;
|
pdiv = 1;
|
||||||
cp = "selected clock";
|
cp = "selected clock";
|
||||||
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
pdiv = 2;
|
pdiv = 2;
|
||||||
cp = "clock/2";
|
cp = "clock/2";
|
||||||
@@ -1374,14 +1662,14 @@ sam3_explain_mckr(struct sam3_chip *pChip)
|
|||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sam3_sprintf(pChip, "(%s)\n", cp);
|
LOG_USER("(%s)", cp);
|
||||||
fin = fin / pdiv;
|
fin = fin / pdiv;
|
||||||
// sam3 has a *SINGLE* clock -
|
// sam3 has a *SINGLE* clock -
|
||||||
// other at91 series parts have divisors for these.
|
// other at91 series parts have divisors for these.
|
||||||
pChip->cfg.cpu_freq = fin;
|
pChip->cfg.cpu_freq = fin;
|
||||||
pChip->cfg.mclk_freq = fin;
|
pChip->cfg.mclk_freq = fin;
|
||||||
pChip->cfg.fclk_freq = fin;
|
pChip->cfg.fclk_freq = fin;
|
||||||
sam3_sprintf(pChip, "\t\tResult CPU Freq: %3.03f\n",
|
LOG_USER("\t\tResult CPU Freq: %3.03f",
|
||||||
_tomhz(fin));
|
_tomhz(fin));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1417,7 +1705,7 @@ sam3_get_reg_ptr(struct sam3_cfg *pCfg, const struct sam3_reg_list *pList)
|
|||||||
// By using prototypes - we can detect what would
|
// By using prototypes - we can detect what would
|
||||||
// be casting errors.
|
// be casting errors.
|
||||||
|
|
||||||
return ((uint32_t *)(((char *)(pCfg)) + pList->struct_offset));
|
return ((uint32_t *)(void *)(((char *)(pCfg)) + pList->struct_offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1471,7 +1759,7 @@ sam3_GetReg(struct sam3_chip *pChip, uint32_t *goes_here)
|
|||||||
// calculate where this one go..
|
// calculate where this one go..
|
||||||
// it is "possibly" this register.
|
// it is "possibly" this register.
|
||||||
|
|
||||||
pPossible = ((uint32_t *)(((char *)(&(pChip->cfg))) + pReg->struct_offset));
|
pPossible = ((uint32_t *)(void *)(((char *)(&(pChip->cfg))) + pReg->struct_offset));
|
||||||
|
|
||||||
// well? Is it this register
|
// well? Is it this register
|
||||||
if (pPossible == goes_here) {
|
if (pPossible == goes_here) {
|
||||||
@@ -1501,7 +1789,7 @@ sam3_ReadThisReg(struct sam3_chip *pChip, uint32_t *goes_here)
|
|||||||
|
|
||||||
r = target_read_u32(pChip->target, pReg->address, goes_here);
|
r = target_read_u32(pChip->target, pReg->address, goes_here);
|
||||||
if (r != ERROR_OK) {
|
if (r != ERROR_OK) {
|
||||||
LOG_ERROR("Cannot read SAM3 register: %s @ 0x%08x, Err: %d\n",
|
LOG_ERROR("Cannot read SAM3 register: %s @ 0x%08x, Err: %d",
|
||||||
pReg->name, (unsigned)(pReg->address), r);
|
pReg->name, (unsigned)(pReg->address), r);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
@@ -1520,7 +1808,7 @@ sam3_ReadAllRegs(struct sam3_chip *pChip)
|
|||||||
r = sam3_ReadThisReg(pChip,
|
r = sam3_ReadThisReg(pChip,
|
||||||
sam3_get_reg_ptr(&(pChip->cfg), pReg));
|
sam3_get_reg_ptr(&(pChip->cfg), pReg));
|
||||||
if (r != ERROR_OK) {
|
if (r != ERROR_OK) {
|
||||||
LOG_ERROR("Cannot read SAM3 registere: %s @ 0x%08x, Error: %d\n",
|
LOG_ERROR("Cannot read SAM3 registere: %s @ 0x%08x, Error: %d",
|
||||||
pReg->name, ((unsigned)(pReg->address)), r);
|
pReg->name, ((unsigned)(pReg->address)), r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -1538,15 +1826,12 @@ sam3_GetInfo(struct sam3_chip *pChip)
|
|||||||
const struct sam3_reg_list *pReg;
|
const struct sam3_reg_list *pReg;
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
|
|
||||||
membuf_reset(pChip->mbuf);
|
|
||||||
|
|
||||||
|
|
||||||
pReg = &(sam3_all_regs[0]);
|
pReg = &(sam3_all_regs[0]);
|
||||||
while (pReg->name) {
|
while (pReg->name) {
|
||||||
// display all regs
|
// display all regs
|
||||||
LOG_DEBUG("Start: %s", pReg->name);
|
LOG_DEBUG("Start: %s", pReg->name);
|
||||||
regval = *sam3_get_reg_ptr(&(pChip->cfg), pReg);
|
regval = *sam3_get_reg_ptr(&(pChip->cfg), pReg);
|
||||||
sam3_sprintf(pChip, "%*s: [0x%08x] -> 0x%08x\n",
|
LOG_USER("%*s: [0x%08x] -> 0x%08x",
|
||||||
REG_NAME_WIDTH,
|
REG_NAME_WIDTH,
|
||||||
pReg->name,
|
pReg->name,
|
||||||
pReg->address,
|
pReg->address,
|
||||||
@@ -1557,14 +1842,14 @@ sam3_GetInfo(struct sam3_chip *pChip)
|
|||||||
LOG_DEBUG("End: %s", pReg->name);
|
LOG_DEBUG("End: %s", pReg->name);
|
||||||
pReg++;
|
pReg++;
|
||||||
}
|
}
|
||||||
sam3_sprintf(pChip," rc-osc: %3.03f MHz\n", _tomhz(pChip->cfg.rc_freq));
|
LOG_USER(" rc-osc: %3.03f MHz", _tomhz(pChip->cfg.rc_freq));
|
||||||
sam3_sprintf(pChip," mainosc: %3.03f MHz\n", _tomhz(pChip->cfg.mainosc_freq));
|
LOG_USER(" mainosc: %3.03f MHz", _tomhz(pChip->cfg.mainosc_freq));
|
||||||
sam3_sprintf(pChip," plla: %3.03f MHz\n", _tomhz(pChip->cfg.plla_freq));
|
LOG_USER(" plla: %3.03f MHz", _tomhz(pChip->cfg.plla_freq));
|
||||||
sam3_sprintf(pChip," cpu-freq: %3.03f MHz\n", _tomhz(pChip->cfg.cpu_freq));
|
LOG_USER(" cpu-freq: %3.03f MHz", _tomhz(pChip->cfg.cpu_freq));
|
||||||
sam3_sprintf(pChip,"mclk-freq: %3.03f MHz\n", _tomhz(pChip->cfg.mclk_freq));
|
LOG_USER("mclk-freq: %3.03f MHz", _tomhz(pChip->cfg.mclk_freq));
|
||||||
|
|
||||||
|
|
||||||
sam3_sprintf(pChip, " UniqueId: 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
LOG_USER(" UniqueId: 0x%08x 0x%08x 0x%08x 0x%08x",
|
||||||
pChip->cfg.unique_id[0],
|
pChip->cfg.unique_id[0],
|
||||||
pChip->cfg.unique_id[1],
|
pChip->cfg.unique_id[1],
|
||||||
pChip->cfg.unique_id[2],
|
pChip->cfg.unique_id[2],
|
||||||
@@ -1586,7 +1871,7 @@ sam3_erase_check(struct flash_bank *bank)
|
|||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
if (0 == bank->num_sectors) {
|
if (0 == bank->num_sectors) {
|
||||||
LOG_ERROR("Target: not supported/not probed\n");
|
LOG_ERROR("Target: not supported/not probed");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1664,32 +1949,38 @@ FLASH_BANK_COMMAND_HANDLER(sam3_flash_bank_command)
|
|||||||
// assumption is this runs at 32khz
|
// assumption is this runs at 32khz
|
||||||
pChip->cfg.slow_freq = 32768;
|
pChip->cfg.slow_freq = 32768;
|
||||||
pChip->probed = 0;
|
pChip->probed = 0;
|
||||||
pChip->mbuf = membuf_new();
|
|
||||||
if (!(pChip->mbuf)) {
|
|
||||||
LOG_ERROR("no memory");
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (bank->base) {
|
switch (bank->base) {
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("Address 0x%08x invalid bank address (try 0x%08x or 0x%08x)",
|
LOG_ERROR("Address 0x%08x invalid bank address (try 0x%08x or 0x%08x \
|
||||||
|
[at91sam3u series] or 0x%08x [at91sam3s series])",
|
||||||
((unsigned int)(bank->base)),
|
((unsigned int)(bank->base)),
|
||||||
((unsigned int)(FLASH_BANK0_BASE)),
|
((unsigned int)(FLASH_BANK0_BASE_U)),
|
||||||
((unsigned int)(FLASH_BANK1_BASE)));
|
((unsigned int)(FLASH_BANK1_BASE_U)),
|
||||||
|
((unsigned int)(FLASH_BANK_BASE_S)));
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
break;
|
break;
|
||||||
case FLASH_BANK0_BASE:
|
|
||||||
|
// at91sam3u series
|
||||||
|
case FLASH_BANK0_BASE_U:
|
||||||
bank->driver_priv = &(pChip->details.bank[0]);
|
bank->driver_priv = &(pChip->details.bank[0]);
|
||||||
bank->bank_number = 0;
|
bank->bank_number = 0;
|
||||||
pChip->details.bank[0].pChip = pChip;
|
pChip->details.bank[0].pChip = pChip;
|
||||||
pChip->details.bank[0].pBank = bank;
|
pChip->details.bank[0].pBank = bank;
|
||||||
break;
|
break;
|
||||||
case FLASH_BANK1_BASE:
|
case FLASH_BANK1_BASE_U:
|
||||||
bank->driver_priv = &(pChip->details.bank[1]);
|
bank->driver_priv = &(pChip->details.bank[1]);
|
||||||
bank->bank_number = 1;
|
bank->bank_number = 1;
|
||||||
pChip->details.bank[1].pChip = pChip;
|
pChip->details.bank[1].pChip = pChip;
|
||||||
pChip->details.bank[1].pBank = bank;
|
pChip->details.bank[1].pBank = bank;
|
||||||
|
|
||||||
|
// at91sam3s series
|
||||||
|
case FLASH_BANK_BASE_S:
|
||||||
|
bank->driver_priv = &(pChip->details.bank[0]);
|
||||||
|
bank->bank_number = 0;
|
||||||
|
pChip->details.bank[0].pChip = pChip;
|
||||||
|
pChip->details.bank[0].pBank = bank;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1702,16 +1993,14 @@ sam3_GetDetails(struct sam3_bank_private *pPrivate)
|
|||||||
{
|
{
|
||||||
const struct sam3_chip_details *pDetails;
|
const struct sam3_chip_details *pDetails;
|
||||||
struct sam3_chip *pChip;
|
struct sam3_chip *pChip;
|
||||||
void *vp;
|
|
||||||
struct flash_bank *saved_banks[SAM3_MAX_FLASH_BANKS];
|
struct flash_bank *saved_banks[SAM3_MAX_FLASH_BANKS];
|
||||||
|
|
||||||
unsigned x;
|
unsigned x;
|
||||||
const char *cp;
|
|
||||||
|
|
||||||
LOG_DEBUG("Begin");
|
LOG_DEBUG("Begin");
|
||||||
pDetails = all_sam3_details;
|
pDetails = all_sam3_details;
|
||||||
while (pDetails->name) {
|
while (pDetails->name) {
|
||||||
if (pDetails->chipid_cidr == pPrivate->pChip->cfg.CHIPID_CIDR) {
|
// Compare cidr without version bits
|
||||||
|
if (pDetails->chipid_cidr == (pPrivate->pChip->cfg.CHIPID_CIDR & 0xFFFFFFE0)) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
pDetails++;
|
pDetails++;
|
||||||
@@ -1721,16 +2010,9 @@ sam3_GetDetails(struct sam3_bank_private *pPrivate)
|
|||||||
LOG_ERROR("SAM3 ChipID 0x%08x not found in table (perhaps you can this chip?)",
|
LOG_ERROR("SAM3 ChipID 0x%08x not found in table (perhaps you can this chip?)",
|
||||||
(unsigned int)(pPrivate->pChip->cfg.CHIPID_CIDR));
|
(unsigned int)(pPrivate->pChip->cfg.CHIPID_CIDR));
|
||||||
// Help the victim, print details about the chip
|
// Help the victim, print details about the chip
|
||||||
membuf_reset(pPrivate->pChip->mbuf);
|
LOG_INFO("SAM3 CHIPID_CIDR: 0x%08x decodes as follows",
|
||||||
membuf_sprintf(pPrivate->pChip->mbuf,
|
|
||||||
"SAM3 CHIPID_CIDR: 0x%08x decodes as follows\n",
|
|
||||||
pPrivate->pChip->cfg.CHIPID_CIDR);
|
pPrivate->pChip->cfg.CHIPID_CIDR);
|
||||||
sam3_explain_chipid_cidr(pPrivate->pChip);
|
sam3_explain_chipid_cidr(pPrivate->pChip);
|
||||||
cp = membuf_strtok(pPrivate->pChip->mbuf, "\n", &vp);
|
|
||||||
while (cp) {
|
|
||||||
LOG_INFO("%s", cp);
|
|
||||||
cp = membuf_strtok(NULL, "\n", &vp);
|
|
||||||
}
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1787,7 +2069,7 @@ _sam3_probe(struct flash_bank *bank, int noise)
|
|||||||
|
|
||||||
pPrivate = get_sam3_bank_private(bank);
|
pPrivate = get_sam3_bank_private(bank);
|
||||||
if (!pPrivate) {
|
if (!pPrivate) {
|
||||||
LOG_ERROR("Invalid/unknown bank number\n");
|
LOG_ERROR("Invalid/unknown bank number");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1798,18 +2080,14 @@ _sam3_probe(struct flash_bank *bank, int noise)
|
|||||||
|
|
||||||
|
|
||||||
LOG_DEBUG("Here");
|
LOG_DEBUG("Here");
|
||||||
r = sam3_GetInfo(pPrivate->pChip);
|
if (pPrivate->pChip->probed) {
|
||||||
|
r = sam3_GetInfo(pPrivate->pChip);
|
||||||
|
} else {
|
||||||
|
r = sam3_GetDetails(pPrivate);
|
||||||
|
}
|
||||||
if (r != ERROR_OK) {
|
if (r != ERROR_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
if (!(pPrivate->pChip->probed)) {
|
|
||||||
pPrivate->pChip->probed = 1;
|
|
||||||
LOG_DEBUG("Here");
|
|
||||||
r = sam3_GetDetails(pPrivate);
|
|
||||||
if (r != ERROR_OK) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the flash bank size
|
// update the flash bank size
|
||||||
for (x = 0 ; x < SAM3_MAX_FLASH_BANKS ; x++) {
|
for (x = 0 ; x < SAM3_MAX_FLASH_BANKS ; x++) {
|
||||||
@@ -2046,9 +2324,7 @@ sam3_page_write_opcodes[] = {
|
|||||||
0x10,0xf0,0x01,0x0f,
|
0x10,0xf0,0x01,0x0f,
|
||||||
// 41 0024 FBD0 beq .L4
|
// 41 0024 FBD0 beq .L4
|
||||||
0xfb,0xd0,
|
0xfb,0xd0,
|
||||||
// 42 .done:
|
0x00,0xBE /* bkpt #0 */
|
||||||
// 43 0026 FEE7 b .done
|
|
||||||
0xfe,0xe7
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -2258,8 +2534,6 @@ sam3_write(struct flash_bank *bank,
|
|||||||
COMMAND_HANDLER(sam3_handle_info_command)
|
COMMAND_HANDLER(sam3_handle_info_command)
|
||||||
{
|
{
|
||||||
struct sam3_chip *pChip;
|
struct sam3_chip *pChip;
|
||||||
void *vp;
|
|
||||||
const char *cp;
|
|
||||||
unsigned x;
|
unsigned x;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@@ -2317,17 +2591,10 @@ COMMAND_HANDLER(sam3_handle_info_command)
|
|||||||
|
|
||||||
r = sam3_GetInfo(pChip);
|
r = sam3_GetInfo(pChip);
|
||||||
if (r != ERROR_OK) {
|
if (r != ERROR_OK) {
|
||||||
LOG_DEBUG("Sam3Info, Failed %d\n",r);
|
LOG_DEBUG("Sam3Info, Failed %d",r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// print results
|
|
||||||
cp = membuf_strtok(pChip->mbuf, "\n", &vp);
|
|
||||||
while (cp) {
|
|
||||||
command_print(CMD_CTX,"%s", cp);
|
|
||||||
cp = membuf_strtok(NULL, "\n", &vp);
|
|
||||||
}
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2418,7 +2685,7 @@ showall:
|
|||||||
(0 == strcmp("clear", CMD_ARGV[0]))) { // quietly accept both
|
(0 == strcmp("clear", CMD_ARGV[0]))) { // quietly accept both
|
||||||
r = FLASHD_ClrGPNVM(&(pChip->details.bank[0]), who);
|
r = FLASHD_ClrGPNVM(&(pChip->details.bank[0]), who);
|
||||||
} else {
|
} else {
|
||||||
command_print(CMD_CTX, "Unkown command: %s", CMD_ARGV[0]);
|
command_print(CMD_CTX, "Unknown command: %s", CMD_ARGV[0]);
|
||||||
r = ERROR_COMMAND_SYNTAX_ERROR;
|
r = ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
@@ -2507,6 +2774,7 @@ struct flash_driver at91sam3_flash = {
|
|||||||
.erase = sam3_erase,
|
.erase = sam3_erase,
|
||||||
.protect = sam3_protect,
|
.protect = sam3_protect,
|
||||||
.write = sam3_write,
|
.write = sam3_write,
|
||||||
|
.read = default_flash_read,
|
||||||
.probe = sam3_probe,
|
.probe = sam3_probe,
|
||||||
.auto_probe = sam3_auto_probe,
|
.auto_probe = sam3_auto_probe,
|
||||||
.erase_check = sam3_erase_check,
|
.erase_check = sam3_erase_check,
|
||||||
|
|||||||
@@ -50,9 +50,55 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "imp.h"
|
#include "imp.h"
|
||||||
#include "at91sam7.h"
|
|
||||||
#include <helper/binarybuffer.h>
|
#include <helper/binarybuffer.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* AT91SAM7 control registers */
|
||||||
|
#define DBGU_CIDR 0xFFFFF240
|
||||||
|
#define CKGR_MCFR 0xFFFFFC24
|
||||||
|
#define CKGR_MOR 0xFFFFFC20
|
||||||
|
#define CKGR_MCFR_MAINRDY 0x10000
|
||||||
|
#define CKGR_PLLR 0xFFFFFC2c
|
||||||
|
#define CKGR_PLLR_DIV 0xff
|
||||||
|
#define CKGR_PLLR_MUL 0x07ff0000
|
||||||
|
#define PMC_MCKR 0xFFFFFC30
|
||||||
|
#define PMC_MCKR_CSS 0x03
|
||||||
|
#define PMC_MCKR_PRES 0x1c
|
||||||
|
|
||||||
|
/* Flash Controller Commands */
|
||||||
|
#define WP 0x01
|
||||||
|
#define SLB 0x02
|
||||||
|
#define WPL 0x03
|
||||||
|
#define CLB 0x04
|
||||||
|
#define EA 0x08
|
||||||
|
#define SGPB 0x0B
|
||||||
|
#define CGPB 0x0D
|
||||||
|
#define SSB 0x0F
|
||||||
|
|
||||||
|
/* MC_FSR bit definitions */
|
||||||
|
#define MC_FSR_FRDY 1
|
||||||
|
#define MC_FSR_EOL 2
|
||||||
|
|
||||||
|
/* AT91SAM7 constants */
|
||||||
|
#define RC_FREQ 32000
|
||||||
|
|
||||||
|
/* Flash timing modes */
|
||||||
|
#define FMR_TIMING_NONE 0
|
||||||
|
#define FMR_TIMING_NVBITS 1
|
||||||
|
#define FMR_TIMING_FLASH 2
|
||||||
|
|
||||||
|
/* Flash size constants */
|
||||||
|
#define FLASH_SIZE_8KB 1
|
||||||
|
#define FLASH_SIZE_16KB 2
|
||||||
|
#define FLASH_SIZE_32KB 3
|
||||||
|
#define FLASH_SIZE_64KB 5
|
||||||
|
#define FLASH_SIZE_128KB 7
|
||||||
|
#define FLASH_SIZE_256KB 9
|
||||||
|
#define FLASH_SIZE_512KB 10
|
||||||
|
#define FLASH_SIZE_1024KB 12
|
||||||
|
#define FLASH_SIZE_2048KB 14
|
||||||
|
|
||||||
|
|
||||||
static int at91sam7_protect_check(struct flash_bank *bank);
|
static int at91sam7_protect_check(struct flash_bank *bank);
|
||||||
static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count);
|
static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count);
|
||||||
|
|
||||||
@@ -67,6 +113,50 @@ static uint32_t MC_FSR[4] = { 0xFFFFFF68, 0xFFFFFF78, 0xFFFFFF88, 0xFFFFFF98 };
|
|||||||
|
|
||||||
static char * EPROC[8]= {"Unknown","ARM946-E","ARM7TDMI","Unknown","ARM920T","ARM926EJ-S","Unknown","Unknown"};
|
static char * EPROC[8]= {"Unknown","ARM946-E","ARM7TDMI","Unknown","ARM920T","ARM926EJ-S","Unknown","Unknown"};
|
||||||
|
|
||||||
|
struct at91sam7_flash_bank
|
||||||
|
{
|
||||||
|
/* chip id register */
|
||||||
|
uint32_t cidr;
|
||||||
|
uint16_t cidr_ext;
|
||||||
|
uint16_t cidr_nvptyp;
|
||||||
|
uint16_t cidr_arch;
|
||||||
|
uint16_t cidr_sramsiz;
|
||||||
|
uint16_t cidr_nvpsiz;
|
||||||
|
uint16_t cidr_nvpsiz2;
|
||||||
|
uint16_t cidr_eproc;
|
||||||
|
uint16_t cidr_version;
|
||||||
|
const char *target_name;
|
||||||
|
|
||||||
|
/* flash auto-detection */
|
||||||
|
uint8_t flash_autodetection;
|
||||||
|
|
||||||
|
/* flash geometry */
|
||||||
|
uint16_t pages_per_sector;
|
||||||
|
uint16_t pagesize;
|
||||||
|
uint16_t pages_in_lockregion;
|
||||||
|
|
||||||
|
/* nv memory bits */
|
||||||
|
uint16_t num_lockbits_on;
|
||||||
|
uint16_t lockbits;
|
||||||
|
uint16_t num_nvmbits;
|
||||||
|
uint16_t num_nvmbits_on;
|
||||||
|
uint16_t nvmbits;
|
||||||
|
uint8_t securitybit;
|
||||||
|
|
||||||
|
/* 0: not init
|
||||||
|
* 1: fmcn for nvbits (1uS)
|
||||||
|
* 2: fmcn for flash (1.5uS) */
|
||||||
|
uint8_t flashmode;
|
||||||
|
|
||||||
|
/* main clock status */
|
||||||
|
uint8_t mck_valid;
|
||||||
|
uint32_t mck_freq;
|
||||||
|
|
||||||
|
/* external clock frequency */
|
||||||
|
uint32_t ext_freq;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static long SRAMSIZ[16] = {
|
static long SRAMSIZ[16] = {
|
||||||
-1,
|
-1,
|
||||||
@@ -298,7 +388,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
|||||||
uint32_t ext_freq;
|
uint32_t ext_freq;
|
||||||
uint32_t bank_size;
|
uint32_t bank_size;
|
||||||
uint32_t base_address = 0;
|
uint32_t base_address = 0;
|
||||||
char *target_name = "Unknown";
|
char *target_name_t = "Unknown";
|
||||||
|
|
||||||
at91sam7_info = t_bank->driver_priv;
|
at91sam7_info = t_bank->driver_priv;
|
||||||
|
|
||||||
@@ -386,7 +476,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
|||||||
if (arch == 0x70)
|
if (arch == 0x70)
|
||||||
{
|
{
|
||||||
num_nvmbits = 2;
|
num_nvmbits = 2;
|
||||||
target_name = "AT91SAM7S161/16";
|
target_name_t = "AT91SAM7S161/16";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -399,12 +489,12 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
|||||||
if (arch == 0x70)
|
if (arch == 0x70)
|
||||||
{
|
{
|
||||||
num_nvmbits = 2;
|
num_nvmbits = 2;
|
||||||
target_name = "AT91SAM7S321/32";
|
target_name_t = "AT91SAM7S321/32";
|
||||||
}
|
}
|
||||||
if (arch == 0x72)
|
if (arch == 0x72)
|
||||||
{
|
{
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name = "AT91SAM7SE32";
|
target_name_t = "AT91SAM7SE32";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -417,7 +507,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
|||||||
if (arch == 0x70)
|
if (arch == 0x70)
|
||||||
{
|
{
|
||||||
num_nvmbits = 2;
|
num_nvmbits = 2;
|
||||||
target_name = "AT91SAM7S64";
|
target_name_t = "AT91SAM7S64";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -430,22 +520,22 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
|||||||
if (arch == 0x70)
|
if (arch == 0x70)
|
||||||
{
|
{
|
||||||
num_nvmbits = 2;
|
num_nvmbits = 2;
|
||||||
target_name = "AT91SAM7S128";
|
target_name_t = "AT91SAM7S128";
|
||||||
}
|
}
|
||||||
if (arch == 0x71)
|
if (arch == 0x71)
|
||||||
{
|
{
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name = "AT91SAM7XC128";
|
target_name_t = "AT91SAM7XC128";
|
||||||
}
|
}
|
||||||
if (arch == 0x72)
|
if (arch == 0x72)
|
||||||
{
|
{
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name = "AT91SAM7SE128";
|
target_name_t = "AT91SAM7SE128";
|
||||||
}
|
}
|
||||||
if (arch == 0x75)
|
if (arch == 0x75)
|
||||||
{
|
{
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name = "AT91SAM7X128";
|
target_name_t = "AT91SAM7X128";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -458,27 +548,27 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
|||||||
if (arch == 0x60)
|
if (arch == 0x60)
|
||||||
{
|
{
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name = "AT91SAM7A3";
|
target_name_t = "AT91SAM7A3";
|
||||||
}
|
}
|
||||||
if (arch == 0x70)
|
if (arch == 0x70)
|
||||||
{
|
{
|
||||||
num_nvmbits = 2;
|
num_nvmbits = 2;
|
||||||
target_name = "AT91SAM7S256";
|
target_name_t = "AT91SAM7S256";
|
||||||
}
|
}
|
||||||
if (arch == 0x71)
|
if (arch == 0x71)
|
||||||
{
|
{
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name = "AT91SAM7XC256";
|
target_name_t = "AT91SAM7XC256";
|
||||||
}
|
}
|
||||||
if (arch == 0x72)
|
if (arch == 0x72)
|
||||||
{
|
{
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name = "AT91SAM7SE256";
|
target_name_t = "AT91SAM7SE256";
|
||||||
}
|
}
|
||||||
if (arch == 0x75)
|
if (arch == 0x75)
|
||||||
{
|
{
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name = "AT91SAM7X256";
|
target_name_t = "AT91SAM7X256";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -491,22 +581,22 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
|||||||
if (arch == 0x70)
|
if (arch == 0x70)
|
||||||
{
|
{
|
||||||
num_nvmbits = 2;
|
num_nvmbits = 2;
|
||||||
target_name = "AT91SAM7S512";
|
target_name_t = "AT91SAM7S512";
|
||||||
}
|
}
|
||||||
if (arch == 0x71)
|
if (arch == 0x71)
|
||||||
{
|
{
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name = "AT91SAM7XC512";
|
target_name_t = "AT91SAM7XC512";
|
||||||
}
|
}
|
||||||
if (arch == 0x72)
|
if (arch == 0x72)
|
||||||
{
|
{
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name = "AT91SAM7SE512";
|
target_name_t = "AT91SAM7SE512";
|
||||||
}
|
}
|
||||||
if (arch == 0x75)
|
if (arch == 0x75)
|
||||||
{
|
{
|
||||||
num_nvmbits = 3;
|
num_nvmbits = 3;
|
||||||
target_name = "AT91SAM7X512";
|
target_name_t = "AT91SAM7X512";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -517,7 +607,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(target_name, "Unknown") == 0)
|
if (strcmp(target_name_t, "Unknown") == 0)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Target autodetection failed! Please specify target parameters in configuration file");
|
LOG_ERROR("Target autodetection failed! Please specify target parameters in configuration file");
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
@@ -573,7 +663,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
|||||||
at91sam7_info->cidr_eproc = (cidr >> 5)&0x0007;
|
at91sam7_info->cidr_eproc = (cidr >> 5)&0x0007;
|
||||||
at91sam7_info->cidr_version = cidr&0x001F;
|
at91sam7_info->cidr_version = cidr&0x001F;
|
||||||
|
|
||||||
at91sam7_info->target_name = target_name;
|
at91sam7_info->target_name = target_name_t;
|
||||||
at91sam7_info->flashmode = 0;
|
at91sam7_info->flashmode = 0;
|
||||||
at91sam7_info->ext_freq = ext_freq;
|
at91sam7_info->ext_freq = ext_freq;
|
||||||
at91sam7_info->num_nvmbits = num_nvmbits;
|
at91sam7_info->num_nvmbits = num_nvmbits;
|
||||||
@@ -731,7 +821,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
|
|||||||
uint16_t page_size;
|
uint16_t page_size;
|
||||||
uint16_t num_nvmbits;
|
uint16_t num_nvmbits;
|
||||||
|
|
||||||
char *target_name;
|
char *target_name_t;
|
||||||
|
|
||||||
int bnk, sec;
|
int bnk, sec;
|
||||||
|
|
||||||
@@ -775,8 +865,8 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
|
|||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
target_name = calloc(strlen(CMD_ARGV[7]) + 1, sizeof(char));
|
target_name_t = calloc(strlen(CMD_ARGV[7]) + 1, sizeof(char));
|
||||||
strcpy(target_name, CMD_ARGV[7]);
|
strcpy(target_name_t, CMD_ARGV[7]);
|
||||||
|
|
||||||
/* calculate bank size */
|
/* calculate bank size */
|
||||||
bank_size = num_sectors * pages_per_sector * page_size;
|
bank_size = num_sectors * pages_per_sector * page_size;
|
||||||
@@ -816,7 +906,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
|
|||||||
|
|
||||||
at91sam7_info = t_bank->driver_priv;
|
at91sam7_info = t_bank->driver_priv;
|
||||||
|
|
||||||
at91sam7_info->target_name = target_name;
|
at91sam7_info->target_name = target_name_t;
|
||||||
at91sam7_info->flashmode = 0;
|
at91sam7_info->flashmode = 0;
|
||||||
at91sam7_info->ext_freq = ext_freq;
|
at91sam7_info->ext_freq = ext_freq;
|
||||||
at91sam7_info->num_nvmbits = num_nvmbits;
|
at91sam7_info->num_nvmbits = num_nvmbits;
|
||||||
@@ -1034,7 +1124,7 @@ static int at91sam7_probe(struct flash_bank *bank)
|
|||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int at91sam7_info(struct flash_bank *bank, char *buf, int buf_size)
|
static int get_at91sam7_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
{
|
{
|
||||||
int printed;
|
int printed;
|
||||||
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
|
struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
|
||||||
@@ -1171,7 +1261,7 @@ COMMAND_HANDLER(at91sam7_handle_gpnvm_command)
|
|||||||
|
|
||||||
/* GPNVM and SECURITY bits apply only for MC_FSR of EFC0 */
|
/* GPNVM and SECURITY bits apply only for MC_FSR of EFC0 */
|
||||||
status = at91sam7_get_flash_status(bank->target, 0);
|
status = at91sam7_get_flash_status(bank->target, 0);
|
||||||
LOG_DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value %d, status 0x%" PRIx32 " \n", flashcmd, bit, status);
|
LOG_DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value %d, status 0x%" PRIx32, flashcmd, bit, status);
|
||||||
|
|
||||||
/* check protect state */
|
/* check protect state */
|
||||||
at91sam7_protect_check(bank);
|
at91sam7_protect_check(bank);
|
||||||
@@ -1207,9 +1297,10 @@ struct flash_driver at91sam7_flash = {
|
|||||||
.erase = at91sam7_erase,
|
.erase = at91sam7_erase,
|
||||||
.protect = at91sam7_protect,
|
.protect = at91sam7_protect,
|
||||||
.write = at91sam7_write,
|
.write = at91sam7_write,
|
||||||
|
.read = default_flash_read,
|
||||||
.probe = at91sam7_probe,
|
.probe = at91sam7_probe,
|
||||||
.auto_probe = at91sam7_probe,
|
.auto_probe = at91sam7_probe,
|
||||||
.erase_check = at91sam7_erase_check,
|
.erase_check = at91sam7_erase_check,
|
||||||
.protect_check = at91sam7_protect_check,
|
.protect_check = at91sam7_protect_check,
|
||||||
.info = at91sam7_info,
|
.info = get_at91sam7_info,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,116 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
* Copyright (C) 2006 by Magnus Lundin *
|
|
||||||
* lundin@mlu.mine.nu *
|
|
||||||
* *
|
|
||||||
* Copyright (C) 2006 by Gheorghe Guran (atlas) *
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program is distributed in the hope that it will be useful, *
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
||||||
* GNU General Public License for more details. *
|
|
||||||
* *
|
|
||||||
* You should have received a copy of the GNU General Public License *
|
|
||||||
* along with this program; if not, write to the *
|
|
||||||
* Free Software Foundation, Inc., *
|
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef AT91SAM7_H
|
|
||||||
#define AT91SAM7_H
|
|
||||||
|
|
||||||
struct at91sam7_flash_bank
|
|
||||||
{
|
|
||||||
/* chip id register */
|
|
||||||
uint32_t cidr;
|
|
||||||
uint16_t cidr_ext;
|
|
||||||
uint16_t cidr_nvptyp;
|
|
||||||
uint16_t cidr_arch;
|
|
||||||
uint16_t cidr_sramsiz;
|
|
||||||
uint16_t cidr_nvpsiz;
|
|
||||||
uint16_t cidr_nvpsiz2;
|
|
||||||
uint16_t cidr_eproc;
|
|
||||||
uint16_t cidr_version;
|
|
||||||
char *target_name;
|
|
||||||
|
|
||||||
/* flash auto-detection */
|
|
||||||
uint8_t flash_autodetection;
|
|
||||||
|
|
||||||
/* flash geometry */
|
|
||||||
uint16_t pages_per_sector;
|
|
||||||
uint16_t pagesize;
|
|
||||||
uint16_t pages_in_lockregion;
|
|
||||||
|
|
||||||
/* nv memory bits */
|
|
||||||
uint16_t num_lockbits_on;
|
|
||||||
uint16_t lockbits;
|
|
||||||
uint16_t num_nvmbits;
|
|
||||||
uint16_t num_nvmbits_on;
|
|
||||||
uint16_t nvmbits;
|
|
||||||
uint8_t securitybit;
|
|
||||||
|
|
||||||
/* 0: not init
|
|
||||||
* 1: fmcn for nvbits (1uS)
|
|
||||||
* 2: fmcn for flash (1.5uS) */
|
|
||||||
uint8_t flashmode;
|
|
||||||
|
|
||||||
/* main clock status */
|
|
||||||
uint8_t mck_valid;
|
|
||||||
uint32_t mck_freq;
|
|
||||||
|
|
||||||
/* external clock frequency */
|
|
||||||
uint32_t ext_freq;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* AT91SAM7 control registers */
|
|
||||||
#define DBGU_CIDR 0xFFFFF240
|
|
||||||
#define CKGR_MCFR 0xFFFFFC24
|
|
||||||
#define CKGR_MOR 0xFFFFFC20
|
|
||||||
#define CKGR_MCFR_MAINRDY 0x10000
|
|
||||||
#define CKGR_PLLR 0xFFFFFC2c
|
|
||||||
#define CKGR_PLLR_DIV 0xff
|
|
||||||
#define CKGR_PLLR_MUL 0x07ff0000
|
|
||||||
#define PMC_MCKR 0xFFFFFC30
|
|
||||||
#define PMC_MCKR_CSS 0x03
|
|
||||||
#define PMC_MCKR_PRES 0x1c
|
|
||||||
|
|
||||||
/* Flash Controller Commands */
|
|
||||||
#define WP 0x01
|
|
||||||
#define SLB 0x02
|
|
||||||
#define WPL 0x03
|
|
||||||
#define CLB 0x04
|
|
||||||
#define EA 0x08
|
|
||||||
#define SGPB 0x0B
|
|
||||||
#define CGPB 0x0D
|
|
||||||
#define SSB 0x0F
|
|
||||||
|
|
||||||
/* MC_FSR bit definitions */
|
|
||||||
#define MC_FSR_FRDY 1
|
|
||||||
#define MC_FSR_EOL 2
|
|
||||||
|
|
||||||
/* AT91SAM7 constants */
|
|
||||||
#define RC_FREQ 32000
|
|
||||||
|
|
||||||
/* Flash timing modes */
|
|
||||||
#define FMR_TIMING_NONE 0
|
|
||||||
#define FMR_TIMING_NVBITS 1
|
|
||||||
#define FMR_TIMING_FLASH 2
|
|
||||||
|
|
||||||
/* Flash size constants */
|
|
||||||
#define FLASH_SIZE_8KB 1
|
|
||||||
#define FLASH_SIZE_16KB 2
|
|
||||||
#define FLASH_SIZE_32KB 3
|
|
||||||
#define FLASH_SIZE_64KB 5
|
|
||||||
#define FLASH_SIZE_128KB 7
|
|
||||||
#define FLASH_SIZE_256KB 9
|
|
||||||
#define FLASH_SIZE_512KB 10
|
|
||||||
#define FLASH_SIZE_1024KB 12
|
|
||||||
#define FLASH_SIZE_2048KB 14
|
|
||||||
|
|
||||||
#endif /* AT91SAM7_H */
|
|
||||||
@@ -22,7 +22,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "imp.h"
|
#include "imp.h"
|
||||||
#include "avrf.h"
|
|
||||||
#include <target/avrt.h>
|
#include <target/avrt.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -50,24 +49,30 @@
|
|||||||
#define AVR_JTAG_REG_ProgrammingCommand_Len 15
|
#define AVR_JTAG_REG_ProgrammingCommand_Len 15
|
||||||
#define AVR_JTAG_REG_FlashDataByte_Len 16
|
#define AVR_JTAG_REG_FlashDataByte_Len 16
|
||||||
|
|
||||||
struct avrf_type avft_chips_info[] =
|
struct avrf_type
|
||||||
{
|
{
|
||||||
// name, chip_id, flash_page_size, flash_page_num, eeprom_page_size, eeprom_page_num
|
char name[15];
|
||||||
{"atmega128", 0x9702, 256, 512, 8, 512},
|
uint16_t chip_id;
|
||||||
|
int flash_page_size;
|
||||||
|
int flash_page_num;
|
||||||
|
int eeprom_page_size;
|
||||||
|
int eeprom_page_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
int avr_jtag_sendinstr(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out);
|
struct avrf_flash_bank
|
||||||
int avr_jtag_senddat(struct jtag_tap *tap, uint32_t *dr_in, uint32_t dr_out, int len);
|
{
|
||||||
|
int ppage_size;
|
||||||
|
int probed;
|
||||||
|
};
|
||||||
|
|
||||||
int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, int ir_len, int rti);
|
static struct avrf_type avft_chips_info[] =
|
||||||
int mcu_write_dr(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, int dr_len, int rti);
|
{
|
||||||
int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out, int ir_len, int rti);
|
/* name, chip_id, flash_page_size, flash_page_num,
|
||||||
int mcu_write_dr_u8(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out, int dr_len, int rti);
|
* eeprom_page_size, eeprom_page_num
|
||||||
int mcu_write_ir_u16(struct jtag_tap *tap, uint16_t *ir_in, uint16_t ir_out, int ir_len, int rti);
|
*/
|
||||||
int mcu_write_dr_u16(struct jtag_tap *tap, uint16_t *ir_in, uint16_t ir_out, int dr_len, int rti);
|
{"atmega128", 0x9702, 256, 512, 8, 512},
|
||||||
int mcu_write_ir_u32(struct jtag_tap *tap, uint32_t *ir_in, uint32_t ir_out, int ir_len, int rti);
|
{"at90can128", 0x9781, 256, 512, 8, 512},
|
||||||
int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *ir_in, uint32_t ir_out, int dr_len, int rti);
|
};
|
||||||
int mcu_execute_queue(void);
|
|
||||||
|
|
||||||
/* avr program functions */
|
/* avr program functions */
|
||||||
static int avr_jtag_reset(struct avr_common *avr, uint32_t reset)
|
static int avr_jtag_reset(struct avr_common *avr, uint32_t reset)
|
||||||
@@ -200,8 +205,27 @@ FLASH_BANK_COMMAND_HANDLER(avrf_flash_bank_command)
|
|||||||
|
|
||||||
static int avrf_erase(struct flash_bank *bank, int first, int last)
|
static int avrf_erase(struct flash_bank *bank, int first, int last)
|
||||||
{
|
{
|
||||||
LOG_INFO("%s", __FUNCTION__);
|
struct target *target = bank->target;
|
||||||
return ERROR_OK;
|
struct avr_common *avr = target->arch_info;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
LOG_DEBUG("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
if (target->state != TARGET_HALTED)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Target not halted");
|
||||||
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = avr_jtagprg_enterprogmode(avr);
|
||||||
|
if (status != ERROR_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = avr_jtagprg_chiperase(avr);
|
||||||
|
if (status != ERROR_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return avr_jtagprg_leaveprogmode(avr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avrf_protect(struct flash_bank *bank, int set, int first, int last)
|
static int avrf_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
@@ -302,6 +326,12 @@ static int avrf_probe(struct flash_bank *bank)
|
|||||||
|
|
||||||
if (avr_info != NULL)
|
if (avr_info != NULL)
|
||||||
{
|
{
|
||||||
|
if (bank->sectors)
|
||||||
|
{
|
||||||
|
free(bank->sectors);
|
||||||
|
bank->sectors = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// chip found
|
// chip found
|
||||||
bank->base = 0x00000000;
|
bank->base = 0x00000000;
|
||||||
bank->size = (avr_info->flash_page_size * avr_info->flash_page_num);
|
bank->size = (avr_info->flash_page_size * avr_info->flash_page_num);
|
||||||
@@ -475,6 +505,7 @@ struct flash_driver avr_flash = {
|
|||||||
.erase = avrf_erase,
|
.erase = avrf_erase,
|
||||||
.protect = avrf_protect,
|
.protect = avrf_protect,
|
||||||
.write = avrf_write,
|
.write = avrf_write,
|
||||||
|
.read = default_flash_read,
|
||||||
.probe = avrf_probe,
|
.probe = avrf_probe,
|
||||||
.auto_probe = avrf_auto_probe,
|
.auto_probe = avrf_auto_probe,
|
||||||
.erase_check = default_flash_mem_blank_check,
|
.erase_check = default_flash_mem_blank_check,
|
||||||
|
|||||||
2059
src/flash/nor/cfi.c
2059
src/flash/nor/cfi.c
File diff suppressed because it is too large
Load Diff
@@ -35,7 +35,7 @@ struct cfi_flash_bank
|
|||||||
uint16_t manufacturer;
|
uint16_t manufacturer;
|
||||||
uint16_t device_id;
|
uint16_t device_id;
|
||||||
|
|
||||||
char qry[3];
|
uint8_t qry[3];
|
||||||
|
|
||||||
/* identification string */
|
/* identification string */
|
||||||
uint16_t pri_id;
|
uint16_t pri_id;
|
||||||
@@ -68,6 +68,12 @@ struct cfi_flash_bank
|
|||||||
|
|
||||||
void *pri_ext;
|
void *pri_ext;
|
||||||
void *alt_ext;
|
void *alt_ext;
|
||||||
|
|
||||||
|
/* calculated timeouts */
|
||||||
|
unsigned word_write_timeout;
|
||||||
|
unsigned buf_write_timeout;
|
||||||
|
unsigned block_erase_timeout;
|
||||||
|
unsigned chip_erase_timeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Intel primary extended query table
|
/* Intel primary extended query table
|
||||||
@@ -76,7 +82,7 @@ struct cfi_flash_bank
|
|||||||
*/
|
*/
|
||||||
struct cfi_intel_pri_ext
|
struct cfi_intel_pri_ext
|
||||||
{
|
{
|
||||||
char pri[3];
|
uint8_t pri[3];
|
||||||
uint8_t major_version;
|
uint8_t major_version;
|
||||||
uint8_t minor_version;
|
uint8_t minor_version;
|
||||||
uint32_t feature_support;
|
uint32_t feature_support;
|
||||||
@@ -144,7 +150,7 @@ struct cfi_fixup
|
|||||||
{
|
{
|
||||||
uint16_t mfr;
|
uint16_t mfr;
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
void (*fixup)(struct flash_bank *flash, void *param);
|
void (*fixup)(struct flash_bank *bank, void *param);
|
||||||
void *param;
|
void *param;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
|
* Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
|
||||||
* Copyright (C) 2007,2008 Øyvind Harboe <oyvind.harboe@zylin.com> *
|
* Copyright (C) 2007-2010 Øyvind Harboe <oyvind.harboe@zylin.com> *
|
||||||
* Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
|
* Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
|
||||||
* Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
|
* Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
|
||||||
|
* Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published by *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
@@ -36,7 +37,7 @@
|
|||||||
* primarily support access from Tcl scripts or from GDB.
|
* primarily support access from Tcl scripts or from GDB.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct flash_bank *flash_banks;
|
static struct flash_bank *flash_banks;
|
||||||
|
|
||||||
int flash_driver_erase(struct flash_bank *bank, int first, int last)
|
int flash_driver_erase(struct flash_bank *bank, int first, int last)
|
||||||
{
|
{
|
||||||
@@ -45,7 +46,7 @@ int flash_driver_erase(struct flash_bank *bank, int first, int last)
|
|||||||
retval = bank->driver->erase(bank, first, last);
|
retval = bank->driver->erase(bank, first, last);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
{
|
||||||
LOG_ERROR("failed erasing sectors %d to %d (%d)", first, last, retval);
|
LOG_ERROR("failed erasing sectors %d to %d", first, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
@@ -55,10 +56,31 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
|
|||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
/* callers may not supply illegal parameters ... */
|
||||||
|
if (first < 0 || first > last || last >= bank->num_sectors)
|
||||||
|
{
|
||||||
|
LOG_ERROR("illegal sector range");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* force "set" to 0/1 */
|
||||||
|
set = !!set;
|
||||||
|
|
||||||
|
/* DANGER!
|
||||||
|
*
|
||||||
|
* We must not use any cached information about protection state!!!!
|
||||||
|
*
|
||||||
|
* There are a million things that could change the protect state:
|
||||||
|
*
|
||||||
|
* the target could have reset, power cycled, been hot plugged,
|
||||||
|
* the application could have run, etc.
|
||||||
|
*
|
||||||
|
* Drivers only receive valid sector range.
|
||||||
|
*/
|
||||||
retval = bank->driver->protect(bank, set, first, last);
|
retval = bank->driver->protect(bank, set, first, last);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
{
|
||||||
LOG_ERROR("failed setting protection for areas %d to %d (%d)", first, last, retval);
|
LOG_ERROR("failed setting protection for areas %d to %d", first, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
@@ -72,13 +94,36 @@ int flash_driver_write(struct flash_bank *bank,
|
|||||||
retval = bank->driver->write(bank, buffer, offset, count);
|
retval = bank->driver->write(bank, buffer, offset, count);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
{
|
||||||
LOG_ERROR("error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32 " (%d)",
|
LOG_ERROR("error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
|
||||||
bank->base, offset, retval);
|
bank->base, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int flash_driver_read(struct flash_bank *bank,
|
||||||
|
uint8_t *buffer, uint32_t offset, uint32_t count)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
LOG_DEBUG("call flash_driver_read()");
|
||||||
|
|
||||||
|
retval = bank->driver->read(bank, buffer, offset, count);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
{
|
||||||
|
LOG_ERROR("error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
|
||||||
|
bank->base, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int default_flash_read(struct flash_bank *bank,
|
||||||
|
uint8_t *buffer, uint32_t offset, uint32_t count)
|
||||||
|
{
|
||||||
|
return target_read_buffer(bank->target, offset + bank->base, count, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
void flash_bank_add(struct flash_bank *bank)
|
void flash_bank_add(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
/* put flash bank in linked list */
|
/* put flash bank in linked list */
|
||||||
@@ -133,7 +178,7 @@ int flash_get_bank_count(void)
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct flash_bank *get_flash_bank_by_name(const char *name)
|
struct flash_bank *get_flash_bank_by_name_noprobe(const char *name)
|
||||||
{
|
{
|
||||||
unsigned requested = get_flash_name_index(name);
|
unsigned requested = get_flash_name_index(name);
|
||||||
unsigned found = 0;
|
unsigned found = 0;
|
||||||
@@ -152,26 +197,51 @@ struct flash_bank *get_flash_bank_by_name(const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct flash_bank *get_flash_bank_by_num(int num)
|
int get_flash_bank_by_name(const char *name, struct flash_bank **bank_result)
|
||||||
|
{
|
||||||
|
struct flash_bank *bank;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
bank = get_flash_bank_by_name_noprobe(name);
|
||||||
|
if (bank != NULL)
|
||||||
|
{
|
||||||
|
retval = bank->driver->auto_probe(bank);
|
||||||
|
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
{
|
||||||
|
LOG_ERROR("auto_probe failed");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*bank_result = bank;
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_flash_bank_by_num(int num, struct flash_bank **bank)
|
||||||
{
|
{
|
||||||
struct flash_bank *p = get_flash_bank_by_num_noprobe(num);
|
struct flash_bank *p = get_flash_bank_by_num_noprobe(num);
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
return NULL;
|
{
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
retval = p->driver->auto_probe(p);
|
retval = p->driver->auto_probe(p);
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
{
|
||||||
LOG_ERROR("auto_probe failed %d\n", retval);
|
LOG_ERROR("auto_probe failed");
|
||||||
return NULL;
|
return retval;
|
||||||
}
|
}
|
||||||
return p;
|
*bank = p;
|
||||||
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* lookup flash bank by address */
|
/* lookup flash bank by address, bank not found is success, but
|
||||||
struct flash_bank *get_flash_bank_by_addr(struct target *target, uint32_t addr)
|
* result_bank is set to NULL. */
|
||||||
|
int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check, struct flash_bank **result_bank)
|
||||||
{
|
{
|
||||||
struct flash_bank *c;
|
struct flash_bank *c;
|
||||||
|
|
||||||
@@ -183,15 +253,23 @@ struct flash_bank *get_flash_bank_by_addr(struct target *target, uint32_t addr)
|
|||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
{
|
||||||
LOG_ERROR("auto_probe failed %d\n", retval);
|
LOG_ERROR("auto_probe failed");
|
||||||
return NULL;
|
return retval;
|
||||||
}
|
}
|
||||||
/* check whether address belongs to this flash bank */
|
/* check whether address belongs to this flash bank */
|
||||||
if ((addr >= c->base) && (addr <= c->base + (c->size - 1)) && target == c->target)
|
if ((addr >= c->base) && (addr <= c->base + (c->size - 1)) && target == c->target)
|
||||||
return c;
|
{
|
||||||
|
*result_bank = c;
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LOG_ERROR("No flash at address 0x%08" PRIx32 "\n", addr);
|
*result_bank = NULL;
|
||||||
return NULL;
|
if (check)
|
||||||
|
{
|
||||||
|
LOG_ERROR("No flash at address 0x%08" PRIx32, addr);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int default_flash_mem_blank_check(struct flash_bank *bank)
|
int default_flash_mem_blank_check(struct flash_bank *bank)
|
||||||
@@ -301,7 +379,7 @@ int default_flash_blank_check(struct flash_bank *bank)
|
|||||||
* sectors will be added to the range, and that reason string is used when
|
* sectors will be added to the range, and that reason string is used when
|
||||||
* warning about those additions.
|
* warning about those additions.
|
||||||
*/
|
*/
|
||||||
static int flash_iterate_address_range(struct target *target,
|
static int flash_iterate_address_range_inner(struct target *target,
|
||||||
char *pad_reason, uint32_t addr, uint32_t length,
|
char *pad_reason, uint32_t addr, uint32_t length,
|
||||||
int (*callback)(struct flash_bank *bank, int first, int last))
|
int (*callback)(struct flash_bank *bank, int first, int last))
|
||||||
{
|
{
|
||||||
@@ -311,8 +389,9 @@ static int flash_iterate_address_range(struct target *target,
|
|||||||
int last = -1;
|
int last = -1;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if ((c = get_flash_bank_by_addr(target, addr)) == NULL)
|
int retval = get_flash_bank_by_addr(target, addr, true, &c);
|
||||||
return ERROR_FLASH_DST_OUT_OF_BANK; /* no corresponding bank found */
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
if (c->size == 0 || c->num_sectors == 0)
|
if (c->size == 0 || c->num_sectors == 0)
|
||||||
{
|
{
|
||||||
@@ -419,6 +498,43 @@ static int flash_iterate_address_range(struct target *target,
|
|||||||
return callback(c, first, last);
|
return callback(c, first, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The inner fn only handles a single bank, we could be spanning
|
||||||
|
* multiple chips.
|
||||||
|
*/
|
||||||
|
static int flash_iterate_address_range(struct target *target,
|
||||||
|
char *pad_reason, uint32_t addr, uint32_t length,
|
||||||
|
int (*callback)(struct flash_bank *bank, int first, int last))
|
||||||
|
{
|
||||||
|
struct flash_bank *c;
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
|
/* Danger! zero-length iterations means entire bank! */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
retval = get_flash_bank_by_addr(target, addr, true, &c);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
uint32_t cur_length = length;
|
||||||
|
/* check whether it all fits in this bank */
|
||||||
|
if (addr + length - 1 > c->base + c->size - 1)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("iterating over more than one flash bank.");
|
||||||
|
cur_length = c->base + c->size - addr;
|
||||||
|
}
|
||||||
|
retval = flash_iterate_address_range_inner(target,
|
||||||
|
pad_reason, addr, cur_length,
|
||||||
|
callback);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
length -= cur_length;
|
||||||
|
addr += cur_length;
|
||||||
|
} while (length > 0);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
int flash_erase_address_range(struct target *target,
|
int flash_erase_address_range(struct target *target,
|
||||||
bool pad, uint32_t addr, uint32_t length)
|
bool pad, uint32_t addr, uint32_t length)
|
||||||
{
|
{
|
||||||
@@ -431,7 +547,7 @@ static int flash_driver_unprotect(struct flash_bank *bank, int first, int last)
|
|||||||
return flash_driver_protect(bank, 0, first, last);
|
return flash_driver_protect(bank, 0, first, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length)
|
int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length)
|
||||||
{
|
{
|
||||||
/* By default, pad to sector boundaries ... the real issue here
|
/* By default, pad to sector boundaries ... the real issue here
|
||||||
* is that our (only) caller *permanently* removes protection,
|
* is that our (only) caller *permanently* removes protection,
|
||||||
@@ -441,6 +557,25 @@ static int flash_unlock_address_range(struct target *target, uint32_t addr, uint
|
|||||||
addr, length, &flash_driver_unprotect);
|
addr, length, &flash_driver_unprotect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int compare_section (const void * a, const void * b)
|
||||||
|
{
|
||||||
|
struct imagesection *b1, *b2;
|
||||||
|
b1=*((struct imagesection **)a);
|
||||||
|
b2=*((struct imagesection **)b);
|
||||||
|
|
||||||
|
if (b1->base_address == b2->base_address)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
} else if (b1->base_address > b2->base_address)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int flash_write_unlock(struct target *target, struct image *image,
|
int flash_write_unlock(struct target *target, struct image *image,
|
||||||
uint32_t *written, int erase, bool unlock)
|
uint32_t *written, int erase, bool unlock)
|
||||||
{
|
{
|
||||||
@@ -451,12 +586,6 @@ int flash_write_unlock(struct target *target, struct image *image,
|
|||||||
struct flash_bank *c;
|
struct flash_bank *c;
|
||||||
int *padding;
|
int *padding;
|
||||||
|
|
||||||
/* REVISIT do_pad should perhaps just be another parameter.
|
|
||||||
* GDB wouldn't ever need it, since it erases separately.
|
|
||||||
* But "flash write_image" commands might want that option.
|
|
||||||
*/
|
|
||||||
bool do_pad = false;
|
|
||||||
|
|
||||||
section = 0;
|
section = 0;
|
||||||
section_offset = 0;
|
section_offset = 0;
|
||||||
|
|
||||||
@@ -474,18 +603,30 @@ int flash_write_unlock(struct target *target, struct image *image,
|
|||||||
/* allocate padding array */
|
/* allocate padding array */
|
||||||
padding = calloc(image->num_sections, sizeof(*padding));
|
padding = calloc(image->num_sections, sizeof(*padding));
|
||||||
|
|
||||||
|
/* This fn requires all sections to be in ascending order of addresses,
|
||||||
|
* whereas an image can have sections out of order. */
|
||||||
|
struct imagesection **sections = malloc(sizeof(struct imagesection *) *
|
||||||
|
image->num_sections);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < image->num_sections; i++)
|
||||||
|
{
|
||||||
|
sections[i] = &image->sections[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort(sections, image->num_sections, sizeof(struct imagesection *),
|
||||||
|
compare_section);
|
||||||
|
|
||||||
/* loop until we reach end of the image */
|
/* loop until we reach end of the image */
|
||||||
while (section < image->num_sections)
|
while (section < image->num_sections)
|
||||||
{
|
{
|
||||||
uint32_t buffer_size;
|
uint32_t buffer_size;
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
int section_first;
|
|
||||||
int section_last;
|
int section_last;
|
||||||
uint32_t run_address = image->sections[section].base_address + section_offset;
|
uint32_t run_address = sections[section]->base_address + section_offset;
|
||||||
uint32_t run_size = image->sections[section].size - section_offset;
|
uint32_t run_size = sections[section]->size - section_offset;
|
||||||
int pad_bytes = 0;
|
int pad_bytes = 0;
|
||||||
|
|
||||||
if (image->sections[section].size == 0)
|
if (sections[section]->size == 0)
|
||||||
{
|
{
|
||||||
LOG_WARNING("empty section %d", section);
|
LOG_WARNING("empty section %d", section);
|
||||||
section++;
|
section++;
|
||||||
@@ -494,7 +635,12 @@ int flash_write_unlock(struct target *target, struct image *image,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* find the corresponding flash bank */
|
/* find the corresponding flash bank */
|
||||||
if ((c = get_flash_bank_by_addr(target, run_address)) == NULL)
|
retval = get_flash_bank_by_addr(target, run_address, false, &c);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
{
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (c == NULL)
|
||||||
{
|
{
|
||||||
section++; /* and skip it */
|
section++; /* and skip it */
|
||||||
section_offset = 0;
|
section_offset = 0;
|
||||||
@@ -502,21 +648,17 @@ int flash_write_unlock(struct target *target, struct image *image,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* collect consecutive sections which fall into the same bank */
|
/* collect consecutive sections which fall into the same bank */
|
||||||
section_first = section;
|
|
||||||
section_last = section;
|
section_last = section;
|
||||||
padding[section] = 0;
|
padding[section] = 0;
|
||||||
while ((run_address + run_size - 1 < c->base + c->size - 1)
|
while ((run_address + run_size - 1 < c->base + c->size - 1)
|
||||||
&& (section_last + 1 < image->num_sections))
|
&& (section_last + 1 < image->num_sections))
|
||||||
{
|
{
|
||||||
if (image->sections[section_last + 1].base_address < (run_address + run_size))
|
/* sections are sorted */
|
||||||
|
assert(sections[section_last + 1]->base_address >= c->base);
|
||||||
|
if (sections[section_last + 1]->base_address >= (c->base + c->size))
|
||||||
{
|
{
|
||||||
LOG_DEBUG("section %d out of order "
|
/* Done with this bank */
|
||||||
"(surprising, but supported)",
|
break;
|
||||||
section_last + 1);
|
|
||||||
/* REVISIT this can break with autoerase ...
|
|
||||||
* clobbering data after it's written.
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME This needlessly touches sectors BETWEEN the
|
/* FIXME This needlessly touches sectors BETWEEN the
|
||||||
@@ -536,25 +678,24 @@ int flash_write_unlock(struct target *target, struct image *image,
|
|||||||
/* if we have multiple sections within our image,
|
/* if we have multiple sections within our image,
|
||||||
* flash programming could fail due to alignment issues
|
* flash programming could fail due to alignment issues
|
||||||
* attempt to rebuild a consecutive buffer for the flash loader */
|
* attempt to rebuild a consecutive buffer for the flash loader */
|
||||||
pad_bytes = (image->sections[section_last + 1].base_address) - (run_address + run_size);
|
pad_bytes = (sections[section_last + 1]->base_address) - (run_address + run_size);
|
||||||
if ((run_address + run_size + pad_bytes) > (c->base + c->size))
|
|
||||||
break;
|
|
||||||
padding[section_last] = pad_bytes;
|
padding[section_last] = pad_bytes;
|
||||||
run_size += image->sections[++section_last].size;
|
run_size += sections[++section_last]->size;
|
||||||
run_size += pad_bytes;
|
run_size += pad_bytes;
|
||||||
|
|
||||||
LOG_INFO("Padding image section %d with %d bytes", section_last-1, pad_bytes);
|
if (pad_bytes > 0)
|
||||||
|
LOG_INFO("Padding image section %d with %d bytes", section_last-1, pad_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fit the run into bank constraints */
|
|
||||||
if (run_address + run_size - 1 > c->base + c->size - 1)
|
if (run_address + run_size - 1 > c->base + c->size - 1)
|
||||||
{
|
{
|
||||||
/* REVISIT isn't this superfluous, given the while()
|
/* If we have more than one flash chip back to back, then we limit
|
||||||
* loop conditions above??
|
* the current write operation to the current chip.
|
||||||
*/
|
*/
|
||||||
LOG_WARNING("writing %d bytes only - as image section is %d bytes and bank is only %d bytes", \
|
LOG_DEBUG("Truncate flash run size to the current flash chip.");
|
||||||
(int)(c->base + c->size - run_address), (int)(run_size), (int)(c->size));
|
|
||||||
run_size = c->base + c->size - run_address;
|
run_size = c->base + c->size - run_address;
|
||||||
|
assert(run_size > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're applying any sector automagic, then pad this
|
/* If we're applying any sector automagic, then pad this
|
||||||
@@ -580,6 +721,12 @@ int flash_write_unlock(struct target *target, struct image *image,
|
|||||||
|
|
||||||
/* allocate buffer */
|
/* allocate buffer */
|
||||||
buffer = malloc(run_size);
|
buffer = malloc(run_size);
|
||||||
|
if (buffer == NULL)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Out of memory for flash bank buffer");
|
||||||
|
retval = ERROR_FAIL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
buffer_size = 0;
|
buffer_size = 0;
|
||||||
|
|
||||||
/* read sections to the buffer */
|
/* read sections to the buffer */
|
||||||
@@ -588,15 +735,25 @@ int flash_write_unlock(struct target *target, struct image *image,
|
|||||||
size_t size_read;
|
size_t size_read;
|
||||||
|
|
||||||
size_read = run_size - buffer_size;
|
size_read = run_size - buffer_size;
|
||||||
if (size_read > image->sections[section].size - section_offset)
|
if (size_read > sections[section]->size - section_offset)
|
||||||
size_read = image->sections[section].size - section_offset;
|
size_read = sections[section]->size - section_offset;
|
||||||
|
|
||||||
if ((retval = image_read_section(image, section, section_offset,
|
/* KLUDGE!
|
||||||
|
*
|
||||||
|
* #¤%#"%¤% we have to figure out the section # from the sorted
|
||||||
|
* list of pointers to sections to invoke image_read_section()...
|
||||||
|
*/
|
||||||
|
intptr_t diff = (intptr_t)sections[section] - (intptr_t)image->sections;
|
||||||
|
int t_section_num = diff / sizeof(struct imagesection);
|
||||||
|
|
||||||
|
LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, section_offset = %d, buffer_size = %d, size_read = %d",
|
||||||
|
(int)section,
|
||||||
|
(int)t_section_num, (int)section_offset, (int)buffer_size, (int)size_read);
|
||||||
|
if ((retval = image_read_section(image, t_section_num, section_offset,
|
||||||
size_read, buffer + buffer_size, &size_read)) != ERROR_OK || size_read == 0)
|
size_read, buffer + buffer_size, &size_read)) != ERROR_OK || size_read == 0)
|
||||||
{
|
{
|
||||||
free(buffer);
|
free(buffer);
|
||||||
free(padding);
|
goto done;
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* see if we need to pad the section */
|
/* see if we need to pad the section */
|
||||||
@@ -606,7 +763,7 @@ int flash_write_unlock(struct target *target, struct image *image,
|
|||||||
buffer_size += size_read;
|
buffer_size += size_read;
|
||||||
section_offset += size_read;
|
section_offset += size_read;
|
||||||
|
|
||||||
if (section_offset >= image->sections[section].size)
|
if (section_offset >= sections[section]->size)
|
||||||
{
|
{
|
||||||
section++;
|
section++;
|
||||||
section_offset = 0;
|
section_offset = 0;
|
||||||
@@ -625,7 +782,7 @@ int flash_write_unlock(struct target *target, struct image *image,
|
|||||||
{
|
{
|
||||||
/* calculate and erase sectors */
|
/* calculate and erase sectors */
|
||||||
retval = flash_erase_address_range(target,
|
retval = flash_erase_address_range(target,
|
||||||
do_pad, run_address, run_size);
|
true, run_address, run_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,14 +796,17 @@ int flash_write_unlock(struct target *target, struct image *image,
|
|||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
{
|
{
|
||||||
free(padding);
|
/* abort operation */
|
||||||
return retval; /* abort operation */
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (written != NULL)
|
if (written != NULL)
|
||||||
*written += run_size; /* add run size to total written counter */
|
*written += run_size; /* add run size to total written counter */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
done:
|
||||||
|
free(sections);
|
||||||
free(padding);
|
free(padding);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* Copyright (C) 2007,2008 Øyvind Harboe <oyvind.harboe@zylin.com> *
|
* Copyright (C) 2007,2008 Øyvind Harboe <oyvind.harboe@zylin.com> *
|
||||||
* Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
|
* Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
|
||||||
* Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
|
* Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
|
||||||
|
* Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published by *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
@@ -53,6 +54,10 @@ struct flash_sector
|
|||||||
* Indication of protection status: 0 = unprotected/unlocked,
|
* Indication of protection status: 0 = unprotected/unlocked,
|
||||||
* 1 = protected/locked, other = unknown. Set by
|
* 1 = protected/locked, other = unknown. Set by
|
||||||
* @c flash_driver_s::protect_check.
|
* @c flash_driver_s::protect_check.
|
||||||
|
*
|
||||||
|
* This information must be considered stale immediately.
|
||||||
|
* A million things could make it stale: power cycle,
|
||||||
|
* reset of target, code running on target, etc.
|
||||||
*/
|
*/
|
||||||
int is_protected;
|
int is_protected;
|
||||||
};
|
};
|
||||||
@@ -69,7 +74,7 @@ struct flash_sector
|
|||||||
*/
|
*/
|
||||||
struct flash_bank
|
struct flash_bank
|
||||||
{
|
{
|
||||||
char *name;
|
const char *name;
|
||||||
|
|
||||||
struct target *target; /**< Target to which this bank belongs. */
|
struct target *target; /**< Target to which this bank belongs. */
|
||||||
|
|
||||||
@@ -97,8 +102,6 @@ struct flash_bank
|
|||||||
|
|
||||||
/// Registers the 'flash' subsystem commands
|
/// Registers the 'flash' subsystem commands
|
||||||
int flash_register_commands(struct command_context *cmd_ctx);
|
int flash_register_commands(struct command_context *cmd_ctx);
|
||||||
/// Initializes the 'flash' subsystem drivers
|
|
||||||
int flash_init_drivers(struct command_context *cmd_ctx);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Erases @a length bytes in the @a target flash, starting at @a addr.
|
* Erases @a length bytes in the @a target flash, starting at @a addr.
|
||||||
@@ -110,6 +113,9 @@ int flash_init_drivers(struct command_context *cmd_ctx);
|
|||||||
int flash_erase_address_range(struct target *target,
|
int flash_erase_address_range(struct target *target,
|
||||||
bool pad, uint32_t addr, uint32_t length);
|
bool pad, uint32_t addr, uint32_t length);
|
||||||
|
|
||||||
|
int flash_unlock_address_range(struct target *target, uint32_t addr,
|
||||||
|
uint32_t length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes @a image into the @a target flash. The @a written parameter
|
* Writes @a image into the @a target flash. The @a written parameter
|
||||||
* will contain the
|
* will contain the
|
||||||
@@ -122,6 +128,7 @@ int flash_erase_address_range(struct target *target,
|
|||||||
*/
|
*/
|
||||||
int flash_write(struct target *target,
|
int flash_write(struct target *target,
|
||||||
struct image *image, uint32_t *written, int erase);
|
struct image *image, uint32_t *written, int erase);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forces targets to re-examine their erase/protection state.
|
* Forces targets to re-examine their erase/protection state.
|
||||||
* This routine must be called when the system may modify the status.
|
* This routine must be called when the system may modify the status.
|
||||||
@@ -129,6 +136,16 @@ int flash_write(struct target *target,
|
|||||||
void flash_set_dirty(void);
|
void flash_set_dirty(void);
|
||||||
/// @returns The number of flash banks currently defined.
|
/// @returns The number of flash banks currently defined.
|
||||||
int flash_get_bank_count(void);
|
int flash_get_bank_count(void);
|
||||||
|
/**
|
||||||
|
* Provides default read implementation for flash memory.
|
||||||
|
* @param bank The bank to read.
|
||||||
|
* @param buffer The data bytes read.
|
||||||
|
* @param offset The offset into the chip to read.
|
||||||
|
* @param count The number of bytes to read.
|
||||||
|
* @returns ERROR_OK if successful; otherwise, an error code.
|
||||||
|
*/
|
||||||
|
int default_flash_read(struct flash_bank *bank,
|
||||||
|
uint8_t *buffer, uint32_t offset, uint32_t count);
|
||||||
/**
|
/**
|
||||||
* Provides default erased-bank check handling. Checks to see if
|
* Provides default erased-bank check handling. Checks to see if
|
||||||
* the flash driver knows they are erased; if things look uncertain,
|
* the flash driver knows they are erased; if things look uncertain,
|
||||||
@@ -151,13 +168,22 @@ int default_flash_mem_blank_check(struct flash_bank *bank);
|
|||||||
* bank number: when two str9x banks are defined, then 'str9x.1' refers
|
* bank number: when two str9x banks are defined, then 'str9x.1' refers
|
||||||
* to the second.
|
* to the second.
|
||||||
*/
|
*/
|
||||||
struct flash_bank *get_flash_bank_by_name(const char *name);
|
int get_flash_bank_by_name(const char *name, struct flash_bank **bank_result);
|
||||||
/**
|
/**
|
||||||
* Returns a flash bank by the specified flash_bank_s bank_number, @a num.
|
* Returns the flash bank specified by @a name, which matches the
|
||||||
* @param num The flash bank number.
|
* driver name and a suffix (option) specify the driver-specific
|
||||||
* @returns A struct flash_bank for flash bank @a num, or NULL
|
* bank number. The suffix consists of the '.' and the driver-specific
|
||||||
|
* bank number: when two str9x banks are defined, then 'str9x.1' refers
|
||||||
|
* to the second.
|
||||||
*/
|
*/
|
||||||
struct flash_bank *get_flash_bank_by_num(int num);
|
struct flash_bank *get_flash_bank_by_name_noprobe(const char *name);
|
||||||
|
/**
|
||||||
|
* Returns the flash bank like get_flash_bank_by_name(), without probing.
|
||||||
|
* @param num The flash bank number.
|
||||||
|
* @param bank returned bank if fn returns ERROR_OK
|
||||||
|
* @returns ERROR_OK if successful
|
||||||
|
*/
|
||||||
|
int get_flash_bank_by_num(int num, struct flash_bank **bank);
|
||||||
/**
|
/**
|
||||||
* Retreives @a bank from a command argument, reporting errors parsing
|
* Retreives @a bank from a command argument, reporting errors parsing
|
||||||
* the bank identifier or retreiving the specified bank. The bank
|
* the bank identifier or retreiving the specified bank. The bank
|
||||||
@@ -180,8 +206,9 @@ struct flash_bank *get_flash_bank_by_num_noprobe(int num);
|
|||||||
* Returns the flash bank located at a specified address.
|
* Returns the flash bank located at a specified address.
|
||||||
* @param target The target, presumed to contain one or more banks.
|
* @param target The target, presumed to contain one or more banks.
|
||||||
* @param addr An address that is within the range of the bank.
|
* @param addr An address that is within the range of the bank.
|
||||||
|
* @param check return ERROR_OK and result_bank NULL if the bank does not exist
|
||||||
* @returns The struct flash_bank located at @a addr, or NULL.
|
* @returns The struct flash_bank located at @a addr, or NULL.
|
||||||
*/
|
*/
|
||||||
struct flash_bank *get_flash_bank_by_addr(struct target *target, uint32_t addr);
|
int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check, struct flash_bank **result_bank);
|
||||||
|
|
||||||
#endif // FLASH_NOR_CORE_H
|
#endif // FLASH_NOR_CORE_H
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* Copyright (C) 2007,2008 Øyvind Harboe <oyvind.harboe@zylin.com> *
|
* Copyright (C) 2007,2008 Øyvind Harboe <oyvind.harboe@zylin.com> *
|
||||||
* Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
|
* Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
|
||||||
* Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
|
* Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
|
||||||
|
* Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published by *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
@@ -53,7 +54,7 @@ struct flash_driver
|
|||||||
* Gives a human-readable name of this flash driver,
|
* Gives a human-readable name of this flash driver,
|
||||||
* This field is used to select and initialize the driver.
|
* This field is used to select and initialize the driver.
|
||||||
*/
|
*/
|
||||||
char *name;
|
const char *name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array of driver-specific commands to register. When called
|
* An array of driver-specific commands to register. When called
|
||||||
@@ -75,11 +76,12 @@ struct flash_driver
|
|||||||
* CMD_ARGV[2] = baseaddress
|
* CMD_ARGV[2] = baseaddress
|
||||||
* CMD_ARGV[3] = lengthbytes
|
* CMD_ARGV[3] = lengthbytes
|
||||||
* CMD_ARGV[4] = chip_width_in bytes
|
* CMD_ARGV[4] = chip_width_in bytes
|
||||||
* CMD_ARGV[5] = bus_width_bytes
|
* CMD_ARGV[5] = bus_width_in_bytes
|
||||||
* CMD_ARGV[6] = driver-specific parameters
|
* CMD_ARGV[6] = driver-specific parameters
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* For example, CMD_ARGV[4] = 16 bit flash, CMD_ARGV[5] = 32bit bus.
|
* For example, CMD_ARGV[4] = 2 (for 16 bit flash),
|
||||||
|
* CMD_ARGV[5] = 4 (for 32 bit bus).
|
||||||
*
|
*
|
||||||
* If extra arguments are provided (@a CMD_ARGC > 6), they will
|
* If extra arguments are provided (@a CMD_ARGC > 6), they will
|
||||||
* start in @a CMD_ARGV[6]. These can be used to implement
|
* start in @a CMD_ARGV[6]. These can be used to implement
|
||||||
@@ -103,9 +105,12 @@ struct flash_driver
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Bank/sector protection routine (target-specific).
|
* Bank/sector protection routine (target-specific).
|
||||||
* When called, the driver should disable 'flash write' bits (or
|
*
|
||||||
* enable 'erase protection' bits) for the given @a bank and @a
|
* When called, the driver should enable/disable protection
|
||||||
* sectors.
|
* for MINIMUM the range covered by first..last sectors
|
||||||
|
* inclusive. Some chips have alignment requirements will
|
||||||
|
* cause the actual range to be protected / unprotected to
|
||||||
|
* be larger than the first..last range.
|
||||||
*
|
*
|
||||||
* @param bank The bank to protect or unprotect.
|
* @param bank The bank to protect or unprotect.
|
||||||
* @param set If non-zero, enable protection; if 0, disable it.
|
* @param set If non-zero, enable protection; if 0, disable it.
|
||||||
@@ -129,6 +134,20 @@ struct flash_driver
|
|||||||
int (*write)(struct flash_bank *bank,
|
int (*write)(struct flash_bank *bank,
|
||||||
uint8_t *buffer, uint32_t offset, uint32_t count);
|
uint8_t *buffer, uint32_t offset, uint32_t count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read data from the flash. Note CPU address will be
|
||||||
|
* "bank->base + offset", while the physical address is
|
||||||
|
* dependent upon current target MMU mappings.
|
||||||
|
*
|
||||||
|
* @param bank The bank to read.
|
||||||
|
* @param buffer The data bytes read.
|
||||||
|
* @param offset The offset into the chip to read.
|
||||||
|
* @param count The number of bytes to read.
|
||||||
|
* @returns ERROR_OK if successful; otherwise, an error code.
|
||||||
|
*/
|
||||||
|
int (*read)(struct flash_bank *bank,
|
||||||
|
uint8_t *buffer, uint32_t offset, uint32_t count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Probe to determine what kind of flash is present.
|
* Probe to determine what kind of flash is present.
|
||||||
* This is invoked by the "probe" script command.
|
* This is invoked by the "probe" script command.
|
||||||
|
|||||||
@@ -32,19 +32,25 @@ extern struct flash_driver str9x_flash;
|
|||||||
extern struct flash_driver aduc702x_flash;
|
extern struct flash_driver aduc702x_flash;
|
||||||
extern struct flash_driver stellaris_flash;
|
extern struct flash_driver stellaris_flash;
|
||||||
extern struct flash_driver str9xpec_flash;
|
extern struct flash_driver str9xpec_flash;
|
||||||
extern struct flash_driver stm32x_flash;
|
extern struct flash_driver stm32f1x_flash;
|
||||||
|
extern struct flash_driver stm32f2x_flash;
|
||||||
extern struct flash_driver tms470_flash;
|
extern struct flash_driver tms470_flash;
|
||||||
extern struct flash_driver ecosflash_flash;
|
extern struct flash_driver ecosflash_flash;
|
||||||
extern struct flash_driver ocl_flash;
|
extern struct flash_driver ocl_flash;
|
||||||
extern struct flash_driver pic32mx_flash;
|
extern struct flash_driver pic32mx_flash;
|
||||||
extern struct flash_driver avr_flash;
|
extern struct flash_driver avr_flash;
|
||||||
extern struct flash_driver faux_flash;
|
extern struct flash_driver faux_flash;
|
||||||
|
extern struct flash_driver virtual_flash;
|
||||||
|
extern struct flash_driver stmsmi_flash;
|
||||||
|
extern struct flash_driver em357_flash;
|
||||||
|
//extern struct flash_driver dsp5680xx_flash;
|
||||||
|
extern struct flash_driver fm3_flash;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of built-in flash drivers.
|
* The list of built-in flash drivers.
|
||||||
* @todo Make this dynamically extendable with loadable modules.
|
* @todo Make this dynamically extendable with loadable modules.
|
||||||
*/
|
*/
|
||||||
struct flash_driver *flash_drivers[] = {
|
static struct flash_driver *flash_drivers[] = {
|
||||||
&lpc2000_flash,
|
&lpc2000_flash,
|
||||||
&lpc288x_flash,
|
&lpc288x_flash,
|
||||||
&lpc2900_flash,
|
&lpc2900_flash,
|
||||||
@@ -56,13 +62,20 @@ struct flash_driver *flash_drivers[] = {
|
|||||||
&aduc702x_flash,
|
&aduc702x_flash,
|
||||||
&stellaris_flash,
|
&stellaris_flash,
|
||||||
&str9xpec_flash,
|
&str9xpec_flash,
|
||||||
&stm32x_flash,
|
&stm32f1x_flash,
|
||||||
|
&stm32f2x_flash,
|
||||||
&tms470_flash,
|
&tms470_flash,
|
||||||
&ecosflash_flash,
|
&ecosflash_flash,
|
||||||
&ocl_flash,
|
&ocl_flash,
|
||||||
&pic32mx_flash,
|
&pic32mx_flash,
|
||||||
&avr_flash,
|
&avr_flash,
|
||||||
&faux_flash,
|
&faux_flash,
|
||||||
|
&virtual_flash,
|
||||||
|
&stmsmi_flash,
|
||||||
|
&em357_flash,
|
||||||
|
// Disabled for now, it generates warnings
|
||||||
|
//&dsp5680xx_flash,
|
||||||
|
&fm3_flash,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
245
src/flash/nor/dsp5680xx_flash.c
Normal file
245
src/flash/nor/dsp5680xx_flash.c
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2011 by Rodrigo L. Rosa *
|
||||||
|
* rodrigorosa.LG@gmail.com *
|
||||||
|
* *
|
||||||
|
* Based on a file written by: *
|
||||||
|
* Kevin McGuire *
|
||||||
|
* Marcel Wijlaars *
|
||||||
|
* Michael Ashton *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file dsp5680xx_flash.c
|
||||||
|
* @author Rodrigo L. Rosa <rodrigorosa.LG@gmail.com>
|
||||||
|
* @date Thu Jun 9 18:21:58 2011
|
||||||
|
*
|
||||||
|
* @brief This file implements the basic functions to run flashing commands
|
||||||
|
* from the TCL interface.
|
||||||
|
* It allows the user to flash the Freescale 5680xx DSP.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DSP5680XX_FLASH_H
|
||||||
|
#define DSP5680XX_FLASH_H
|
||||||
|
|
||||||
|
#include "imp.h"
|
||||||
|
#include <helper/binarybuffer.h>
|
||||||
|
#include <helper/time_support.h>
|
||||||
|
#include <target/algorithm.h>
|
||||||
|
#include <target/dsp5680xx.h>
|
||||||
|
|
||||||
|
struct dsp5680xx_flash_bank {
|
||||||
|
struct working_area *write_algorithm;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int dsp5680xx_build_sector_list(struct flash_bank *bank){
|
||||||
|
uint32_t offset = HFM_FLASH_BASE_ADDR;
|
||||||
|
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < bank->num_sectors; ++i){
|
||||||
|
bank->sectors[i].offset = i*HFM_SECTOR_SIZE;
|
||||||
|
bank->sectors[i].size = HFM_SECTOR_SIZE;
|
||||||
|
offset += bank->sectors[i].size;
|
||||||
|
bank->sectors[i].is_erased = -1;
|
||||||
|
bank->sectors[i].is_protected = -1;
|
||||||
|
}
|
||||||
|
LOG_USER("%s not tested yet.",__FUNCTION__);
|
||||||
|
return ERROR_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// flash bank dsp5680xx 0 0 0 0 <target#>
|
||||||
|
FLASH_BANK_COMMAND_HANDLER(dsp5680xx_flash_bank_command){
|
||||||
|
struct dsp5680xx_flash_bank *nbank;
|
||||||
|
|
||||||
|
nbank = malloc(sizeof(struct dsp5680xx_flash_bank));
|
||||||
|
|
||||||
|
bank->base = HFM_FLASH_BASE_ADDR;
|
||||||
|
bank->size = HFM_SIZE_BYTES; // top 4k not accessible
|
||||||
|
bank->driver_priv = nbank;
|
||||||
|
bank->num_sectors = HFM_SECTOR_COUNT;
|
||||||
|
dsp5680xx_build_sector_list(bank);
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A memory mapped register (PROT) holds information regarding sector protection.
|
||||||
|
* Protection refers to undesired core access.
|
||||||
|
* The value in this register is loaded from flash upon reset.
|
||||||
|
*
|
||||||
|
* @param bank
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static int dsp5680xx_flash_protect_check(struct flash_bank *bank){
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
uint16_t protected = 0;
|
||||||
|
retval = dsp5680xx_f_protect_check(bank->target,&protected);
|
||||||
|
if(retval != ERROR_OK){
|
||||||
|
for(int i = 0;i<HFM_SECTOR_COUNT;i++)
|
||||||
|
bank->sectors[i].is_protected = -1;
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
for(int i = 0;i<HFM_SECTOR_COUNT/2;i++){
|
||||||
|
if(protected & 1){
|
||||||
|
bank->sectors[2*i].is_protected = 1;
|
||||||
|
bank->sectors[2*i+1].is_protected = 1;
|
||||||
|
}else{
|
||||||
|
bank->sectors[2*i].is_protected = 0;
|
||||||
|
bank->sectors[2*i+1].is_protected = 0;
|
||||||
|
}
|
||||||
|
protected = (protected >> 1);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protection funcionality is not implemented.
|
||||||
|
* The current implementation applies/removes security on the chip.
|
||||||
|
* The chip is effectively secured/unsecured after the first reset following the execution of this function.
|
||||||
|
*
|
||||||
|
* @param bank
|
||||||
|
* @param set Apply or remove security on the chip.
|
||||||
|
* @param first This parameter is ignored.
|
||||||
|
* @param last This parameter is ignored.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first, int last){
|
||||||
|
// This applies security to flash module after next reset, it does not actually apply protection (protection refers to undesired access from the core)
|
||||||
|
int retval;
|
||||||
|
if(set)
|
||||||
|
retval = dsp5680xx_f_lock(bank->target);
|
||||||
|
else
|
||||||
|
retval = dsp5680xx_f_unlock(bank->target);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The dsp5680xx use word addressing. The "/2" that appear in the following code are a workaround for the fact that OpenOCD uses byte addressing.
|
||||||
|
*
|
||||||
|
* @param bank
|
||||||
|
* @param buffer Data to write to flash.
|
||||||
|
* @param offset
|
||||||
|
* @param count In bytes (2 bytes per address).
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static int dsp5680xx_flash_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count){
|
||||||
|
int retval;
|
||||||
|
if((offset + count/2)>bank->size){
|
||||||
|
LOG_ERROR("%s: Flash bank cannot fit data.",__FUNCTION__);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
if(offset%2){
|
||||||
|
LOG_ERROR("%s: Writing to odd addresses not supported. This chip uses word addressing, Openocd only supports byte addressing. The workaround results in disabling writing to odd byte addresses.",__FUNCTION__);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
retval = dsp5680xx_f_wr(bank->target, buffer, bank->base + offset/2, count);
|
||||||
|
uint32_t addr_word;
|
||||||
|
for(addr_word = bank->base + offset/2;addr_word<count/2;addr_word+=(HFM_SECTOR_SIZE/2)){
|
||||||
|
if(retval == ERROR_OK)
|
||||||
|
bank->sectors[addr_word/(HFM_SECTOR_SIZE/2)].is_erased = 0;
|
||||||
|
else
|
||||||
|
bank->sectors[addr_word/(HFM_SECTOR_SIZE/2)].is_erased = -1;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dsp5680xx_probe(struct flash_bank *bank){
|
||||||
|
LOG_DEBUG("%s not implemented",__FUNCTION__);
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dsp5680xx_flash_info(struct flash_bank *bank, char *buf, int buf_size){
|
||||||
|
snprintf(buf, buf_size, "\ndsp5680xx flash driver info:\n - Currently only full erase/lock/unlock are implemented. \n - Call with bank==0 and sector 0 to 0.\n - Protect requires arp_init-reset to complete. \n - Before removing protection the master tap must be selected, and arp_init-reset is required to complete unlocking.");
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The flash module (FM) on the dsp5680xx supports both individual sector and mass erase of the flash memory.
|
||||||
|
* If this function is called with @first == @last == 0 or if @first is the first sector (#0) and @last is the last sector then the mass erase command is executed (much faster than erasing each sector individually).
|
||||||
|
*
|
||||||
|
* @param bank
|
||||||
|
* @param first
|
||||||
|
* @param last
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static int dsp5680xx_flash_erase(struct flash_bank * bank, int first, int last){
|
||||||
|
int retval;
|
||||||
|
retval = dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last);
|
||||||
|
if(retval == ERROR_OK)
|
||||||
|
for(int i = first;i<=last;i++)
|
||||||
|
bank->sectors[i].is_erased = 1;
|
||||||
|
else
|
||||||
|
// If an error occurred unknown status is set even though some sector could have been correctly erased.
|
||||||
|
for(int i = first;i<=last;i++)
|
||||||
|
bank->sectors[i].is_erased = -1;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The flash module (FM) on the dsp5680xx support a blank check function.
|
||||||
|
* This function executes the FM's blank check functionality on each and every sector.
|
||||||
|
*
|
||||||
|
* @param bank
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static int dsp5680xx_flash_erase_check(struct flash_bank * bank){
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
uint8_t erased = 0;
|
||||||
|
uint32_t i;
|
||||||
|
for(i=0;i<HFM_SECTOR_COUNT;i++){
|
||||||
|
if(bank->sectors[i].is_erased == -1){
|
||||||
|
retval = dsp5680xx_f_erase_check(bank->target,&erased,i);
|
||||||
|
if (retval != ERROR_OK){
|
||||||
|
bank->sectors[i].is_erased = -1;
|
||||||
|
}else{
|
||||||
|
if(erased)
|
||||||
|
bank->sectors[i].is_erased = 1;
|
||||||
|
else
|
||||||
|
bank->sectors[i].is_erased = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct flash_driver dsp5680xx_flash = {
|
||||||
|
.name = "dsp5680xx_flash",
|
||||||
|
.flash_bank_command = dsp5680xx_flash_bank_command,
|
||||||
|
.erase = dsp5680xx_flash_erase,
|
||||||
|
.protect = dsp5680xx_flash_protect,
|
||||||
|
.write = dsp5680xx_flash_write,
|
||||||
|
//.read = default_flash_read,
|
||||||
|
.probe = dsp5680xx_probe,
|
||||||
|
.auto_probe = dsp5680xx_probe,
|
||||||
|
.erase_check = dsp5680xx_flash_erase_check,
|
||||||
|
.protect_check = dsp5680xx_flash_protect_check,
|
||||||
|
.info = dsp5680xx_flash_info
|
||||||
|
};
|
||||||
|
#endif // dsp5680xx_flash.h
|
||||||
@@ -173,7 +173,6 @@ static int loadDriver(struct ecosflash_flash_bank *info)
|
|||||||
for (i = 0; i < image.num_sections; i++)
|
for (i = 0; i < image.num_sections; i++)
|
||||||
{
|
{
|
||||||
void *buffer = malloc(image.sections[i].size);
|
void *buffer = malloc(image.sections[i].size);
|
||||||
int retval;
|
|
||||||
if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
|
if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
|
||||||
{
|
{
|
||||||
free(buffer);
|
free(buffer);
|
||||||
@@ -265,7 +264,7 @@ static int eCosBoard_erase(struct ecosflash_flash_bank *info, uint32_t address,
|
|||||||
|
|
||||||
if (flashErr != 0x0)
|
if (flashErr != 0x0)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Flash erase failed with %d (%s)\n", (int)flashErr, flash_errmsg(flashErr));
|
LOG_ERROR("Flash erase failed with %d (%s)", (int)flashErr, flash_errmsg(flashErr));
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +304,6 @@ static int eCosBoard_flash(struct ecosflash_flash_bank *info, void *data, uint32
|
|||||||
t = chunk;
|
t = chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
int retval;
|
|
||||||
retval = target_write_buffer(target, buffer, t, ((uint8_t *)data) + i);
|
retval = target_write_buffer(target, buffer, t, ((uint8_t *)data) + i);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
@@ -324,7 +322,7 @@ static int eCosBoard_flash(struct ecosflash_flash_bank *info, void *data, uint32
|
|||||||
|
|
||||||
if (flashErr != 0x0)
|
if (flashErr != 0x0)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Flash prog failed with %d (%s)\n", (int)flashErr, flash_errmsg(flashErr));
|
LOG_ERROR("Flash prog failed with %d (%s)", (int)flashErr, flash_errmsg(flashErr));
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -436,6 +434,7 @@ struct flash_driver ecosflash_flash = {
|
|||||||
.erase = ecosflash_erase,
|
.erase = ecosflash_erase,
|
||||||
.protect = ecosflash_protect,
|
.protect = ecosflash_protect,
|
||||||
.write = ecosflash_write,
|
.write = ecosflash_write,
|
||||||
|
.read = default_flash_read,
|
||||||
.probe = ecosflash_probe,
|
.probe = ecosflash_probe,
|
||||||
.auto_probe = ecosflash_probe,
|
.auto_probe = ecosflash_probe,
|
||||||
.erase_check = default_flash_blank_check,
|
.erase_check = default_flash_blank_check,
|
||||||
|
|||||||
974
src/flash/nor/em357.c
Normal file
974
src/flash/nor/em357.c
Normal file
@@ -0,0 +1,974 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2005 by Dominic Rath *
|
||||||
|
* Dominic.Rath@gmx.de *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2008 by Spencer Oliver *
|
||||||
|
* spen@spen-soft.co.uk *
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 by Erik Botö
|
||||||
|
* erik.boto@pelagicore.com
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "imp.h"
|
||||||
|
#include <helper/binarybuffer.h>
|
||||||
|
#include <target/algorithm.h>
|
||||||
|
#include <target/armv7m.h>
|
||||||
|
|
||||||
|
/* em357 register locations */
|
||||||
|
|
||||||
|
#define EM357_FLASH_ACR 0x40008000
|
||||||
|
#define EM357_FLASH_KEYR 0x40008004
|
||||||
|
#define EM357_FLASH_OPTKEYR 0x40008008
|
||||||
|
#define EM357_FLASH_SR 0x4000800C
|
||||||
|
#define EM357_FLASH_CR 0x40008010
|
||||||
|
#define EM357_FLASH_AR 0x40008014
|
||||||
|
#define EM357_FLASH_OBR 0x4000801C
|
||||||
|
#define EM357_FLASH_WRPR 0x40008020
|
||||||
|
|
||||||
|
#define EM357_FPEC_CLK 0x4000402c
|
||||||
|
/* option byte location */
|
||||||
|
|
||||||
|
#define EM357_OB_RDP 0x08040800
|
||||||
|
#define EM357_OB_WRP0 0x08040808
|
||||||
|
#define EM357_OB_WRP1 0x0804080A
|
||||||
|
#define EM357_OB_WRP2 0x0804080C
|
||||||
|
|
||||||
|
/* FLASH_CR register bits */
|
||||||
|
|
||||||
|
#define FLASH_PG (1 << 0)
|
||||||
|
#define FLASH_PER (1 << 1)
|
||||||
|
#define FLASH_MER (1 << 2)
|
||||||
|
#define FLASH_OPTPG (1 << 4)
|
||||||
|
#define FLASH_OPTER (1 << 5)
|
||||||
|
#define FLASH_STRT (1 << 6)
|
||||||
|
#define FLASH_LOCK (1 << 7)
|
||||||
|
#define FLASH_OPTWRE (1 << 9)
|
||||||
|
|
||||||
|
/* FLASH_SR register bits */
|
||||||
|
|
||||||
|
#define FLASH_BSY (1 << 0)
|
||||||
|
#define FLASH_PGERR (1 << 2)
|
||||||
|
#define FLASH_WRPRTERR (1 << 4)
|
||||||
|
#define FLASH_EOP (1 << 5)
|
||||||
|
|
||||||
|
/* EM357_FLASH_OBR bit definitions (reading) */
|
||||||
|
|
||||||
|
#define OPT_ERROR 0
|
||||||
|
#define OPT_READOUT 1
|
||||||
|
|
||||||
|
/* register unlock keys */
|
||||||
|
|
||||||
|
#define KEY1 0x45670123
|
||||||
|
#define KEY2 0xCDEF89AB
|
||||||
|
|
||||||
|
struct em357_options
|
||||||
|
{
|
||||||
|
uint16_t RDP;
|
||||||
|
uint16_t user_options;
|
||||||
|
uint16_t protection[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct em357_flash_bank
|
||||||
|
{
|
||||||
|
struct em357_options option_bytes;
|
||||||
|
struct working_area *write_algorithm;
|
||||||
|
int ppage_size;
|
||||||
|
int probed;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int em357_mass_erase(struct flash_bank *bank);
|
||||||
|
|
||||||
|
/* flash bank em357 <base> <size> 0 0 <target#>
|
||||||
|
*/
|
||||||
|
FLASH_BANK_COMMAND_HANDLER(em357_flash_bank_command)
|
||||||
|
{
|
||||||
|
struct em357_flash_bank *em357_info;
|
||||||
|
|
||||||
|
if (CMD_ARGC < 6)
|
||||||
|
{
|
||||||
|
LOG_WARNING("incomplete flash_bank em357 configuration");
|
||||||
|
return ERROR_FLASH_BANK_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
em357_info = malloc(sizeof(struct em357_flash_bank));
|
||||||
|
bank->driver_priv = em357_info;
|
||||||
|
|
||||||
|
em357_info->write_algorithm = NULL;
|
||||||
|
em357_info->probed = 0;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int em357_get_flash_status(struct flash_bank *bank, uint32_t *status)
|
||||||
|
{
|
||||||
|
struct target *target = bank->target;
|
||||||
|
return target_read_u32(target, EM357_FLASH_SR, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int em357_wait_status_busy(struct flash_bank *bank, int timeout)
|
||||||
|
{
|
||||||
|
struct target *target = bank->target;
|
||||||
|
uint32_t status;
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
|
/* wait for busy to clear */
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
retval = em357_get_flash_status(bank, &status);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
LOG_DEBUG("status: 0x%" PRIx32 "", status);
|
||||||
|
if ((status & FLASH_BSY) == 0)
|
||||||
|
break;
|
||||||
|
if (timeout-- <= 0)
|
||||||
|
{
|
||||||
|
LOG_ERROR("timed out waiting for flash");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
alive_sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status & FLASH_WRPRTERR)
|
||||||
|
{
|
||||||
|
LOG_ERROR("em357 device protected");
|
||||||
|
retval = ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status & FLASH_PGERR)
|
||||||
|
{
|
||||||
|
LOG_ERROR("em357 device programming failed");
|
||||||
|
retval = ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear but report errors */
|
||||||
|
if (status & (FLASH_WRPRTERR | FLASH_PGERR))
|
||||||
|
{
|
||||||
|
/* If this operation fails, we ignore it and report the original
|
||||||
|
* retval
|
||||||
|
*/
|
||||||
|
target_write_u32(target, EM357_FLASH_SR, FLASH_WRPRTERR | FLASH_PGERR);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int em357_read_options(struct flash_bank *bank)
|
||||||
|
{
|
||||||
|
uint32_t optiondata;
|
||||||
|
struct em357_flash_bank *em357_info = NULL;
|
||||||
|
struct target *target = bank->target;
|
||||||
|
|
||||||
|
em357_info = bank->driver_priv;
|
||||||
|
|
||||||
|
/* read current option bytes */
|
||||||
|
int retval = target_read_u32(target, EM357_FLASH_OBR, &optiondata);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
em357_info->option_bytes.user_options = (uint16_t)0xFFFC | ((optiondata >> 2) & 0x03);
|
||||||
|
em357_info->option_bytes.RDP = (optiondata & (1 << OPT_READOUT)) ? 0xFFFF : 0x5AA5;
|
||||||
|
|
||||||
|
if (optiondata & (1 << OPT_READOUT))
|
||||||
|
LOG_INFO("Device Security Bit Set");
|
||||||
|
|
||||||
|
/* each bit refers to a 4bank protection */
|
||||||
|
retval = target_read_u32(target, EM357_FLASH_WRPR, &optiondata);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
em357_info->option_bytes.protection[0] = (uint16_t)optiondata;
|
||||||
|
em357_info->option_bytes.protection[1] = (uint16_t)(optiondata >> 8);
|
||||||
|
em357_info->option_bytes.protection[2] = (uint16_t)(optiondata >> 16);
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int em357_erase_options(struct flash_bank *bank)
|
||||||
|
{
|
||||||
|
struct em357_flash_bank *em357_info = NULL;
|
||||||
|
struct target *target = bank->target;
|
||||||
|
|
||||||
|
em357_info = bank->driver_priv;
|
||||||
|
|
||||||
|
/* read current options */
|
||||||
|
em357_read_options(bank);
|
||||||
|
|
||||||
|
/* unlock flash registers */
|
||||||
|
int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* unlock option flash registers */
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY2);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* erase option bytes */
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_OPTER | FLASH_OPTWRE);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_OPTER | FLASH_STRT | FLASH_OPTWRE);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = em357_wait_status_busy(bank, 10);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* clear readout protection and complementary option bytes
|
||||||
|
* this will also force a device unlock if set */
|
||||||
|
em357_info->option_bytes.RDP = 0x5AA5;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int em357_write_options(struct flash_bank *bank)
|
||||||
|
{
|
||||||
|
struct em357_flash_bank *em357_info = NULL;
|
||||||
|
struct target *target = bank->target;
|
||||||
|
|
||||||
|
em357_info = bank->driver_priv;
|
||||||
|
|
||||||
|
/* unlock flash registers */
|
||||||
|
int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* unlock option flash registers */
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY2);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* program option bytes */
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_OPTPG | FLASH_OPTWRE);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = em357_wait_status_busy(bank, 10);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* write protection byte 1 */
|
||||||
|
retval = target_write_u16(target, EM357_OB_WRP0, em357_info->option_bytes.protection[0]);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = em357_wait_status_busy(bank, 10);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* write protection byte 2 */
|
||||||
|
retval = target_write_u16(target, EM357_OB_WRP1, em357_info->option_bytes.protection[1]);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = em357_wait_status_busy(bank, 10);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* write protection byte 3 */
|
||||||
|
retval = target_write_u16(target, EM357_OB_WRP2, em357_info->option_bytes.protection[2]);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = em357_wait_status_busy(bank, 10);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* write readout protection bit */
|
||||||
|
retval = target_write_u16(target, EM357_OB_RDP, em357_info->option_bytes.RDP);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = em357_wait_status_busy(bank, 10);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int em357_protect_check(struct flash_bank *bank)
|
||||||
|
{
|
||||||
|
struct target *target = bank->target;
|
||||||
|
struct em357_flash_bank *em357_info = bank->driver_priv;
|
||||||
|
|
||||||
|
uint32_t protection;
|
||||||
|
int i, s;
|
||||||
|
int num_bits;
|
||||||
|
int set;
|
||||||
|
|
||||||
|
if (target->state != TARGET_HALTED)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Target not halted");
|
||||||
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* each bit refers to a 4bank protection (bit 0-23) */
|
||||||
|
int retval = target_read_u32(target, EM357_FLASH_WRPR, &protection);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* each protection bit is for 4 * 2K pages */
|
||||||
|
num_bits = (bank->num_sectors / em357_info->ppage_size);
|
||||||
|
|
||||||
|
for (i = 0; i < num_bits; i++)
|
||||||
|
{
|
||||||
|
set = 1;
|
||||||
|
if (protection & (1 << i))
|
||||||
|
set = 0;
|
||||||
|
|
||||||
|
for (s = 0; s < em357_info->ppage_size; s++)
|
||||||
|
bank->sectors[(i * em357_info->ppage_size) + s].is_protected = set;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int em357_erase(struct flash_bank *bank, int first, int last)
|
||||||
|
{
|
||||||
|
struct target *target = bank->target;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (bank->target->state != TARGET_HALTED)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Target not halted");
|
||||||
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((first == 0) && (last == (bank->num_sectors - 1)))
|
||||||
|
{
|
||||||
|
return em357_mass_erase(bank);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unlock flash registers */
|
||||||
|
int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
for (i = first; i <= last; i++)
|
||||||
|
{
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PER);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_AR,
|
||||||
|
bank->base + bank->sectors[i].offset);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PER | FLASH_STRT);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = em357_wait_status_busy(bank, 100);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
bank->sectors[i].is_erased = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int em357_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
|
{
|
||||||
|
struct em357_flash_bank *em357_info = NULL;
|
||||||
|
struct target *target = bank->target;
|
||||||
|
uint16_t prot_reg[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
|
||||||
|
int i, reg, bit;
|
||||||
|
int status;
|
||||||
|
uint32_t protection;
|
||||||
|
|
||||||
|
em357_info = bank->driver_priv;
|
||||||
|
|
||||||
|
if (target->state != TARGET_HALTED)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Target not halted");
|
||||||
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((first % em357_info->ppage_size) != 0)
|
||||||
|
{
|
||||||
|
LOG_WARNING("aligned start protect sector to a %d sector boundary",
|
||||||
|
em357_info->ppage_size);
|
||||||
|
first = first - (first % em357_info->ppage_size);
|
||||||
|
}
|
||||||
|
if (((last + 1) % em357_info->ppage_size) != 0)
|
||||||
|
{
|
||||||
|
LOG_WARNING("aligned end protect sector to a %d sector boundary",
|
||||||
|
em357_info->ppage_size);
|
||||||
|
last++;
|
||||||
|
last = last - (last % em357_info->ppage_size);
|
||||||
|
last--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* each bit refers to a 4bank protection */
|
||||||
|
int retval = target_read_u32(target, EM357_FLASH_WRPR, &protection);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
prot_reg[0] = (uint16_t)protection;
|
||||||
|
prot_reg[1] = (uint16_t)(protection >> 8);
|
||||||
|
prot_reg[2] = (uint16_t)(protection >> 16);
|
||||||
|
|
||||||
|
for (i = first; i <= last; i++)
|
||||||
|
{
|
||||||
|
reg = (i / em357_info->ppage_size) / 8;
|
||||||
|
bit = (i / em357_info->ppage_size) - (reg * 8);
|
||||||
|
|
||||||
|
LOG_WARNING("reg, bit: %d, %d", reg, bit);
|
||||||
|
if (set)
|
||||||
|
prot_reg[reg] &= ~(1 << bit);
|
||||||
|
else
|
||||||
|
prot_reg[reg] |= (1 << bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status = em357_erase_options(bank)) != ERROR_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
em357_info->option_bytes.protection[0] = prot_reg[0];
|
||||||
|
em357_info->option_bytes.protection[1] = prot_reg[1];
|
||||||
|
em357_info->option_bytes.protection[2] = prot_reg[2];
|
||||||
|
|
||||||
|
return em357_write_options(bank);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int em357_write_block(struct flash_bank *bank, uint8_t *buffer,
|
||||||
|
uint32_t offset, uint32_t count)
|
||||||
|
{
|
||||||
|
struct em357_flash_bank *em357_info = bank->driver_priv;
|
||||||
|
struct target *target = bank->target;
|
||||||
|
uint32_t buffer_size = 16384;
|
||||||
|
struct working_area *source;
|
||||||
|
uint32_t address = bank->base + offset;
|
||||||
|
struct reg_param reg_params[4];
|
||||||
|
struct armv7m_algorithm armv7m_info;
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
|
/* see contib/loaders/flash/stm32x.s for src, the same is used here except for
|
||||||
|
* a modified *_FLASH_BASE */
|
||||||
|
|
||||||
|
static const uint8_t em357_flash_write_code[] = {
|
||||||
|
/* #define EM357_FLASH_CR_OFFSET 0x10 */
|
||||||
|
/* #define EM357_FLASH_SR_OFFSET 0x0C */
|
||||||
|
/* write: */
|
||||||
|
0x08, 0x4c, /* ldr r4, EM357_FLASH_BASE */
|
||||||
|
0x1c, 0x44, /* add r4, r3 */
|
||||||
|
/* write_half_word: */
|
||||||
|
0x01, 0x23, /* movs r3, #0x01 */
|
||||||
|
0x23, 0x61, /* str r3, [r4, #EM357_FLASH_CR_OFFSET] */
|
||||||
|
0x30, 0xf8, 0x02, 0x3b, /* ldrh r3, [r0], #0x02 */
|
||||||
|
0x21, 0xf8, 0x02, 0x3b, /* strh r3, [r1], #0x02 */
|
||||||
|
/* busy: */
|
||||||
|
0xe3, 0x68, /* ldr r3, [r4, #EM357_FLASH_SR_OFFSET] */
|
||||||
|
0x13, 0xf0, 0x01, 0x0f, /* tst r3, #0x01 */
|
||||||
|
0xfb, 0xd0, /* beq busy */
|
||||||
|
0x13, 0xf0, 0x14, 0x0f, /* tst r3, #0x14 */
|
||||||
|
0x01, 0xd1, /* bne exit */
|
||||||
|
0x01, 0x3a, /* subs r2, r2, #0x01 */
|
||||||
|
0xf0, 0xd1, /* bne write_half_word */
|
||||||
|
/* exit: */
|
||||||
|
0x00, 0xbe, /* bkpt #0x00 */
|
||||||
|
0x00, 0x80, 0x00, 0x40, /* EM357_FLASH_BASE: .word 0x40008000 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* flash write code */
|
||||||
|
if (target_alloc_working_area(target, sizeof(em357_flash_write_code),
|
||||||
|
&em357_info->write_algorithm) != ERROR_OK)
|
||||||
|
{
|
||||||
|
LOG_WARNING("no working area available, can't do block memory writes");
|
||||||
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((retval = target_write_buffer(target, em357_info->write_algorithm->address,
|
||||||
|
sizeof(em357_flash_write_code),
|
||||||
|
(uint8_t*)em357_flash_write_code)) != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* memory buffer */
|
||||||
|
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
|
||||||
|
{
|
||||||
|
buffer_size /= 2;
|
||||||
|
if (buffer_size <= 256)
|
||||||
|
{
|
||||||
|
/* if we already allocated the writing code, but failed to get a
|
||||||
|
* buffer, free the algorithm */
|
||||||
|
if (em357_info->write_algorithm)
|
||||||
|
target_free_working_area(target, em357_info->write_algorithm);
|
||||||
|
|
||||||
|
LOG_WARNING("no large enough working area available, can't do block memory writes");
|
||||||
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
|
||||||
|
armv7m_info.core_mode = ARMV7M_MODE_ANY;
|
||||||
|
|
||||||
|
init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
|
||||||
|
init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
|
||||||
|
init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
|
||||||
|
init_reg_param(®_params[3], "r3", 32, PARAM_IN_OUT);
|
||||||
|
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
uint32_t thisrun_count = (count > (buffer_size / 2)) ?
|
||||||
|
(buffer_size / 2) : count;
|
||||||
|
|
||||||
|
if ((retval = target_write_buffer(target, source->address,
|
||||||
|
thisrun_count * 2, buffer)) != ERROR_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
buf_set_u32(reg_params[0].value, 0, 32, source->address);
|
||||||
|
buf_set_u32(reg_params[1].value, 0, 32, address);
|
||||||
|
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
|
||||||
|
buf_set_u32(reg_params[3].value, 0, 32, 0);
|
||||||
|
|
||||||
|
if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
|
||||||
|
em357_info->write_algorithm->address,
|
||||||
|
0,
|
||||||
|
10000, &armv7m_info)) != ERROR_OK)
|
||||||
|
{
|
||||||
|
LOG_ERROR("error executing em357 flash write algorithm");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_PGERR)
|
||||||
|
{
|
||||||
|
LOG_ERROR("flash memory not erased before writing");
|
||||||
|
/* Clear but report errors */
|
||||||
|
target_write_u32(target, EM357_FLASH_SR, FLASH_PGERR);
|
||||||
|
retval = ERROR_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_WRPRTERR)
|
||||||
|
{
|
||||||
|
LOG_ERROR("flash memory write protected");
|
||||||
|
/* Clear but report errors */
|
||||||
|
target_write_u32(target, EM357_FLASH_SR, FLASH_WRPRTERR);
|
||||||
|
retval = ERROR_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer += thisrun_count * 2;
|
||||||
|
address += thisrun_count * 2;
|
||||||
|
count -= thisrun_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_free_working_area(target, source);
|
||||||
|
target_free_working_area(target, em357_info->write_algorithm);
|
||||||
|
|
||||||
|
destroy_reg_param(®_params[0]);
|
||||||
|
destroy_reg_param(®_params[1]);
|
||||||
|
destroy_reg_param(®_params[2]);
|
||||||
|
destroy_reg_param(®_params[3]);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int em357_write(struct flash_bank *bank, uint8_t *buffer,
|
||||||
|
uint32_t offset, uint32_t count)
|
||||||
|
{
|
||||||
|
struct target *target = bank->target;
|
||||||
|
uint32_t words_remaining = (count / 2);
|
||||||
|
uint32_t bytes_remaining = (count & 0x00000001);
|
||||||
|
uint32_t address = bank->base + offset;
|
||||||
|
uint32_t bytes_written = 0;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
if (bank->target->state != TARGET_HALTED)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Target not halted");
|
||||||
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset & 0x1)
|
||||||
|
{
|
||||||
|
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
|
||||||
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unlock flash registers */
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* multiple half words (2-byte) to be programmed? */
|
||||||
|
if (words_remaining > 0)
|
||||||
|
{
|
||||||
|
/* try using a block write */
|
||||||
|
if ((retval = em357_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
|
||||||
|
{
|
||||||
|
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
|
||||||
|
{
|
||||||
|
/* if block write failed (no sufficient working area),
|
||||||
|
* we use normal (slow) single dword accesses */
|
||||||
|
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer += words_remaining * 2;
|
||||||
|
address += words_remaining * 2;
|
||||||
|
words_remaining = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE))
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
while (words_remaining > 0)
|
||||||
|
{
|
||||||
|
uint16_t value;
|
||||||
|
memcpy(&value, buffer + bytes_written, sizeof(uint16_t));
|
||||||
|
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PG);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = target_write_u16(target, address, value);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = em357_wait_status_busy(bank, 5);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
bytes_written += 2;
|
||||||
|
words_remaining--;
|
||||||
|
address += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes_remaining)
|
||||||
|
{
|
||||||
|
uint16_t value = 0xffff;
|
||||||
|
memcpy(&value, buffer + bytes_written, bytes_remaining);
|
||||||
|
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PG);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = target_write_u16(target, address, value);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = em357_wait_status_busy(bank, 5);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
return target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int em357_probe(struct flash_bank *bank)
|
||||||
|
{
|
||||||
|
struct target *target = bank->target;
|
||||||
|
struct em357_flash_bank *em357_info = bank->driver_priv;
|
||||||
|
int i;
|
||||||
|
uint16_t num_pages;
|
||||||
|
int page_size;
|
||||||
|
uint32_t base_address = 0x08000000;
|
||||||
|
|
||||||
|
em357_info->probed = 0;
|
||||||
|
|
||||||
|
/* Enable FPEC CLK */
|
||||||
|
int retval = target_write_u32(target, EM357_FPEC_CLK, 0x00000001);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
page_size = 2048;
|
||||||
|
em357_info->ppage_size = 4;
|
||||||
|
num_pages = 96;
|
||||||
|
|
||||||
|
LOG_INFO("flash size = %dkbytes", num_pages*page_size/1024);
|
||||||
|
|
||||||
|
if (bank->sectors)
|
||||||
|
{
|
||||||
|
free(bank->sectors);
|
||||||
|
bank->sectors = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bank->base = base_address;
|
||||||
|
bank->size = (num_pages * page_size);
|
||||||
|
bank->num_sectors = num_pages;
|
||||||
|
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
|
||||||
|
|
||||||
|
for (i = 0; i < num_pages; i++)
|
||||||
|
{
|
||||||
|
bank->sectors[i].offset = i * page_size;
|
||||||
|
bank->sectors[i].size = page_size;
|
||||||
|
bank->sectors[i].is_erased = -1;
|
||||||
|
bank->sectors[i].is_protected = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
em357_info->probed = 1;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int em357_auto_probe(struct flash_bank *bank)
|
||||||
|
{
|
||||||
|
struct em357_flash_bank *em357_info = bank->driver_priv;
|
||||||
|
if (em357_info->probed)
|
||||||
|
return ERROR_OK;
|
||||||
|
return em357_probe(bank);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int get_em357_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
|
{
|
||||||
|
int printed;
|
||||||
|
printed = snprintf(buf, buf_size, "em357\n");
|
||||||
|
buf += printed;
|
||||||
|
buf_size -= printed;
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
COMMAND_HANDLER(em357_handle_lock_command)
|
||||||
|
{
|
||||||
|
struct target *target = NULL;
|
||||||
|
struct em357_flash_bank *em357_info = NULL;
|
||||||
|
|
||||||
|
if (CMD_ARGC < 1)
|
||||||
|
{
|
||||||
|
command_print(CMD_CTX, "em357 lock <bank>");
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct flash_bank *bank;
|
||||||
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
if (ERROR_OK != retval)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
em357_info = bank->driver_priv;
|
||||||
|
|
||||||
|
target = bank->target;
|
||||||
|
|
||||||
|
if (target->state != TARGET_HALTED)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Target not halted");
|
||||||
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (em357_erase_options(bank) != ERROR_OK)
|
||||||
|
{
|
||||||
|
command_print(CMD_CTX, "em357 failed to erase options");
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set readout protection */
|
||||||
|
em357_info->option_bytes.RDP = 0;
|
||||||
|
|
||||||
|
if (em357_write_options(bank) != ERROR_OK)
|
||||||
|
{
|
||||||
|
command_print(CMD_CTX, "em357 failed to lock device");
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
command_print(CMD_CTX, "em357 locked");
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
COMMAND_HANDLER(em357_handle_unlock_command)
|
||||||
|
{
|
||||||
|
struct target *target = NULL;
|
||||||
|
|
||||||
|
if (CMD_ARGC < 1)
|
||||||
|
{
|
||||||
|
command_print(CMD_CTX, "em357 unlock <bank>");
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct flash_bank *bank;
|
||||||
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
if (ERROR_OK != retval)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
target = bank->target;
|
||||||
|
|
||||||
|
if (target->state != TARGET_HALTED)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Target not halted");
|
||||||
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (em357_erase_options(bank) != ERROR_OK)
|
||||||
|
{
|
||||||
|
command_print(CMD_CTX, "em357 failed to unlock device");
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (em357_write_options(bank) != ERROR_OK)
|
||||||
|
{
|
||||||
|
command_print(CMD_CTX, "em357 failed to lock device");
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
command_print(CMD_CTX, "em357 unlocked.\n"
|
||||||
|
"INFO: a reset or power cycle is required "
|
||||||
|
"for the new settings to take effect.");
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int em357_mass_erase(struct flash_bank *bank)
|
||||||
|
{
|
||||||
|
struct target *target = bank->target;
|
||||||
|
|
||||||
|
if (target->state != TARGET_HALTED)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Target not halted");
|
||||||
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unlock option flash registers */
|
||||||
|
int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* mass erase flash memory */
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_MER);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_MER | FLASH_STRT);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = em357_wait_status_busy(bank, 100);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
COMMAND_HANDLER(em357_handle_mass_erase_command)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (CMD_ARGC < 1)
|
||||||
|
{
|
||||||
|
command_print(CMD_CTX, "em357 mass_erase <bank>");
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct flash_bank *bank;
|
||||||
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
if (ERROR_OK != retval)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = em357_mass_erase(bank);
|
||||||
|
if (retval == ERROR_OK)
|
||||||
|
{
|
||||||
|
/* set all sectors as erased */
|
||||||
|
for (i = 0; i < bank->num_sectors; i++)
|
||||||
|
{
|
||||||
|
bank->sectors[i].is_erased = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
command_print(CMD_CTX, "em357 mass erase complete");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
command_print(CMD_CTX, "em357 mass erase failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct command_registration em357_exec_command_handlers[] = {
|
||||||
|
{
|
||||||
|
.name = "lock",
|
||||||
|
.handler = em357_handle_lock_command,
|
||||||
|
.mode = COMMAND_EXEC,
|
||||||
|
.usage = "bank_id",
|
||||||
|
.help = "Lock entire flash device.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "unlock",
|
||||||
|
.handler = em357_handle_unlock_command,
|
||||||
|
.mode = COMMAND_EXEC,
|
||||||
|
.usage = "bank_id",
|
||||||
|
.help = "Unlock entire protected flash device.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "mass_erase",
|
||||||
|
.handler = em357_handle_mass_erase_command,
|
||||||
|
.mode = COMMAND_EXEC,
|
||||||
|
.usage = "bank_id",
|
||||||
|
.help = "Erase entire flash device.",
|
||||||
|
},
|
||||||
|
COMMAND_REGISTRATION_DONE
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct command_registration em357_command_handlers[] = {
|
||||||
|
{
|
||||||
|
.name = "em357",
|
||||||
|
.mode = COMMAND_ANY,
|
||||||
|
.help = "em357 flash command group",
|
||||||
|
.chain = em357_exec_command_handlers,
|
||||||
|
},
|
||||||
|
COMMAND_REGISTRATION_DONE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct flash_driver em357_flash = {
|
||||||
|
.name = "em357",
|
||||||
|
.commands = em357_command_handlers,
|
||||||
|
.flash_bank_command = em357_flash_bank_command,
|
||||||
|
.erase = em357_erase,
|
||||||
|
.protect = em357_protect,
|
||||||
|
.write = em357_write,
|
||||||
|
.read = default_flash_read,
|
||||||
|
.probe = em357_probe,
|
||||||
|
.auto_probe = em357_auto_probe,
|
||||||
|
.erase_check = default_flash_mem_blank_check,
|
||||||
|
.protect_check = em357_protect_check,
|
||||||
|
.info = get_em357_info,
|
||||||
|
};
|
||||||
@@ -141,6 +141,7 @@ struct flash_driver faux_flash = {
|
|||||||
.erase = faux_erase,
|
.erase = faux_erase,
|
||||||
.protect = faux_protect,
|
.protect = faux_protect,
|
||||||
.write = faux_write,
|
.write = faux_write,
|
||||||
|
.read = default_flash_read,
|
||||||
.probe = faux_probe,
|
.probe = faux_probe,
|
||||||
.auto_probe = faux_probe,
|
.auto_probe = faux_probe,
|
||||||
.erase_check = default_flash_blank_check,
|
.erase_check = default_flash_blank_check,
|
||||||
|
|||||||
654
src/flash/nor/fm3.c
Normal file
654
src/flash/nor/fm3.c
Normal file
@@ -0,0 +1,654 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2011 by Marc Willam, Holger Wech *
|
||||||
|
* m.willam@gmx.eu *
|
||||||
|
* Copyright (C) 2011 Ronny Strutz *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "imp.h"
|
||||||
|
#include <helper/binarybuffer.h>
|
||||||
|
#include <target/algorithm.h>
|
||||||
|
#include <target/armv7m.h>
|
||||||
|
|
||||||
|
#define FLASH_DQ6 0x00000040 /* Data toggle flag bit (TOGG) position */
|
||||||
|
#define FLASH_DQ5 0x00000020 /* Time limit exceeding flag bit (TLOV) position */
|
||||||
|
|
||||||
|
enum fm3_variant
|
||||||
|
{
|
||||||
|
mb9bfxx1,
|
||||||
|
mb9bfxx2,
|
||||||
|
mb9bfxx3,
|
||||||
|
mb9bfxx4,
|
||||||
|
mb9bfxx5,
|
||||||
|
mb9bfxx6
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fm3_flash_bank
|
||||||
|
{
|
||||||
|
struct working_area *write_algorithm;
|
||||||
|
enum fm3_variant variant;
|
||||||
|
int probed;
|
||||||
|
};
|
||||||
|
|
||||||
|
FLASH_BANK_COMMAND_HANDLER(fm3_flash_bank_command)
|
||||||
|
{
|
||||||
|
struct fm3_flash_bank *fm3_info;
|
||||||
|
|
||||||
|
if (CMD_ARGC < 6)
|
||||||
|
{
|
||||||
|
LOG_WARNING("incomplete flash_bank fm3 configuration");
|
||||||
|
return ERROR_FLASH_BANK_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("******HWE* FLASH CMD Parameter %s", CMD_ARGV[5]);
|
||||||
|
|
||||||
|
fm3_info = malloc(sizeof(struct fm3_flash_bank));
|
||||||
|
bank->driver_priv = fm3_info;
|
||||||
|
|
||||||
|
if (strcmp(CMD_ARGV[5], "mb9bfxx1.cpu") == 0)
|
||||||
|
{
|
||||||
|
fm3_info->variant = mb9bfxx1;
|
||||||
|
}
|
||||||
|
else if (strcmp(CMD_ARGV[5], "mb9bfxx2.cpu") == 0)
|
||||||
|
{
|
||||||
|
fm3_info->variant = mb9bfxx2;
|
||||||
|
}
|
||||||
|
else if (strcmp(CMD_ARGV[5], "mb9bfxx3.cpu") == 0)
|
||||||
|
{
|
||||||
|
fm3_info->variant = mb9bfxx3;
|
||||||
|
}
|
||||||
|
else if (strcmp(CMD_ARGV[5], "mb9bfxx4.cpu") == 0)
|
||||||
|
{
|
||||||
|
fm3_info->variant = mb9bfxx4;
|
||||||
|
}
|
||||||
|
else if (strcmp(CMD_ARGV[5], "mb9bfxx5.cpu") == 0)
|
||||||
|
{
|
||||||
|
fm3_info->variant = mb9bfxx5;
|
||||||
|
}
|
||||||
|
else if (strcmp(CMD_ARGV[5], "mb9bfxx6.cpu") == 0)
|
||||||
|
{
|
||||||
|
fm3_info->variant = mb9bfxx6;
|
||||||
|
LOG_INFO("******HWE* fm3 Variant set to: mb9bfxx6");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR("unknown fm3 variant: %s", CMD_ARGV[5]);
|
||||||
|
free(fm3_info);
|
||||||
|
return ERROR_FLASH_BANK_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
fm3_info->write_algorithm = NULL;
|
||||||
|
fm3_info->probed = 0;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fm3_busy_wait(struct target *target, uint32_t offset, int timeout_ms)
|
||||||
|
{
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
uint16_t state1, state2;
|
||||||
|
int ms = 0;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
target_read_u16(target, offset, &state1); /* dummy-read - see flash manual */
|
||||||
|
target_read_u16(target, offset, &state1);
|
||||||
|
target_read_u16(target, offset, &state2);
|
||||||
|
|
||||||
|
if ( (state1 & FLASH_DQ6) == (state2 & FLASH_DQ6) ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (state1 & FLASH_DQ5) {
|
||||||
|
target_read_u16(target, offset, &state1);
|
||||||
|
target_read_u16(target, offset, &state2);
|
||||||
|
if ( (state1 & FLASH_DQ6) != (state2 & FLASH_DQ6) )
|
||||||
|
retval = ERROR_FLASH_OPERATION_FAILED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
usleep(1000);
|
||||||
|
++ms;
|
||||||
|
|
||||||
|
if (ms > timeout_ms) {
|
||||||
|
LOG_ERROR("toggle bit reading timed out!");
|
||||||
|
retval = ERROR_FLASH_OPERATION_FAILED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval == ERROR_OK)
|
||||||
|
LOG_DEBUG("fm3_busy_wait(%x) needs about %d ms", offset, ms);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fm3_erase(struct flash_bank *bank, int first, int last)
|
||||||
|
{
|
||||||
|
struct target *target = bank->target;
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
uint32_t u32DummyRead;
|
||||||
|
int sector, odd;
|
||||||
|
|
||||||
|
if (target->state != TARGET_HALTED) {
|
||||||
|
LOG_ERROR("Target not halted");
|
||||||
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("Fujitsu MB9Bxxx: Sector Erase ... (%d to %d)", first, last);
|
||||||
|
|
||||||
|
target_write_u32(target, 0x40000000, 0x0001); /* FASZR = 0x01, Enables CPU Programming Mode */
|
||||||
|
target_read_u32(target, 0x40000000, &u32DummyRead); /* dummy read of FASZR */
|
||||||
|
|
||||||
|
for (sector = first ; sector <= last ; sector++) {
|
||||||
|
uint32_t offset = bank->sectors[sector].offset;
|
||||||
|
|
||||||
|
for (odd = 0; odd < 2 ; odd++) {
|
||||||
|
|
||||||
|
if (odd)
|
||||||
|
offset += 4;
|
||||||
|
|
||||||
|
target_write_u16(target, 0x1550, 0x00AA);
|
||||||
|
target_write_u16(target, 0x0AA8, 0x0055);
|
||||||
|
target_write_u16(target, 0x1550, 0x0080);
|
||||||
|
target_write_u16(target, 0x1550, 0x00AA);
|
||||||
|
target_write_u16(target, 0x0AA8, 0x0055);
|
||||||
|
target_write_u16(target, offset, 0x0030);
|
||||||
|
|
||||||
|
retval = fm3_busy_wait(target, offset, 500);
|
||||||
|
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bank->sectors[sector].is_erased = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_write_u32(target, 0x40000000, 0x0002);
|
||||||
|
target_read_u32(target, 0x40000000, &u32DummyRead); /* dummy read of FASZR */
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fm3_write_block(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
|
||||||
|
{
|
||||||
|
struct fm3_flash_bank *fm3_info = bank->driver_priv;
|
||||||
|
struct target *target = bank->target;
|
||||||
|
uint32_t buffer_size = 8192;
|
||||||
|
struct working_area *source;
|
||||||
|
uint32_t address = bank->base + offset;
|
||||||
|
struct reg_param reg_params[4];
|
||||||
|
struct armv7m_algorithm armv7m_info;
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
|
/* RAMCODE used for fm3 Flash programming: */
|
||||||
|
/* R0 keeps source start address (u32Source) */
|
||||||
|
/* R1 keeps target start address (u32Target) */
|
||||||
|
/* R2 keeps number of halfwords to write (u32Count) */
|
||||||
|
/* R3 returns result value (u32FlashResult) */
|
||||||
|
|
||||||
|
const uint8_t fm3_flash_write_code[] = {
|
||||||
|
/* fm3_FLASH_IF->FASZ &= 0xFFFD; */
|
||||||
|
0x00, 0xBF, /* NOP */
|
||||||
|
0x5F, 0xF0, 0x80, 0x43, /* MOVS.W R3, #(fm3_FLASH_IF->FASZ) */
|
||||||
|
0x1B, 0x68, /* LDR R3, [R3] */
|
||||||
|
0x4F, 0xF6, 0xFD, 0x74, /* MOVW R4, #0xFFFD */
|
||||||
|
0x23, 0x40, /* ANDS R3, R3, R4 */
|
||||||
|
0x5F, 0xF0, 0x80, 0x44, /* MOVS.W R4, #(fm3_FLASH_IF->FASZ) */
|
||||||
|
0x23, 0x60, /* STR R3, [R4] */
|
||||||
|
/* fm3_FLASH_IF->FASZ |= 1; */
|
||||||
|
0x5F, 0xF0, 0x80, 0x43, /* MOVS.W R3, #(fm3_FLASH_IF->FASZ) */
|
||||||
|
0x1B, 0x68, /* LDR R3, [R3] */
|
||||||
|
0x53, 0xF0, 0x01, 0x03, /* ORRS.W R3, R3, #1 */
|
||||||
|
0x5F, 0xF0, 0x80, 0x44, /* MOVS.W R4, #(fm3_FLASH_IF->FASZ) */
|
||||||
|
0x23, 0x60, /* STR R3, [R4] */
|
||||||
|
/* u32DummyRead = fm3_FLASH_IF->FASZ; */
|
||||||
|
0x2B, 0x4B, /* LDR.N R3, ??u32DummyRead */
|
||||||
|
0x5F, 0xF0, 0x80, 0x44, /* MOVS.W R4, #(fm3_FLASH_IF->FASZ) */
|
||||||
|
0x24, 0x68, /* LDR R4, [R4] */
|
||||||
|
0x1C, 0x60, /* STR R4, [R3] */
|
||||||
|
/* u32FlashResult = FLASH_WRITE_NO_RESULT */
|
||||||
|
0x2A, 0x4B, /* LDR.N R3, ??u32FlashResult */
|
||||||
|
0x00, 0x24, /* MOVS R4, #0 */
|
||||||
|
0x1C, 0x60, /* STR R4, [R3] */
|
||||||
|
/* while ((u32Count > 0 ) && (u32FlashResult */
|
||||||
|
/* == FLASH_WRITE_NO_RESULT)) */
|
||||||
|
0x01, 0x2A, /* L0: CMP R2, #1 */
|
||||||
|
0x32, 0xDB, /* BLT.N L1 */
|
||||||
|
0x27, 0x4B, /* LDR.N R3, ??u32FlashResult */
|
||||||
|
0x1B, 0x68, /* LDR R3, [R3] */
|
||||||
|
0x00, 0x2B, /* CMP R3, #0 */
|
||||||
|
0x2E, 0xD1, /* BNE.N L1 */
|
||||||
|
/* *(FLASH_SEQ_1550) = FLASH_WRITE_1; */
|
||||||
|
0x41, 0xF2, 0x50, 0x53, /* MOVW R3, #0x1550 */
|
||||||
|
0xAA, 0x24, /* MOVS R4. #0xAA */
|
||||||
|
0x1C, 0x80, /* STRH R4, [R3] */
|
||||||
|
/* *(FLASH_SEQ_0AA8) = FLASH_WRITE_2; */
|
||||||
|
0x40, 0xF6, 0xA8, 0x23, /* MOVW R3, #0x0AA8 */
|
||||||
|
0x55, 0x24, /* MOVS R4. #0x55 */
|
||||||
|
0x1C, 0x80, /* STRH R4, [R3] */
|
||||||
|
/* *(FLASH_SEQ_1550) = FLASH_WRITE_3; */
|
||||||
|
0x41, 0xF2, 0x50, 0x53, /* MOVW R3, #0x1550 */
|
||||||
|
0xA0, 0x24, /* MOVS R4. #0xA0 */
|
||||||
|
0x1C, 0x80, /* STRH R4, [R3] */
|
||||||
|
/* *(volatile uint16_t*)u32Target */
|
||||||
|
/* = *(volatile uint16_t*)u32Source; */
|
||||||
|
0x03, 0x88, /* LDRH R3, [R0] */
|
||||||
|
0x0B, 0x80, /* STRH R3, [R1] */
|
||||||
|
/* while (u32FlashResult == FLASH_WRITE_NO_RESTULT) */
|
||||||
|
0x1E, 0x4B, /* L2: LDR.N R3, ??u32FlashResult */
|
||||||
|
0x1B, 0x68, /* LDR R3, [R3] */
|
||||||
|
0x00, 0x2B, /* CMP R3, #0 */
|
||||||
|
0x11, 0xD1, /* BNE.N L3 */
|
||||||
|
/* if ((*(volatile uint16_t*)u32Target & FLASH_DQ5) */
|
||||||
|
/* == FLASH_DQ5) */
|
||||||
|
0x0B, 0x88, /* LDRH R3, [R1] */
|
||||||
|
0x9B, 0x06, /* LSLS R3, R3, #0x1A */
|
||||||
|
0x02, 0xD5, /* BPL.N L4 */
|
||||||
|
/* u32FlashResult = FLASH_WRITE_TIMEOUT */
|
||||||
|
0x1B, 0x4B, /* LDR.N R3, ??u32FlashResult */
|
||||||
|
0x02, 0x24, /* MOVS R4, #2 */
|
||||||
|
0x1C, 0x60, /* STR R4, [R3] */
|
||||||
|
/* if ((*(volatile uint16_t *)u32Target & FLASH_DQ7) */
|
||||||
|
/* == (*(volatile uint16_t*)u32Source & FLASH_DQ7)) */
|
||||||
|
0x0B, 0x88, /* L4: LDRH R3, [R1] */
|
||||||
|
0x13, 0xF0, 0x80, 0x03, /* ANDS.W R3, R3, #0x80 */
|
||||||
|
0x04, 0x88, /* LDRH R4, [R0] */
|
||||||
|
0x14, 0xF0, 0x80, 0x04, /* ANDS.W R4, R4, #0x80 */
|
||||||
|
0xA3, 0x42, /* CMP R3, R4 */
|
||||||
|
0xED, 0xD1, /* BNE.N L2 */
|
||||||
|
/* u32FlashResult = FLASH_WRITE_OKAY */
|
||||||
|
0x15, 0x4B, /* LDR.N R3, ??u32FlashResult */
|
||||||
|
0x01, 0x24, /* MOVS R4, #1 */
|
||||||
|
0x1C, 0x60, /* STR R4, [R3] */
|
||||||
|
0xE9, 0xE7, /* B.N L2 */
|
||||||
|
/* if (u32FlashResult != FLASH_WRITE_TIMEOUT) */
|
||||||
|
0x13, 0x4B, /* LDR.N R3, ??u32FlashResult */
|
||||||
|
0x1B, 0x68, /* LDR R3, [R3] */
|
||||||
|
0x02, 0x2B, /* CMP R3, #2 */
|
||||||
|
0x02, 0xD0, /* BEQ.N L5 */
|
||||||
|
/* u32FlashResult = FLASH_WRITE_NO_RESULT */
|
||||||
|
0x11, 0x4B, /* LDR.N R3, ??u32FlashResult */
|
||||||
|
0x00, 0x24, /* MOVS R4, #0 */
|
||||||
|
0x1C, 0x60, /* STR R4, [R3] */
|
||||||
|
/* u32Count--; */
|
||||||
|
0x52, 0x1E, /* L5: SUBS R2, R2, #1 */
|
||||||
|
/* u32Source += 2; */
|
||||||
|
0x80, 0x1C, /* ADDS R0, R0, #2 */
|
||||||
|
/* u32Target += 2; */
|
||||||
|
0x89, 0x1C, /* ADDS R1, R1, #2 */
|
||||||
|
0xCA, 0xE7, /* B.N L0 */
|
||||||
|
/* fm3_FLASH_IF->FASZ &= 0xFFFE; */
|
||||||
|
0x5F, 0xF0, 0x80, 0x43, /* L1: MOVS.W R3, #(fm3_FLASH_IF->FASZ) */
|
||||||
|
0x1B, 0x68, /* LDR R3, [R3] */
|
||||||
|
0x4F, 0xF6, 0xFE, 0x74, /* MOVW R4, #0xFFFE */
|
||||||
|
0x23, 0x40, /* ANDS R3, R3, R4 */
|
||||||
|
0x5F, 0xF0, 0x80, 0x44, /* MOVS.W R4, #(fm3_FLASH_IF->FASZ) */
|
||||||
|
0x23, 0x60, /* STR R3, [R4] */
|
||||||
|
/* fm3_FLASH_IF->FASZ |= 2; */
|
||||||
|
0x5F, 0xF0, 0x80, 0x43, /* MOVS.W R3, #(fm3_FLASH_IF->FASZ) */
|
||||||
|
0x1B, 0x68, /* LDR R3, [R3] */
|
||||||
|
0x53, 0xF0, 0x02, 0x03, /* ORRS.W R3, R3, #2 */
|
||||||
|
0x5F, 0xF0, 0x80, 0x44, /* MOVS.W R4, #(fm3_FLASH_IF->FASZ) */
|
||||||
|
0x23, 0x60, /* STR R4, [R3] */
|
||||||
|
/* u32DummyRead = fm3_FLASH_IF->FASZ; */
|
||||||
|
0x04, 0x4B, /* LDR.N R3, ??u32DummyRead */
|
||||||
|
0x5F, 0xF0, 0x80, 0x44, /* MOVS.W R4, #(fm3_FLASH_IF->FASZ) */
|
||||||
|
0x24, 0x68, /* LDR R4, [R4] */
|
||||||
|
0x1C, 0x60, /* STR R4, [R3] */
|
||||||
|
/* copy u32FlashResult to R3 for return value */
|
||||||
|
0xDF, 0xF8, 0x0C, 0x30, /* LDR.W R3, ??u32FlashResult */
|
||||||
|
0x1B, 0x68, /* LDR R3, [R3] */
|
||||||
|
/* Breakpoint here */
|
||||||
|
0x00, 0xBE, /* Breakpoint #0 */
|
||||||
|
0x00, 0x00, /* alignment padding bytes */
|
||||||
|
0x00, 0x80, 0xFF, 0x1F, /* u32DummyRead address in RAM (0x1FFF8000) */
|
||||||
|
0x04, 0x80, 0xFF, 0x1F /* u32FlashResult address in RAM (0x1FFF8004) */
|
||||||
|
};
|
||||||
|
|
||||||
|
LOG_INFO("Fujitsu MB9B500: FLASH Write ...");
|
||||||
|
|
||||||
|
/* disable HW watchdog */
|
||||||
|
target_write_u32(target, 0x40011C00, 0x1ACCE551);
|
||||||
|
target_write_u32(target, 0x40011C00, 0xE5331AAE);
|
||||||
|
target_write_u32(target, 0x40011008, 0x00000000);
|
||||||
|
|
||||||
|
count = count / 2; /* number bytes -> number halfwords */
|
||||||
|
|
||||||
|
/* check code alignment */
|
||||||
|
if (offset & 0x1)
|
||||||
|
{
|
||||||
|
LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
|
||||||
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate working area with flash programming code */
|
||||||
|
if (target_alloc_working_area(target, sizeof(fm3_flash_write_code),
|
||||||
|
&fm3_info->write_algorithm) != ERROR_OK)
|
||||||
|
{
|
||||||
|
LOG_WARNING("no working area available, can't do block memory writes");
|
||||||
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = target_write_buffer(target, fm3_info->write_algorithm->address,
|
||||||
|
sizeof(fm3_flash_write_code), fm3_flash_write_code);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/* memory buffer */
|
||||||
|
while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
|
||||||
|
{
|
||||||
|
buffer_size /= 2;
|
||||||
|
if (buffer_size <= 256)
|
||||||
|
{
|
||||||
|
/* free working area, if write algorithm already allocated */
|
||||||
|
if (fm3_info->write_algorithm)
|
||||||
|
{
|
||||||
|
target_free_working_area(target, fm3_info->write_algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_WARNING("no large enough working area available, can't do block memory writes");
|
||||||
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
|
||||||
|
armv7m_info.core_mode = ARMV7M_MODE_ANY;
|
||||||
|
|
||||||
|
init_reg_param(®_params[0], "r0", 32, PARAM_OUT); // source start address
|
||||||
|
init_reg_param(®_params[1], "r1", 32, PARAM_OUT); // target start address
|
||||||
|
init_reg_param(®_params[2], "r2", 32, PARAM_OUT); // number of halfwords to program
|
||||||
|
init_reg_param(®_params[3], "r3", 32, PARAM_IN); // result
|
||||||
|
|
||||||
|
/* write code buffer and use Flash programming code within fm3 */
|
||||||
|
/* Set breakpoint to 0 with time-out of 1000 ms */
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
|
||||||
|
|
||||||
|
/* for some reason the first 8 byte of code are corrupt when target_run_algorithm() returns */
|
||||||
|
/* need some more investigation on this */
|
||||||
|
retval = target_write_buffer(target,
|
||||||
|
fm3_info->write_algorithm->address, 8, fm3_flash_write_code);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
|
||||||
|
retval = target_write_buffer(target,
|
||||||
|
source->address, thisrun_count * 2, buffer);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
buf_set_u32(reg_params[0].value, 0, 32, source->address);
|
||||||
|
buf_set_u32(reg_params[1].value, 0, 32, address);
|
||||||
|
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
|
||||||
|
|
||||||
|
|
||||||
|
retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
|
||||||
|
fm3_info->write_algorithm->address, 0, 1000, &armv7m_info);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
{
|
||||||
|
LOG_ERROR("error executing fm3 Flash programming algorithm");
|
||||||
|
retval = ERROR_FLASH_OPERATION_FAILED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* debug the corrupted 8 bytes */
|
||||||
|
unsigned char buf[256];
|
||||||
|
retval = target_read_buffer(target, fm3_info->write_algorithm->address, 256, buf);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
printf("cannot read buffer\n");
|
||||||
|
unsigned int i;
|
||||||
|
for ( i = 0; i < sizeof(fm3_flash_write_code); i++)
|
||||||
|
if (buf[i] != fm3_flash_write_code[i])
|
||||||
|
printf("broken: %d %02x != %02x\n", i, buf[i], fm3_flash_write_code[i]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (buf_get_u32(reg_params[3].value, 0, 32) != ERROR_OK)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Fujitsu MB9B500: FLASH programming ERROR (Timeout) -> Reg R3: %x",
|
||||||
|
buf_get_u32(reg_params[3].value, 0, 32));
|
||||||
|
retval = ERROR_FLASH_OPERATION_FAILED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer += thisrun_count * 2;
|
||||||
|
address += thisrun_count * 2;
|
||||||
|
count -= thisrun_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_free_working_area(target, source);
|
||||||
|
target_free_working_area(target, fm3_info->write_algorithm);
|
||||||
|
|
||||||
|
destroy_reg_param(®_params[0]);
|
||||||
|
destroy_reg_param(®_params[1]);
|
||||||
|
destroy_reg_param(®_params[2]);
|
||||||
|
destroy_reg_param(®_params[3]);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fm3_probe(struct flash_bank *bank)
|
||||||
|
{
|
||||||
|
struct fm3_flash_bank *fm3_info = bank->driver_priv;
|
||||||
|
uint16_t num_pages;
|
||||||
|
|
||||||
|
if (bank->target->state != TARGET_HALTED)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Target not halted");
|
||||||
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
num_pages = 6; /* max number of Flash pages for malloc */
|
||||||
|
fm3_info->probed = 0;
|
||||||
|
|
||||||
|
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
|
||||||
|
bank->base = 0x00000000;
|
||||||
|
num_pages = 2; /* start with smallest Flash pages number */
|
||||||
|
bank->size = 32 * 1024; /* bytes */
|
||||||
|
|
||||||
|
bank->sectors[0].offset = 0;
|
||||||
|
bank->sectors[0].size = 16 * 1024;
|
||||||
|
bank->sectors[0].is_erased = -1;
|
||||||
|
bank->sectors[0].is_protected = -1;
|
||||||
|
|
||||||
|
bank->sectors[1].offset = 0x4000;
|
||||||
|
bank->sectors[1].size = 16 * 1024;
|
||||||
|
bank->sectors[1].is_erased = -1;
|
||||||
|
bank->sectors[1].is_protected = -1;
|
||||||
|
|
||||||
|
if (fm3_info->variant == mb9bfxx1)
|
||||||
|
{
|
||||||
|
num_pages = 3;
|
||||||
|
bank->size = 64 * 1024; /* bytes */
|
||||||
|
bank->num_sectors = num_pages;
|
||||||
|
|
||||||
|
bank->sectors[2].offset = 0x8000;
|
||||||
|
bank->sectors[2].size = 32 * 1024;
|
||||||
|
bank->sectors[2].is_erased = -1;
|
||||||
|
bank->sectors[2].is_protected = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (fm3_info->variant == mb9bfxx2)
|
||||||
|
|| (fm3_info->variant == mb9bfxx4)
|
||||||
|
|| (fm3_info->variant == mb9bfxx5)
|
||||||
|
|| (fm3_info->variant == mb9bfxx6))
|
||||||
|
{
|
||||||
|
num_pages = 3;
|
||||||
|
bank->size = 128 * 1024; // bytes
|
||||||
|
bank->num_sectors = num_pages;
|
||||||
|
|
||||||
|
bank->sectors[2].offset = 0x8000;
|
||||||
|
bank->sectors[2].size = 96 * 1024;
|
||||||
|
bank->sectors[2].is_erased = -1;
|
||||||
|
bank->sectors[2].is_protected = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (fm3_info->variant == mb9bfxx4)
|
||||||
|
|| (fm3_info->variant == mb9bfxx5)
|
||||||
|
|| (fm3_info->variant == mb9bfxx6))
|
||||||
|
{
|
||||||
|
num_pages = 4;
|
||||||
|
bank->size = 256 * 1024; // bytes
|
||||||
|
bank->num_sectors = num_pages;
|
||||||
|
|
||||||
|
bank->sectors[3].offset = 0x20000;
|
||||||
|
bank->sectors[3].size = 128 * 1024;
|
||||||
|
bank->sectors[3].is_erased = -1;
|
||||||
|
bank->sectors[3].is_protected = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (fm3_info->variant == mb9bfxx5)
|
||||||
|
|| (fm3_info->variant == mb9bfxx6))
|
||||||
|
{
|
||||||
|
num_pages = 5;
|
||||||
|
bank->size = 384 * 1024; // bytes
|
||||||
|
bank->num_sectors = num_pages;
|
||||||
|
|
||||||
|
bank->sectors[4].offset = 0x40000;
|
||||||
|
bank->sectors[4].size = 128 * 1024;
|
||||||
|
bank->sectors[4].is_erased = -1;
|
||||||
|
bank->sectors[4].is_protected = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fm3_info->variant == mb9bfxx6)
|
||||||
|
{
|
||||||
|
num_pages = 6;
|
||||||
|
bank->size = 512 * 1024; // bytes
|
||||||
|
bank->num_sectors = num_pages;
|
||||||
|
|
||||||
|
bank->sectors[5].offset = 0x60000;
|
||||||
|
bank->sectors[5].size = 128 * 1024;
|
||||||
|
bank->sectors[5].is_erased = -1;
|
||||||
|
bank->sectors[5].is_protected = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fm3_info->probed = 1;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fm3_auto_probe(struct flash_bank *bank)
|
||||||
|
{
|
||||||
|
struct fm3_flash_bank *fm3_info = bank->driver_priv;
|
||||||
|
if (fm3_info->probed)
|
||||||
|
return ERROR_OK;
|
||||||
|
return fm3_probe(bank);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fm3_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
|
{
|
||||||
|
snprintf(buf, buf_size, "Fujitsu fm3 Device does not support Chip-ID (Type unknown)");
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fm3_chip_erase(struct flash_bank *bank)
|
||||||
|
{
|
||||||
|
struct target *target = bank->target;
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
uint32_t u32DummyRead;
|
||||||
|
|
||||||
|
if (target->state != TARGET_HALTED)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Target not halted");
|
||||||
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("Fujitsu MB9Bxxx: Chip Erase ... (may take several seconds)");
|
||||||
|
|
||||||
|
/* Implement Flash chip erase (mass erase) completely on host */
|
||||||
|
target_write_u32(target, 0x40000000, 0x0001); /* FASZR = 0x01, Enables CPU Programming Mode (16-bit Flash access) */
|
||||||
|
target_read_u32(target, 0x40000000, &u32DummyRead); /* dummy read of FASZR */
|
||||||
|
|
||||||
|
target_write_u16(target, 0x00001550, 0x00AA); /* Flash unlock sequence */
|
||||||
|
target_write_u16(target, 0x00000AA8, 0x0055);
|
||||||
|
target_write_u16(target, 0x00001550, 0x0080);
|
||||||
|
target_write_u16(target, 0x00001550, 0x00AA);
|
||||||
|
target_write_u16(target, 0x00000AA8, 0x0055);
|
||||||
|
target_write_u16(target, 0x00001550, 0x0010); /* Chip Erase command */
|
||||||
|
|
||||||
|
retval = fm3_busy_wait(target, 0xAA8, 20000);
|
||||||
|
|
||||||
|
target_write_u32(target, 0x40000000, 0x0002);
|
||||||
|
target_read_u32(target, 0x40000000, &u32DummyRead); /* dummy read of FASZR */
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
COMMAND_HANDLER(fm3_handle_chip_erase_command)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (CMD_ARGC < 1)
|
||||||
|
{
|
||||||
|
command_print(CMD_CTX, "fm3 chip_erase <bank>");
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct flash_bank *bank;
|
||||||
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
if (ERROR_OK != retval)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
if (fm3_chip_erase(bank) == ERROR_OK)
|
||||||
|
{
|
||||||
|
/* set all sectors as erased */
|
||||||
|
for (i = 0; i < bank->num_sectors; i++)
|
||||||
|
bank->sectors[i].is_erased = 1;
|
||||||
|
|
||||||
|
command_print(CMD_CTX, "fm3 chip erase complete");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
command_print(CMD_CTX, "fm3 chip erase failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct command_registration fm3_exec_command_handlers[] = {
|
||||||
|
{
|
||||||
|
.name = "chip_erase",
|
||||||
|
.handler = fm3_handle_chip_erase_command,
|
||||||
|
.mode = COMMAND_EXEC,
|
||||||
|
.usage = "bank_id",
|
||||||
|
.help = "Erase entire Flash device.",
|
||||||
|
},
|
||||||
|
COMMAND_REGISTRATION_DONE
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct command_registration fm3_command_handlers[] = {
|
||||||
|
{
|
||||||
|
.name = "fm3",
|
||||||
|
.mode = COMMAND_ANY,
|
||||||
|
.help = "fm3 Flash command group",
|
||||||
|
.chain = fm3_exec_command_handlers,
|
||||||
|
},
|
||||||
|
COMMAND_REGISTRATION_DONE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct flash_driver fm3_flash = {
|
||||||
|
.name = "fm3",
|
||||||
|
.commands = fm3_command_handlers,
|
||||||
|
.flash_bank_command = fm3_flash_bank_command,
|
||||||
|
.erase = fm3_erase,
|
||||||
|
.write = fm3_write_block,
|
||||||
|
.probe = fm3_probe,
|
||||||
|
.auto_probe = fm3_auto_probe,
|
||||||
|
.erase_check = default_flash_mem_blank_check,
|
||||||
|
.info = fm3_info,
|
||||||
|
};
|
||||||
@@ -40,6 +40,8 @@ int flash_driver_erase(struct flash_bank *bank, int first, int last);
|
|||||||
int flash_driver_protect(struct flash_bank *bank, int set, int first, int last);
|
int flash_driver_protect(struct flash_bank *bank, int set, int first, int last);
|
||||||
int flash_driver_write(struct flash_bank *bank,
|
int flash_driver_write(struct flash_bank *bank,
|
||||||
uint8_t *buffer, uint32_t offset, uint32_t count);
|
uint8_t *buffer, uint32_t offset, uint32_t count);
|
||||||
|
int flash_driver_read(struct flash_bank *bank,
|
||||||
|
uint8_t *buffer, uint32_t offset, uint32_t count);
|
||||||
|
|
||||||
/* write (optional verify) an image to flash memory of the given target */
|
/* write (optional verify) an image to flash memory of the given target */
|
||||||
int flash_write_unlock(struct target *target, struct image *image,
|
int flash_write_unlock(struct target *target, struct image *image,
|
||||||
|
|||||||
@@ -26,14 +26,21 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "imp.h"
|
#include "imp.h"
|
||||||
#include "lpc2000.h"
|
|
||||||
#include <helper/binarybuffer.h>
|
#include <helper/binarybuffer.h>
|
||||||
#include <target/algorithm.h>
|
#include <target/algorithm.h>
|
||||||
#include <target/arm_opcodes.h>
|
#include <target/arm_opcodes.h>
|
||||||
#include <target/armv7m.h>
|
#include <target/armv7m.h>
|
||||||
|
|
||||||
|
|
||||||
/* flash programming support for NXP LPC17xx and LPC2xxx devices
|
/**
|
||||||
|
* @file
|
||||||
|
* flash programming support for NXP LPC17xx and LPC2xxx devices.
|
||||||
|
*
|
||||||
|
* @todo Provide a way to update CCLK after declaring the flash bank.
|
||||||
|
* The value which is correct after chip reset will rarely still work
|
||||||
|
* right after the clocks switch to use the PLL (e.g. 4MHz --> 100 MHz).
|
||||||
|
*/
|
||||||
|
/*
|
||||||
* currently supported devices:
|
* currently supported devices:
|
||||||
* variant 1 (lpc2000_v1):
|
* variant 1 (lpc2000_v1):
|
||||||
* - 2104 | 5 | 6
|
* - 2104 | 5 | 6
|
||||||
@@ -55,6 +62,51 @@
|
|||||||
* - 176x (tested with LPC1768)
|
* - 176x (tested with LPC1768)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
lpc2000_v1,
|
||||||
|
lpc2000_v2,
|
||||||
|
lpc1700
|
||||||
|
} lpc2000_variant;
|
||||||
|
|
||||||
|
struct lpc2000_flash_bank
|
||||||
|
{
|
||||||
|
lpc2000_variant variant;
|
||||||
|
struct working_area *iap_working_area;
|
||||||
|
uint32_t cclk;
|
||||||
|
int cmd51_dst_boundary;
|
||||||
|
int cmd51_can_256b;
|
||||||
|
int cmd51_can_8192b;
|
||||||
|
int calc_checksum;
|
||||||
|
uint32_t cmd51_max_buffer;
|
||||||
|
int checksum_vector;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum lpc2000_status_codes
|
||||||
|
{
|
||||||
|
LPC2000_CMD_SUCCESS = 0,
|
||||||
|
LPC2000_INVALID_COMMAND = 1,
|
||||||
|
LPC2000_SRC_ADDR_ERROR = 2,
|
||||||
|
LPC2000_DST_ADDR_ERROR = 3,
|
||||||
|
LPC2000_SRC_ADDR_NOT_MAPPED = 4,
|
||||||
|
LPC2000_DST_ADDR_NOT_MAPPED = 5,
|
||||||
|
LPC2000_COUNT_ERROR = 6,
|
||||||
|
LPC2000_INVALID_SECTOR = 7,
|
||||||
|
LPC2000_SECTOR_NOT_BLANK = 8,
|
||||||
|
LPC2000_SECTOR_NOT_PREPARED = 9,
|
||||||
|
LPC2000_COMPARE_ERROR = 10,
|
||||||
|
LPC2000_BUSY = 11,
|
||||||
|
LPC2000_PARAM_ERROR = 12,
|
||||||
|
LPC2000_ADDR_ERROR = 13,
|
||||||
|
LPC2000_ADDR_NOT_MAPPED = 14,
|
||||||
|
LPC2000_CMD_NOT_LOCKED = 15,
|
||||||
|
LPC2000_INVALID_CODE = 16,
|
||||||
|
LPC2000_INVALID_BAUD_RATE = 17,
|
||||||
|
LPC2000_INVALID_STOP_BIT = 18,
|
||||||
|
LPC2000_CRP_ENABLED = 19
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
static int lpc2000_build_sector_list(struct flash_bank *bank)
|
static int lpc2000_build_sector_list(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
|
struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
|
||||||
@@ -144,10 +196,13 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
|
|||||||
case 256 * 1024:
|
case 256 * 1024:
|
||||||
bank->num_sectors = 15;
|
bank->num_sectors = 15;
|
||||||
break;
|
break;
|
||||||
case 512 * 1024:
|
|
||||||
case 500 * 1024:
|
case 500 * 1024:
|
||||||
bank->num_sectors = 27;
|
bank->num_sectors = 27;
|
||||||
break;
|
break;
|
||||||
|
case 512 * 1024:
|
||||||
|
case 504 * 1024:
|
||||||
|
bank->num_sectors = 28;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("BUG: unknown bank->size encountered");
|
LOG_ERROR("BUG: unknown bank->size encountered");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
@@ -158,7 +213,7 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
|
|||||||
|
|
||||||
for (i = 0; i < bank->num_sectors; i++)
|
for (i = 0; i < bank->num_sectors; i++)
|
||||||
{
|
{
|
||||||
if ((i >= 0) && (i < 8))
|
if (i < 8)
|
||||||
{
|
{
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
bank->sectors[i].size = 4 * 1024;
|
bank->sectors[i].size = 4 * 1024;
|
||||||
@@ -166,7 +221,7 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
|
|||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
bank->sectors[i].is_protected = 1;
|
bank->sectors[i].is_protected = 1;
|
||||||
}
|
}
|
||||||
if ((i >= 8) && (i < 22))
|
else if (i < 22)
|
||||||
{
|
{
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
bank->sectors[i].size = 32 * 1024;
|
bank->sectors[i].size = 32 * 1024;
|
||||||
@@ -174,7 +229,7 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
|
|||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
bank->sectors[i].is_protected = 1;
|
bank->sectors[i].is_protected = 1;
|
||||||
}
|
}
|
||||||
if ((i >= 22) && (i < 27))
|
else if (i < 28)
|
||||||
{
|
{
|
||||||
bank->sectors[i].offset = offset;
|
bank->sectors[i].offset = offset;
|
||||||
bank->sectors[i].size = 4 * 1024;
|
bank->sectors[i].size = 4 * 1024;
|
||||||
@@ -267,7 +322,7 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta
|
|||||||
target_buffer_set_u32(target, jump_gate,
|
target_buffer_set_u32(target, jump_gate,
|
||||||
ARMV4_5_T_BX(12));
|
ARMV4_5_T_BX(12));
|
||||||
target_buffer_set_u32(target, jump_gate + 4,
|
target_buffer_set_u32(target, jump_gate + 4,
|
||||||
ARMV4_5_T_B(0xfffffe));
|
ARMV5_T_BKPT(0));
|
||||||
break;
|
break;
|
||||||
case lpc2000_v1:
|
case lpc2000_v1:
|
||||||
case lpc2000_v2:
|
case lpc2000_v2:
|
||||||
@@ -338,7 +393,7 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta
|
|||||||
init_reg_param(®_params[4], "lr", 32, PARAM_OUT);
|
init_reg_param(®_params[4], "lr", 32, PARAM_OUT);
|
||||||
buf_set_u32(reg_params[4].value, 0, 32, (lpc2000_info->iap_working_area->address + 0x04) | 1); /* bit0 of LR = 1 to return in Thumb mode */
|
buf_set_u32(reg_params[4].value, 0, 32, (lpc2000_info->iap_working_area->address + 0x04) | 1); /* bit0 of LR = 1 to return in Thumb mode */
|
||||||
|
|
||||||
target_run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, lpc2000_info->iap_working_area->address + 0x4, 10000, &armv7m_info);
|
target_run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, 0, 10000, &armv7m_info);
|
||||||
break;
|
break;
|
||||||
case lpc2000_v1:
|
case lpc2000_v1:
|
||||||
case lpc2000_v2:
|
case lpc2000_v2:
|
||||||
@@ -586,7 +641,6 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs
|
|||||||
if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum)
|
if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum)
|
||||||
{
|
{
|
||||||
uint32_t checksum = 0;
|
uint32_t checksum = 0;
|
||||||
int i;
|
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4, buf_get_u32(buffer + (i * 4), 0, 32));
|
LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4, buf_get_u32(buffer + (i * 4), 0, 32));
|
||||||
@@ -732,7 +786,7 @@ static int lpc2000_protect_check(struct flash_bank *bank)
|
|||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lpc2000_info(struct flash_bank *bank, char *buf, int buf_size)
|
static int get_lpc2000_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
{
|
{
|
||||||
struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
|
struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
|
||||||
|
|
||||||
@@ -806,9 +860,10 @@ struct flash_driver lpc2000_flash = {
|
|||||||
.erase = lpc2000_erase,
|
.erase = lpc2000_erase,
|
||||||
.protect = lpc2000_protect,
|
.protect = lpc2000_protect,
|
||||||
.write = lpc2000_write,
|
.write = lpc2000_write,
|
||||||
|
.read = default_flash_read,
|
||||||
.probe = lpc2000_probe,
|
.probe = lpc2000_probe,
|
||||||
.auto_probe = lpc2000_probe,
|
.auto_probe = lpc2000_probe,
|
||||||
.erase_check = lpc2000_erase_check,
|
.erase_check = lpc2000_erase_check,
|
||||||
.protect_check = lpc2000_protect_check,
|
.protect_check = lpc2000_protect_check,
|
||||||
.info = lpc2000_info,
|
.info = get_lpc2000_info,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "imp.h"
|
#include "imp.h"
|
||||||
#include "lpc288x.h"
|
|
||||||
#include <helper/binarybuffer.h>
|
#include <helper/binarybuffer.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -85,6 +84,19 @@
|
|||||||
/* F_CLK_TIME */
|
/* F_CLK_TIME */
|
||||||
#define FCT_CLK_DIV_MASK 0x0FFF
|
#define FCT_CLK_DIV_MASK 0x0FFF
|
||||||
|
|
||||||
|
struct lpc288x_flash_bank
|
||||||
|
{
|
||||||
|
uint32_t working_area;
|
||||||
|
uint32_t working_area_size;
|
||||||
|
|
||||||
|
/* chip id register */
|
||||||
|
uint32_t cidr;
|
||||||
|
const char * target_name;
|
||||||
|
uint32_t cclk;
|
||||||
|
|
||||||
|
uint32_t sector_size_break;
|
||||||
|
};
|
||||||
|
|
||||||
static uint32_t lpc288x_wait_status_busy(struct flash_bank *bank, int timeout);
|
static uint32_t lpc288x_wait_status_busy(struct flash_bank *bank, int timeout);
|
||||||
static void lpc288x_load_timer(int erase, struct target *target);
|
static void lpc288x_load_timer(int erase, struct target *target);
|
||||||
static void lpc288x_set_flash_clk(struct flash_bank *bank);
|
static void lpc288x_set_flash_clk(struct flash_bank *bank);
|
||||||
@@ -478,6 +490,7 @@ struct flash_driver lpc288x_flash = {
|
|||||||
.erase = lpc288x_erase,
|
.erase = lpc288x_erase,
|
||||||
.protect = lpc288x_protect,
|
.protect = lpc288x_protect,
|
||||||
.write = lpc288x_write,
|
.write = lpc288x_write,
|
||||||
|
.read = default_flash_read,
|
||||||
.probe = lpc288x_probe,
|
.probe = lpc288x_probe,
|
||||||
.auto_probe = lpc288x_probe,
|
.auto_probe = lpc288x_probe,
|
||||||
.erase_check = lpc288x_erase_check,
|
.erase_check = lpc288x_erase_check,
|
||||||
|
|||||||
@@ -131,6 +131,11 @@
|
|||||||
*/
|
*/
|
||||||
struct lpc2900_flash_bank
|
struct lpc2900_flash_bank
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* This flag is set when the device has been successfully probed.
|
||||||
|
*/
|
||||||
|
bool is_probed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the value read from CHIPID register.
|
* Holds the value read from CHIPID register.
|
||||||
* The driver will not load if the chipid doesn't match the expected
|
* The driver will not load if the chipid doesn't match the expected
|
||||||
@@ -179,7 +184,7 @@ static uint32_t lpc2900_run_bist128(struct flash_bank *bank,
|
|||||||
uint32_t addr_from, uint32_t addr_to,
|
uint32_t addr_from, uint32_t addr_to,
|
||||||
uint32_t (*signature)[4] );
|
uint32_t (*signature)[4] );
|
||||||
static uint32_t lpc2900_address2sector(struct flash_bank *bank, uint32_t offset);
|
static uint32_t lpc2900_address2sector(struct flash_bank *bank, uint32_t offset);
|
||||||
static uint32_t lpc2900_calc_tr( uint32_t clock, uint32_t time );
|
static uint32_t lpc2900_calc_tr(uint32_t clock_var, uint32_t time_var);
|
||||||
|
|
||||||
|
|
||||||
/*********************** Helper functions **************************/
|
/*********************** Helper functions **************************/
|
||||||
@@ -255,7 +260,7 @@ static uint32_t lpc2900_is_ready( struct flash_bank *bank )
|
|||||||
{
|
{
|
||||||
struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv;
|
struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv;
|
||||||
|
|
||||||
if( lpc2900_info->chipid != EXPECTED_CHIPID )
|
if( !lpc2900_info->is_probed )
|
||||||
{
|
{
|
||||||
return ERROR_FLASH_BANK_NOT_PROBED;
|
return ERROR_FLASH_BANK_NOT_PROBED;
|
||||||
}
|
}
|
||||||
@@ -306,39 +311,39 @@ static uint32_t lpc2900_read_security_status( struct flash_bank *bank )
|
|||||||
* a protected sector!
|
* a protected sector!
|
||||||
*/
|
*/
|
||||||
int sector;
|
int sector;
|
||||||
int index;
|
int index_t;
|
||||||
for( sector = 0; sector < bank->num_sectors; sector++ )
|
for( sector = 0; sector < bank->num_sectors; sector++ )
|
||||||
{
|
{
|
||||||
/* Convert logical sector number to physical sector number */
|
/* Convert logical sector number to physical sector number */
|
||||||
if( sector <= 4 )
|
if( sector <= 4 )
|
||||||
{
|
{
|
||||||
index = sector + 11;
|
index_t = sector + 11;
|
||||||
}
|
}
|
||||||
else if( sector <= 7 )
|
else if( sector <= 7 )
|
||||||
{
|
{
|
||||||
index = sector + 27;
|
index_t = sector + 27;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
index = sector - 8;
|
index_t = sector - 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
bank->sectors[sector].is_protected = -1;
|
bank->sectors[sector].is_protected = -1;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(iss_secured_field[index][0] == 0x00000000) &&
|
(iss_secured_field[index_t][0] == 0x00000000) &&
|
||||||
(iss_secured_field[index][1] == 0x00000000) &&
|
(iss_secured_field[index_t][1] == 0x00000000) &&
|
||||||
(iss_secured_field[index][2] == 0x00000000) &&
|
(iss_secured_field[index_t][2] == 0x00000000) &&
|
||||||
(iss_secured_field[index][3] == 0x00000000) )
|
(iss_secured_field[index_t][3] == 0x00000000) )
|
||||||
{
|
{
|
||||||
bank->sectors[sector].is_protected = 1;
|
bank->sectors[sector].is_protected = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(iss_secured_field[index][0] == 0xFFFFFFFF) &&
|
(iss_secured_field[index_t][0] == 0xFFFFFFFF) &&
|
||||||
(iss_secured_field[index][1] == 0xFFFFFFFF) &&
|
(iss_secured_field[index_t][1] == 0xFFFFFFFF) &&
|
||||||
(iss_secured_field[index][2] == 0xFFFFFFFF) &&
|
(iss_secured_field[index_t][2] == 0xFFFFFFFF) &&
|
||||||
(iss_secured_field[index][3] == 0xFFFFFFFF) )
|
(iss_secured_field[index_t][3] == 0xFFFFFFFF) )
|
||||||
{
|
{
|
||||||
bank->sectors[sector].is_protected = 0;
|
bank->sectors[sector].is_protected = 0;
|
||||||
}
|
}
|
||||||
@@ -507,16 +512,14 @@ static int lpc2900_write_index_page( struct flash_bank *bank,
|
|||||||
* @param clock System clock in Hz
|
* @param clock System clock in Hz
|
||||||
* @param time Program/erase time in µs
|
* @param time Program/erase time in µs
|
||||||
*/
|
*/
|
||||||
static uint32_t lpc2900_calc_tr( uint32_t clock, uint32_t time )
|
static uint32_t lpc2900_calc_tr( uint32_t clock_var, uint32_t time_var )
|
||||||
{
|
{
|
||||||
/* ((time[µs]/1e6) * f[Hz]) + 511
|
/* ((time[µs]/1e6) * f[Hz]) + 511
|
||||||
* FPTR.TR = -------------------------------
|
* FPTR.TR = -------------------------------
|
||||||
* 512
|
* 512
|
||||||
*
|
|
||||||
* The result is the
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint32_t tr_val = (uint32_t)((((time / 1e6) * clock) + 511.0) / 512.0);
|
uint32_t tr_val = (uint32_t)((((time_var / 1e6) * clock_var) + 511.0) / 512.0);
|
||||||
|
|
||||||
return tr_val;
|
return tr_val;
|
||||||
}
|
}
|
||||||
@@ -1050,6 +1053,7 @@ FLASH_BANK_COMMAND_HANDLER(lpc2900_flash_bank_command)
|
|||||||
|
|
||||||
/* Chip ID will be obtained by probing the device later */
|
/* Chip ID will be obtained by probing the device later */
|
||||||
lpc2900_info->chipid = 0;
|
lpc2900_info->chipid = 0;
|
||||||
|
lpc2900_info->is_probed = false;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
@@ -1288,7 +1292,7 @@ static int lpc2900_write(struct flash_bank *bank, uint8_t *buffer,
|
|||||||
reduced size if that fails. */
|
reduced size if that fails. */
|
||||||
struct working_area *warea;
|
struct working_area *warea;
|
||||||
uint32_t buffer_size = lpc2900_info->max_ram_block - 1 * KiB;
|
uint32_t buffer_size = lpc2900_info->max_ram_block - 1 * KiB;
|
||||||
while( (retval = target_alloc_working_area(target,
|
while( (retval = target_alloc_working_area_try(target,
|
||||||
buffer_size + target_code_size,
|
buffer_size + target_code_size,
|
||||||
&warea)) != ERROR_OK )
|
&warea)) != ERROR_OK )
|
||||||
{
|
{
|
||||||
@@ -1365,7 +1369,7 @@ static int lpc2900_write(struct flash_bank *bank, uint8_t *buffer,
|
|||||||
this_buffer = buffer;
|
this_buffer = buffer;
|
||||||
|
|
||||||
/* Make sure we stop at the next secured sector */
|
/* Make sure we stop at the next secured sector */
|
||||||
int sector = start_sector + 1;
|
sector = start_sector + 1;
|
||||||
while( sector < bank->num_sectors )
|
while( sector < bank->num_sectors )
|
||||||
{
|
{
|
||||||
/* Secured? */
|
/* Secured? */
|
||||||
@@ -1554,10 +1558,8 @@ static int lpc2900_probe(struct flash_bank *bank)
|
|||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We want to do this only once. Check if we already have a valid CHIPID,
|
/* We want to do this only once. */
|
||||||
* because then we will have already successfully probed the device.
|
if (lpc2900_info->is_probed)
|
||||||
*/
|
|
||||||
if (lpc2900_info->chipid == EXPECTED_CHIPID)
|
|
||||||
{
|
{
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
@@ -1636,7 +1638,11 @@ static int lpc2900_probe(struct flash_bank *bank)
|
|||||||
else if ( package_code == 4 )
|
else if ( package_code == 4 )
|
||||||
{
|
{
|
||||||
/* 144-pin package */
|
/* 144-pin package */
|
||||||
if ( (bank->size == 512*KiB) && (feat3 == 0xFFFFFCF0) )
|
if ( (bank->size == 256*KiB) && (feat3 == 0xFFFFFFE9) )
|
||||||
|
{
|
||||||
|
lpc2900_info->target_name = "LPC2926";
|
||||||
|
}
|
||||||
|
else if ( (bank->size == 512*KiB) && (feat3 == 0xFFFFFCF0) )
|
||||||
{
|
{
|
||||||
lpc2900_info->target_name = "LPC2917/01";
|
lpc2900_info->target_name = "LPC2917/01";
|
||||||
}
|
}
|
||||||
@@ -1670,7 +1676,11 @@ static int lpc2900_probe(struct flash_bank *bank)
|
|||||||
|
|
||||||
if ( !found )
|
if ( !found )
|
||||||
{
|
{
|
||||||
LOG_WARNING("Unknown LPC29xx derivative");
|
LOG_WARNING("Unknown LPC29xx derivative"
|
||||||
|
" (FEATx="
|
||||||
|
"%08" PRIx32 ":%08" PRIx32 ":%08" PRIx32 ":%08" PRIx32 ")",
|
||||||
|
feat0, feat1, feat2, feat3
|
||||||
|
);
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1723,6 +1733,8 @@ static int lpc2900_probe(struct flash_bank *bank)
|
|||||||
offset += bank->sectors[i].size;
|
offset += bank->sectors[i].size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lpc2900_info->is_probed = true;
|
||||||
|
|
||||||
/* Read sector security status */
|
/* Read sector security status */
|
||||||
if ( lpc2900_read_security_status(bank) != ERROR_OK )
|
if ( lpc2900_read_security_status(bank) != ERROR_OK )
|
||||||
{
|
{
|
||||||
@@ -1830,6 +1842,7 @@ struct flash_driver lpc2900_flash =
|
|||||||
.erase = lpc2900_erase,
|
.erase = lpc2900_erase,
|
||||||
.protect = lpc2900_protect,
|
.protect = lpc2900_protect,
|
||||||
.write = lpc2900_write,
|
.write = lpc2900_write,
|
||||||
|
.read = default_flash_read,
|
||||||
.probe = lpc2900_probe,
|
.probe = lpc2900_probe,
|
||||||
.auto_probe = lpc2900_probe,
|
.auto_probe = lpc2900_probe,
|
||||||
.erase_check = lpc2900_erase_check,
|
.erase_check = lpc2900_erase_check,
|
||||||
|
|||||||
@@ -90,6 +90,20 @@ static struct non_cfi non_cfi_flashes[] = {
|
|||||||
ERASE_REGION(128, 4*KB)
|
ERASE_REGION(128, 4*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.mfr = CFI_MFR_AMD, /* Spansion AM29LV040B */
|
||||||
|
.id = 0x4f,
|
||||||
|
.pri_id = 0x02,
|
||||||
|
.dev_size = 512*KB,
|
||||||
|
.interface_desc = 0x0, /* x8 only device */
|
||||||
|
.max_buf_write_size = 0x0,
|
||||||
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
|
.num_erase_regions = 1,
|
||||||
|
.erase_region_info =
|
||||||
|
{
|
||||||
|
ERASE_REGION(8, 64*KB)
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.mfr = CFI_MFR_SST,
|
.mfr = CFI_MFR_SST,
|
||||||
.id = 0x2780,
|
.id = 0x2780,
|
||||||
@@ -230,6 +244,20 @@ static struct non_cfi non_cfi_flashes[] = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
.mfr = CFI_MFR_SST,
|
||||||
|
.id = 0x236d, /* SST39VF6401B */
|
||||||
|
.pri_id = 0x02,
|
||||||
|
.dev_size = 8*MB,
|
||||||
|
.interface_desc = 0x2, /* x8 or x16 device with nBYTE */
|
||||||
|
.max_buf_write_size = 0x0,
|
||||||
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
|
||||||
|
.num_erase_regions = 1,
|
||||||
|
.erase_region_info =
|
||||||
|
{
|
||||||
|
ERASE_REGION(2048, 4*KB)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
.mfr = CFI_MFR_AMD,
|
.mfr = CFI_MFR_AMD,
|
||||||
.id = 0x22ab, /* AM29F400BB */
|
.id = 0x22ab, /* AM29F400BB */
|
||||||
.pri_id = 0x02,
|
.pri_id = 0x02,
|
||||||
@@ -280,6 +308,23 @@ static struct non_cfi non_cfi_flashes[] = {
|
|||||||
ERASE_REGION(15, 64*KB)
|
ERASE_REGION(15, 64*KB)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.mfr = CFI_MFR_FUJITSU,
|
||||||
|
.id = 0x22ea, /* MBM29SL800TE */
|
||||||
|
.pri_id = 0x02,
|
||||||
|
.dev_size = 1*MB,
|
||||||
|
.interface_desc = 0x2, /* x8 or x16 device with nBYTE */
|
||||||
|
.max_buf_write_size = 0x0,
|
||||||
|
.status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
|
||||||
|
.num_erase_regions = 4,
|
||||||
|
.erase_region_info =
|
||||||
|
{
|
||||||
|
ERASE_REGION(15, 64*KB),
|
||||||
|
ERASE_REGION(1, 32*KB),
|
||||||
|
ERASE_REGION(2, 8*KB),
|
||||||
|
ERASE_REGION(1, 16*KB)
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.mfr = CFI_MFR_FUJITSU,
|
.mfr = CFI_MFR_FUJITSU,
|
||||||
.id = 0xba, /* 29LV400BC */
|
.id = 0xba, /* 29LV400BC */
|
||||||
@@ -423,13 +468,19 @@ static struct non_cfi non_cfi_flashes[] = {
|
|||||||
|
|
||||||
void cfi_fixup_non_cfi(struct flash_bank *bank)
|
void cfi_fixup_non_cfi(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
|
unsigned int mask;
|
||||||
struct cfi_flash_bank *cfi_info = bank->driver_priv;
|
struct cfi_flash_bank *cfi_info = bank->driver_priv;
|
||||||
struct non_cfi *non_cfi = non_cfi_flashes;
|
struct non_cfi *non_cfi = non_cfi_flashes;
|
||||||
|
|
||||||
|
if(cfi_info->x16_as_x8)
|
||||||
|
mask = 0xFF;
|
||||||
|
else
|
||||||
|
mask = 0xFFFF;
|
||||||
|
|
||||||
for (non_cfi = non_cfi_flashes; non_cfi->mfr; non_cfi++)
|
for (non_cfi = non_cfi_flashes; non_cfi->mfr; non_cfi++)
|
||||||
{
|
{
|
||||||
if ((cfi_info->manufacturer == non_cfi->mfr)
|
if ((cfi_info->manufacturer == non_cfi->mfr)
|
||||||
&& (cfi_info->device_id == non_cfi->id))
|
&& (cfi_info->device_id == (non_cfi->id & mask)))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -446,10 +497,12 @@ void cfi_fixup_non_cfi(struct flash_bank *bank)
|
|||||||
cfi_info->vcc_max = 0x0;
|
cfi_info->vcc_max = 0x0;
|
||||||
cfi_info->vpp_min = 0x0;
|
cfi_info->vpp_min = 0x0;
|
||||||
cfi_info->vpp_max = 0x0;
|
cfi_info->vpp_max = 0x0;
|
||||||
cfi_info->word_write_timeout_typ = 0x0;
|
/* these are used for timeouts - use vales that should be long enough
|
||||||
cfi_info->buf_write_timeout_typ = 0x0;
|
for normal operation. */
|
||||||
cfi_info->block_erase_timeout_typ = 0x0;
|
cfi_info->word_write_timeout_typ = 0x0a;
|
||||||
cfi_info->chip_erase_timeout_typ = 0x0;
|
cfi_info->buf_write_timeout_typ = 0x0d;
|
||||||
|
cfi_info->block_erase_timeout_typ = 0x0d;
|
||||||
|
cfi_info->chip_erase_timeout_typ = 0x10;
|
||||||
cfi_info->word_write_timeout_max = 0x0;
|
cfi_info->word_write_timeout_max = 0x0;
|
||||||
cfi_info->buf_write_timeout_max = 0x0;
|
cfi_info->buf_write_timeout_max = 0x0;
|
||||||
cfi_info->block_erase_timeout_max = 0x0;
|
cfi_info->block_erase_timeout_max = 0x0;
|
||||||
@@ -469,7 +522,11 @@ void cfi_fixup_non_cfi(struct flash_bank *bank)
|
|||||||
cfi_info->max_buf_write_size = non_cfi->max_buf_write_size;
|
cfi_info->max_buf_write_size = non_cfi->max_buf_write_size;
|
||||||
cfi_info->status_poll_mask = non_cfi->status_poll_mask;
|
cfi_info->status_poll_mask = non_cfi->status_poll_mask;
|
||||||
cfi_info->num_erase_regions = non_cfi->num_erase_regions;
|
cfi_info->num_erase_regions = non_cfi->num_erase_regions;
|
||||||
cfi_info->erase_region_info = non_cfi->erase_region_info;
|
size_t erase_region_info_size = sizeof(*cfi_info->erase_region_info) *
|
||||||
|
cfi_info->num_erase_regions;
|
||||||
|
cfi_info->erase_region_info = malloc(erase_region_info_size);
|
||||||
|
memcpy(cfi_info->erase_region_info,
|
||||||
|
non_cfi->erase_region_info, erase_region_info_size);
|
||||||
cfi_info->dev_size = non_cfi->dev_size;
|
cfi_info->dev_size = non_cfi->dev_size;
|
||||||
|
|
||||||
if (cfi_info->pri_id == 0x2)
|
if (cfi_info->pri_id == 0x2)
|
||||||
|
|||||||
@@ -101,8 +101,6 @@ static int ocl_erase(struct flash_bank *bank, int first, int last)
|
|||||||
/* wait for response, fixed timeout of 1 s */
|
/* wait for response, fixed timeout of 1 s */
|
||||||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
|
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
|
||||||
{
|
{
|
||||||
if (retval == ERROR_TARGET_TIMEOUT)
|
|
||||||
LOG_ERROR("loader not responding");
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,8 +204,6 @@ static int ocl_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
|
|||||||
/* wait for response, fixed timeout of 1 s */
|
/* wait for response, fixed timeout of 1 s */
|
||||||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
|
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
|
||||||
{
|
{
|
||||||
if (retval == ERROR_TARGET_TIMEOUT)
|
|
||||||
LOG_ERROR("loader not responding");
|
|
||||||
free(dcc_buffer);
|
free(dcc_buffer);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@@ -252,8 +248,6 @@ static int ocl_probe(struct flash_bank *bank)
|
|||||||
/* wait for response, fixed timeout of 1 s */
|
/* wait for response, fixed timeout of 1 s */
|
||||||
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
|
if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
|
||||||
{
|
{
|
||||||
if (retval == ERROR_TARGET_TIMEOUT)
|
|
||||||
LOG_ERROR("loader not responding");
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,6 +347,7 @@ struct flash_driver ocl_flash = {
|
|||||||
.erase = ocl_erase,
|
.erase = ocl_erase,
|
||||||
.protect = ocl_protect,
|
.protect = ocl_protect,
|
||||||
.write = ocl_write,
|
.write = ocl_write,
|
||||||
|
.read = default_flash_read,
|
||||||
.probe = ocl_probe,
|
.probe = ocl_probe,
|
||||||
.erase_check = ocl_erase_check,
|
.erase_check = ocl_erase_check,
|
||||||
.protect_check = ocl_protect_check,
|
.protect_check = ocl_protect_check,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user