// SPDX-License-Identifier: Apache-2.0 /* * Copyright (C) 2024 openFPGALoader contributors * BPI (Parallel NOR) Flash support via JTAG bridge */ #ifndef SRC_BPIFLASH_HPP_ #define SRC_BPIFLASH_HPP_ #include #include #include "jtag.hpp" /*! * \class BPIFlash * \brief Intel CFI parallel NOR flash programming via JTAG bridge */ class BPIFlash { public: BPIFlash(Jtag *jtag, int8_t verbose); ~BPIFlash(); /*! * \brief Read device ID and manufacturer info * \return true if device detected */ bool detect(); /*! * \brief Read flash content * \param[out] data: buffer to store read data * \param[in] addr: start address (word address) * \param[in] len: number of bytes to read * \return true on success */ bool read(uint8_t *data, uint32_t addr, uint32_t len); /*! * \brief Write data to flash (handles erase internally) * \param[in] addr: start address (word address) * \param[in] data: data to write * \param[in] len: number of bytes to write * \return true on success */ bool write(uint32_t addr, const uint8_t *data, uint32_t len); /*! * \brief Erase a block * \param[in] addr: address within the block to erase * \return true on success */ bool erase_block(uint32_t addr); /*! * \brief Bulk erase entire flash * \return true on success */ bool bulk_erase(); /*! * \brief Get flash capacity in bytes */ uint32_t capacity() const { return _capacity; } /*! * \brief Get block size in bytes */ uint32_t block_size() const { return _block_size; } private: /* BPI bridge command codes (match bpiOverJtag_core.v) */ static const uint8_t CMD_WRITE = 0x1; static const uint8_t CMD_READ = 0x2; static const uint8_t CMD_NOP = 0x3; static const uint8_t CMD_BURST_WRITE = 0x4; /* Intel CFI flash commands */ static const uint16_t FLASH_CMD_READ_ARRAY = 0x00FF; static const uint16_t FLASH_CMD_READ_ID = 0x0090; static const uint16_t FLASH_CMD_READ_CFI = 0x0098; static const uint16_t FLASH_CMD_READ_STATUS = 0x0070; static const uint16_t FLASH_CMD_CLEAR_STATUS = 0x0050; static const uint16_t FLASH_CMD_PROGRAM = 0x0041; /* Single-word program (MT28GU512AAA) */ static const uint16_t FLASH_CMD_BUFFERED_PRG = 0x00E9; static const uint16_t FLASH_CMD_CONFIRM = 0x00D0; static const uint16_t FLASH_CMD_BLOCK_ERASE = 0x0020; static const uint16_t FLASH_CMD_UNLOCK_BLOCK = 0x0060; static const uint16_t FLASH_CMD_UNLOCK_CONF = 0x00D0; /* Status register bits */ static const uint16_t SR_READY = 0x0080; static const uint16_t SR_ERASE_ERR = 0x0020; static const uint16_t SR_PROG_ERR = 0x0010; static const uint16_t SR_VPP_ERR = 0x0008; static const uint16_t SR_BLOCK_LOCK = 0x0002; /*! * \brief Read a 16-bit word from flash at word address */ uint16_t bpi_read(uint32_t word_addr); /*! * \brief Write a 16-bit word to flash at word address */ void bpi_write(uint32_t word_addr, uint16_t data); /*! * \brief Write a 16-bit word without IR shift or flush (for batched writes) */ void bpi_write_no_flush(uint32_t word_addr, uint16_t data); /*! * \brief Burst write multiple 16-bit words in a single DR shift */ void bpi_burst_write(uint32_t word_addr, const uint16_t *data, uint32_t count); /*! * \brief Wait for operation to complete * \return true if completed successfully */ bool wait_ready(uint32_t timeout_ms = 10000); /*! * \brief Unlock a block for programming/erase */ bool unlock_block(uint32_t word_addr); Jtag *_jtag; int8_t _verbose; int _irlen; uint32_t _capacity; uint32_t _block_size; uint16_t _manufacturer_id; uint16_t _device_id; bool _has_burst; }; #endif // SRC_BPIFLASH_HPP_