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