1 /*
2 * Copyright (c) 2020 Peter Bigot Consulting, LLC
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #ifndef ZEPHYR_DRIVERS_FLASH_JESD216_H_
8 #define ZEPHYR_DRIVERS_FLASH_JESD216_H_
9
10 #include <errno.h>
11 #include <sys/byteorder.h>
12 #include <sys/util.h>
13 #include <zephyr/types.h>
14
15 /* Following are structures and constants supporting the JEDEC Serial
16 * Flash Discoverable Parameters standard, JESD216 and its successors,
17 * available at
18 * https://www.jedec.org/standards-documents/docs/jesd216b
19 */
20
21 #define JESD216_CMD_READ_SFDP 0x5A
22 #define JESD216_CMD_BURST_SFDP 0x5B
23
24 /* Layout of a JESD216 parameter header. */
25 struct jesd216_param_header {
26 uint8_t id_lsb; /* ID LSB */
27 uint8_t rev_minor; /* Minor revision number */
28 uint8_t rev_major; /* Major revision number */
29 uint8_t len_dw; /* Length of table in 32-bit DWORDs */
30 uint8_t ptp[3]; /* Address of table in SFDP space (LSB@0) */
31 uint8_t id_msb; /* ID MSB */
32 } __packed;
33
34 /* Get the number of bytes required for the parameter table. */
jesd216_param_len(const struct jesd216_param_header * hp)35 static inline uint32_t jesd216_param_len(const struct jesd216_param_header *hp)
36 {
37 return sizeof(uint32_t) * hp->len_dw;
38 }
39
40 /* Get the ID that identifies the content of the parameter table. */
jesd216_param_id(const struct jesd216_param_header * hp)41 static inline uint16_t jesd216_param_id(const struct jesd216_param_header *hp)
42 {
43 return ((uint16_t)hp->id_msb << 8) | hp->id_lsb;
44 }
45
46 /* Get the address within the SFDP where the data for the table is
47 * stored.
48 */
jesd216_param_addr(const struct jesd216_param_header * hp)49 static inline uint32_t jesd216_param_addr(const struct jesd216_param_header *hp)
50 {
51 return ((hp->ptp[2] << 16)
52 | (hp->ptp[1] << 8)
53 | (hp->ptp[0] << 0));
54 }
55
56 /* Layout of the Serial Flash Discoverable Parameters header. */
57 struct jesd216_sfdp_header {
58 uint32_t magic; /* "SFDP" in little endian */
59 uint8_t rev_minor; /* Minor revision number */
60 uint8_t rev_major; /* Major revision number */
61 uint8_t nph; /* Number of parameter headers */
62 uint8_t access; /* Access protocol */
63 struct jesd216_param_header phdr[]; /* Headers */
64 } __packed;
65
66 /* SFDP access protocol for backwards compatibility with JESD216B. */
67 #define JESD216_SFDP_AP_LEGACY 0xFF
68
69 /* The expected value from the jesd216_sfdp::magic field in host byte
70 * order.
71 */
72 #define JESD216_SFDP_MAGIC 0x50444653
73
74 /* All JESD216 data is read from the device in little-endian byte
75 * order. For JEDEC parameter tables defined through JESD216D-01 the
76 * parameters are defined by 32-bit words that may need to be
77 * byte-swapped to extract their information.
78 *
79 * A 16-bit ID from the parameter header is used to identify the
80 * content of each table. The first parameter table in the SFDP
81 * hierarchy must be a Basic Flash Parameter table (ID 0xFF00).
82 */
83
84 /* JESD216D-01 section 6.4: Basic Flash Parameter */
85 #define JESD216_SFDP_PARAM_ID_BFP 0xFF00
86 /* JESD216D-01 section 6.5: Sector Map Parameter */
87 #define JESD216_SFDP_PARAM_ID_SECTOR_MAP 0xFF81
88 /* JESD216D-01 section 6.6: 4-Byte Address Instruction Parameter */
89 #define JESD216_SFDP_PARAM_ID_4B_ADDR_INSTR 0xFF84
90 /* JESD216D-01 section 6.7: xSPI (Profile 1.0) Parameter */
91 #define JESD216_SFDP_PARAM_ID_XSPI_PROFILE_1V0 0xFF05
92 /* JESD216D-01 section 6.8: xSPI (Profile 2.0) Parameter */
93 #define JESD216_SFDP_PARAM_ID_XSPI_PROFILE_2V0 0xFF06
94
95 /* Macro to define the number of bytes required for the SFDP pheader
96 * and @p nph parameter headers.
97 *
98 * @param nph the number of parameter headers to be read. 1 is
99 * sufficient for basic functionality.
100 *
101 * @return required buffer size in bytes.
102 */
103 #define JESD216_SFDP_SIZE(nph) (sizeof(struct jesd216_sfdp_header) \
104 + ((nph) * sizeof(struct jesd216_param_header)))
105
106 /** Extract the magic number from the SFDP structure in host byte order.
107 *
108 * If this compares equal to JESD216_SFDP_MAGIC then the SFDP header
109 * may have been read correctly.
110 */
jesd216_sfdp_magic(const struct jesd216_sfdp_header * hp)111 static inline uint32_t jesd216_sfdp_magic(const struct jesd216_sfdp_header *hp)
112 {
113 return sys_le32_to_cpu(hp->magic);
114 }
115
116 /* Layout of the Basic Flash Parameters table.
117 *
118 * SFDP through JESD216B supported 9 DWORD values. JESD216C extended
119 * this to 17, and JESD216D to 20.
120 *
121 * All values are expected to be stored as little-endian and must be
122 * converted to host byte order to extract the bit fields defined in
123 * the standard. Rather than pre-define layouts to access to all
124 * potential fields this header provides functions for specific fields
125 * known to be important, such as density and erase command support.
126 */
127 struct jesd216_bfp {
128 uint32_t dw1;
129 uint32_t dw2;
130 uint32_t dw3;
131 uint32_t dw4;
132 uint32_t dw5;
133 uint32_t dw6;
134 uint32_t dw7;
135 uint32_t dw8;
136 uint32_t dw9;
137 uint32_t dw10[];
138 } __packed;
139
140 /* Provide a few word-specific flags and bitfield ranges for values
141 * that an application or driver might expect to want to extract.
142 *
143 * See the JESD216 specification for the interpretation of these
144 * bitfields.
145 */
146 #define JESD216_SFDP_BFP_DW1_DTRCLK_FLG BIT(19)
147 #define JESD216_SFDP_BFP_DW1_ADDRBYTES_MASK (BIT(17) | BIT(18))
148 #define JESD216_SFDP_BFP_DW1_ADDRBYTES_SHFT 17
149 #define JESD216_SFDP_BFP_DW1_ADDRBYTES_VAL_3B 0
150 #define JESD216_SFDP_BFP_DW1_ADDRBYTES_VAL_3B4B 1
151 #define JESD216_SFDP_BFP_DW1_ADDRBYTES_VAL_4B 2
152 #define JESD216_SFDP_BFP_DW1_4KERASEINSTR_SHFT 8
153 #define JESD216_SFDP_BFP_DW1_4KERASEINSTR_MASK (0xFF << JESD216_SFDP_BFP_DW1_4KERASEINSTR_SHFT)
154 #define JESD216_SFDP_BFP_DW1_WEISWVSR_FLG BIT(4)
155 #define JESD216_SFDP_BFP_DW1_VSRBP_FLG BIT(3)
156 #define JESD216_SFDP_BFP_DW1_WRTGRAN_FLG BIT(2)
157 #define JESD216_SFDP_BFP_DW1_BSERSZ_SHFT 0
158 #define JESD216_SFDP_BFP_DW1_BSERSZ_MASK (0x03 << JESD216_SFDP_BFP_DW1_BSERSZ_SHFT)
159 #define JESD216_SFDP_BFP_DW1_BSERSZ_VAL_4KSUP 0x01
160 #define JESD216_SFDP_BFP_DW1_BSERSZ_VAL_4KNOTSUP 0x03
161
162 #define JESD216_SFDP_BFP_DW12_SUSPRESSUP_FLG BIT(31)
163
164 /* Data can be extracted from the BFP words using these APIs:
165 *
166 * * DW1 (capabilities) use DW1 bitfield macros above or
167 * jesd216_read_support().
168 * * DW2 (density) use jesd216_bfp_density().
169 * * DW3-DW7 (instr) use jesd216_bfp_read_support().
170 * * DW8-DW9 (erase types) use jesd216_bfp_erase().
171 *
172 * JESD216A (16 DW)
173 *
174 * * DW10 (erase times) use jesd216_bfp_erase_type_times().
175 * * DW11 (other times) use jesd216_bfp_decode_dw11().
176 * * DW12-13 (suspend/resume) no API except
177 * JESD216_SFDP_BFP_DW12_SUSPRESSUP_FLG.
178 * * DW14 (deep power down) use jesd216_bfp_decode_dw14().
179 * * DW15-16 no API except jesd216_bfp_read_support().
180 *
181 * JESD216C (20 DW)
182 * * DW17-20 (quad/oct support) no API except jesd216_bfp_read_support().
183 */
184
185 /* Extract the supported address bytes from BFP DW1. */
jesd216_bfp_addrbytes(const struct jesd216_bfp * hp)186 static inline uint8_t jesd216_bfp_addrbytes(const struct jesd216_bfp *hp)
187 {
188 uint32_t dw1 = sys_le32_to_cpu(hp->dw1);
189 uint8_t addr_support = (dw1 & JESD216_SFDP_BFP_DW1_ADDRBYTES_MASK)
190 >> JESD216_SFDP_BFP_DW1_ADDRBYTES_SHFT;
191
192 return addr_support;
193 }
194
195 /* Extract the density of the chip in bits from BFP DW2. */
jesd216_bfp_density(const struct jesd216_bfp * hp)196 static inline uint64_t jesd216_bfp_density(const struct jesd216_bfp *hp)
197 {
198 uint32_t dw = sys_le32_to_cpu(hp->dw2);
199
200 if (dw & BIT(31)) {
201 return BIT64(dw & BIT_MASK(31));
202 }
203 return 1U + (uint64_t)dw;
204 }
205
206 /* Protocol mode enumeration types.
207 *
208 * Modes are identified by fields representing the number of I/O
209 * signals and the data rate in the transfer. The I/O width may be 1,
210 * 2, 4, or 8 I/O signals. The data rate may be single or double.
211 * SDR is assumed; DDR is indicated by a D following the I/O width.
212 *
213 * A transfer has three phases, and width/rate is specified for each
214 * in turn:
215 * * Transfer of the command
216 * * Transfer of the command modifier (e.g. address)
217 * * Transfer of the data.
218 *
219 * Modes explicitly mentioned in JESD216 or JESD251 are given
220 * enumeration values below, which can be used to extract information
221 * about instruction support.
222 */
223 enum jesd216_mode_type {
224 JESD216_MODE_044, /* implied instruction, execute in place */
225 JESD216_MODE_088,
226 JESD216_MODE_111,
227 JESD216_MODE_112,
228 JESD216_MODE_114,
229 JESD216_MODE_118,
230 JESD216_MODE_122,
231 JESD216_MODE_144,
232 JESD216_MODE_188,
233 JESD216_MODE_222,
234 JESD216_MODE_444,
235 JESD216_MODE_44D4D,
236 JESD216_MODE_888,
237 JESD216_MODE_8D8D8D,
238 JESD216_MODE_LIMIT,
239 };
240
241 /* Command to use for fast read operations in a specified protocol
242 * mode.
243 */
244 struct jesd216_instr {
245 uint8_t instr;
246 uint8_t mode_clocks;
247 uint8_t wait_states;
248 };
249
250 /* Determine whether a particular operational mode is supported for
251 * read, and possibly what command may be used.
252 *
253 * @note For @p mode JESD216_MODE_111 this function will return zero
254 * to indicate that standard read (instruction 03h) is supported, but
255 * without providing information on how. SFDP does not provide an
256 * indication of support for 1-1-1 Fast Read (0Bh).
257 *
258 * @param php pointer to the BFP header.
259 *
260 * @param bfp pointer to the BFP table.
261 *
262 * @param mode the desired protocol mode.
263 *
264 * @param res where to store instruction information. Pass a null
265 * pointer to test for support without retrieving instruction
266 * information.
267 *
268 * @retval positive if instruction is supported and *res has been set.
269 *
270 * @retval 0 if instruction is supported but *res has not been set
271 * (e.g. no instruction needed, or instruction cannot be read from
272 * BFP).
273 *
274 * @retval -ENOTSUP if instruction is not supported.
275 */
276 int jesd216_bfp_read_support(const struct jesd216_param_header *php,
277 const struct jesd216_bfp *bfp,
278 enum jesd216_mode_type mode,
279 struct jesd216_instr *res);
280
281 /* Description of a supported erase operation. */
282 struct jesd216_erase_type {
283 /* The command opcode used for an erase operation. */
284 uint8_t cmd;
285
286 /* The value N when the erase operation erases a 2^N byte
287 * region.
288 */
289 uint8_t exp;
290 };
291
292 /* The number of erase types defined in a JESD216 Basic Flash
293 * Parameter table.
294 */
295 #define JESD216_NUM_ERASE_TYPES 4
296
297 /* Extract a supported erase size and command from BFP DW8 or DW9.
298 *
299 * @param bfp pointer to the parameter table.
300 *
301 * @param idx the erase type index, from 1 through 4. Only index 1 is
302 * guaranteed to be present.
303 *
304 * @param etp where to store the command and size used for the erase.
305 *
306 * @retval 0 if the erase type index provided usable information.
307 * @retval -EINVAL if the erase type index is undefined.
308 */
309 int jesd216_bfp_erase(const struct jesd216_bfp *bfp,
310 uint8_t idx,
311 struct jesd216_erase_type *etp);
312
313 /* Extract typical and maximum erase times from DW10.
314 *
315 * @param php pointer to the BFP header.
316 *
317 * @param bfp pointer to the BFP table.
318 *
319 * @param idx the erase type index, from 1 through 4. For meaningful
320 * results the index should be one for which jesd216_bfp_erase()
321 * returns success.
322 *
323 * @param typ_ms where to store the typical erase time (in
324 * milliseconds) for the specified erase type.
325 *
326 * @retval -ENOTSUP if the erase type index is undefined.
327 * @retval positive is a multiplier that converts typical erase times
328 * to maximum erase times.
329 */
330 int jesd216_bfp_erase_type_times(const struct jesd216_param_header *php,
331 const struct jesd216_bfp *bfp,
332 uint8_t idx,
333 uint32_t *typ_ms);
334
335 /* Get the page size from the Basic Flash Parameters.
336 *
337 * @param php pointer to the BFP header.
338 *
339 * @param bfp pointer to the BFP table.
340 *
341 * @return the page size in bytes from the parameters if supported,
342 * otherwise 256.
343 */
jesd216_bfp_page_size(const struct jesd216_param_header * php,const struct jesd216_bfp * bfp)344 static inline uint32_t jesd216_bfp_page_size(const struct jesd216_param_header *php,
345 const struct jesd216_bfp *bfp)
346 {
347 /* Page size introduced in JESD216A */
348 if (php->len_dw < 11) {
349 return 256;
350 }
351
352 uint32_t dw11 = sys_le32_to_cpu(bfp->dw10[1]);
353 uint8_t exp = (dw11 >> 4) & 0x0F;
354
355 return BIT(exp);
356 }
357
358 /* Decoded data from JESD216 DW11. */
359 struct jesd216_bfp_dw11 {
360 /* Typical time for chip (die) erase, in milliseconds */
361 uint16_t chip_erase_ms;
362
363 /* Typical time for first byte program, in microseconds */
364 uint16_t byte_prog_first_us;
365
366 /* Typical time per byte for byte program after first, in
367 * microseconds
368 */
369 uint16_t byte_prog_addl_us;
370
371 /* Typical time for page program, in microseconds */
372 uint16_t page_prog_us;
373
374 /* Multiplier to get maximum time from typical times. */
375 uint16_t typ_max_factor;
376
377 /* Number of bytes in a page. */
378 uint16_t page_size;
379 };
380
381 /* Get data from BFP DW11.
382 *
383 * @param php pointer to the BFP header.
384 *
385 * @param bfp pointer to the BFP table.
386 *
387 * @param res pointer to where to store the decoded data.
388 *
389 * @retval -ENOTSUP if this information is not available from this BFP table.
390 * @retval 0 on successful storage into @c *res.
391 */
392 int jesd216_bfp_decode_dw11(const struct jesd216_param_header *php,
393 const struct jesd216_bfp *bfp,
394 struct jesd216_bfp_dw11 *res);
395
396 /* Decoded data from JESD216 DW14 */
397 struct jesd216_bfp_dw14 {
398 /* Instruction used to enter deep power-down */
399 uint8_t enter_dpd_instr;
400
401 /* Instruction used to exit deep power-down */
402 uint8_t exit_dpd_instr;
403
404 /* Bits defining ways busy status may be polled. */
405 uint8_t poll_options;
406
407 /* Time after issuing exit instruction until device is ready
408 * to accept a command, in nanoseconds.
409 */
410 uint32_t exit_delay_ns;
411 };
412
413 /* Get data from BFP DW14.
414 *
415 * @param php pointer to the BFP header.
416 *
417 * @param bfp pointer to the BFP table.
418 *
419 * @param res pointer to where to store the decoded data.
420 *
421 * @retval -ENOTSUP if this information is not available from this BFP table.
422 * @retval 0 on successful storage into @c *res.
423 */
424 int jesd216_bfp_decode_dw14(const struct jesd216_param_header *php,
425 const struct jesd216_bfp *bfp,
426 struct jesd216_bfp_dw14 *res);
427
428 /* DW15 Quad Enable Requirements specifies status register QE bits.
429 *
430 * Two common configurations are summarized; see the specification for
431 * full details of how to use these values.
432 */
433 enum jesd216_dw15_qer_type {
434 /* No QE status required for 1-1-4 or 1-4-4 mode */
435 JESD216_DW15_QER_NONE = 0,
436 JESD216_DW15_QER_S2B1v1 = 1,
437 /* Bit 6 of SR byte must be set to enable 1-1-4 or 1-4-4 mode.
438 * SR is one byte.
439 */
440 JESD216_DW15_QER_S1B6 = 2,
441 JESD216_DW15_QER_S2B7 = 3,
442 JESD216_DW15_QER_S2B1v4 = 4,
443 JESD216_DW15_QER_S2B1v5 = 5,
444 JESD216_DW15_QER_S2B1v6 = 6,
445 };
446
447 /* Decoded data from JESD216 DW15 */
448 struct jesd216_bfp_dw15 {
449 /* If true clear NVECR bit 4 to disable HOLD/RESET */
450 bool hold_reset_disable: 1;
451 /* Encoded jesd216_qer_type */
452 unsigned int qer: 3;
453 /* 0-4-4 mode entry method */
454 unsigned int entry_044: 4;
455 /* 0-4-4 mode exit method */
456 unsigned int exit_044: 6;
457 /* True if 0-4-4 mode is supported */
458 bool support_044: 1;
459 /* 4-4-4 mode enable sequences */
460 unsigned int enable_444: 5;
461 /* 4-4-4 mode disable sequences */
462 unsigned int disable_444: 4;
463 };
464
465 /* Get data from BFP DW15.
466 *
467 * @param php pointer to the BFP header.
468 *
469 * @param bfp pointer to the BFP table.
470 *
471 * @param res pointer to where to store the decoded data.
472 *
473 * @retval -ENOTSUP if this information is not available from this BFP table.
474 * @retval 0 on successful storage into @c *res.
475 */
476 int jesd216_bfp_decode_dw15(const struct jesd216_param_header *php,
477 const struct jesd216_bfp *bfp,
478 struct jesd216_bfp_dw15 *res);
479
480 /* Decoded data from JESD216_DW16 */
481 struct jesd216_bfp_dw16 {
482 /* Bits specifying supported modes of entering 4-byte
483 * addressing.
484 */
485 unsigned int enter_4ba: 8;
486
487 /* Bits specifying supported modes of exiting 4-byte
488 * addressing.
489 */
490 unsigned int exit_4ba: 10;
491
492 /* Bits specifying the soft reset and rescue sequence to
493 * restore the device to its power-on state.
494 */
495 unsigned int srrs_support: 6;
496
497 /* Bits specifying how to modify status register 1, and which
498 * bits are non-volatile.
499 */
500 unsigned int sr1_interface: 7;
501 };
502
503 /* Get data from BFP DW16.
504 *
505 * @param php pointer to the BFP header.
506 *
507 * @param bfp pointer to the BFP table.
508 *
509 * @param res pointer to where to store the decoded data.
510 *
511 * @retval -ENOTSUP if this information is not available from this BFP table.
512 * @retval 0 on successful storage into @c *res.
513 */
514 int jesd216_bfp_decode_dw16(const struct jesd216_param_header *php,
515 const struct jesd216_bfp *bfp,
516 struct jesd216_bfp_dw16 *res);
517
518 #endif /* ZEPHYR_DRIVERS_FLASH_JESD216_H_ */
519