summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab+samsung@kernel.org>2019-04-18 12:44:38 -0400
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2019-07-15 08:20:25 -0400
commit6e58e2d81367308ffd891bd0b34d47e9104e7ae4 (patch)
treeac0316fd44e5645dff35a91802602f6cf0a7697f
parent7ed44d59f1959942b8d882e6eeea51616b72e2ec (diff)
docs: mtd: convert to ReST
Rename the mtd documentation files to ReST, add an index for them and adjust in order to produce a nice html output via the Sphinx build system. It should be noticed that Sphinx doesn't handle very well URLs with dots in the middle. Thankfully, internally, the '.' char is translated to %2E, so we can jus use %2E instead of dots, and this will work fine on both text and processed files. At its new index.rst, let's add a :orphan: while this is not linked to the main index.rst file, in order to avoid build warnings. Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
-rw-r--r--Documentation/mtd/index.rst12
-rw-r--r--Documentation/mtd/intel-spi.rst (renamed from Documentation/mtd/intel-spi.txt)46
-rw-r--r--Documentation/mtd/nand_ecc.rst (renamed from Documentation/mtd/nand_ecc.txt)497
-rw-r--r--Documentation/mtd/spi-nor.rst (renamed from Documentation/mtd/spi-nor.txt)7
-rw-r--r--drivers/mtd/nand/raw/nand_ecc.c2
5 files changed, 314 insertions, 250 deletions
diff --git a/Documentation/mtd/index.rst b/Documentation/mtd/index.rst
new file mode 100644
index 000000000000..4fdae418ac97
--- /dev/null
+++ b/Documentation/mtd/index.rst
@@ -0,0 +1,12 @@
1:orphan:
2
3==============================
4Memory Technology Device (MTD)
5==============================
6
7.. toctree::
8 :maxdepth: 1
9
10 intel-spi
11 nand_ecc
12 spi-nor
diff --git a/Documentation/mtd/intel-spi.txt b/Documentation/mtd/intel-spi.rst
index bc357729c2cb..0e6d9cd5388d 100644
--- a/Documentation/mtd/intel-spi.txt
+++ b/Documentation/mtd/intel-spi.rst
@@ -1,5 +1,6 @@
1==============================
1Upgrading BIOS using intel-spi 2Upgrading BIOS using intel-spi
2------------------------------ 3==============================
3 4
4Many Intel CPUs like Baytrail and Braswell include SPI serial flash host 5Many Intel CPUs like Baytrail and Braswell include SPI serial flash host
5controller which is used to hold BIOS and other platform specific data. 6controller which is used to hold BIOS and other platform specific data.
@@ -36,45 +37,45 @@ Linux.
36 module parameter to modprobe). 37 module parameter to modprobe).
37 38
38 4) Once the board is up and running again, find the right MTD partition 39 4) Once the board is up and running again, find the right MTD partition
39 (it is named as "BIOS"): 40 (it is named as "BIOS")::
40 41
41 # cat /proc/mtd 42 # cat /proc/mtd
42 dev: size erasesize name 43 dev: size erasesize name
43 mtd0: 00800000 00001000 "BIOS" 44 mtd0: 00800000 00001000 "BIOS"
44 45
45 So here it will be /dev/mtd0 but it may vary. 46 So here it will be /dev/mtd0 but it may vary.
46 47
47 5) Make backup of the existing image first: 48 5) Make backup of the existing image first::
48 49
49 # dd if=/dev/mtd0ro of=bios.bak 50 # dd if=/dev/mtd0ro of=bios.bak
50 16384+0 records in 51 16384+0 records in
51 16384+0 records out 52 16384+0 records out
52 8388608 bytes (8.4 MB) copied, 10.0269 s, 837 kB/s 53 8388608 bytes (8.4 MB) copied, 10.0269 s, 837 kB/s
53 54
54 6) Verify the backup 55 6) Verify the backup:
55 56
56 # sha1sum /dev/mtd0ro bios.bak 57 # sha1sum /dev/mtd0ro bios.bak
57 fdbb011920572ca6c991377c4b418a0502668b73 /dev/mtd0ro 58 fdbb011920572ca6c991377c4b418a0502668b73 /dev/mtd0ro
58 fdbb011920572ca6c991377c4b418a0502668b73 bios.bak 59 fdbb011920572ca6c991377c4b418a0502668b73 bios.bak
59 60
60 The SHA1 sums must match. Otherwise do not continue any further! 61 The SHA1 sums must match. Otherwise do not continue any further!
61 62
62 7) Erase the SPI serial flash. After this step, do not reboot the 63 7) Erase the SPI serial flash. After this step, do not reboot the
63 board! Otherwise it will not start anymore. 64 board! Otherwise it will not start anymore::
64 65
65 # flash_erase /dev/mtd0 0 0 66 # flash_erase /dev/mtd0 0 0
66 Erasing 4 Kibyte @ 7ff000 -- 100 % complete 67 Erasing 4 Kibyte @ 7ff000 -- 100 % complete
67 68
68 8) Once completed without errors you can write the new BIOS image: 69 8) Once completed without errors you can write the new BIOS image:
69 70
70 # dd if=MNW2MAX1.X64.0092.R01.1605221712.bin of=/dev/mtd0 71 # dd if=MNW2MAX1.X64.0092.R01.1605221712.bin of=/dev/mtd0
71 72
72 9) Verify that the new content of the SPI serial flash matches the new 73 9) Verify that the new content of the SPI serial flash matches the new
73 BIOS image: 74 BIOS image::
74 75
75 # sha1sum /dev/mtd0ro MNW2MAX1.X64.0092.R01.1605221712.bin 76 # sha1sum /dev/mtd0ro MNW2MAX1.X64.0092.R01.1605221712.bin
76 9b4df9e4be2057fceec3a5529ec3d950836c87a2 /dev/mtd0ro 77 9b4df9e4be2057fceec3a5529ec3d950836c87a2 /dev/mtd0ro
77 9b4df9e4be2057fceec3a5529ec3d950836c87a2 MNW2MAX1.X64.0092.R01.1605221712.bin 78 9b4df9e4be2057fceec3a5529ec3d950836c87a2 MNW2MAX1.X64.0092.R01.1605221712.bin
78 79
79 The SHA1 sums should match. 80 The SHA1 sums should match.
80 81
@@ -84,5 +85,6 @@ Linux.
84References 85References
85---------- 86----------
86 87
87[1] https://firmware.intel.com/sites/default/files/MinnowBoard.MAX_.X64.92.R01.zip 88[1] https://firmware.intel.com/sites/default/files/MinnowBoard%2EMAX_%2EX64%2E92%2ER01%2Ezip
89
88[2] http://www.linux-mtd.infradead.org/ 90[2] http://www.linux-mtd.infradead.org/
diff --git a/Documentation/mtd/nand_ecc.txt b/Documentation/mtd/nand_ecc.rst
index f8c3284bf6a7..e8d3c53a5056 100644
--- a/Documentation/mtd/nand_ecc.txt
+++ b/Documentation/mtd/nand_ecc.rst
@@ -1,3 +1,7 @@
1==========================
2NAND Error-correction Code
3==========================
4
1Introduction 5Introduction
2============ 6============
3 7
@@ -37,63 +41,79 @@ sometimes also referred to as xor. In C the operator for xor is ^
37Back to ecc. 41Back to ecc.
38Let's give a small figure: 42Let's give a small figure:
39 43
44========= ==== ==== ==== ==== ==== ==== ==== ==== === === === === ====
40byte 0: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 rp0 rp2 rp4 ... rp14 45byte 0: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 rp0 rp2 rp4 ... rp14
41byte 1: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 rp1 rp2 rp4 ... rp14 46byte 1: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 rp1 rp2 rp4 ... rp14
42byte 2: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 rp0 rp3 rp4 ... rp14 47byte 2: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 rp0 rp3 rp4 ... rp14
43byte 3: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 rp1 rp3 rp4 ... rp14 48byte 3: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 rp1 rp3 rp4 ... rp14
44byte 4: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 rp0 rp2 rp5 ... rp14 49byte 4: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 rp0 rp2 rp5 ... rp14
45.... 50...
46byte 254: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 rp0 rp3 rp5 ... rp15 51byte 254: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 rp0 rp3 rp5 ... rp15
47byte 255: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 rp1 rp3 rp5 ... rp15 52byte 255: bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 rp1 rp3 rp5 ... rp15
48 cp1 cp0 cp1 cp0 cp1 cp0 cp1 cp0 53 cp1 cp0 cp1 cp0 cp1 cp0 cp1 cp0
49 cp3 cp3 cp2 cp2 cp3 cp3 cp2 cp2 54 cp3 cp3 cp2 cp2 cp3 cp3 cp2 cp2
50 cp5 cp5 cp5 cp5 cp4 cp4 cp4 cp4 55 cp5 cp5 cp5 cp5 cp4 cp4 cp4 cp4
56========= ==== ==== ==== ==== ==== ==== ==== ==== === === === === ====
51 57
52This figure represents a sector of 256 bytes. 58This figure represents a sector of 256 bytes.
53cp is my abbreviation for column parity, rp for row parity. 59cp is my abbreviation for column parity, rp for row parity.
54 60
55Let's start to explain column parity. 61Let's start to explain column parity.
56cp0 is the parity that belongs to all bit0, bit2, bit4, bit6. 62
57so the sum of all bit0, bit2, bit4 and bit6 values + cp0 itself is even. 63- cp0 is the parity that belongs to all bit0, bit2, bit4, bit6.
64
65 so the sum of all bit0, bit2, bit4 and bit6 values + cp0 itself is even.
66
58Similarly cp1 is the sum of all bit1, bit3, bit5 and bit7. 67Similarly cp1 is the sum of all bit1, bit3, bit5 and bit7.
59cp2 is the parity over bit0, bit1, bit4 and bit5 68
60cp3 is the parity over bit2, bit3, bit6 and bit7. 69- cp2 is the parity over bit0, bit1, bit4 and bit5
61cp4 is the parity over bit0, bit1, bit2 and bit3. 70- cp3 is the parity over bit2, bit3, bit6 and bit7.
62cp5 is the parity over bit4, bit5, bit6 and bit7. 71- cp4 is the parity over bit0, bit1, bit2 and bit3.
72- cp5 is the parity over bit4, bit5, bit6 and bit7.
73
63Note that each of cp0 .. cp5 is exactly one bit. 74Note that each of cp0 .. cp5 is exactly one bit.
64 75
65Row parity actually works almost the same. 76Row parity actually works almost the same.
66rp0 is the parity of all even bytes (0, 2, 4, 6, ... 252, 254) 77
67rp1 is the parity of all odd bytes (1, 3, 5, 7, ..., 253, 255) 78- rp0 is the parity of all even bytes (0, 2, 4, 6, ... 252, 254)
68rp2 is the parity of all bytes 0, 1, 4, 5, 8, 9, ... 79- rp1 is the parity of all odd bytes (1, 3, 5, 7, ..., 253, 255)
69(so handle two bytes, then skip 2 bytes). 80- rp2 is the parity of all bytes 0, 1, 4, 5, 8, 9, ...
70rp3 is covers the half rp2 does not cover (bytes 2, 3, 6, 7, 10, 11, ...) 81 (so handle two bytes, then skip 2 bytes).
71for rp4 the rule is cover 4 bytes, skip 4 bytes, cover 4 bytes, skip 4 etc. 82- rp3 is covers the half rp2 does not cover (bytes 2, 3, 6, 7, 10, 11, ...)
72so rp4 calculates parity over bytes 0, 1, 2, 3, 8, 9, 10, 11, 16, ...) 83- for rp4 the rule is cover 4 bytes, skip 4 bytes, cover 4 bytes, skip 4 etc.
73and rp5 covers the other half, so bytes 4, 5, 6, 7, 12, 13, 14, 15, 20, .. 84
85 so rp4 calculates parity over bytes 0, 1, 2, 3, 8, 9, 10, 11, 16, ...)
86- and rp5 covers the other half, so bytes 4, 5, 6, 7, 12, 13, 14, 15, 20, ..
87
74The story now becomes quite boring. I guess you get the idea. 88The story now becomes quite boring. I guess you get the idea.
75rp6 covers 8 bytes then skips 8 etc 89
76rp7 skips 8 bytes then covers 8 etc 90- rp6 covers 8 bytes then skips 8 etc
77rp8 covers 16 bytes then skips 16 etc 91- rp7 skips 8 bytes then covers 8 etc
78rp9 skips 16 bytes then covers 16 etc 92- rp8 covers 16 bytes then skips 16 etc
79rp10 covers 32 bytes then skips 32 etc 93- rp9 skips 16 bytes then covers 16 etc
80rp11 skips 32 bytes then covers 32 etc 94- rp10 covers 32 bytes then skips 32 etc
81rp12 covers 64 bytes then skips 64 etc 95- rp11 skips 32 bytes then covers 32 etc
82rp13 skips 64 bytes then covers 64 etc 96- rp12 covers 64 bytes then skips 64 etc
83rp14 covers 128 bytes then skips 128 97- rp13 skips 64 bytes then covers 64 etc
84rp15 skips 128 bytes then covers 128 98- rp14 covers 128 bytes then skips 128
99- rp15 skips 128 bytes then covers 128
85 100
86In the end the parity bits are grouped together in three bytes as 101In the end the parity bits are grouped together in three bytes as
87follows: 102follows:
103
104===== ===== ===== ===== ===== ===== ===== ===== =====
88ECC Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 105ECC Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
106===== ===== ===== ===== ===== ===== ===== ===== =====
89ECC 0 rp07 rp06 rp05 rp04 rp03 rp02 rp01 rp00 107ECC 0 rp07 rp06 rp05 rp04 rp03 rp02 rp01 rp00
90ECC 1 rp15 rp14 rp13 rp12 rp11 rp10 rp09 rp08 108ECC 1 rp15 rp14 rp13 rp12 rp11 rp10 rp09 rp08
91ECC 2 cp5 cp4 cp3 cp2 cp1 cp0 1 1 109ECC 2 cp5 cp4 cp3 cp2 cp1 cp0 1 1
110===== ===== ===== ===== ===== ===== ===== ===== =====
92 111
93I detected after writing this that ST application note AN1823 112I detected after writing this that ST application note AN1823
94(http://www.st.com/stonline/) gives a much 113(http://www.st.com/stonline/) gives a much
95nicer picture.(but they use line parity as term where I use row parity) 114nicer picture.(but they use line parity as term where I use row parity)
96Oh well, I'm graphically challenged, so suffer with me for a moment :-) 115Oh well, I'm graphically challenged, so suffer with me for a moment :-)
116
97And I could not reuse the ST picture anyway for copyright reasons. 117And I could not reuse the ST picture anyway for copyright reasons.
98 118
99 119
@@ -101,9 +121,10 @@ Attempt 0
101========= 121=========
102 122
103Implementing the parity calculation is pretty simple. 123Implementing the parity calculation is pretty simple.
104In C pseudocode: 124In C pseudocode::
105for (i = 0; i < 256; i++) 125
106{ 126 for (i = 0; i < 256; i++)
127 {
107 if (i & 0x01) 128 if (i & 0x01)
108 rp1 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp1; 129 rp1 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp1;
109 else 130 else
@@ -142,7 +163,7 @@ for (i = 0; i < 256; i++)
142 cp3 = bit7 ^ bit6 ^ bit3 ^ bit2 ^ cp3 163 cp3 = bit7 ^ bit6 ^ bit3 ^ bit2 ^ cp3
143 cp4 = bit3 ^ bit2 ^ bit1 ^ bit0 ^ cp4 164 cp4 = bit3 ^ bit2 ^ bit1 ^ bit0 ^ cp4
144 cp5 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ cp5 165 cp5 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ cp5
145} 166 }
146 167
147 168
148Analysis 0 169Analysis 0
@@ -167,82 +188,84 @@ This leads to:
167Attempt 1 188Attempt 1
168========= 189=========
169 190
170const char parity[256] = { 191::
171 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 192
172 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 193 const char parity[256] = {
173 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 194 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
174 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 195 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
175 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 196 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
176 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 197 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
177 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 198 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
178 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 199 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
179 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 200 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
180 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 201 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
181 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 202 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
182 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 203 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
183 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 204 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
184 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 205 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
185 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 206 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
186 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 207 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
187}; 208 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
188 209 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0
189void ecc1(const unsigned char *buf, unsigned char *code) 210 };
190{ 211
191 int i; 212 void ecc1(const unsigned char *buf, unsigned char *code)
192 const unsigned char *bp = buf; 213 {
193 unsigned char cur; 214 int i;
194 unsigned char rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7; 215 const unsigned char *bp = buf;
195 unsigned char rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15; 216 unsigned char cur;
196 unsigned char par; 217 unsigned char rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7;
197 218 unsigned char rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15;
198 par = 0; 219 unsigned char par;
199 rp0 = 0; rp1 = 0; rp2 = 0; rp3 = 0; 220
200 rp4 = 0; rp5 = 0; rp6 = 0; rp7 = 0; 221 par = 0;
201 rp8 = 0; rp9 = 0; rp10 = 0; rp11 = 0; 222 rp0 = 0; rp1 = 0; rp2 = 0; rp3 = 0;
202 rp12 = 0; rp13 = 0; rp14 = 0; rp15 = 0; 223 rp4 = 0; rp5 = 0; rp6 = 0; rp7 = 0;
203 224 rp8 = 0; rp9 = 0; rp10 = 0; rp11 = 0;
204 for (i = 0; i < 256; i++) 225 rp12 = 0; rp13 = 0; rp14 = 0; rp15 = 0;
205 { 226
206 cur = *bp++; 227 for (i = 0; i < 256; i++)
207 par ^= cur; 228 {
208 if (i & 0x01) rp1 ^= cur; else rp0 ^= cur; 229 cur = *bp++;
209 if (i & 0x02) rp3 ^= cur; else rp2 ^= cur; 230 par ^= cur;
210 if (i & 0x04) rp5 ^= cur; else rp4 ^= cur; 231 if (i & 0x01) rp1 ^= cur; else rp0 ^= cur;
211 if (i & 0x08) rp7 ^= cur; else rp6 ^= cur; 232 if (i & 0x02) rp3 ^= cur; else rp2 ^= cur;
212 if (i & 0x10) rp9 ^= cur; else rp8 ^= cur; 233 if (i & 0x04) rp5 ^= cur; else rp4 ^= cur;
213 if (i & 0x20) rp11 ^= cur; else rp10 ^= cur; 234 if (i & 0x08) rp7 ^= cur; else rp6 ^= cur;
214 if (i & 0x40) rp13 ^= cur; else rp12 ^= cur; 235 if (i & 0x10) rp9 ^= cur; else rp8 ^= cur;
215 if (i & 0x80) rp15 ^= cur; else rp14 ^= cur; 236 if (i & 0x20) rp11 ^= cur; else rp10 ^= cur;
216 } 237 if (i & 0x40) rp13 ^= cur; else rp12 ^= cur;
217 code[0] = 238 if (i & 0x80) rp15 ^= cur; else rp14 ^= cur;
218 (parity[rp7] << 7) | 239 }
219 (parity[rp6] << 6) | 240 code[0] =
220 (parity[rp5] << 5) | 241 (parity[rp7] << 7) |
221 (parity[rp4] << 4) | 242 (parity[rp6] << 6) |
222 (parity[rp3] << 3) | 243 (parity[rp5] << 5) |
223 (parity[rp2] << 2) | 244 (parity[rp4] << 4) |
224 (parity[rp1] << 1) | 245 (parity[rp3] << 3) |
225 (parity[rp0]); 246 (parity[rp2] << 2) |
226 code[1] = 247 (parity[rp1] << 1) |
227 (parity[rp15] << 7) | 248 (parity[rp0]);
228 (parity[rp14] << 6) | 249 code[1] =
229 (parity[rp13] << 5) | 250 (parity[rp15] << 7) |
230 (parity[rp12] << 4) | 251 (parity[rp14] << 6) |
231 (parity[rp11] << 3) | 252 (parity[rp13] << 5) |
232 (parity[rp10] << 2) | 253 (parity[rp12] << 4) |
233 (parity[rp9] << 1) | 254 (parity[rp11] << 3) |
234 (parity[rp8]); 255 (parity[rp10] << 2) |
235 code[2] = 256 (parity[rp9] << 1) |
236 (parity[par & 0xf0] << 7) | 257 (parity[rp8]);
237 (parity[par & 0x0f] << 6) | 258 code[2] =
238 (parity[par & 0xcc] << 5) | 259 (parity[par & 0xf0] << 7) |
239 (parity[par & 0x33] << 4) | 260 (parity[par & 0x0f] << 6) |
240 (parity[par & 0xaa] << 3) | 261 (parity[par & 0xcc] << 5) |
241 (parity[par & 0x55] << 2); 262 (parity[par & 0x33] << 4) |
242 code[0] = ~code[0]; 263 (parity[par & 0xaa] << 3) |
243 code[1] = ~code[1]; 264 (parity[par & 0x55] << 2);
244 code[2] = ~code[2]; 265 code[0] = ~code[0];
245} 266 code[1] = ~code[1];
267 code[2] = ~code[2];
268 }
246 269
247Still pretty straightforward. The last three invert statements are there to 270Still pretty straightforward. The last three invert statements are there to
248give a checksum of 0xff 0xff 0xff for an empty flash. In an empty flash 271give a checksum of 0xff 0xff 0xff for an empty flash. In an empty flash
@@ -293,88 +316,90 @@ Let's give it a try...
293Attempt 2 316Attempt 2
294========= 317=========
295 318
296extern const char parity[256]; 319::
297 320
298void ecc2(const unsigned char *buf, unsigned char *code) 321 extern const char parity[256];
299{ 322
300 int i; 323 void ecc2(const unsigned char *buf, unsigned char *code)
301 const unsigned long *bp = (unsigned long *)buf; 324 {
302 unsigned long cur; 325 int i;
303 unsigned long rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7; 326 const unsigned long *bp = (unsigned long *)buf;
304 unsigned long rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15; 327 unsigned long cur;
305 unsigned long par; 328 unsigned long rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7;
306 329 unsigned long rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15;
307 par = 0; 330 unsigned long par;
308 rp0 = 0; rp1 = 0; rp2 = 0; rp3 = 0; 331
309 rp4 = 0; rp5 = 0; rp6 = 0; rp7 = 0; 332 par = 0;
310 rp8 = 0; rp9 = 0; rp10 = 0; rp11 = 0; 333 rp0 = 0; rp1 = 0; rp2 = 0; rp3 = 0;
311 rp12 = 0; rp13 = 0; rp14 = 0; rp15 = 0; 334 rp4 = 0; rp5 = 0; rp6 = 0; rp7 = 0;
312 335 rp8 = 0; rp9 = 0; rp10 = 0; rp11 = 0;
313 for (i = 0; i < 64; i++) 336 rp12 = 0; rp13 = 0; rp14 = 0; rp15 = 0;
314 { 337
315 cur = *bp++; 338 for (i = 0; i < 64; i++)
316 par ^= cur; 339 {
317 if (i & 0x01) rp5 ^= cur; else rp4 ^= cur; 340 cur = *bp++;
318 if (i & 0x02) rp7 ^= cur; else rp6 ^= cur; 341 par ^= cur;
319 if (i & 0x04) rp9 ^= cur; else rp8 ^= cur; 342 if (i & 0x01) rp5 ^= cur; else rp4 ^= cur;
320 if (i & 0x08) rp11 ^= cur; else rp10 ^= cur; 343 if (i & 0x02) rp7 ^= cur; else rp6 ^= cur;
321 if (i & 0x10) rp13 ^= cur; else rp12 ^= cur; 344 if (i & 0x04) rp9 ^= cur; else rp8 ^= cur;
322 if (i & 0x20) rp15 ^= cur; else rp14 ^= cur; 345 if (i & 0x08) rp11 ^= cur; else rp10 ^= cur;
323 } 346 if (i & 0x10) rp13 ^= cur; else rp12 ^= cur;
324 /* 347 if (i & 0x20) rp15 ^= cur; else rp14 ^= cur;
325 we need to adapt the code generation for the fact that rp vars are now 348 }
326 long; also the column parity calculation needs to be changed. 349 /*
327 we'll bring rp4 to 15 back to single byte entities by shifting and 350 we need to adapt the code generation for the fact that rp vars are now
328 xoring 351 long; also the column parity calculation needs to be changed.
329 */ 352 we'll bring rp4 to 15 back to single byte entities by shifting and
330 rp4 ^= (rp4 >> 16); rp4 ^= (rp4 >> 8); rp4 &= 0xff; 353 xoring
331 rp5 ^= (rp5 >> 16); rp5 ^= (rp5 >> 8); rp5 &= 0xff; 354 */
332 rp6 ^= (rp6 >> 16); rp6 ^= (rp6 >> 8); rp6 &= 0xff; 355 rp4 ^= (rp4 >> 16); rp4 ^= (rp4 >> 8); rp4 &= 0xff;
333 rp7 ^= (rp7 >> 16); rp7 ^= (rp7 >> 8); rp7 &= 0xff; 356 rp5 ^= (rp5 >> 16); rp5 ^= (rp5 >> 8); rp5 &= 0xff;
334 rp8 ^= (rp8 >> 16); rp8 ^= (rp8 >> 8); rp8 &= 0xff; 357 rp6 ^= (rp6 >> 16); rp6 ^= (rp6 >> 8); rp6 &= 0xff;
335 rp9 ^= (rp9 >> 16); rp9 ^= (rp9 >> 8); rp9 &= 0xff; 358 rp7 ^= (rp7 >> 16); rp7 ^= (rp7 >> 8); rp7 &= 0xff;
336 rp10 ^= (rp10 >> 16); rp10 ^= (rp10 >> 8); rp10 &= 0xff; 359 rp8 ^= (rp8 >> 16); rp8 ^= (rp8 >> 8); rp8 &= 0xff;
337 rp11 ^= (rp11 >> 16); rp11 ^= (rp11 >> 8); rp11 &= 0xff; 360 rp9 ^= (rp9 >> 16); rp9 ^= (rp9 >> 8); rp9 &= 0xff;
338 rp12 ^= (rp12 >> 16); rp12 ^= (rp12 >> 8); rp12 &= 0xff; 361 rp10 ^= (rp10 >> 16); rp10 ^= (rp10 >> 8); rp10 &= 0xff;
339 rp13 ^= (rp13 >> 16); rp13 ^= (rp13 >> 8); rp13 &= 0xff; 362 rp11 ^= (rp11 >> 16); rp11 ^= (rp11 >> 8); rp11 &= 0xff;
340 rp14 ^= (rp14 >> 16); rp14 ^= (rp14 >> 8); rp14 &= 0xff; 363 rp12 ^= (rp12 >> 16); rp12 ^= (rp12 >> 8); rp12 &= 0xff;
341 rp15 ^= (rp15 >> 16); rp15 ^= (rp15 >> 8); rp15 &= 0xff; 364 rp13 ^= (rp13 >> 16); rp13 ^= (rp13 >> 8); rp13 &= 0xff;
342 rp3 = (par >> 16); rp3 ^= (rp3 >> 8); rp3 &= 0xff; 365 rp14 ^= (rp14 >> 16); rp14 ^= (rp14 >> 8); rp14 &= 0xff;
343 rp2 = par & 0xffff; rp2 ^= (rp2 >> 8); rp2 &= 0xff; 366 rp15 ^= (rp15 >> 16); rp15 ^= (rp15 >> 8); rp15 &= 0xff;
344 par ^= (par >> 16); 367 rp3 = (par >> 16); rp3 ^= (rp3 >> 8); rp3 &= 0xff;
345 rp1 = (par >> 8); rp1 &= 0xff; 368 rp2 = par & 0xffff; rp2 ^= (rp2 >> 8); rp2 &= 0xff;
346 rp0 = (par & 0xff); 369 par ^= (par >> 16);
347 par ^= (par >> 8); par &= 0xff; 370 rp1 = (par >> 8); rp1 &= 0xff;
348 371 rp0 = (par & 0xff);
349 code[0] = 372 par ^= (par >> 8); par &= 0xff;
350 (parity[rp7] << 7) | 373
351 (parity[rp6] << 6) | 374 code[0] =
352 (parity[rp5] << 5) | 375 (parity[rp7] << 7) |
353 (parity[rp4] << 4) | 376 (parity[rp6] << 6) |
354 (parity[rp3] << 3) | 377 (parity[rp5] << 5) |
355 (parity[rp2] << 2) | 378 (parity[rp4] << 4) |
356 (parity[rp1] << 1) | 379 (parity[rp3] << 3) |
357 (parity[rp0]); 380 (parity[rp2] << 2) |
358 code[1] = 381 (parity[rp1] << 1) |
359 (parity[rp15] << 7) | 382 (parity[rp0]);
360 (parity[rp14] << 6) | 383 code[1] =
361 (parity[rp13] << 5) | 384 (parity[rp15] << 7) |
362 (parity[rp12] << 4) | 385 (parity[rp14] << 6) |
363 (parity[rp11] << 3) | 386 (parity[rp13] << 5) |
364 (parity[rp10] << 2) | 387 (parity[rp12] << 4) |
365 (parity[rp9] << 1) | 388 (parity[rp11] << 3) |
366 (parity[rp8]); 389 (parity[rp10] << 2) |
367 code[2] = 390 (parity[rp9] << 1) |
368 (parity[par & 0xf0] << 7) | 391 (parity[rp8]);
369 (parity[par & 0x0f] << 6) | 392 code[2] =
370 (parity[par & 0xcc] << 5) | 393 (parity[par & 0xf0] << 7) |
371 (parity[par & 0x33] << 4) | 394 (parity[par & 0x0f] << 6) |
372 (parity[par & 0xaa] << 3) | 395 (parity[par & 0xcc] << 5) |
373 (parity[par & 0x55] << 2); 396 (parity[par & 0x33] << 4) |
374 code[0] = ~code[0]; 397 (parity[par & 0xaa] << 3) |
375 code[1] = ~code[1]; 398 (parity[par & 0x55] << 2);
376 code[2] = ~code[2]; 399 code[0] = ~code[0];
377} 400 code[1] = ~code[1];
401 code[2] = ~code[2];
402 }
378 403
379The parity array is not shown any more. Note also that for these 404The parity array is not shown any more. Note also that for these
380examples I kinda deviated from my regular programming style by allowing 405examples I kinda deviated from my regular programming style by allowing
@@ -403,28 +428,32 @@ lookups
403Attempt 3 428Attempt 3
404========= 429=========
405 430
406Odd replaced: 431Odd replaced::
407 if (i & 0x01) rp5 ^= cur; else rp4 ^= cur; 432
408 if (i & 0x02) rp7 ^= cur; else rp6 ^= cur; 433 if (i & 0x01) rp5 ^= cur; else rp4 ^= cur;
409 if (i & 0x04) rp9 ^= cur; else rp8 ^= cur; 434 if (i & 0x02) rp7 ^= cur; else rp6 ^= cur;
410 if (i & 0x08) rp11 ^= cur; else rp10 ^= cur; 435 if (i & 0x04) rp9 ^= cur; else rp8 ^= cur;
411 if (i & 0x10) rp13 ^= cur; else rp12 ^= cur; 436 if (i & 0x08) rp11 ^= cur; else rp10 ^= cur;
412 if (i & 0x20) rp15 ^= cur; else rp14 ^= cur; 437 if (i & 0x10) rp13 ^= cur; else rp12 ^= cur;
413with 438 if (i & 0x20) rp15 ^= cur; else rp14 ^= cur;
414 if (i & 0x01) rp5 ^= cur; 439
415 if (i & 0x02) rp7 ^= cur; 440with::
416 if (i & 0x04) rp9 ^= cur; 441
417 if (i & 0x08) rp11 ^= cur; 442 if (i & 0x01) rp5 ^= cur;
418 if (i & 0x10) rp13 ^= cur; 443 if (i & 0x02) rp7 ^= cur;
419 if (i & 0x20) rp15 ^= cur; 444 if (i & 0x04) rp9 ^= cur;
420 445 if (i & 0x08) rp11 ^= cur;
421 and outside the loop added: 446 if (i & 0x10) rp13 ^= cur;
422 rp4 = par ^ rp5; 447 if (i & 0x20) rp15 ^= cur;
423 rp6 = par ^ rp7; 448
424 rp8 = par ^ rp9; 449and outside the loop added::
425 rp10 = par ^ rp11; 450
426 rp12 = par ^ rp13; 451 rp4 = par ^ rp5;
427 rp14 = par ^ rp15; 452 rp6 = par ^ rp7;
453 rp8 = par ^ rp9;
454 rp10 = par ^ rp11;
455 rp12 = par ^ rp13;
456 rp14 = par ^ rp15;
428 457
429And after that the code takes about 30% more time, although the number of 458And after that the code takes about 30% more time, although the number of
430statements is reduced. This is also reflected in the assembly code. 459statements is reduced. This is also reflected in the assembly code.
@@ -448,7 +477,7 @@ Attempt 4
448========= 477=========
449 478
450Unrolled the loop 1, 2, 3 and 4 times. 479Unrolled the loop 1, 2, 3 and 4 times.
451For 4 the code starts with: 480For 4 the code starts with::
452 481
453 for (i = 0; i < 4; i++) 482 for (i = 0; i < 4; i++)
454 { 483 {
@@ -471,8 +500,11 @@ Analysis 4
471========== 500==========
472 501
473Unrolling once gains about 15% 502Unrolling once gains about 15%
503
474Unrolling twice keeps the gain at about 15% 504Unrolling twice keeps the gain at about 15%
505
475Unrolling three times gives a gain of 30% compared to attempt 2. 506Unrolling three times gives a gain of 30% compared to attempt 2.
507
476Unrolling four times gives a marginal improvement compared to unrolling 508Unrolling four times gives a marginal improvement compared to unrolling
477three times. 509three times.
478 510
@@ -492,8 +524,10 @@ Attempt 5
492 524
493Effectively so all odd digit rp assignments in the loop were removed. 525Effectively so all odd digit rp assignments in the loop were removed.
494This included the else clause of the if statements. 526This included the else clause of the if statements.
495Of course after the loop we need to correct things by adding code like: 527Of course after the loop we need to correct things by adding code like::
528
496 rp5 = par ^ rp4; 529 rp5 = par ^ rp4;
530
497Also the initial assignments (rp5 = 0; etc) could be removed. 531Also the initial assignments (rp5 = 0; etc) could be removed.
498Along the line I also removed the initialisation of rp0/1/2/3. 532Along the line I also removed the initialisation of rp0/1/2/3.
499 533
@@ -513,7 +547,7 @@ statement. Time for yet another version!
513Attempt 6 547Attempt 6
514========= 548=========
515 549
516THe code within the for loop was changed to: 550THe code within the for loop was changed to::
517 551
518 for (i = 0; i < 4; i++) 552 for (i = 0; i < 4; i++)
519 { 553 {
@@ -564,13 +598,17 @@ million iterations in order not to lose too much accuracy. This one
564definitely seemed to be the jackpot! 598definitely seemed to be the jackpot!
565 599
566There is a little bit more room for improvement though. There are three 600There is a little bit more room for improvement though. There are three
567places with statements: 601places with statements::
568rp4 ^= cur; rp6 ^= cur; 602
603 rp4 ^= cur; rp6 ^= cur;
604
569It seems more efficient to also maintain a variable rp4_6 in the while 605It seems more efficient to also maintain a variable rp4_6 in the while
570loop; This eliminates 3 statements per loop. Of course after the loop we 606loop; This eliminates 3 statements per loop. Of course after the loop we
571need to correct by adding: 607need to correct by adding::
572 rp4 ^= rp4_6; 608
573 rp6 ^= rp4_6 609 rp4 ^= rp4_6;
610 rp6 ^= rp4_6
611
574Furthermore there are 4 sequential assignments to rp8. This can be 612Furthermore there are 4 sequential assignments to rp8. This can be
575encoded slightly more efficiently by saving tmppar before those 4 lines 613encoded slightly more efficiently by saving tmppar before those 4 lines
576and later do rp8 = rp8 ^ tmppar ^ notrp8; 614and later do rp8 = rp8 ^ tmppar ^ notrp8;
@@ -582,7 +620,7 @@ Time for a new test!
582Attempt 7 620Attempt 7
583========= 621=========
584 622
585The new code now looks like: 623The new code now looks like::
586 624
587 for (i = 0; i < 4; i++) 625 for (i = 0; i < 4; i++)
588 { 626 {
@@ -644,9 +682,12 @@ Although it seems that the code within the loop cannot be optimised
644further there is still room to optimize the generation of the ecc codes. 682further there is still room to optimize the generation of the ecc codes.
645We can simply calculate the total parity. If this is 0 then rp4 = rp5 683We can simply calculate the total parity. If this is 0 then rp4 = rp5
646etc. If the parity is 1, then rp4 = !rp5; 684etc. If the parity is 1, then rp4 = !rp5;
685
647But if rp4 = rp5 we do not need rp5 etc. We can just write the even bits 686But if rp4 = rp5 we do not need rp5 etc. We can just write the even bits
648in the result byte and then do something like 687in the result byte and then do something like::
688
649 code[0] |= (code[0] << 1); 689 code[0] |= (code[0] << 1);
690
650Lets test this. 691Lets test this.
651 692
652 693
@@ -657,11 +698,13 @@ Changed the code but again this slightly degrades performance. Tried all
657kind of other things, like having dedicated parity arrays to avoid the 698kind of other things, like having dedicated parity arrays to avoid the
658shift after parity[rp7] << 7; No gain. 699shift after parity[rp7] << 7; No gain.
659Change the lookup using the parity array by using shift operators (e.g. 700Change the lookup using the parity array by using shift operators (e.g.
660replace parity[rp7] << 7 with: 701replace parity[rp7] << 7 with::
661rp7 ^= (rp7 << 4); 702
662rp7 ^= (rp7 << 2); 703 rp7 ^= (rp7 << 4);
663rp7 ^= (rp7 << 1); 704 rp7 ^= (rp7 << 2);
664rp7 &= 0x80; 705 rp7 ^= (rp7 << 1);
706 rp7 &= 0x80;
707
665No gain. 708No gain.
666 709
667The only marginal change was inverting the parity bits, so we can remove 710The only marginal change was inverting the parity bits, so we can remove
@@ -683,13 +726,16 @@ Correcting errors
683 726
684For correcting errors I again used the ST application note as a starter, 727For correcting errors I again used the ST application note as a starter,
685but I also peeked at the existing code. 728but I also peeked at the existing code.
729
686The algorithm itself is pretty straightforward. Just xor the given and 730The algorithm itself is pretty straightforward. Just xor the given and
687the calculated ecc. If all bytes are 0 there is no problem. If 11 bits 731the calculated ecc. If all bytes are 0 there is no problem. If 11 bits
688are 1 we have one correctable bit error. If there is 1 bit 1, we have an 732are 1 we have one correctable bit error. If there is 1 bit 1, we have an
689error in the given ecc code. 733error in the given ecc code.
734
690It proved to be fastest to do some table lookups. Performance gain 735It proved to be fastest to do some table lookups. Performance gain
691introduced by this is about a factor 2 on my system when a repair had to 736introduced by this is about a factor 2 on my system when a repair had to
692be done, and 1% or so if no repair had to be done. 737be done, and 1% or so if no repair had to be done.
738
693Code size increased from 330 bytes to 686 bytes for this function. 739Code size increased from 330 bytes to 686 bytes for this function.
694(gcc 4.2, -O3) 740(gcc 4.2, -O3)
695 741
@@ -700,8 +746,10 @@ Conclusion
700The gain when calculating the ecc is tremendous. Om my development hardware 746The gain when calculating the ecc is tremendous. Om my development hardware
701a speedup of a factor of 18 for ecc calculation was achieved. On a test on an 747a speedup of a factor of 18 for ecc calculation was achieved. On a test on an
702embedded system with a MIPS core a factor 7 was obtained. 748embedded system with a MIPS core a factor 7 was obtained.
749
703On a test with a Linksys NSLU2 (ARMv5TE processor) the speedup was a factor 750On a test with a Linksys NSLU2 (ARMv5TE processor) the speedup was a factor
7045 (big endian mode, gcc 4.1.2, -O3) 7515 (big endian mode, gcc 4.1.2, -O3)
752
705For correction not much gain could be obtained (as bitflips are rare). Then 753For correction not much gain could be obtained (as bitflips are rare). Then
706again there are also much less cycles spent there. 754again there are also much less cycles spent there.
707 755
@@ -711,4 +759,5 @@ out of it with an assembler program, but due to pipeline behaviour etc
711this is very tricky (at least for intel hw). 759this is very tricky (at least for intel hw).
712 760
713Author: Frans Meulenbroeks 761Author: Frans Meulenbroeks
762
714Copyright (C) 2008 Koninklijke Philips Electronics NV. 763Copyright (C) 2008 Koninklijke Philips Electronics NV.
diff --git a/Documentation/mtd/spi-nor.txt b/Documentation/mtd/spi-nor.rst
index da1fbff5a24c..f5333e3bf486 100644
--- a/Documentation/mtd/spi-nor.txt
+++ b/Documentation/mtd/spi-nor.rst
@@ -1,5 +1,6 @@
1 SPI NOR framework 1=================
2 ============================================ 2SPI NOR framework
3=================
3 4
4Part I - Why do we need this framework? 5Part I - Why do we need this framework?
5--------------------------------------- 6---------------------------------------
@@ -23,7 +24,7 @@ This framework just adds a new layer between the MTD and the SPI bus driver.
23With this new layer, the SPI NOR controller driver does not depend on the 24With this new layer, the SPI NOR controller driver does not depend on the
24m25p80 code anymore. 25m25p80 code anymore.
25 26
26 Before this framework, the layer is like: 27Before this framework, the layer is like::
27 28
28 MTD 29 MTD
29 ------------------------ 30 ------------------------
diff --git a/drivers/mtd/nand/raw/nand_ecc.c b/drivers/mtd/nand/raw/nand_ecc.c
index 223fbd8052b3..f6a7808db818 100644
--- a/drivers/mtd/nand/raw/nand_ecc.c
+++ b/drivers/mtd/nand/raw/nand_ecc.c
@@ -11,7 +11,7 @@
11 * Thomas Gleixner (tglx@linutronix.de) 11 * Thomas Gleixner (tglx@linutronix.de)
12 * 12 *
13 * Information on how this algorithm works and how it was developed 13 * Information on how this algorithm works and how it was developed
14 * can be found in Documentation/mtd/nand_ecc.txt 14 * can be found in Documentation/mtd/nand_ecc.rst
15 */ 15 */
16 16
17#include <linux/types.h> 17#include <linux/types.h>