| .. | .. |
|---|
| 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); |
|---|