.. | .. |
---|
32 | 32 | SPI_MEM_OP_NO_DUMMY, \ |
---|
33 | 33 | SPI_MEM_OP_NO_DATA) |
---|
34 | 34 | |
---|
35 | | -#define SPINAND_READID_OP(ndummy, buf, len) \ |
---|
| 35 | +#define SPINAND_READID_OP(naddr, ndummy, buf, len) \ |
---|
36 | 36 | SPI_MEM_OP(SPI_MEM_OP_CMD(0x9f, 1), \ |
---|
37 | | - SPI_MEM_OP_NO_ADDR, \ |
---|
| 37 | + SPI_MEM_OP_ADDR(naddr, 0, 1), \ |
---|
38 | 38 | SPI_MEM_OP_DUMMY(ndummy, 1), \ |
---|
39 | 39 | SPI_MEM_OP_DATA_IN(len, buf, 1)) |
---|
40 | 40 | |
---|
.. | .. |
---|
68 | 68 | SPI_MEM_OP_DUMMY(ndummy, 1), \ |
---|
69 | 69 | SPI_MEM_OP_DATA_IN(len, buf, 1)) |
---|
70 | 70 | |
---|
| 71 | +#define SPINAND_PAGE_READ_FROM_CACHE_OP_3A(fast, addr, ndummy, buf, len) \ |
---|
| 72 | + SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1), \ |
---|
| 73 | + SPI_MEM_OP_ADDR(3, addr, 1), \ |
---|
| 74 | + SPI_MEM_OP_DUMMY(ndummy, 1), \ |
---|
| 75 | + SPI_MEM_OP_DATA_IN(len, buf, 1)) |
---|
| 76 | + |
---|
71 | 77 | #define SPINAND_PAGE_READ_FROM_CACHE_X2_OP(addr, ndummy, buf, len) \ |
---|
72 | 78 | SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \ |
---|
73 | 79 | SPI_MEM_OP_ADDR(2, addr, 1), \ |
---|
| 80 | + SPI_MEM_OP_DUMMY(ndummy, 1), \ |
---|
| 81 | + SPI_MEM_OP_DATA_IN(len, buf, 2)) |
---|
| 82 | + |
---|
| 83 | +#define SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(addr, ndummy, buf, len) \ |
---|
| 84 | + SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \ |
---|
| 85 | + SPI_MEM_OP_ADDR(3, addr, 1), \ |
---|
74 | 86 | SPI_MEM_OP_DUMMY(ndummy, 1), \ |
---|
75 | 87 | SPI_MEM_OP_DATA_IN(len, buf, 2)) |
---|
76 | 88 | |
---|
.. | .. |
---|
80 | 92 | SPI_MEM_OP_DUMMY(ndummy, 1), \ |
---|
81 | 93 | SPI_MEM_OP_DATA_IN(len, buf, 4)) |
---|
82 | 94 | |
---|
| 95 | +#define SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(addr, ndummy, buf, len) \ |
---|
| 96 | + SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \ |
---|
| 97 | + SPI_MEM_OP_ADDR(3, addr, 1), \ |
---|
| 98 | + SPI_MEM_OP_DUMMY(ndummy, 1), \ |
---|
| 99 | + SPI_MEM_OP_DATA_IN(len, buf, 4)) |
---|
| 100 | + |
---|
83 | 101 | #define SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(addr, ndummy, buf, len) \ |
---|
84 | 102 | SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \ |
---|
85 | 103 | SPI_MEM_OP_ADDR(2, addr, 2), \ |
---|
86 | 104 | SPI_MEM_OP_DUMMY(ndummy, 2), \ |
---|
87 | 105 | SPI_MEM_OP_DATA_IN(len, buf, 2)) |
---|
88 | 106 | |
---|
| 107 | +#define SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP_3A(addr, ndummy, buf, len) \ |
---|
| 108 | + SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \ |
---|
| 109 | + SPI_MEM_OP_ADDR(3, addr, 2), \ |
---|
| 110 | + SPI_MEM_OP_DUMMY(ndummy, 2), \ |
---|
| 111 | + SPI_MEM_OP_DATA_IN(len, buf, 2)) |
---|
| 112 | + |
---|
89 | 113 | #define SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(addr, ndummy, buf, len) \ |
---|
90 | 114 | SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1), \ |
---|
91 | 115 | SPI_MEM_OP_ADDR(2, addr, 4), \ |
---|
| 116 | + SPI_MEM_OP_DUMMY(ndummy, 4), \ |
---|
| 117 | + SPI_MEM_OP_DATA_IN(len, buf, 4)) |
---|
| 118 | + |
---|
| 119 | +#define SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP_3A(addr, ndummy, buf, len) \ |
---|
| 120 | + SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1), \ |
---|
| 121 | + SPI_MEM_OP_ADDR(3, addr, 4), \ |
---|
92 | 122 | SPI_MEM_OP_DUMMY(ndummy, 4), \ |
---|
93 | 123 | SPI_MEM_OP_DATA_IN(len, buf, 4)) |
---|
94 | 124 | |
---|
.. | .. |
---|
119 | 149 | /* feature register */ |
---|
120 | 150 | #define REG_BLOCK_LOCK 0xa0 |
---|
121 | 151 | #define BL_ALL_UNLOCKED 0x00 |
---|
| 152 | +#define HWP_EN 0x02 /* Skyhigh feature, Hardware write protection */ |
---|
122 | 153 | |
---|
123 | 154 | /* configuration register */ |
---|
124 | 155 | #define REG_CFG 0xb0 |
---|
.. | .. |
---|
146 | 177 | * @data: buffer containing the id bytes. Currently 4 bytes large, but can |
---|
147 | 178 | * be extended if required |
---|
148 | 179 | * @len: ID length |
---|
149 | | - * |
---|
150 | | - * struct_spinand_id->data contains all bytes returned after a READ_ID command, |
---|
151 | | - * including dummy bytes if the chip does not emit ID bytes right after the |
---|
152 | | - * READ_ID command. The responsibility to extract real ID bytes is left to |
---|
153 | | - * struct_manufacurer_ops->detect(). |
---|
154 | 180 | */ |
---|
155 | 181 | struct spinand_id { |
---|
156 | 182 | u8 data[SPINAND_MAX_ID_LEN]; |
---|
157 | 183 | int len; |
---|
158 | 184 | }; |
---|
159 | 185 | |
---|
| 186 | +enum spinand_readid_method { |
---|
| 187 | + SPINAND_READID_METHOD_OPCODE, |
---|
| 188 | + SPINAND_READID_METHOD_OPCODE_ADDR, |
---|
| 189 | + SPINAND_READID_METHOD_OPCODE_DUMMY, |
---|
| 190 | +}; |
---|
| 191 | + |
---|
| 192 | +/** |
---|
| 193 | + * struct spinand_devid - SPI NAND device id structure |
---|
| 194 | + * @id: device id of current chip |
---|
| 195 | + * @len: number of bytes in device id |
---|
| 196 | + * @method: method to read chip id |
---|
| 197 | + * There are 3 possible variants: |
---|
| 198 | + * SPINAND_READID_METHOD_OPCODE: chip id is returned immediately |
---|
| 199 | + * after read_id opcode. |
---|
| 200 | + * SPINAND_READID_METHOD_OPCODE_ADDR: chip id is returned after |
---|
| 201 | + * read_id opcode + 1-byte address. |
---|
| 202 | + * SPINAND_READID_METHOD_OPCODE_DUMMY: chip id is returned after |
---|
| 203 | + * read_id opcode + 1 dummy byte. |
---|
| 204 | + */ |
---|
| 205 | +struct spinand_devid { |
---|
| 206 | + const u8 *id; |
---|
| 207 | + const u8 len; |
---|
| 208 | + const enum spinand_readid_method method; |
---|
| 209 | +}; |
---|
| 210 | + |
---|
160 | 211 | /** |
---|
161 | 212 | * struct manufacurer_ops - SPI NAND manufacturer specific operations |
---|
162 | | - * @detect: detect a SPI NAND device. Every time a SPI NAND device is probed |
---|
163 | | - * the core calls the struct_manufacurer_ops->detect() hook of each |
---|
164 | | - * registered manufacturer until one of them return 1. Note that |
---|
165 | | - * the first thing to check in this hook is that the manufacturer ID |
---|
166 | | - * in struct_spinand_device->id matches the manufacturer whose |
---|
167 | | - * ->detect() hook has been called. Should return 1 if there's a |
---|
168 | | - * match, 0 if the manufacturer ID does not match and a negative |
---|
169 | | - * error code otherwise. When true is returned, the core assumes |
---|
170 | | - * that properties of the NAND chip (spinand->base.memorg and |
---|
171 | | - * spinand->base.eccreq) have been filled |
---|
172 | 213 | * @init: initialize a SPI NAND device |
---|
173 | 214 | * @cleanup: cleanup a SPI NAND device |
---|
174 | 215 | * |
---|
175 | 216 | * Each SPI NAND manufacturer driver should implement this interface so that |
---|
176 | | - * NAND chips coming from this vendor can be detected and initialized properly. |
---|
| 217 | + * NAND chips coming from this vendor can be initialized properly. |
---|
177 | 218 | */ |
---|
178 | 219 | struct spinand_manufacturer_ops { |
---|
179 | | - int (*detect)(struct spinand_device *spinand); |
---|
180 | 220 | int (*init)(struct spinand_device *spinand); |
---|
181 | 221 | void (*cleanup)(struct spinand_device *spinand); |
---|
182 | 222 | }; |
---|
.. | .. |
---|
185 | 225 | * struct spinand_manufacturer - SPI NAND manufacturer instance |
---|
186 | 226 | * @id: manufacturer ID |
---|
187 | 227 | * @name: manufacturer name |
---|
| 228 | + * @devid_len: number of bytes in device ID |
---|
| 229 | + * @chips: supported SPI NANDs under current manufacturer |
---|
| 230 | + * @nchips: number of SPI NANDs available in chips array |
---|
188 | 231 | * @ops: manufacturer operations |
---|
189 | 232 | */ |
---|
190 | 233 | struct spinand_manufacturer { |
---|
191 | 234 | u8 id; |
---|
192 | 235 | char *name; |
---|
| 236 | + const struct spinand_info *chips; |
---|
| 237 | + const size_t nchips; |
---|
193 | 238 | const struct spinand_manufacturer_ops *ops; |
---|
194 | 239 | }; |
---|
195 | 240 | |
---|
196 | 241 | /* SPI NAND manufacturers */ |
---|
| 242 | +extern const struct spinand_manufacturer biwin_spinand_manufacturer; |
---|
| 243 | +extern const struct spinand_manufacturer dosilicon_spinand_manufacturer; |
---|
| 244 | +extern const struct spinand_manufacturer esmt_spinand_manufacturer; |
---|
| 245 | +extern const struct spinand_manufacturer etron_spinand_manufacturer; |
---|
| 246 | +extern const struct spinand_manufacturer fmsh_spinand_manufacturer; |
---|
| 247 | +extern const struct spinand_manufacturer foresee_spinand_manufacturer; |
---|
| 248 | +extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; |
---|
| 249 | +extern const struct spinand_manufacturer gsto_spinand_manufacturer; |
---|
| 250 | +extern const struct spinand_manufacturer hyf_spinand_manufacturer; |
---|
| 251 | +extern const struct spinand_manufacturer jsc_spinand_manufacturer; |
---|
197 | 252 | extern const struct spinand_manufacturer macronix_spinand_manufacturer; |
---|
198 | 253 | extern const struct spinand_manufacturer micron_spinand_manufacturer; |
---|
| 254 | +extern const struct spinand_manufacturer paragon_spinand_manufacturer; |
---|
| 255 | +extern const struct spinand_manufacturer toshiba_spinand_manufacturer; |
---|
| 256 | +extern const struct spinand_manufacturer silicongo_spinand_manufacturer; |
---|
| 257 | +extern const struct spinand_manufacturer skyhigh_spinand_manufacturer; |
---|
| 258 | +extern const struct spinand_manufacturer unim_spinand_manufacturer; |
---|
| 259 | +extern const struct spinand_manufacturer unim_zl_spinand_manufacturer; |
---|
199 | 260 | extern const struct spinand_manufacturer winbond_spinand_manufacturer; |
---|
| 261 | +extern const struct spinand_manufacturer xincun_spinand_manufacturer; |
---|
| 262 | +extern const struct spinand_manufacturer xtx_spinand_manufacturer; |
---|
200 | 263 | |
---|
201 | 264 | /** |
---|
202 | 265 | * struct spinand_op_variants - SPI NAND operation variants |
---|
.. | .. |
---|
237 | 300 | }; |
---|
238 | 301 | |
---|
239 | 302 | #define SPINAND_HAS_QE_BIT BIT(0) |
---|
| 303 | +#define SPINAND_HAS_CR_FEAT_BIT BIT(1) |
---|
| 304 | + |
---|
| 305 | +/** |
---|
| 306 | + * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure |
---|
| 307 | + * @status: status of the last wait operation that will be used in case |
---|
| 308 | + * ->get_status() is not populated by the spinand device. |
---|
| 309 | + */ |
---|
| 310 | +struct spinand_ondie_ecc_conf { |
---|
| 311 | + u8 status; |
---|
| 312 | +}; |
---|
240 | 313 | |
---|
241 | 314 | /** |
---|
242 | 315 | * struct spinand_info - Structure used to describe SPI NAND chips |
---|
.. | .. |
---|
258 | 331 | */ |
---|
259 | 332 | struct spinand_info { |
---|
260 | 333 | const char *model; |
---|
261 | | - u8 devid; |
---|
| 334 | + struct spinand_devid devid; |
---|
262 | 335 | u32 flags; |
---|
263 | 336 | struct nand_memory_organization memorg; |
---|
264 | | - struct nand_ecc_req eccreq; |
---|
| 337 | + struct nand_ecc_props eccreq; |
---|
265 | 338 | struct spinand_ecc_info eccinfo; |
---|
266 | 339 | struct { |
---|
267 | 340 | const struct spinand_op_variants *read_cache; |
---|
.. | .. |
---|
271 | 344 | int (*select_target)(struct spinand_device *spinand, |
---|
272 | 345 | unsigned int target); |
---|
273 | 346 | }; |
---|
| 347 | + |
---|
| 348 | +#define SPINAND_ID(__method, ...) \ |
---|
| 349 | + { \ |
---|
| 350 | + .id = (const u8[]){ __VA_ARGS__ }, \ |
---|
| 351 | + .len = sizeof((u8[]){ __VA_ARGS__ }), \ |
---|
| 352 | + .method = __method, \ |
---|
| 353 | + } |
---|
274 | 354 | |
---|
275 | 355 | #define SPINAND_INFO_OP_VARIANTS(__read, __write, __update) \ |
---|
276 | 356 | { \ |
---|
.. | .. |
---|
299 | 379 | .flags = __flags, \ |
---|
300 | 380 | __VA_ARGS__ \ |
---|
301 | 381 | } |
---|
| 382 | + |
---|
| 383 | +struct spinand_dirmap { |
---|
| 384 | + struct spi_mem_dirmap_desc *wdesc; |
---|
| 385 | + struct spi_mem_dirmap_desc *rdesc; |
---|
| 386 | +}; |
---|
302 | 387 | |
---|
303 | 388 | /** |
---|
304 | 389 | * struct spinand_device - SPI NAND device instance |
---|
.. | .. |
---|
338 | 423 | const struct spi_mem_op *write_cache; |
---|
339 | 424 | const struct spi_mem_op *update_cache; |
---|
340 | 425 | } op_templates; |
---|
| 426 | + |
---|
| 427 | + struct spinand_dirmap *dirmaps; |
---|
341 | 428 | |
---|
342 | 429 | int (*select_target)(struct spinand_device *spinand, |
---|
343 | 430 | unsigned int target); |
---|
.. | .. |
---|
411 | 498 | nanddev_set_of_node(&spinand->base, np); |
---|
412 | 499 | } |
---|
413 | 500 | |
---|
414 | | -int spinand_match_and_init(struct spinand_device *dev, |
---|
| 501 | +int spinand_match_and_init(struct spinand_device *spinand, |
---|
415 | 502 | const struct spinand_info *table, |
---|
416 | | - unsigned int table_size, u8 devid); |
---|
| 503 | + unsigned int table_size, |
---|
| 504 | + enum spinand_readid_method rdid_method); |
---|
417 | 505 | |
---|
418 | 506 | int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val); |
---|
419 | 507 | int spinand_select_target(struct spinand_device *spinand, unsigned int target); |
---|