|
2 | 2 | SPI NOR framework
|
3 | 3 | =================
|
4 | 4 |
|
5 |
| -Part I - Why do we need this framework? |
6 |
| ---------------------------------------- |
7 |
| - |
8 |
| -SPI bus controllers (drivers/spi/) only deal with streams of bytes; the bus |
9 |
| -controller operates agnostic of the specific device attached. However, some |
10 |
| -controllers (such as Freescale's QuadSPI controller) cannot easily handle |
11 |
| -arbitrary streams of bytes, but rather are designed specifically for SPI NOR. |
12 |
| - |
13 |
| -In particular, Freescale's QuadSPI controller must know the NOR commands to |
14 |
| -find the right LUT sequence. Unfortunately, the SPI subsystem has no notion of |
15 |
| -opcodes, addresses, or data payloads; a SPI controller simply knows to send or |
16 |
| -receive bytes (Tx and Rx). Therefore, we must define a new layering scheme under |
17 |
| -which the controller driver is aware of the opcodes, addressing, and other |
18 |
| -details of the SPI NOR protocol. |
19 |
| - |
20 |
| -Part II - How does the framework work? |
21 |
| --------------------------------------- |
22 |
| - |
23 |
| -This framework just adds a new layer between the MTD and the SPI bus driver. |
24 |
| -With this new layer, the SPI NOR controller driver does not depend on the |
25 |
| -m25p80 code anymore. |
26 |
| - |
27 |
| -Before this framework, the layer is like:: |
28 |
| - |
29 |
| - MTD |
30 |
| - ------------------------ |
31 |
| - m25p80 |
32 |
| - ------------------------ |
33 |
| - SPI bus driver |
34 |
| - ------------------------ |
35 |
| - SPI NOR chip |
36 |
| - |
37 |
| -After this framework, the layer is like:: |
38 |
| - |
39 |
| - MTD |
40 |
| - ------------------------ |
41 |
| - SPI NOR framework |
42 |
| - ------------------------ |
43 |
| - m25p80 |
44 |
| - ------------------------ |
45 |
| - SPI bus driver |
46 |
| - ------------------------ |
47 |
| - SPI NOR chip |
48 |
| - |
49 |
| -With the SPI NOR controller driver (Freescale QuadSPI), it looks like:: |
50 |
| - |
51 |
| - MTD |
52 |
| - ------------------------ |
53 |
| - SPI NOR framework |
54 |
| - ------------------------ |
55 |
| - fsl-quadSPI |
56 |
| - ------------------------ |
57 |
| - SPI NOR chip |
58 |
| - |
59 |
| -Part III - How can drivers use the framework? |
60 |
| ---------------------------------------------- |
61 |
| - |
62 |
| -The main API is spi_nor_scan(). Before you call the hook, a driver should |
63 |
| -initialize the necessary fields for spi_nor{}. Please see |
64 |
| -drivers/mtd/spi-nor/spi-nor.c for detail. Please also refer to spi-fsl-qspi.c |
65 |
| -when you want to write a new driver for a SPI NOR controller. |
| 5 | +How to propose a new flash addition |
| 6 | +----------------------------------- |
| 7 | + |
| 8 | +Most SPI NOR flashes comply with the JEDEC JESD216 |
| 9 | +Serial Flash Discoverable Parameter (SFDP) standard. SFDP describes |
| 10 | +the functional and feature capabilities of serial flash devices in a |
| 11 | +standard set of internal read-only parameter tables. |
| 12 | + |
| 13 | +The SPI NOR driver queries the SFDP tables in order to determine the |
| 14 | +flash's parameters and settings. If the flash defines the SFDP tables |
| 15 | +it's likely that you won't need a flash entry at all, and instead |
| 16 | +rely on the generic flash driver which probes the flash solely based |
| 17 | +on its SFDP data. All one has to do is to specify the "jedec,spi-nor" |
| 18 | +compatible in the device tree. |
| 19 | + |
| 20 | +There are cases however where you need to define an explicit flash |
| 21 | +entry. This typically happens when the flash has settings or support |
| 22 | +that is not covered by the SFDP tables (e.g. Block Protection), or |
| 23 | +when the flash contains mangled SFDP data. If the later, one needs |
| 24 | +to implement the ``spi_nor_fixups`` hooks in order to amend the SFDP |
| 25 | +parameters with the correct values. |
| 26 | + |
| 27 | +Minimum testing requirements |
| 28 | +----------------------------- |
| 29 | + |
| 30 | +Do all the tests from below and paste them in the commit's comments |
| 31 | +section, after the ``---`` marker. |
| 32 | + |
| 33 | +1) Specify the controller that you used to test the flash and specify |
| 34 | + the frequency at which the flash was operated, e.g.:: |
| 35 | + |
| 36 | + This flash is populated on the X board and was tested at Y |
| 37 | + frequency using the Z (put compatible) SPI controller. |
| 38 | + |
| 39 | +2) Dump the sysfs entries and print the md5/sha1/sha256 SFDP checksum:: |
| 40 | + |
| 41 | + root@1:~# cat /sys/bus/spi/devices/spi0.0/spi-nor/partname |
| 42 | + sst26vf064b |
| 43 | + root@1:~# cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id |
| 44 | + bf2643 |
| 45 | + root@1:~# cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer |
| 46 | + sst |
| 47 | + root@1:~# xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp |
| 48 | + 53464450060102ff00060110300000ff81000106000100ffbf0001180002 |
| 49 | + 0001fffffffffffffffffffffffffffffffffd20f1ffffffff0344eb086b |
| 50 | + 083b80bbfeffffffffff00ffffff440b0c200dd80fd810d820914824806f |
| 51 | + 1d81ed0f773830b030b0f7ffffff29c25cfff030c080ffffffffffffffff |
| 52 | + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
| 53 | + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
| 54 | + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
| 55 | + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
| 56 | + ffffffffffffffffffffffffffffffffff0004fff37f0000f57f0000f9ff |
| 57 | + 7d00f57f0000f37f0000ffffffffffffffffffffffffffffffffffffffff |
| 58 | + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
| 59 | + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
| 60 | + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
| 61 | + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
| 62 | + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
| 63 | + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
| 64 | + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
| 65 | + ffffbf2643ffb95ffdff30f260f332ff0a122346ff0f19320f1919ffffff |
| 66 | + ffffffff00669938ff05013506040232b03072428de89888a585c09faf5a |
| 67 | + ffff06ec060c0003080bffffffffff07ffff0202ff060300fdfd040700fc |
| 68 | + 0300fefe0202070e |
| 69 | + root@1:~# sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp |
| 70 | + 428f34d0461876f189ac97f93e68a05fa6428c6650b3b7baf736a921e5898ed1 /sys/bus/spi/devices/spi0.0/spi-nor/sfdp |
| 71 | + |
| 72 | + Please dump the SFDP tables using ``xxd -p``. It enables us to do |
| 73 | + the reverse operation and convert the hexdump to binary with |
| 74 | + ``xxd -rp``. Dumping the SFDP data with ``hexdump -Cv`` is accepted, |
| 75 | + but less desirable. |
| 76 | + |
| 77 | +3) Dump debugfs data:: |
| 78 | + |
| 79 | + root@1:~# cat /sys/kernel/debug/spi-nor/spi0.0/capabilities |
| 80 | + Supported read modes by the flash |
| 81 | + 1S-1S-1S |
| 82 | + opcode 0x03 |
| 83 | + mode cycles 0 |
| 84 | + dummy cycles 0 |
| 85 | + 1S-1S-1S (fast read) |
| 86 | + opcode 0x0b |
| 87 | + mode cycles 0 |
| 88 | + dummy cycles 8 |
| 89 | + 1S-1S-2S |
| 90 | + opcode 0x3b |
| 91 | + mode cycles 0 |
| 92 | + dummy cycles 8 |
| 93 | + 1S-2S-2S |
| 94 | + opcode 0xbb |
| 95 | + mode cycles 4 |
| 96 | + dummy cycles 0 |
| 97 | + 1S-1S-4S |
| 98 | + opcode 0x6b |
| 99 | + mode cycles 0 |
| 100 | + dummy cycles 8 |
| 101 | + 1S-4S-4S |
| 102 | + opcode 0xeb |
| 103 | + mode cycles 2 |
| 104 | + dummy cycles 4 |
| 105 | + 4S-4S-4S |
| 106 | + opcode 0x0b |
| 107 | + mode cycles 2 |
| 108 | + dummy cycles 4 |
| 109 | + |
| 110 | + Supported page program modes by the flash |
| 111 | + 1S-1S-1S |
| 112 | + opcode 0x02 |
| 113 | + |
| 114 | + root@1:~# cat /sys/kernel/debug/spi-nor/spi0.0/params |
| 115 | + name sst26vf064b |
| 116 | + id bf 26 43 bf 26 43 |
| 117 | + size 8.00 MiB |
| 118 | + write size 1 |
| 119 | + page size 256 |
| 120 | + address nbytes 3 |
| 121 | + flags HAS_LOCK | HAS_16BIT_SR | SOFT_RESET | SWP_IS_VOLATILE |
| 122 | + |
| 123 | + opcodes |
| 124 | + read 0xeb |
| 125 | + dummy cycles 6 |
| 126 | + erase 0x20 |
| 127 | + program 0x02 |
| 128 | + 8D extension none |
| 129 | + |
| 130 | + protocols |
| 131 | + read 1S-4S-4S |
| 132 | + write 1S-1S-1S |
| 133 | + register 1S-1S-1S |
| 134 | + |
| 135 | + erase commands |
| 136 | + 20 (4.00 KiB) [0] |
| 137 | + d8 (8.00 KiB) [1] |
| 138 | + d8 (32.0 KiB) [2] |
| 139 | + d8 (64.0 KiB) [3] |
| 140 | + c7 (8.00 MiB) |
| 141 | + |
| 142 | + sector map |
| 143 | + region (in hex) | erase mask | flags |
| 144 | + ------------------+------------+---------- |
| 145 | + 00000000-00007fff | [01 ] | |
| 146 | + 00008000-0000ffff | [0 2 ] | |
| 147 | + 00010000-007effff | [0 3] | |
| 148 | + 007f0000-007f7fff | [0 2 ] | |
| 149 | + 007f8000-007fffff | [01 ] | |
| 150 | + |
| 151 | +4) Use `mtd-utils <https://git.infradead.org/mtd-utils.git>`__ |
| 152 | + and verify that erase, read and page program operations work fine:: |
| 153 | + |
| 154 | + root@1:~# dd if=/dev/urandom of=./spi_test bs=1M count=2 |
| 155 | + 2+0 records in |
| 156 | + 2+0 records out |
| 157 | + 2097152 bytes (2.1 MB, 2.0 MiB) copied, 0.848566 s, 2.5 MB/s |
| 158 | + |
| 159 | + root@1:~# mtd_debug erase /dev/mtd0 0 2097152 |
| 160 | + Erased 2097152 bytes from address 0x00000000 in flash |
| 161 | + |
| 162 | + root@1:~# mtd_debug read /dev/mtd0 0 2097152 spi_read |
| 163 | + Copied 2097152 bytes from address 0x00000000 in flash to spi_read |
| 164 | + |
| 165 | + root@1:~# hexdump spi_read |
| 166 | + 0000000 ffff ffff ffff ffff ffff ffff ffff ffff |
| 167 | + * |
| 168 | + 0200000 |
| 169 | + |
| 170 | + root@1:~# sha256sum spi_read |
| 171 | + 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read |
| 172 | + |
| 173 | + root@1:~# mtd_debug write /dev/mtd0 0 2097152 spi_test |
| 174 | + Copied 2097152 bytes from spi_test to address 0x00000000 in flash |
| 175 | + |
| 176 | + root@1:~# mtd_debug read /dev/mtd0 0 2097152 spi_read |
| 177 | + Copied 2097152 bytes from address 0x00000000 in flash to spi_read |
| 178 | + |
| 179 | + root@1:~# sha256sum spi* |
| 180 | + c444216a6ba2a4a66cccd60a0dd062bce4b865dd52b200ef5e21838c4b899ac8 spi_read |
| 181 | + c444216a6ba2a4a66cccd60a0dd062bce4b865dd52b200ef5e21838c4b899ac8 spi_test |
| 182 | + |
| 183 | + If the flash comes erased by default and the previous erase was ignored, |
| 184 | + we won't catch it, thus test the erase again:: |
| 185 | + |
| 186 | + root@1:~# mtd_debug erase /dev/mtd0 0 2097152 |
| 187 | + Erased 2097152 bytes from address 0x00000000 in flash |
| 188 | + |
| 189 | + root@1:~# mtd_debug read /dev/mtd0 0 2097152 spi_read |
| 190 | + Copied 2097152 bytes from address 0x00000000 in flash to spi_read |
| 191 | + |
| 192 | + root@1:~# sha256sum spi* |
| 193 | + 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read |
| 194 | + c444216a6ba2a4a66cccd60a0dd062bce4b865dd52b200ef5e21838c4b899ac8 spi_test |
| 195 | + |
| 196 | + Dump some other relevant data:: |
| 197 | + |
| 198 | + root@1:~# mtd_debug info /dev/mtd0 |
| 199 | + mtd.type = MTD_NORFLASH |
| 200 | + mtd.flags = MTD_CAP_NORFLASH |
| 201 | + mtd.size = 8388608 (8M) |
| 202 | + mtd.erasesize = 4096 (4K) |
| 203 | + mtd.writesize = 1 |
| 204 | + mtd.oobsize = 0 |
| 205 | + regions = 0 |
0 commit comments