/* mbed Microcontroller Library ******************************************************************************* * Copyright (c) 2014, Realtek Semiconductor Corp. * All rights reserved. * * This module is a confidential and proprietary property of RealTek and * possession or use of this module requires written permission of RealTek. ******************************************************************************* */ #include "objects.h" #include "PinNames.h" #include "pinmap.h" #include "rtl8195a.h" #include "hal_spi_flash.h" #include "hal_platform.h" #include "rtl8195a_spi_flash.h" #include "hal_api.h" #include "flash_api.h" extern u32 ConfigDebugInfo; /** * global data structure */ flash_t flash; static void flash_init(flash_t *obj); /** * @brief lock flash access * @param none * @retval none */ void flash_lock() { HAL_WRITE32(0xE000ED00, 0x9C, 0x9807E012); HAL_WRITE32(0xE000ED00, 0xA0, 0x06000017); } /** * @brief unlock flash access * @param none * @retval none */ void flash_unlock() { HAL_WRITE32(0xE000ED00, 0x9C, 0x9807E012); HAL_WRITE32(0xE000ED00, 0xA0, 0x03000017); } /** * @brief Control the flash chip write protect enable/disable * @param protect: 1/0: protect/unprotect * @retval none */ void flash_write_protect(flash_t *obj, uint32_t protect) { flash_init(obj); SpicWriteProtectFlashRtl8195A(protect); SpicDisableRtl8195A(); } /** * @brief Init Flash * @param obj: address of the flash object * @retval none */ static void flash_init(flash_t *obj) { //SPIC_INIT_PARA spic_init_para; // Init SPI Flash Controller // DBG_8195A("Initial Spi Flash Controller\n"); SPI_FLASH_PIN_FCTRL(ON); if (!SpicFlashInitRtl8195A(SpicOneBitMode)){ DBG_8195A("SPI Init Fail!!!!!!\n"); HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSTBY_INFO3, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSTBY_INFO3)|0xf); } else { // DBG_8195A("SPI Init SUCCESS\n"); } } /** * @brief Erase flash sector * @param address: Specifies the starting address to be erased. * @retval none */ void flash_erase_sector(flash_t *obj, uint32_t address) { flash_init(obj); SpicSectorEraseFlashRtl8195A(SPI_FLASH_BASE + address); SpicDisableRtl8195A(); } /** * @brief Read a word from specified address * @param obj: Specifies the parameter of flash object. * @param address: Specifies the address to be read. * @param data: Specified the address to save the readback data. * @retval status: Success:1 or Failure: Others. */ int flash_read_word(flash_t *obj, uint32_t address, uint32_t * data) { // Check address // Read Word flash_init(obj); // Wait flash busy done (wip=0) SpicWaitWipDoneRefinedRtl8195A(obj->SpicInitPara); * data = HAL_READ32(SPI_FLASH_BASE, address); SpicDisableRtl8195A(); return 1; } /** * @brief Write a word to specified address * @param obj: Specifies the parameter of flash object. * @param address: Specifies the address to be programmed. * @param data: Specified the data to be programmed. * @retval status: Success:1 or Failure: Others. */ int flash_write_word(flash_t *obj, uint32_t address, uint32_t data) { // Disable write protection // flash_unlock(); flash_init(obj); //Write word HAL_WRITE32(SPI_FLASH_BASE, address, data); // Wait spic busy done SpicWaitBusyDoneRtl8195A(); // Wait flash busy done (wip=0) SpicWaitWipDoneRefinedRtl8195A(obj->SpicInitPara); SpicDisableRtl8195A(); // Enable write protection // flash_lock(); return 1; } /** * @brief Read a stream of data from specified address * @param obj: Specifies the parameter of flash object. * @param address: Specifies the address to be read. * @param len: Specifies the length of the data to read. * @param data: Specified the address to save the readback data. * @retval status: Success:1 or Failure: Others. */ int flash_stream_read(flash_t *obj, uint32_t address, uint32_t len, uint8_t * data) { u32 offset_to_align; u32 i; u32 read_word; uint8_t *ptr; uint8_t *pbuf; flash_init(obj); // Wait flash busy done (wip=0) SpicWaitWipDoneRefinedRtl8195A(obj->SpicInitPara); offset_to_align = address & 0x03; pbuf = data; if (offset_to_align != 0) { // the start address is not 4-bytes aligned read_word = HAL_READ32(SPI_FLASH_BASE, (address - offset_to_align)); ptr = (uint8_t*)&read_word + offset_to_align; offset_to_align = 4 - offset_to_align; for (i=0;i> 2) + 1) << 2; // address = next 4-bytes aligned ptr = (uint8_t*)&read_word; if ((u32)pbuf & 0x03) { while (len >= 4) { read_word = HAL_READ32(SPI_FLASH_BASE, address); for (i=0;i<4;i++) { *pbuf = *(ptr+i); pbuf++; } address += 4; len -= 4; } } else { while (len >= 4) { *((u32 *)pbuf) = HAL_READ32(SPI_FLASH_BASE, address); pbuf += 4; address += 4; len -= 4; } } if (len > 0) { read_word = HAL_READ32(SPI_FLASH_BASE, address); for (i=0;iSpicInitPara); } address = (((address-1) >> 2) + 1) << 2; // address = next 4-bytes aligned if ((u32)pbuf & 0x03) { while (len >= 4) { write_word = (u32)(*pbuf) | ((u32)(*(pbuf+1)) << 8) | ((u32)(*(pbuf+2)) << 16) | ((u32)(*(pbuf+3)) << 24); //Write word HAL_WRITE32(SPI_FLASH_BASE, address, write_word); // Wait spic busy done SpicWaitBusyDoneRtl8195A(); // Wait flash busy done (wip=0) SpicWaitWipDoneRefinedRtl8195A(obj->SpicInitPara); pbuf += 4; address += 4; len -= 4; } } else { while (len >= 4) { //Write word HAL_WRITE32(SPI_FLASH_BASE, address, (u32)*((u32 *)pbuf)); // Wait spic busy done SpicWaitBusyDoneRtl8195A(); // Wait flash busy done (wip=0) SpicWaitWipDoneRefinedRtl8195A(obj->SpicInitPara); pbuf += 4; address += 4; len -= 4; } } if (len > 0) { write_word = HAL_READ32(SPI_FLASH_BASE, address); ptr = (uint8_t*)&write_word; for (i=0;iSpicInitPara); } SpicDisableRtl8195A(); return 1; }