/* Copyright (C) 2018 RDA Technologies Limited and/or its affiliates("RDA"). * All rights reserved. * * This software is supplied "AS IS" without any warranties. * RDA assumes no responsibility or liability for the use of the software, * conveys no license or title under any patent, copyright, or mask work * right to the product. RDA reserves the right to make changes in the * software without notification. RDA also make no representation or * warranty that such application will be suitable for the specified use * without further testing or modification. */ #ifndef _HAL_SPI_FLASH_H_ #define _HAL_SPI_FLASH_H_ #include #include #include #include "drv_config.h" #include "osi_compiler.h" #ifdef __cplusplus extern "C" { #endif /** * \brief flash instance * * The preperty is derived from manufacture ID. It is found that even * for the same manufacture ID, the property may be different, for * example, security register block size. In this case, user can * override the perperty. */ typedef struct halSpiFlash { /** hardware controller register base */ uintptr_t hwp; /** manufacture id */ unsigned mid; /** capacity in bytes */ unsigned capacity; /** security register block size, 0 for not support */ uint16_t sreg_block_size; /** internal flash type */ uint8_t type : 4; /** status register wp type */ uint8_t wp_type : 4; /** read uid type */ uint8_t uid_type : 4; /** whether cpid is supported */ uint8_t cpid_type : 4; /** minimal security register number */ uint8_t sreg_min_num : 4; /** maximum security register number */ uint8_t sreg_max_num : 4; /** whether volatile sr is supported */ bool volatile_sr_en : 1; /** whether suspend resume is supported */ bool suspend_en : 1; /** whether 5AH to read SFDP supported */ bool sfdp_en : 1; /** whether 01H can write both SR1 and SR2 */ bool write_sr12 : 1; /** whether 35H can read SR2 */ bool has_sr2 : 1; /** whether has GD_SR_SUS1 */ bool has_sus1 : 1; /** whether has GD_SR_SUS2 */ bool has_sus2 : 1; /** force 4K erase on first block */ bool force_4k_first_block : 1; /** force 4K erase on last block */ bool force_4k_last_block : 1; } halSpiFlash_t; /** * \brief write enable * * \param d hal spi flash instance */ void halSpiFlashWriteEnable(const halSpiFlash_t *d); #if defined(CONFIG_SOC_8910) && defined(CONFIG_SUPPORT_LC_FLASH) void halSpiFlash4ByteAddressMode(const halSpiFlash_t *d); void halSpiFlashDisenable4ByteAddressMode(const halSpiFlash_t *d); #endif /** * \brief write disable * * \param d hal spi flash instance */ void halSpiFlashWriteDisable(const halSpiFlash_t *d); /** * \brief program suspend * * \param d hal spi flash instance */ void halSpiFlashProgramSuspend(const halSpiFlash_t *d); /** * \brief erase suspend * * \param d hal spi flash instance */ void halSpiFlashEraseSuspend(const halSpiFlash_t *d); /** * \brief program resume * * \param d hal spi flash instance */ void halSpiFlashProgramResume(const halSpiFlash_t *d); /** * \brief erase resume * * \param d hal spi flash instance */ void halSpiFlashEraseResume(const halSpiFlash_t *d); /** * \brief chip erase * * \param d hal spi flash instance */ void halSpiFlashChipErase(const halSpiFlash_t *d); /** * \brief reset enable * * \param d hal spi flash instance */ void halSpiFlashResetEnable(const halSpiFlash_t *d); /** * \brief reset * * \param d hal spi flash instance */ void halSpiFlashReset(const halSpiFlash_t *d); /** * \brief read status register * * When only one SR is supported, it will return the SR. When two SR are * supported, it will return 16bits SR, SR-1 at LSB and SR-2 at MSB. * * \param d hal spi flash instance * \return status register */ uint16_t halSpiFlashReadSR(const halSpiFlash_t *d); /** * \brief write status register * * The implementation will depend on flash property, one status register, * two status registers with one command, or two status registers with * separated commands. * * Inside, it will send write enable command, and wait write finish. * * \param d hal spi flash instance * \param sr status register value */ void halSpiFlashWriteSR(const halSpiFlash_t *d, uint16_t sr); /** * \brief page program * * \p data shouldn't be allocated in flash. \p size should be less than * hardware TX fifo size. * * It will only send program command, write enable and wait finish shall * be considered by caller. * * \param d hal spi flash instance * \param offset flash address * \param data data to be programmed * \param size data size */ void halSpiFlashPageProgram(const halSpiFlash_t *d, uint32_t offset, const void *data, uint32_t size); /** * \brief 4K/32K/64K erase * * \p size can only be 4K, 32K or 64K. \p offset should be \p size aligned. * * \param d hal spi flash instance * \param offset flash address * \param size erase size */ void halSpiFlashErase(const halSpiFlash_t *d, uint32_t offset, uint32_t size); /** * \brief read unique id number * * Not all flash supports unique id, and the unique id size is different even * supported. \p uid should be large enough. * * \param d hal spi flash instance * \param uid unique id * \return * - unique id size * - 0 if unique id is not supported */ int halSpiFlashReadUniqueId(const halSpiFlash_t *d, uint8_t *uid); /** * \brief read cp id * * Not all flash support cp id. * * \param d hal spi flash instance * \return * - cp id * - 0 if not supported */ uint16_t halSpiFlashReadCpId(const halSpiFlash_t *d); /** * \brief deep power down * * \param d hal spi flash instance */ void halSpiFlashDeepPowerDown(const halSpiFlash_t *d); /** * \brief release from deep power down * * There are delay inside, to make sure flash is accessible at return. * * \param d hal spi flash instance */ void halSpiFlashReleaseDeepPowerDown(const halSpiFlash_t *d); /** * \brief read SFDP * * \param d hal spi flash instance * \param address SFDP address * \param data data to be read * \param size read size * \return * - true on success * - false of the feature is not supported */ bool halSpiFlashReadSFDP(const halSpiFlash_t *d, uint32_t address, void *data, uint32_t size); /** * \brief read status register and check WIP bit * * \param d hal spi flash instance * \return * - true if WIP is not set in status register * - false WIP is set in status register */ bool halSpiFlashIsWipFinished(const halSpiFlash_t *d); /** * \brief wait WIP bit in status register unset * * \param d hal spi flash instance */ void halSpiFlashWaitWipFinish(const halSpiFlash_t *d); /** * \brief read security register * * Not all flash supports security register, and the valid \p num and * \p address is different even supported. * * The maximum \p size is 4. When more bytes are needed, caller should * use loop for multiple read. * * \param d hal spi flash instance * \param num securerity register number * \param address security register address * \param data pointer to output data * \param size read size * \return * - true on success * - false on failed, invalid parameter or not support */ bool halSpiFlashReadSecurityRegister(const halSpiFlash_t *d, uint8_t num, uint16_t address, void *data, uint32_t size); /** * \brief program security register * * Not all flash supports security register, and the valid \p num and * \p address is different even supported. * * \p data shouldn't be allocated in flash. \p size should be less than * (can't be equal to) hardware TX fifo size. * * \param d hal spi flash instance * \param num securerity register number * \param address security register address * \param data data to be programed * \param size program size * \return * - true on success * - false on failed, invalid parameter or not support */ bool halSpiFlashProgramSecurityRegister(const halSpiFlash_t *d, uint8_t num, uint16_t address, const void *data, uint32_t size); /** * \brief erase security register * * Not all flash supports security register, and the valid \p num is * different even supported. * * \param d hal spi flash instance * \param num securerity register number * \return * - true on success * - false on failed, invalid parameter or not support */ bool halSpiFlashEraseSecurityRegister(const halSpiFlash_t *d, uint8_t num); /** * \brief lock security register * * Not all flash supports security register, and the valid \p num is * different even supported. * * \param d hal spi flash instance * \param num securerity register number * \return * - true on success * - false on failed, invalid parameter or not support */ bool halSpiFlashLockSecurityRegister(const halSpiFlash_t *d, uint8_t num); /** * \brief whether security register is locked * * Not all flash supports security register, and the valid \p num is * different even supported. * * \param d hal spi flash instance * \param num securerity register number * \return * - true if \p num is valid and locked * - false if not locked, or invalid parameter */ bool halSpiFlashIsSecurityRegisterLocked(const halSpiFlash_t *d, uint8_t num); /** * \brief the actual write protected region * * Status register can't set write protection for arbitrary region. This returns * the real protected region. * * \param d hal spi flash instance * \param offset range start * \param size range size * \return real protected range */ osiUintRange_t halSpiFlashWpRange(const halSpiFlash_t *prop, uint32_t offset, uint32_t size); /** * \brief handling before program/erase * * Check status register to ensure the range is not write protected, and * send write enable command. * * When volatile status register feature is not supported, it won't change * status register. * * \param d hal spi flash instance * \param offset range start to be program/erase * \param size range size to be program/erase */ void halSpiFlashPrepareEraseProgram(const halSpiFlash_t *prop, uint32_t offset, uint32_t size); /** * \brief handling after program/erase is completed * * After program/erase is completed, status register will be set to * protect all. * * When volatile status register feature is not supported, it won't change * status register. * * \param d hal spi flash instance */ void halSpiFlashFinishEraseProgram(const halSpiFlash_t *d); /** * \brief check status register * * Check status register: * - When there are suspend bits, reset * - QE should be 1 * - reasonable WP setting * * \param d hal spi flash instance */ void halSpiFlashStatusCheck(const halSpiFlash_t *d); /** * \brief initialize flash * * \p d->hwp should be valid flash controller base address. Inside, flash ID * will be read, and properties inside \p d will be set based on flash ID. * * If flash ID is unknown, it will panic inside. * * Also \p halSpiFlashStatusCheck will be called inside to ensure status * register is reasonable. * * It should be called before configure quad read in flash controller. * * \param d hal spi flash instance */ void halSpiFlashInit(halSpiFlash_t *d); #ifdef __cplusplus } #endif #endif