From 8a55d66481f589149ff71490b3ddbb081d95c2b2 Mon Sep 17 00:00:00 2001 From: Jihoon Park Date: Tue, 14 Mar 2017 14:11:13 +0900 Subject: [PATCH] s5j/qspi: clean up unnecessary function and support 80Mhz/QUADIO provides initialize FLASH function. The GPIO is not set for FLASH control, and clock for FLASH is 40Mhz as default. After s5j_qspi_init(), GPIO sets to CS/SO/SI/WP/HLD signal and can control FLASH. The Clock incresed by 80Mhz with QUAD_IO mode for enhanced perfomance. Change-Id: Id96b4c837bc379a167b0fa548a27f625cfc3cd73 Signed-off-by: Jihoon Park --- os/arch/arm/src/s5j/s5j_qspi.c | 1231 ++--------------------- os/arch/arm/src/s5j/s5j_qspi.h | 36 +- os/arch/arm/src/sidk_s5jt200/src/s5jt200_tash.c | 14 +- 3 files changed, 107 insertions(+), 1174 deletions(-) diff --git a/os/arch/arm/src/s5j/s5j_qspi.c b/os/arch/arm/src/s5j/s5j_qspi.c index 8212882..1ea2456 100644 --- a/os/arch/arm/src/s5j/s5j_qspi.c +++ b/os/arch/arm/src/s5j/s5j_qspi.c @@ -18,8 +18,8 @@ /**************************************************************************** * arch/arm/src/s5j/s5j_qspi.c * - * Copyright (C) 2009, 2014 Gregory Nutt. All rights reserved. - * Author: + * Copyright (C) 2009-2010, 2014-2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -49,11 +49,9 @@ * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ - /**************************************************************************** * Included Files ****************************************************************************/ - #include #include @@ -71,30 +69,21 @@ #include "chip.h" #include "up_arch.h" #include "cache.h" +#include "mpu.h" #include #include +#include +#include +#include /**************************************************************************** * Private Functions Prototypes ****************************************************************************/ -static void qspi_open(void); -static void qspi_close(void); -static ssize_t qspi_read(FAR struct file *filep, FAR char *buffer, size_t buflen); -static ssize_t qspi_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); -static long qspi_ioctl(struct file *filep, int cmd, unsigned long arg); /**************************************************************************** * Private Types ****************************************************************************/ -static const struct file_operations drv_fops = { - (void *)qspi_open, /* open */ - (void *)qspi_close, /* close */ - (void *)qspi_read, /* read */ - (void *)qspi_write, /* write */ - 0, /* seek */ - (void *)qspi_ioctl /* ioctl */ -}; /**************************************************************************** * Static Function Prototypes @@ -103,79 +92,54 @@ static const struct file_operations drv_fops = { /**************************************************************************** * Private Data ****************************************************************************/ -#define DATA_SIZE 0x1000 /* 4096 */ -#define USE_MALLOC (1) - -#define WL_SIZE 100 -#define AREA_A 0 -#define AREA_B 1 -int g_base_address; - -u32 a[DATA_SIZE], b[DATA_SIZE]; +static sem_t count_sem; /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -#ifdef CONFIG_TEST_QSPI -#define qspitest printf -#else -#define qspitest(x...) -#endif - -#ifdef CONFIG_WL_DEBUG_QSPI -#define qspi_wl_debug printf -#else -#define qspi_wl_debug(x...) -#endif - /**************************************************************************** * Private Types ****************************************************************************/ - /**************************************************************************** * Private Functions ****************************************************************************/ - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -void copy4B(u32 targetAddr, u32 sourceAddr, u32 sizeByte) +static void s5j_qspi_copy_4byte(unsigned int target_addr, unsigned int source_addr, unsigned int sizebyte) { - u32 loopt; - u32 uRoundup; + unsigned int loopt; + unsigned int roundup; int i; - uRoundup = sizeByte % 4; - if (uRoundup) { - sizeByte += (4 - uRoundup); + roundup = sizebyte % 4; + if (roundup) { + sizebyte += (4 - roundup); } - loopt = sizeByte / 4; + loopt = sizebyte / 4; for (i = 0; i < loopt; i++) { - Outp32(targetAddr + (4 * i), Inp32(sourceAddr + (4 * i))); + Outp32(target_addr + (4 * i), Inp32(source_addr + (4 * i))); } return; } -void copy1B(u32 targetAddr, u32 sourceAddr, u32 sizeByte) +static void s5j_qspi_copy_1byte(unsigned int target_addr, unsigned int source_addr, unsigned int sizebyte) { - u32 loopt; + unsigned int loopt; int i; - loopt = sizeByte; + loopt = sizebyte; for (i = 0; i < loopt; i++) { - Outp8(targetAddr + (i), Inp8(sourceAddr + (i))); + Outp8(target_addr + (i), Inp8(source_addr + (i))); } return; + } -void QSPI_Set_GPIOPort(void) +static void s5j_qspi_set_gpio(void) { - s32 gpio_sf_clk, gpio_sf_cs, gpio_sf_si, gpio_sf_so, gpio_sf_wp, gpio_sf_hld; + signed int gpio_sf_clk, gpio_sf_cs, gpio_sf_si, gpio_sf_so, gpio_sf_wp, gpio_sf_hld; gpio_sf_clk = s5j_gpio(GPP1, 0); gpio_sf_cs = s5j_gpio(GPP1, 1); @@ -201,1106 +165,115 @@ void QSPI_Set_GPIOPort(void) return; } -void QSPI_disable_wp(void) -{ - HW_REG32(0x80310000, 0x04) &= ~(0x1 << 31); - HW_REG32(0x80310000, 0x04) |= (0x1 << 31); -} - -void QSPI_enable_wp(void) -{ - HW_REG32(0x80310000, 0x04) &= ~(0x1 << 31); -} - -void QSPI_Init(void) -{ - QSPI_Set_GPIOPort(); - HW_REG32(0x80310000, 0x04) = 0x8010001A; /* disable WP */ - HW_REG32(0x80310000, 0x78) = 0x8; //FLASH_IO_MODE - HW_REG32(0x80310000, 0x74) = 0x4; //QUAD_FAST_READ - - /* COMMNAD1 will be asserted by default value */ - - cal_clk_setrate(d1_serialflash, 80000000); -} - -void qspi_get_base(void) -{ - u32 ctrlInfo[DATA_SIZE]; - int countA; - int countB; - int flag; - - copy4B((u32) ctrlInfo, QSPI_SECURE_AREA_CTRL_ADDRESS, DATA_SIZE); - countA = ctrlInfo[0]; - countB = ctrlInfo[1]; - flag = ctrlInfo[2]; - - if (flag == AREA_A) { - g_base_address = QSPI_SECURE_AREA_START_ADDRESS_A; - } else if (flag == AREA_B) { - g_base_address = QSPI_SECURE_AREA_START_ADDRESS_B; - } - - qspi_wl_debug("flag:%d coutA:%d countB:%d\n", flag, countA, countB); -} - -void QSPI_Set_Vendor(eQSPI_VENDOR vendor) -{ - SetBits(rSF_CON, 16, 0x3F, (u32)vendor); - return; -} - -u8 QSPI_Get_Vendor(void) -{ - return GetBits(rSF_CON, 16, 0x3F); -} - -void QSPI_Set_Vendor_Command(u8 vendor) -{ - eQSPI_VENDOR id; - switch (vendor) { - case 0xC2: - //MXIC - id = QSPI_VENDOR_MACRONIX; - break; - - case 0xEF: - //Winbond - id = QSPI_VENDOR_WINBOND; - break; - - case 0x20: - //ST Micronics (MICRO) - id = QSPI_VENDOR_STMICRO; - break; - - case 0xBF: - //SST(Silicon Storage Technology) - id = QSPI_VENDOR_SST; - break; - - case 0x1F: - //ATMEL - id = QSPI_VENDOR_ATMEL; - break; - - case 0x01: - //AMD(Spansion) - id = QSPI_VENDOR_AMD; - break; - - default: - id = (eQSPI_VENDOR) QSPI_Get_Vendor(); - break; - } - - QSPI_Set_Vendor(id); -} - -void QSPI_Set_ReadMode(eQSPI_MODE mode, u32 command) -{ - switch (mode) { - case QSPI_SINGLE_IO: - - //Disable performance enhancement - SetBits(rFLASH_IO_MODE, 0, 0xF, 0x8); - - //Set READ command manually. - if (command != 0) { - SetBits(rCOMMAND5, 0, 0xFFU, command); - } - break; - - case QSPI_DUAL_FAST: - SetBits(rFLASH_IO_MODE, 0, 0xF, 0x2); - SetBits(rFLASH_PERF_MODE, 3, 1, 0); - - //Set READ command manually. - if (command != 0) { - SetBits(rCOMMAND5, 16, 0xFFU, command); - } - - break; - - case QSPI_DUAL_IO: - SetBits(rFLASH_IO_MODE, 0, 0xF, 0x2); - SetBits(rFLASH_PERF_MODE, 3, 1, 1); - - //Set READ command manually. - if (command != 0) { - SetBits(rCOMMAND5, 16, 0xFFU, command); - } - - break; - - case QSPI_QUAD_FAST: - - SetBits(rFLASH_IO_MODE, 0, 0xF, 0x4); - SetBits(rFLASH_PERF_MODE, 3, 1, 0); - - //Set READ command manually. - if (command != 0) { - SetBits(rCOMMAND5, 24, 0xFFU, command); - } - - break; - - case QSPI_QUAD_IO: - SetBits(rFLASH_IO_MODE, 0, 0xF, 0x4); - SetBits(rFLASH_PERF_MODE, 3, 1, 1); - - //Set READ command manually. - if (command != 0) { - SetBits(rCOMMAND1, 24, 0xFFU, command); - } - - break; - } - - return; -} - -void QSPI_Set_WriteMode(eQSPI_WR_MODE mode, u32 command) -{ - switch (mode) { - case QSPI_WREN: - - SetBits(rCOMMAND4, 8, 0xFF, command); - break; - - case QSPI_WRDI: - SetBits(rCOMMAND4, 0, 0xFF, command); - - break; - - case QSPI_WRSR: - SetBits(rCOMMAND3, 16, 0xFF, command); - - break; - } - - return; -} - -void QSPI_Set_Page_Size(eQSPI_PAGE_SIZE size) -{ - //Bytes per Page - SetBits(rSF_CON, 8, 0xF, size); - - return; -} - -void QSPI_Read_ID(u32 *vendor) -{ - *vendor = Inp32(rRDID); - return; -} - -sRead_Status_Register QSPI_Get_Status_Register(void) +/** +* +* @brief read status register from FLASH +* @param void +* @return void +* @note +*/ +static flash_status_register s5j_qspi_get_status_register(void) { - sRead_Status_Register reg = { 0 }; + flash_status_register reg = { 0 }; + reg.rdsr = Inp8(rRDSR); - reg.rdsr = Inp32(rRDSR); + lldbg("0x%x\n", reg.rdsr); return reg; } -void QSPI_Write_Status_Register(u16 wrsr) -{ - Outp16(rWRSR, wrsr); - - return; -} - -void QSPI_Sector_Erase(u32 targetAddr) -{ - Outp32(rERASE_ADDRESS, targetAddr); - - Outp8(rSE, QSPI_DUMMY_DATA); - - arch_invalidate_dcache(targetAddr + CONFIG_S5J_FLASH_BASE, (targetAddr + CONFIG_S5J_FLASH_BASE + QSPI_SIZE_4KB)); -} - -void QSPI_Block_Erase(u32 targetAddr, eQSPI_BLOCK_SIZE unit) -{ - u32 blockEraseSize = 0; - - if (unit == BLOCK_64KB) { - SetBits(rCOMMAND2, 16, 0xFF, COMMAND_ERASE_64KB); - blockEraseSize = QSPI_SIZE_64KB; - } else { - SetBits(rCOMMAND2, 16, 0xFF, COMMAND_ERASE_32KB); - blockEraseSize = QSPI_SIZE_32KB; - } - - Outp32(rERASE_ADDRESS, targetAddr); - - Outp8(rBE, QSPI_DUMMY_DATA); - - arch_invalidate_dcache(targetAddr + CONFIG_S5J_FLASH_BASE, (targetAddr + CONFIG_S5J_FLASH_BASE + blockEraseSize)); -} - -void QSPI_Chip_Erase(void) -{ - Outp8(rCE, QSPI_DUMMY_DATA); -} - -eERASE_UNIT Get_Erase_Unit(u32 offsetStart, u32 target) -{ - u32 sizeLeft; - sizeLeft = target - offsetStart; - - if (offsetStart == 0) { - if (sizeLeft >= QSPI_SIZE_64KB) { - return TYPE_64KB; - } else if (sizeLeft >= QSPI_SIZE_32KB) { - return TYPE_32KB; - } else if (sizeLeft >= QSPI_SIZE_4KB) { - return TYPE_4KB; - } else { - return TYPE_ERR; - } - } - - if ((offsetStart / QSPI_SIZE_64KB) && (sizeLeft >= QSPI_SIZE_64KB) && !(offsetStart % QSPI_SIZE_64KB)) { - return TYPE_64KB; - } else if ((offsetStart / QSPI_SIZE_32KB) && (sizeLeft >= QSPI_SIZE_32KB) && !(offsetStart % QSPI_SIZE_32KB)) { - return TYPE_32KB; - } else if ((offsetStart / QSPI_SIZE_4KB) && (sizeLeft >= QSPI_SIZE_4KB) && !(offsetStart % QSPI_SIZE_4KB)) { - return TYPE_4KB; - } else { - return TYPE_ERR; - } -} - -//size should 4KB aligned -bool QSPI_Erase(u32 targetAddr, u32 size) +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/** +* +* @brief disable write protection of FLASH +* @param void +* @return void +* @note + writable when wp is disabled +*/ +void s5j_qspi_disable_wp(void) { - u32 temp = 0; - u32 target; - eERASE_UNIT type; - - targetAddr = targetAddr - CONFIG_S5J_FLASH_BASE; - - temp = targetAddr % QSPI_SIZE_4KB; - if (temp) { - return false; - } - - //Check address alignment - if ((size % QSPI_SIZE_4KB) != 0) { - return false; - } + unsigned int reg; - if (size < QSPI_SIZE_4KB) { - return false; + while (sem_wait(&count_sem) != OK) { + ASSERT(errno == EINTR); } - //Erase Offset - temp = targetAddr; - target = temp + size; + /* someone has been disabled wp, we should wait until it's released */ do { - type = Get_Erase_Unit(temp, target); - - switch (type) { - case TYPE_4KB: - QSPI_Sector_Erase(temp); - temp += QSPI_SIZE_4KB; - continue; - - case TYPE_32KB: - QSPI_Block_Erase(temp, BLOCK_32KB); - temp += QSPI_SIZE_32KB; - continue; - - case TYPE_64KB: - QSPI_Block_Erase(temp, BLOCK_64KB); - temp += QSPI_SIZE_64KB; - continue; - - default: - return false; - } - } while (temp < target); - - return true; -} - -void QSPI_Read(u32 targetAddr, u32 sourceAddr, u32 sizeByte) -{ - if (targetAddr >= QSPI_SECURE_AREA_START_ADDRESS) { - lldbg("Unable to access\n"); - return; - } - - copy4B(sourceAddr, targetAddr, sizeByte); - /* copy1B(sourceAddr, targetAddr, sizeByte); */ -} - -void QSPI_Secure_Read(u32 targetOffset, u32 sourceAddr, u32 sizeByte) -{ - u32 targetAddr; - - targetAddr = QSPI_SECURE_AREA_START_ADDRESS + targetOffset; - - if (targetAddr >= QSPI_FLASH_END_ADDRESS) { - lldbg("out of flash: 0x%x\n", targetAddr); - return; - } - if (targetAddr < QSPI_SECURE_AREA_START_ADDRESS) { - lldbg("out of secure area\n"); - return; - } - - copy4B(sourceAddr, targetAddr, sizeByte); -} - -void QSPI_Secure_Read_WL(u32 targetOffset, u32 sourceAddr, u32 sizeByte) -{ - u32 targetAddr; - - targetAddr = g_base_address + targetOffset; - - if (targetAddr >= QSPI_FLASH_END_ADDRESS) { - lldbg("out of flash: 0x%x\n", targetAddr); - return; - } - if (targetAddr < QSPI_SECURE_AREA_START_ADDRESS) { - lldbg("out of secure area\n"); - return; - } - - copy4B(sourceAddr, targetAddr, sizeByte); -} - -u32 wear_leveling(u32 targetAddr) -{ - /* Need to consider speed during swapping */ - int countA; - int countB; - int flag; - int addrA = QSPI_SECURE_AREA_START_ADDRESS_A; - int addrB = QSPI_SECURE_AREA_START_ADDRESS_B; -#if USE_MALLOC - u32 *ctrlInfo; - ctrlInfo = (u32 *)malloc(4 * DATA_SIZE); - - if (ctrlInfo == NULL) { - return 0; - } -#else - u32 ctrlInfo[DATA_SIZE]; -#endif - - /*Read ctrA & ctrB & flag */ - if (g_base_address == addrA) { - QSPI_Secure_Read_WL((2 * QSPI_SECURE_AREA_SIZE), (u32)ctrlInfo, DATA_SIZE); - } else if (g_base_address == addrB) { - QSPI_Secure_Read_WL((QSPI_SECURE_AREA_SIZE), (u32)ctrlInfo, DATA_SIZE); - } - - countA = ctrlInfo[0]; - countB = ctrlInfo[1]; - flag = ctrlInfo[2]; - - qspi_wl_debug("%d %d %d\n", flag, countA, countB); - - if (flag == AREA_A) { - if (countA == countB + WL_SIZE) { /*Switch A to B */ - int i; -#if USE_MALLOC - u8 *TempBuffer; - TempBuffer = (u8 *)malloc(DATA_SIZE); -#else - u8 TempBuffer[DATA_SIZE]; -#endif - - /* copy A to B */ - qspi_wl_debug("swapping A to B\n"); - for (i = 0; i < 23; i++) { - g_base_address = addrA; - QSPI_Secure_Read_WL((i * DATA_SIZE), (u32)TempBuffer, DATA_SIZE); - g_base_address = addrB; - QSPI_Secure_Write_NoWL(i * DATA_SIZE, (u32)TempBuffer, DATA_SIZE); - } -#if USE_MALLOC - free(TempBuffer); -#endif - - /* ctrB++, flag = B, write ctrol */ - ctrlInfo[1] = countB + 1; - ctrlInfo[2] = AREA_B; - g_base_address = addrA; - QSPI_Secure_Write_NoWL(2 * QSPI_SECURE_AREA_SIZE, (u32)ctrlInfo, DATA_SIZE); - g_base_address = addrB; - -#if USE_MALLOC - free(ctrlInfo); -#endif - return (targetAddr + QSPI_SECURE_AREA_SIZE); - } else { - /* ctrA++, write ctrol */ - ctrlInfo[0] = countA + 1; - g_base_address = addrA; - QSPI_Secure_Write_NoWL(2 * QSPI_SECURE_AREA_SIZE, (u32)ctrlInfo, DATA_SIZE); - -#if USE_MALLOC - free(ctrlInfo); -#endif - return (targetAddr); - } - } else if (flag == AREA_B) { /*Switch B to A */ - if (countB == countA + WL_SIZE) { - int i; -#if USE_MALLOC - u8 *TempBuffer; - TempBuffer = (u8 *)malloc(DATA_SIZE); -#else - u8 TempBuffer[DATA_SIZE]; -#endif - - /* copy B to A */ - qspi_wl_debug("swapping B to A\n"); - for (i = 0; i < 23; i++) { - g_base_address = addrB; - QSPI_Secure_Read_WL((i * DATA_SIZE), (u32)TempBuffer, DATA_SIZE); - g_base_address = addrA; - QSPI_Secure_Write_NoWL(i * DATA_SIZE, (u32)TempBuffer, DATA_SIZE); - - } -#if USE_MALLOC - free(TempBuffer); -#endif - /* ctrA++, flag = A, write ctrol */ - g_base_address = addrA; - ctrlInfo[0] = countA + 1; - ctrlInfo[2] = AREA_A; - QSPI_Secure_Write_NoWL(2 * QSPI_SECURE_AREA_SIZE, (u32)ctrlInfo, DATA_SIZE); -#if USE_MALLOC - free(ctrlInfo); -#endif - return (targetAddr - QSPI_SECURE_AREA_SIZE); - } else { - /* ctrB++, write ctrol */ - ctrlInfo[1] = countB + 1; - g_base_address = addrA; - QSPI_Secure_Write_NoWL(2 * QSPI_SECURE_AREA_SIZE, (u32)ctrlInfo, DATA_SIZE); - g_base_address = addrB; -#if USE_MALLOC - free(ctrlInfo); -#endif - return (targetAddr); - } - } -#if USE_MALLOC - free(ctrlInfo); -#endif - return targetAddr; -} - -u32 QSPI_Write(u32 targetAddr, u32 sourceAddr, u32 sizeByte) -{ - if (targetAddr >= QSPI_SECURE_AREA_START_ADDRESS) { - lldbg("Unable to access\n"); - return false; - } - - //Disable WP(Write Protect) - SetBits(rSF_CON, 31, 0x1U, 1U); - - //Page Programming - SetBits(rSF_CON, 15, 0x1, 1); - - // Checks Address range (16MB) - if (((targetAddr - CONFIG_S5J_FLASH_BASE) >> 24) > 0) { // 16MB - lldbg("Flash Address range over!(24bit range)\n"); - return false; - } - //Checks sector(4KB) align - if ((targetAddr & 0xFFF) != 0) { - lldbg("4KB alignment failure\n"); - return false; - } - //should be erased before writing. - if (QSPI_Erase(targetAddr, sizeByte) == false) { - lldbg("Erase Failure\n"); - return false; - } - copy4B(targetAddr, sourceAddr, sizeByte); - - return true; - -} - -u32 QSPI_Write_No_Erase(u32 targetAddr, u32 sourceAddr, u32 sizeByte) -{ - if (targetAddr >= QSPI_SECURE_AREA_START_ADDRESS) { - lldbg("Unable to access\n"); - return false; - } - - SetBits(rSF_CON, 31, 0x1U, 1U); - SetBits(rSF_CON, 15, 0x1, 1); - - if (((targetAddr - CONFIG_S5J_FLASH_BASE) >> 24) > 0) { - lldbg("Flash Address range over!(24bit range)\n"); - return false; - } - - if ((targetAddr & 0xFFF) != 0) { - return false; - } - - copy4B(targetAddr, sourceAddr, sizeByte); - - return true; -} - -u32 QSPI_Secure_Write(u32 targetOffset, u32 sourceAddr, u32 sizeByte) -{ - u32 targetAddr; - u32 aligned_addr; - u32 aligned_size; - u32 aligned_offset; - u32 remainder_offset; - int i; -#if USE_MALLOC - u8 *TempBuffer; - TempBuffer = (u8 *)malloc(8 * 1024 + 32); -#else - u8 TempBuffer[8 * 1024]; -#endif - - targetAddr = QSPI_SECURE_AREA_START_ADDRESS + targetOffset; - /* lldbg("\t\t\t\tw:0x%08x\n", targetOffset); */ - QSPI_disable_wp(); - - //size check - aligned_size = (targetAddr & 0xFFF) + sizeByte; - if (aligned_size > 4 * 1024) { - aligned_size = 8 * 1024; - } else { - aligned_size = 4 * 1024; - } - - //addr align check - aligned_addr = (targetAddr & ~(0xFFF)); - aligned_offset = (targetOffset & ~(0xFFF)); - remainder_offset = (targetOffset & 0xFFF); - - if (targetAddr < QSPI_SECURE_AREA_START_ADDRESS) { - lldbg("out of secure area\n"); -#if USE_MALLOC - free(TempBuffer); -#endif - QSPI_enable_wp(); - return false; - } - - SetBits(rSF_CON, 31, 0x1U, 1U); - SetBits(rSF_CON, 15, 0x1, 1); - - if (((targetAddr - CONFIG_S5J_FLASH_BASE) >> 24) > 0) { - lldbg("Flash Address range over!(24bit range)\n"); -#if USE_MALLOC - free(TempBuffer); -#endif - QSPI_enable_wp(); - return false; - } - - QSPI_Secure_Read(aligned_offset, (u32)TempBuffer, aligned_size); - for (i = 0; i < sizeByte; i++) { - *((u8 *)TempBuffer + remainder_offset + i) = *((u8 *)sourceAddr + i); - } - - aligned_addr = wear_leveling(aligned_addr); - if (QSPI_Erase(aligned_addr, aligned_size) == false) { -#if USE_MALLOC - free(TempBuffer); -#endif - QSPI_enable_wp(); - return false; - } - - copy4B(aligned_addr, (u32)TempBuffer, aligned_size); - arch_flush_dcache(aligned_addr, (aligned_addr + aligned_size)); -#if USE_MALLOC - free(TempBuffer); -#endif - QSPI_enable_wp(); - - return true; -} - -u32 QSPI_Secure_Write_WL(u32 targetOffset, u32 sourceAddr, u32 sizeByte) -{ - u32 targetAddr; - targetAddr = g_base_address + targetOffset; - - if (targetAddr < QSPI_SECURE_AREA_START_ADDRESS) { - lldbg("out of secure area: 0x%x\n", targetAddr); - return false; - } - - SetBits(rSF_CON, 31, 0x1U, 1U); - SetBits(rSF_CON, 15, 0x1, 1); - - if (((targetAddr - CONFIG_S5J_FLASH_BASE) >> 24) > 0) { - lldbg("Flash Address range over!(24bit range)\n"); - return false; - } - - if ((targetAddr & 0xFFF) != 0) { - return false; - } - - targetAddr = wear_leveling(targetAddr); + reg = (HW_REG32(0x80310000, 0x04) & ~(0x1 << 31)) >> 31; + } while (reg); - if (QSPI_Erase(targetAddr, sizeByte) == false) { - return false; - } - - copy4B(targetAddr, sourceAddr, sizeByte); - - return true; -} - -u32 QSPI_Secure_Write_NoWL(u32 targetOffset, u32 sourceAddr, u32 sizeByte) -{ - u32 targetAddr; - targetAddr = g_base_address + targetOffset; - - if (targetAddr < QSPI_SECURE_AREA_START_ADDRESS) { - lldbg("out of secure area: 0x%x\n", targetAddr); - return false; - } - - SetBits(rSF_CON, 31, 0x1U, 1U); - SetBits(rSF_CON, 15, 0x1, 1); - - if (((targetAddr - CONFIG_S5J_FLASH_BASE) >> 24) > 0) { - lldbg("Flash Address range over!(24bit range)\n"); - return false; - } - - if ((targetAddr & 0xFFF) != 0) { - return false; - } - - if (QSPI_Erase(targetAddr, sizeByte) == false) { - return false; - } - - copy4B(targetAddr, sourceAddr, sizeByte); - - return true; -} - -u32 Nv_Write(u32 targetAddr, u32 sourceAddr, u32 sizeByte) -{ - if ((targetAddr < CONFIG_NVRAM_WIFI_START) - || ((targetAddr + sizeByte) > (CONFIG_NVRAM_WIFI_START + 8 * 1024)) - || (sizeByte > (8 * 1024))) { - lldbg("Unable to access\n"); - return false; - } - - //Disable WP(Write Protect) - SetBits(rSF_CON, 31, 0x1U, 1U); - - //Page Programming - SetBits(rSF_CON, 15, 0x1, 1); - - // Checks Address range (16MB) - if (((targetAddr - CONFIG_S5J_FLASH_BASE) >> 24) > 0) { // 16MB - lldbg("Flash Address range over!(24bit range)\n"); - return false; - } - - memcpy((void *)targetAddr, (void *)sourceAddr, sizeByte); - arch_flush_dcache(CONFIG_NVRAM_WIFI_START, CONFIG_NVRAM_WIFI_START + 8 * 1024); - - return true; -} - -u32 Nv_Read(u32 targetAddr, u32 sourceAddr, u32 sizeByte) -{ - if ((sourceAddr < CONFIG_NVRAM_WIFI_START) - || ((sourceAddr + sizeByte) > (CONFIG_NVRAM_WIFI_START + 8 * 1024)) - || (sizeByte > (8 * 1024))) { - lldbg("Unable to access\n"); - return false; - } - - memcpy((void *)targetAddr, (void *)sourceAddr, sizeByte); - return true; -} - -u32 Nv_Erase(u32 targetAddr, u32 sizeByte) -{ - if ((targetAddr < CONFIG_NVRAM_WIFI_START) - || ((targetAddr + sizeByte) > (CONFIG_NVRAM_WIFI_START + 8 * 1024)) - || (sizeByte > (8 * 1024))) { - lldbg("Unable to access\n"); - return false; - } - - //Disable WP(Write Protect) - SetBits(rSF_CON, 31, 0x1U, 1U); - - //Page Programming - SetBits(rSF_CON, 15, 0x1, 1); - - // Checks Address range (16MB) - if (((targetAddr - CONFIG_S5J_FLASH_BASE) >> 24) > 0) { // 16MB - lldbg("Flash Address range over!(24bit range)\n"); - return false; - } - //Checks sector(4KB) align - if ((targetAddr & 0xFFF) != 0) { - lldbg("4KB alignment failure\n"); - return false; - } - - arch_flush_dcache(CONFIG_NVRAM_WIFI_START, CONFIG_NVRAM_WIFI_START + 8 * 1024); - - //should be erased before writing. - if (QSPI_Erase(targetAddr, sizeByte) == false) { - lldbg("Erase Failure\n"); - return false; - } - - return true; -} - -void QSPI_Set_User_Instruction(u8 command) -{ - SetBits(rCOMMAND2, 24, 0xFFU, command); -} - -static void qspi_open(void) -{ - -} - -static void qspi_close(void) -{ - -} - -static ssize_t qspi_read(FAR struct file *filep, FAR char *buffer, size_t buflen) -{ - - return 0; -} - -static ssize_t qspi_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) -{ - return 0; -} - -ssize_t qspi_Wtest(void) -{ - systime_t start = 0; - systime_t elapsed = 0; - int i; - - start = clock_systimer(); - for (i = 0; i < 128; i++) { - QSPI_Write(0x4500000 + (DATA_SIZE * i), (u32)&a[0], DATA_SIZE); - } - elapsed = clock_systimer() - start; - qspitest("w: %d\n", elapsed); - return 0; -} - -ssize_t qspi_Rtest(void) -{ - systime_t start = 0; - systime_t elapsed = 0; - int i; - - for (i = 0; i < DATA_SIZE; i++) { - b[i] = 0; - } - - start = clock_systimer(); - for (i = 0; i < 128; i++) { - QSPI_Read(0x4500000 + (DATA_SIZE * i), (u32)&b[0], DATA_SIZE); - } - elapsed = clock_systimer() - start; - qspitest("r: %d\n", elapsed); - - for (i = 0; i < 8; i++) { - qspitest("0x%x, ", b[i]); - } - return 0; -} - -ssize_t qspi_Etest(void) -{ - systime_t start = 0; - systime_t elapsed = 0; - int i; - - start = clock_systimer(); - for (i = 0; i < 256; i++) { //4K - QSPI_Erase(0x4500000 + (DATA_SIZE * i), DATA_SIZE); - } - for (i = 0; i < 128; i++) { //16K - QSPI_Erase(0x4500000 + (4 * DATA_SIZE * i), (4 * DATA_SIZE)); - } - for (i = 0; i < 64; i++) { //32K - QSPI_Erase(0x4600000 + (8 * DATA_SIZE * i), (8 * DATA_SIZE)); - } - for (i = 0; i < 32; i++) { //64K - QSPI_Erase(0x4600000 + (16 * DATA_SIZE * i), (16 * DATA_SIZE)); - } - elapsed = clock_systimer() - start; - qspitest("\ne: %d\n", elapsed); - return 0; + HW_REG32(0x80310000, 0x04) &= ~(0x1 << 31); + HW_REG32(0x80310000, 0x04) |= (0x1 << 31); } -#if 1 -ssize_t qspi_Secure_Wtest(void) +/** +* +* @brief enable write protection of FLASH +* @param void +* @return void +* @note +*/ +void s5j_qspi_enable_wp(void) { - uint32_t start = 0; - uint32_t elapsed = 0; - int i; - - start = clock_systimer(); - for (i = 0; i < 23; i++) - //QSPI_Secure_Write((DATA_SIZE*i), (u32)&a[0], DATA_SIZE); - { - QSPI_Secure_Write_WL((DATA_SIZE * i), (u32)&a[0], DATA_SIZE); - } - elapsed = clock_systimer() - start; - qspitest("secure w: %d\n", elapsed); - return 0; + HW_REG32(0x80310000, 0x04) &= ~(0x1 << 31); + sem_post(&count_sem); } -ssize_t qspi_Secure_Rtest(void) +/** +* +* @brief semaphore for FLASH access transaction +* @param void +* @return void +* @note +*/ +void s5j_qspi_take_sem(void) { - uint32_t start = 0; - uint32_t elapsed = 0; - int i; - - for (i = 0; i < DATA_SIZE; i++) { - b[i] = 0; + while (sem_wait(&count_sem) != OK) { + ASSERT(errno == EINTR); } - - start = clock_systimer(); - for (i = 0; i < 23; i++) - //QSPI_Secure_Read((DATA_SIZE*i), (u32)&b[0], DATA_SIZE); - { - QSPI_Secure_Read_WL((DATA_SIZE * i), (u32)&b[0], DATA_SIZE); - } - elapsed = clock_systimer() - start; - qspitest("secure r: %d\n", elapsed); - - for (i = 0; i < 8; i++) { - qspitest("%d, ", b[i]); - } - return 0; } -#endif -static long qspi_ioctl(struct file *filep, int cmd, unsigned long arg) +/** +* +* @brief semaphore for FLASH access transaction +* @param void +* @return void +* @note +*/ +void s5j_qspi_release_sem(void) { - u32 data; - u32 vendor_id = 0; - u8 tempBuffer[DATA_SIZE] = { 0 }; - int i; - - switch (cmd) { - case QSPI_READ_INFO: - qspitest("\n: 0x%x, 0x%x, 0x%x", QSPI_SIZE_4KB, QSPI_SIZE_32KB, QSPI_SIZE_64KB); - qspitest("0x%x\n", QSPI_SECURE_AREA_START_ADDRESS); - qspitest("0x%x\n", QSPI_FLASH_END_ADDRESS); - - data = Inp32(rSF_CON); - qspitest("0x%x: 0x%x\n", rSF_CON, data); - data = Inp32(rERASE_ADDRESS); - qspitest("0x%x: 0x%x\n", rERASE_ADDRESS, data); - data = Inp32(rCOMMAND1); - qspitest("0x%x: 0x%x\n", rCOMMAND1, data); - data = Inp32(rCOMMAND2); - qspitest("0x%x: 0x%x\n", rCOMMAND2, data); - data = Inp32(rCOMMAND3); - qspitest("0x%x: 0x%x\n", rCOMMAND3, data); - data = Inp32(rCOMMAND4); - qspitest("0x%x: 0x%x\n", rCOMMAND4, data); - data = Inp32(rCOMMAND5); - qspitest("0x%x: 0x%x\n", rCOMMAND5, data); - data = Inp32(rRDID); - qspitest("0x%x: 0x%x\n", rRDID, data); - data = Inp32(rCOMMAND5); - qspitest("0x%x: 0x%x\n", rRDSR, data); - - break; - case QSPI_READ_ID: - QSPI_Read_ID(&vendor_id); - qspitest("vendor_id 0x%x\n", vendor_id); - break; - - case QSPI_FEATURE_TEST: - qspitest("Disable Write\n"); - QSPI_Set_WriteMode(QSPI_WRDI, 0x04); - qspitest("Enable Write\n"); - QSPI_Set_WriteMode(QSPI_WREN, 0x06); - qspitest("Reset Write Status Register\n"); - QSPI_Set_WriteMode(QSPI_WRSR, 0x01); - - qspitest("Write\n"); - qspi_Wtest(); - - qspitest("Normal Read\n"); - QSPI_Set_ReadMode(QSPI_SINGLE_IO, 0x03); - data = Inp32(rCOMMAND5); - qspitest("0x%x: 0x%x\n", rCOMMAND5, data); - data = Inp32(rFLASH_IO_MODE); - qspitest("0x%x: 0x%x\n", rFLASH_IO_MODE, data); - data = Inp32(rFLASH_PERF_MODE); - qspitest("0x%x: 0x%x\n", rFLASH_PERF_MODE, data); - qspi_Rtest(); - - qspitest("FAST READ\n"); - QSPI_Set_ReadMode(QSPI_SINGLE_IO, 0x0B); - data = Inp32(rCOMMAND5); - qspitest("0x%x: 0x%x\n", rCOMMAND5, data); - SetBits(rFLASH_IO_MODE, 0, 0xF, 0x1); - data = Inp32(rFLASH_IO_MODE); - qspitest("0x%x: 0x%x\n", rFLASH_IO_MODE, data); - data = Inp32(rFLASH_PERF_MODE); - qspitest("0x%x: 0x%x\n", rFLASH_PERF_MODE, data); - qspi_Rtest(); - - qspitest("X2 FAST READ\n"); - QSPI_Set_ReadMode(QSPI_DUAL_FAST, 0x3B); - data = Inp32(rCOMMAND5); - qspitest("0x%x: 0x%x\n", rCOMMAND5, data); - data = Inp32(rFLASH_IO_MODE); - qspitest("0x%x: 0x%x\n", rFLASH_IO_MODE, data); - data = Inp32(rFLASH_PERF_MODE); - qspitest("0x%x: 0x%x\n", rFLASH_PERF_MODE, data); - qspi_Rtest(); - - qspitest("X4 FAST READ\n"); - QSPI_Set_ReadMode(QSPI_QUAD_FAST, 0x6B); - data = Inp32(rCOMMAND5); - qspitest("0x%x: 0x%x\n", rCOMMAND5, data); - data = Inp32(rFLASH_IO_MODE); - qspitest("0x%x: 0x%x\n", rFLASH_IO_MODE, data); - data = Inp32(rFLASH_PERF_MODE); - qspitest("0x%x: 0x%x\n", rFLASH_PERF_MODE, data); - qspi_Rtest(); - - qspitest("X2 IO FAST READ\n"); - QSPI_Set_ReadMode(QSPI_DUAL_IO, 0xBB); - data = Inp32(rCOMMAND5); - qspitest("0x%x: 0x%x\n", rCOMMAND5, data); - data = Inp32(rFLASH_IO_MODE); - qspitest("0x%x: 0x%x\n", rFLASH_IO_MODE, data); - data = Inp32(rFLASH_PERF_MODE); - qspitest("0x%x: 0x%x\n", rFLASH_PERF_MODE, data); - qspi_Rtest(); - - qspitest("X4 IO FAST READ\n"); - QSPI_Set_ReadMode(QSPI_QUAD_IO, 0xEB); - data = Inp32(rCOMMAND5); - qspitest("0x%x: 0x%x\n", rCOMMAND5, data); - data = Inp32(rFLASH_IO_MODE); - qspitest("0x%x: 0x%x\n", rFLASH_IO_MODE, data); - data = Inp32(rFLASH_PERF_MODE); - qspitest("0x%x: 0x%x\n", rFLASH_PERF_MODE, data); - qspi_Rtest(); - - break; - - case QSPI_SECURE_TEST: - qspitest("\nSecure Write\n"); - - for (i = 0; i < 30; i++) { - qspi_Secure_Wtest(); - } - - qspitest("Normal Read\n"); - QSPI_Set_ReadMode(QSPI_SINGLE_IO, 0x03); - data = Inp32(rCOMMAND5); - qspitest("0x%x: 0x%x\n", rCOMMAND5, data); - data = Inp32(rFLASH_IO_MODE); - qspitest("0x%x: 0x%x\n", rFLASH_IO_MODE, data); - data = Inp32(rFLASH_PERF_MODE); - qspitest("0x%x: 0x%x\n", rFLASH_PERF_MODE, data); - qspi_Secure_Rtest(); - - break; - - case QSPI_ERASE_TEST: - SetBits(rSF_CON, 31, 0x1U, 1U); - SetBits(rSF_CON, 15, 0x1, 1); - - qspi_Etest(); - /* QSPI_Chip_Erase(); */ - - break; - - case QSPI_RESET_WL_CTR: - - g_base_address = QSPI_SECURE_AREA_START_ADDRESS_A; - QSPI_Secure_Write_NoWL(2 * QSPI_SECURE_AREA_SIZE, (u32)tempBuffer, DATA_SIZE); - - break; - - default: - break; - } - - return 0; + sem_post(&count_sem); } -void QSPI_print_mode(void) +/** +* +* @brief initialize FLASH for QUAD IO in 80Mhz +* @param void +* @return void +* @note +*/ +void s5j_qspi_init(void) { -#ifdef CONFIG_DEBUG - int data; - bool bwp = (Inp32(rSF_CON) & (0x1 << 31)) >> 31; - data = Inp32(rFLASH_IO_MODE); - data &= 0xf; + /* Set mix i/o to be FLASH signal, CLK/CS/SI/SO/WP/HOLD */ + s5j_qspi_set_gpio(); - switch (data) { - case 0x4: - lldbg("FLASH IO MODE [QUAD_FAST_READ], WP[%s]\n", (bwp) ? "disable" : "enable"); - break; + HW_REG32(0x80310000, 0x04) = 0x8010001A; /* disable WP */ + HW_REG32(0x80310000, 0x78) = 0x8; /* FLASH_IO_MODE */ + HW_REG32(0x80310000, 0x74) = 0x4; /* QUAD */ - case 0x2: - lldbg("FLASH IO MODE [DUAL_FAST_READ], WP[%s]\n", (bwp) ? "disable" : "enable"); - break; + while (!(HW_REG8(0x80310000, 0xDC) & (0x1 << 6))) ; /* Check FLASH has Quad Enabled */ + lldbg("FLASH Quad Enabled\n"); - case 0x1: - lldbg("FLASH IO MODE [FAST_READ], WP[%s]\n", (bwp) ? "disable" : "enable"); - break; + s5j_qspi_get_status_register(); + HW_REG32(0x80310000, 0x04) = 0x0010001A; /* Enable WP */ - case 0x0: - lldbg("FLASH IO MODE [NORMAL_READ], WP[%s]\n", (bwp) ? "disable" : "enable"); - break; - default: - lldbg("FLASH IO MODE [UNKNOWN]\n"); - break; - } -#endif -} + /* Set FLASH clk 80Mhz for Max performance */ + cal_clk_setrate(d1_serialflash, 80000000); -/** - * - * @brief Register the QSPI devices file - * @param void - * @return void - * @note - */ -void qspi_register(void) -{ - register_blockdriver("/dev/nor", (FAR const struct block_operations *)&drv_fops, 0666, NULL); + sem_init(&count_sem, 0, 1); } diff --git a/os/arch/arm/src/s5j/s5j_qspi.h b/os/arch/arm/src/s5j/s5j_qspi.h index 4be54d6..f82c831 100644 --- a/os/arch/arm/src/s5j/s5j_qspi.h +++ b/os/arch/arm/src/s5j/s5j_qspi.h @@ -59,21 +59,10 @@ #define QSPI_DUMMY_DATA 0x1 -#define QSPI_SECTOR_OFFSET (12) -#define QSPI_BLOCK32K_OFFSET (15) -#define QSPI_BLOCK64K_OFFSET (16) - #define QSPI_SIZE_64KB (1<