5 #include "sw/device/silicon_creator/lib/drivers/spi_device.h"
7 #include "dt/dt_spi_device.h"
11 #include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
12 #include "sw/device/silicon_creator/lib/error.h"
14 #include "flash_ctrl_regs.h"
15 #include "spi_device_regs.h"
17 static const dt_spi_device_t kSpiDeviceDt = kDtSpiDevice;
22 static inline uint32_t spi_device_reg_base(
void) {
23 return dt_spi_device_primary_reg_block(kSpiDeviceDt);
31 SPI_DEVICE_EGRESS_BUFFER_REG_OFFSET + kSpiDeviceSfdpAreaOffset,
35 kSfdpAreaEndOff = SPI_DEVICE_EGRESS_BUFFER_REG_OFFSET +
36 kSpiDeviceSfdpAreaOffset + kSpiDeviceSfdpAreaNumBytes,
41 FLASH_CTRL_PARAM_REG_NUM_BANKS * FLASH_CTRL_PARAM_BYTES_PER_BANK * 8,
46 kSfdpSignature = 0x50444653,
57 kSfdpMajorRevision = 0x01,
61 kSfdpMinorRevision = 0x0a,
65 kSfdpAccessProtocol = 0xff,
69 kBfptMajorRevision = 0x01,
73 kBfptMinorRevision = 0x07,
77 kBfptParamIdLsb = 0x00,
81 kBfptParamIdMsb = 0xff,
93 kBfptNotSupported = 0,
96 static_assert(kBfptTablePointer %
sizeof(uint32_t) == 0,
97 "BFPT must be word-aligned");
105 #define BFPT_FIELD_WIDTH(upper, lower) ((upper) - (lower) + 1)
113 #define BFPT_FIELD_MASK(upper, lower) \
114 (((UINT64_C(1) << BFPT_FIELD_WIDTH(upper, lower)) - 1) << (lower))
127 #define BFPT_FIELD_VALUE(upper, lower, value) \
128 ((uint32_t)~BFPT_FIELD_MASK(upper, lower) | \
129 (BFPT_FIELD_MASK(upper, lower) & ((uint32_t)(value) << (uint32_t)(lower))))
151 #define BFPT_WORD_1(X) \
152 X(22, 19, kBfptNotSupported) & \
154 X(16, 16, kBfptNotSupported) & \
155 X(15, 8, kSpiDeviceOpcodeSectorErase) & \
167 #define BFPT_WORD_2(X) \
169 X(30, 0, kFlashBitCount - 1)
176 #define BFPT_WORD_3(X) \
177 X(31, 0, kBfptNotSupported)
184 #define BFPT_WORD_4(X) \
185 X(31, 0, kBfptNotSupported)
195 #define BFPT_WORD_5(X) \
196 X( 4, 4, kBfptNotSupported) & \
197 X( 0, 0, kBfptNotSupported)
205 #define BFPT_WORD_6(X) \
206 X(31, 16, kBfptNotSupported)
214 #define BFPT_WORD_7(X) \
215 X(31, 16, kBfptNotSupported)
224 #define BFPT_WORD_8(X) \
225 X(31, 16, kBfptNotSupported) & \
226 X(15, 8, kSpiDeviceOpcodeSectorErase) & \
234 #define BFPT_WORD_9(X) \
235 X(31, 0, kBfptNotSupported)
248 #define BFPT_WORD_10(X) \
249 X(31, 11, kBfptNotSupported) & \
278 #define BFPT_WORD_11(X) \
298 #define BFPT_WORD_12(X) \
300 X(30, 9, kBfptNotSupported) & \
301 X( 7, 0, kBfptNotSupported)
308 #define BFPT_WORD_13(X) \
309 X(31, 0, kBfptNotSupported)
319 #define BFPT_WORD_14(X) \
321 X(30, 8, kBfptNotSupported) & \
330 #define BFPT_WORD_15(X) \
331 X(23, 0, kBfptNotSupported)
341 #define BFPT_WORD_16(X) \
342 X(31, 14, kBfptNotSupported) & \
351 #define BFPT_WORD_17(X) \
352 X(31, 0, kBfptNotSupported)
361 #define BFPT_WORD_18(X) \
362 X(31, 0, kBfptNotSupported)
371 #define BFPT_WORD_19(X) \
372 X(31, 0, kBfptNotSupported)
380 #define BFPT_WORD_20(X) \
390 #define BFPT_WORD_21(X) \
391 X(31, 0, kBfptNotSupported)
398 #define BFPT_WORD_22(X) \
399 X(31, 0, kBfptNotSupported)
406 #define BFPT_WORD_23(X) \
407 X(31, 0, kBfptNotSupported)
414 .minor_revision = kSfdpMinorRevision,
415 .major_revision = kSfdpMajorRevision,
416 .param_count = kSfdpParamCount,
417 .access_protocol = kSfdpAccessProtocol,
421 .param_id_lsb = kBfptParamIdLsb,
422 .minor_revision = kBfptMinorRevision,
423 .major_revision = kBfptMajorRevision,
424 .table_word_count = kSpiDeviceBfptNumWords,
425 .table_pointer = {kBfptTablePointer},
426 .param_id_msb = kBfptParamIdMsb,
429 BFPT_WORD_1(BFPT_FIELD_VALUE), BFPT_WORD_2(BFPT_FIELD_VALUE),
430 BFPT_WORD_3(BFPT_FIELD_VALUE), BFPT_WORD_4(BFPT_FIELD_VALUE),
431 BFPT_WORD_5(BFPT_FIELD_VALUE), BFPT_WORD_6(BFPT_FIELD_VALUE),
432 BFPT_WORD_7(BFPT_FIELD_VALUE), BFPT_WORD_8(BFPT_FIELD_VALUE),
433 BFPT_WORD_9(BFPT_FIELD_VALUE), BFPT_WORD_10(BFPT_FIELD_VALUE),
434 BFPT_WORD_11(BFPT_FIELD_VALUE), BFPT_WORD_12(BFPT_FIELD_VALUE),
435 BFPT_WORD_13(BFPT_FIELD_VALUE), BFPT_WORD_14(BFPT_FIELD_VALUE),
436 BFPT_WORD_15(BFPT_FIELD_VALUE), BFPT_WORD_16(BFPT_FIELD_VALUE),
437 BFPT_WORD_17(BFPT_FIELD_VALUE), BFPT_WORD_18(BFPT_FIELD_VALUE),
438 BFPT_WORD_19(BFPT_FIELD_VALUE), BFPT_WORD_20(BFPT_FIELD_VALUE),
439 BFPT_WORD_21(BFPT_FIELD_VALUE), BFPT_WORD_22(BFPT_FIELD_VALUE),
440 BFPT_WORD_23(BFPT_FIELD_VALUE),
487 reg, SPI_DEVICE_CMD_INFO_0_ADDR_MODE_0_FIELD,
489 : SPI_DEVICE_CMD_INFO_0_ADDR_MODE_0_VALUE_ADDRDISABLED);
504 void spi_device_init(
void) {
509 abs_mmio_write32(spi_device_reg_base() + SPI_DEVICE_CFG_REG_OFFSET, reg);
512 abs_mmio_write32(spi_device_reg_base() + SPI_DEVICE_ADDR_MODE_REG_OFFSET,
519 kSpiDeviceJedecContCode);
521 kSpiDeviceJedecContCodeCount);
522 abs_mmio_write32(spi_device_reg_base() + SPI_DEVICE_JEDEC_CC_REG_OFFSET, reg);
527 lifecycle_hw_rev_get(&hw_rev);
535 kSpiDeviceJedecDensity);
537 kSpiDeviceJedecManufId);
538 abs_mmio_write32(spi_device_reg_base() + SPI_DEVICE_JEDEC_ID_REG_OFFSET, reg);
541 uint32_t dest = spi_device_reg_base() + kSfdpAreaStartOff;
542 const char *table = (
const char *)&kSpiDeviceSfdpTable;
543 for (
size_t i = 0; i < kSpiDeviceSfdpTableNumWords; ++i) {
544 abs_mmio_write32(dest,
read_32(table));
545 dest +=
sizeof(uint32_t);
546 table +=
sizeof(uint32_t);
549 for (; dest < spi_device_reg_base() + kSfdpAreaEndOff;
550 dest +=
sizeof(uint32_t)) {
551 abs_mmio_write32(dest, UINT32_MAX);
555 abs_mmio_write32(spi_device_reg_base() + SPI_DEVICE_FLASH_STATUS_REG_OFFSET,
560 .reg_offset = SPI_DEVICE_CMD_INFO_0_REG_OFFSET,
561 .op_code = kSpiDeviceOpcodeReadStatus,
564 .handled_in_sw =
false,
568 .reg_offset = SPI_DEVICE_CMD_INFO_3_REG_OFFSET,
569 .op_code = kSpiDeviceOpcodeReadJedecId,
572 .handled_in_sw =
false,
576 .reg_offset = SPI_DEVICE_CMD_INFO_4_REG_OFFSET,
577 .op_code = kSpiDeviceOpcodeReadSfdp,
580 .handled_in_sw =
false,
584 .reg_offset = SPI_DEVICE_CMD_INFO_11_REG_OFFSET,
585 .op_code = kSpiDeviceOpcodeChipErase,
588 .handled_in_sw =
true,
592 .reg_offset = SPI_DEVICE_CMD_INFO_12_REG_OFFSET,
593 .op_code = kSpiDeviceOpcodeSectorErase,
596 .handled_in_sw =
true,
600 .reg_offset = SPI_DEVICE_CMD_INFO_13_REG_OFFSET,
601 .op_code = kSpiDeviceOpcodePageProgram,
604 .handled_in_sw =
true,
608 .reg_offset = SPI_DEVICE_CMD_INFO_14_REG_OFFSET,
609 .op_code = kSpiDeviceOpcodeReset,
612 .handled_in_sw =
true,
616 kSpiDeviceOpcodeWriteEnable);
618 abs_mmio_write32(spi_device_reg_base() + SPI_DEVICE_CMD_INFO_WREN_REG_OFFSET,
621 kSpiDeviceOpcodeWriteDisable);
622 abs_mmio_write32(spi_device_reg_base() + SPI_DEVICE_CMD_INFO_WRDI_REG_OFFSET,
628 bool cmd_pending =
false;
629 while (!cmd_pending) {
632 reg = abs_mmio_read32(spi_device_reg_base() +
633 SPI_DEVICE_INTR_STATE_REG_OFFSET);
635 reg, SPI_DEVICE_INTR_COMMON_UPLOAD_CMDFIFO_NOT_EMPTY_BIT);
637 abs_mmio_write32(spi_device_reg_base() + SPI_DEVICE_INTR_STATE_REG_OFFSET,
640 SPI_DEVICE_INTR_COMMON_UPLOAD_PAYLOAD_OVERFLOW_BIT)) {
641 return kErrorSpiDevicePayloadOverflow;
644 reg = abs_mmio_read32(spi_device_reg_base() +
645 SPI_DEVICE_UPLOAD_CMDFIFO_REG_OFFSET);
648 cmd->
address = kSpiDeviceNoAddress;
649 reg = abs_mmio_read32(spi_device_reg_base() +
650 SPI_DEVICE_UPLOAD_STATUS_REG_OFFSET);
652 SPI_DEVICE_UPLOAD_STATUS_ADDRFIFO_NOTEMPTY_BIT)) {
653 cmd->
address = abs_mmio_read32(spi_device_reg_base() +
654 SPI_DEVICE_UPLOAD_ADDRFIFO_REG_OFFSET);
657 reg = abs_mmio_read32(spi_device_reg_base() +
658 SPI_DEVICE_UPLOAD_STATUS2_REG_OFFSET);
663 uint32_t src = spi_device_reg_base() + SPI_DEVICE_INGRESS_BUFFER_REG_OFFSET +
664 kSpiDevicePayloadAreaOffset;
665 char *dest = (
char *)&cmd->
payload;
667 write_32(abs_mmio_read32(src + i), dest + i);
673 void spi_device_flash_status_clear(
void) {
674 abs_mmio_write32(spi_device_reg_base() + SPI_DEVICE_FLASH_STATUS_REG_OFFSET,
678 uint32_t spi_device_flash_status_get(
void) {
679 return abs_mmio_read32(spi_device_reg_base() +
680 SPI_DEVICE_FLASH_STATUS_REG_OFFSET);