1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <console/console.h>
4 #include <spi-generic.h>
8 #include "spi_flash_internal.h"
11 * Assumptions (not) made in the code:
12 * - code is supposed to be endian-safe
15 * - only legacy access protocol supported:
17 * - read SFDP instruction is sufficient and no fetch SFDP instruction needed
18 * - always 3 byte addresses for SFDP
19 * - only 1 bit SPI mode supported
20 * - always 8 dummy cycles after the address is sent
23 #define CMD_READ_SFDP 0x5a
25 static void read_sfdp_data_update_buffer_offset(uint8_t *buf_cmd
, uint32_t offset
)
27 buf_cmd
[1] = offset
>> 16 & 0xff;
28 buf_cmd
[2] = offset
>> 8 & 0xff;
29 buf_cmd
[3] = offset
>> 0 & 0xff;
32 static enum cb_err
read_sfdp_data(const struct spi_flash
*flash
, uint32_t offset
, size_t len
,
37 buf_cmd
[0] = CMD_READ_SFDP
;
38 /* the read offset in buf_cmd[1..3] gets written in
39 read_sfdp_data_update_buffer_offset */
40 buf_cmd
[4] = 0; /* dummy byte */
44 /* split data transfers into chunks that each fit into the SPI controller's buffer */
46 uint32_t xfer_len
= spi_crop_chunk(&flash
->spi
, sizeof(buf_cmd
), len
);
47 read_sfdp_data_update_buffer_offset(buf_cmd
, offset
);
48 if (spi_flash_cmd_multi(&flash
->spi
, buf_cmd
, sizeof(buf_cmd
), data
, xfer_len
))
58 #define SFDP_HEADER_OFFSET 0
59 #define SFDP_HEADER_LEN (2 * sizeof(uint32_t))
60 #define SFDP_HEADER_SIGNATURE 0x50444653 /* LE: "SFDP" */
61 #define SFDP_HEADER_ACCESS_PROTOCOL_LEGACY 0xff
62 /* header byte offsets */
63 #define SFDP_HEADER_SIGNATURE_0 0
64 #define SFDP_HEADER_SIGNATURE_1 1
65 #define SFDP_HEADER_SIGNATURE_2 2
66 #define SFDP_HEADER_SIGNATURE_3 3
67 #define SFDP_HEADER_MINOR_REV 4
68 #define SFDP_HEADER_MAJOR_REV 5
69 #define SFDP_HEADER_PARAMETER_HEADER_NUMBER 6
70 #define SFDP_HEADER_ACCESS_PROTOCOL 7
72 static enum cb_err
get_sfdp_header(const struct spi_flash
*flash
, uint16_t *sfdp_revision
,
73 uint8_t *number_of_parameter_headers
,
74 uint8_t *access_prototcol
)
76 uint8_t buf
[SFDP_HEADER_LEN
];
79 if (read_sfdp_data(flash
, SFDP_HEADER_OFFSET
, SFDP_HEADER_LEN
, buf
) != CB_SUCCESS
)
82 signature
= buf
[SFDP_HEADER_SIGNATURE_0
] | buf
[SFDP_HEADER_SIGNATURE_1
] << 8 |
83 buf
[SFDP_HEADER_SIGNATURE_2
] << 16 | buf
[SFDP_HEADER_SIGNATURE_3
] << 24;
84 *sfdp_revision
= buf
[SFDP_HEADER_MINOR_REV
] | buf
[SFDP_HEADER_MAJOR_REV
] << 8;
85 *number_of_parameter_headers
= buf
[SFDP_HEADER_PARAMETER_HEADER_NUMBER
] + 1;
86 *access_prototcol
= buf
[SFDP_HEADER_ACCESS_PROTOCOL
];
88 if (signature
!= SFDP_HEADER_SIGNATURE
)
91 /* We make the assumption in the code that the legacy access protocol is used */
92 if (*access_prototcol
!= SFDP_HEADER_ACCESS_PROTOCOL_LEGACY
)
98 #define SFDP_PARAMETER_HEADER_LEN (2 * sizeof(uint32_t))
99 #define SFDP_PARAMETER_HEADER_OFFSET(n) (SFDP_HEADER_OFFSET + SFDP_HEADER_LEN + \
100 n * SFDP_PARAMETER_HEADER_LEN)
101 /* parameter header byte offsets */
102 #define SFDP_PARAMETER_HEADER_ID_LSB 0
103 #define SFDP_PARAMETER_HEADER_MINOR_REV 1
104 #define SFDP_PARAMETER_HEADER_MAJOR_REV 2
105 #define SFDP_PARAMETER_HEADER_LENGTH_DWORDS 3
106 #define SFDP_PARAMETER_HEADER_POINTER_0 4
107 #define SFDP_PARAMETER_HEADER_POINTER_1 5
108 #define SFDP_PARAMETER_HEADER_POINTER_2 6
109 #define SFDP_PARAMETER_HEADER_ID_MSB 7
111 /* get_sfdp_parameter_header_by_index must be called with a valid index */
112 static enum cb_err
get_sfdp_parameter_header_by_index(const struct spi_flash
*flash
,
113 uint8_t index
, uint16_t *id
,
115 uint8_t *length_dwords
,
116 uint32_t *table_pointer
)
118 uint8_t buf
[SFDP_PARAMETER_HEADER_LEN
];
120 if (read_sfdp_data(flash
, SFDP_PARAMETER_HEADER_OFFSET(index
),
121 SFDP_PARAMETER_HEADER_LEN
, buf
) != CB_SUCCESS
)
124 *id
= buf
[SFDP_PARAMETER_HEADER_ID_LSB
] | buf
[SFDP_PARAMETER_HEADER_ID_MSB
] << 8;
125 *revision
= buf
[SFDP_PARAMETER_HEADER_MINOR_REV
] |
126 buf
[SFDP_PARAMETER_HEADER_MAJOR_REV
] << 8;
127 *length_dwords
= buf
[SFDP_PARAMETER_HEADER_LENGTH_DWORDS
];
128 *table_pointer
= buf
[SFDP_PARAMETER_HEADER_POINTER_0
] |
129 buf
[SFDP_PARAMETER_HEADER_POINTER_1
] << 8 |
130 buf
[SFDP_PARAMETER_HEADER_POINTER_2
] << 16;
132 /* the parameter table pointer byte address must be DWORD-aligned */
133 if (!IS_ALIGNED(*table_pointer
, sizeof(uint32_t)))
136 /* TODO: check id validity? */
141 void spi_flash_print_sfdp_headers(const struct spi_flash
*flash
)
145 uint8_t param_header_count
;
146 uint8_t access_protocol
;
148 if (get_sfdp_header(flash
, &sfdp_rev
, ¶m_header_count
, &access_protocol
) !=
150 printk(BIOS_ERR
, "Failed to read SFDP header from SPI flash\n");
154 printk(BIOS_DEBUG
, "SFDP header found in SPI flash.\n");
155 printk(BIOS_DEBUG
, "major rev %#x, minor rev %#x, access protocol %#x, "
156 "number of headers %d\n", sfdp_rev
>> 8, sfdp_rev
& 0xff, access_protocol
,
161 uint8_t tbl_len_dwords
;
162 uint32_t tbl_pointer
;
164 for (unsigned int i
= 0; i
< param_header_count
; i
++) {
165 stat
= get_sfdp_parameter_header_by_index(flash
, i
, &tbl_id
, &tbl_rev
,
166 &tbl_len_dwords
, &tbl_pointer
);
168 if (stat
== CB_SUCCESS
) {
169 printk(BIOS_DEBUG
, "SFPD header with index %d:\n", i
);
170 printk(BIOS_DEBUG
, " table ID %#x, major rev %#x, minor rev %#x\n",
171 tbl_id
, tbl_rev
>> 8, tbl_rev
& 0xff);
172 printk(BIOS_DEBUG
, " table pointer %#x, table length DWORDS %#x\n",
173 tbl_pointer
, tbl_len_dwords
);
175 printk(BIOS_ERR
, "Cound't read SFPD header with index %d.\n", i
);
180 static enum cb_err
find_sfdp_parameter_header(const struct spi_flash
*flash
, uint16_t table_id
,
181 uint16_t *revision
, uint8_t *length_dwords
,
182 uint32_t *table_pointer
)
186 uint8_t param_header_count
;
187 uint8_t access_protocol
;
189 if (get_sfdp_header(flash
, &sfdp_rev
, ¶m_header_count
, &access_protocol
) !=
193 /* TODO: add version check? */
197 uint8_t tbl_len_dwords
;
198 uint32_t tbl_pointer
;
200 for (unsigned int i
= 0; i
< param_header_count
; i
++) {
201 stat
= get_sfdp_parameter_header_by_index(flash
, i
, &tbl_id
, &tbl_rev
,
202 &tbl_len_dwords
, &tbl_pointer
);
204 if (stat
== CB_SUCCESS
&& tbl_id
== table_id
) {
206 *length_dwords
= tbl_len_dwords
;
207 *table_pointer
= tbl_pointer
;
212 printk(BIOS_WARNING
, "Cound't find SFPD header with table ID %#x.\n", table_id
);
217 #define SFDP_PARAMETER_ID_RPMC 0xff03
219 #define SFDP_RPMC_TABLE_LENGTH_DWORDS 2
220 #define SFDP_RPMC_TABLE_SUPPORTED_MAJOR_REV 1
222 /* RPMC parameter table byte offsets and fields */
223 #define SFDP_RPMC_TABLE_CONFIG 0
224 #define SFDP_RPMC_TABLE_CONFIG_FLASH_HARDENING_BIT BIT(0)
225 #define SFDP_RPMC_TABLE_CONFIG_MONOTONIC_COUNTER_SIZE_BIT BIT(1)
226 #define SFDP_RPMC_TABLE_CONFIG_BUSY_POLLING_METHOD BIT(2)
227 #define SFDP_RPMC_TABLE_CONFIG_RESERVED BIT(3)
228 #define SFDP_RPMC_TABLE_CONFIG_RESERVED_VALUE 0x08
229 #define SFDP_RPMC_TABLE_CONFIG_NUM_COUNTERS_MASK 0xf0
230 #define SFDP_RPMC_TABLE_CONFIG_NUM_COUNTERS_SHIFT 4
231 #define SFDP_RPMC_TABLE_RPMC_OP1 1
232 #define SFDP_RPMC_TABLE_RPMC_OP2 2
233 #define SFDP_RPMC_TABLE_UPDATE_RATE 3
234 #define SFDP_RPMC_TABLE_UPDATE_RATE_MASK 0x0f
235 #define SFDP_RPMC_TABLE_UPDATE_RATE_RESERVED_MASK 0xf0
236 #define SFDP_RPMC_TABLE_UPDATE_RATE_RESERVED_VALUE 0xf0
237 #define SFDP_RPMC_TABLE_READ_COUNTER_POLLING_DELAY 4
238 #define SFDP_RPMC_TABLE_WRITE_COUNTER_POLLING_SHORT_DELAY 5
239 #define SFDP_RPMC_TABLE_WRITE_COUNTER_POLLING_LONG_DELAY 6
240 #define SFDP_RPMC_TABLE_RESERVED_BYTE 7
241 #define SFDP_RPMC_TABLE_RESERVED_BYTE_VALUE 0xff
243 static uint64_t calc_rpmc_update_rate_s(uint8_t val
)
245 /* val is at most 15, so this won't overflow */
246 return 5 * 1 << (val
& SFDP_RPMC_TABLE_UPDATE_RATE_MASK
);
249 #define SPDF_RPMC_DELAY_VALUE_MASK 0x1f
250 #define SPDF_RPMC_DELAY_UNIT_MASK 0x60
251 #define SPDF_RPMC_DELAY_UNIT_SHIFT 5
252 #define SPDF_RPMC_DELAY_SHORT_UNIT_0_US 1 /* 1us */
253 #define SPDF_RPMC_DELAY_SHORT_UNIT_1_US 16 /* 16us */
254 #define SPDF_RPMC_DELAY_SHORT_UNIT_2_US 128 /* 128us */
255 #define SPDF_RPMC_DELAY_SHORT_UNIT_3_US 1000 /* 1ms */
256 #define SPDF_RPMC_DELAY_LONG_UNIT_0_US 1000 /* 1ms */
257 #define SPDF_RPMC_DELAY_LONG_UNIT_1_US 16000 /* 16ms */
258 #define SPDF_RPMC_DELAY_LONG_UNIT_2_US 128000 /* 128ms */
259 #define SPDF_RPMC_DELAY_LONG_UNIT_3_US 1000000 /* 1s */
261 static uint64_t calc_rpmc_short_delay_us(uint8_t val
)
263 const uint8_t value
= val
& SPDF_RPMC_DELAY_VALUE_MASK
;
264 const uint8_t shift
= (val
& SPDF_RPMC_DELAY_UNIT_MASK
) >> SPDF_RPMC_DELAY_UNIT_SHIFT
;
269 multiplier
= SPDF_RPMC_DELAY_SHORT_UNIT_0_US
;
272 multiplier
= SPDF_RPMC_DELAY_SHORT_UNIT_1_US
;
275 multiplier
= SPDF_RPMC_DELAY_SHORT_UNIT_2_US
;
278 multiplier
= SPDF_RPMC_DELAY_SHORT_UNIT_3_US
;
282 return value
* multiplier
;
285 static uint64_t calc_rpmc_long_delay_us(uint8_t val
)
287 const uint8_t value
= val
& SPDF_RPMC_DELAY_VALUE_MASK
;
288 const uint8_t shift
= (val
& SPDF_RPMC_DELAY_UNIT_MASK
) >> SPDF_RPMC_DELAY_UNIT_SHIFT
;
293 multiplier
= SPDF_RPMC_DELAY_LONG_UNIT_0_US
;
296 multiplier
= SPDF_RPMC_DELAY_LONG_UNIT_1_US
;
299 multiplier
= SPDF_RPMC_DELAY_LONG_UNIT_2_US
;
302 multiplier
= SPDF_RPMC_DELAY_LONG_UNIT_3_US
;
306 return value
* multiplier
;
309 enum cb_err
spi_flash_get_sfdp_rpmc(const struct spi_flash
*flash
,
310 struct sfdp_rpmc_info
*rpmc_info
)
313 uint8_t length_dwords
;
314 uint32_t table_pointer
;
315 uint8_t buf
[SFDP_RPMC_TABLE_LENGTH_DWORDS
* sizeof(uint32_t)];
317 if (find_sfdp_parameter_header(flash
, SFDP_PARAMETER_ID_RPMC
, &rev
, &length_dwords
,
318 &table_pointer
) != CB_SUCCESS
)
321 if (length_dwords
!= SFDP_RPMC_TABLE_LENGTH_DWORDS
)
324 if (rev
>> 8 != SFDP_RPMC_TABLE_SUPPORTED_MAJOR_REV
) {
325 printk(BIOS_ERR
, "Unsupprted major RPMC table revision %#x\n", rev
>> 8);
329 if (read_sfdp_data(flash
, table_pointer
, sizeof(buf
), buf
) != CB_SUCCESS
)
332 if ((buf
[SFDP_RPMC_TABLE_CONFIG
] & SFDP_RPMC_TABLE_CONFIG_RESERVED
) !=
333 SFDP_RPMC_TABLE_CONFIG_RESERVED_VALUE
||
334 (buf
[SFDP_RPMC_TABLE_UPDATE_RATE
] & SFDP_RPMC_TABLE_UPDATE_RATE_RESERVED_MASK
) !=
335 SFDP_RPMC_TABLE_UPDATE_RATE_RESERVED_VALUE
||
336 buf
[SFDP_RPMC_TABLE_RESERVED_BYTE
] != SFDP_RPMC_TABLE_RESERVED_BYTE_VALUE
) {
337 printk(BIOS_ERR
, "Unexpected reserved values in RPMC table\n");
341 rpmc_info
->flash_hardening
= !!(buf
[SFDP_RPMC_TABLE_CONFIG
] &
342 SFDP_RPMC_TABLE_CONFIG_FLASH_HARDENING_BIT
);
343 rpmc_info
->monotonic_counter_size
= (buf
[SFDP_RPMC_TABLE_CONFIG
] &
344 SFDP_RPMC_TABLE_CONFIG_FLASH_HARDENING_BIT
) ?
345 SFDP_RPMC_COUNTER_BITS_RESERVED
:
346 SFDP_RPMC_COUNTER_BITS_32
;
347 rpmc_info
->busy_polling_method
= (buf
[SFDP_RPMC_TABLE_CONFIG
] &
348 SFDP_RPMC_TABLE_CONFIG_BUSY_POLLING_METHOD
) ?
349 SFDP_RPMC_POLL_READ_STATUS
:
350 SFDP_RPMC_POLL_OP2_EXTENDED_STATUS
;
351 rpmc_info
->number_of_counters
= ((buf
[SFDP_RPMC_TABLE_CONFIG
] &
352 SFDP_RPMC_TABLE_CONFIG_NUM_COUNTERS_MASK
) >>
353 SFDP_RPMC_TABLE_CONFIG_NUM_COUNTERS_SHIFT
) + 1;
354 rpmc_info
->op1_write_command
= buf
[SFDP_RPMC_TABLE_RPMC_OP1
];
355 rpmc_info
->op2_read_command
= buf
[SFDP_RPMC_TABLE_RPMC_OP2
];
356 rpmc_info
->update_rate_s
= calc_rpmc_update_rate_s(buf
[SFDP_RPMC_TABLE_UPDATE_RATE
] &
357 SFDP_RPMC_TABLE_UPDATE_RATE_MASK
);
358 rpmc_info
->read_counter_polling_delay_us
= calc_rpmc_short_delay_us(
359 buf
[SFDP_RPMC_TABLE_READ_COUNTER_POLLING_DELAY
]);
360 rpmc_info
->write_counter_polling_short_delay_us
= calc_rpmc_short_delay_us(
361 buf
[SFDP_RPMC_TABLE_WRITE_COUNTER_POLLING_SHORT_DELAY
]);
362 rpmc_info
->write_counter_polling_long_delay_us
= calc_rpmc_long_delay_us(
363 buf
[SFDP_RPMC_TABLE_WRITE_COUNTER_POLLING_LONG_DELAY
]);