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