/*************************************************************************** * * Copyright 2015-2019 BES. * All rights reserved. All unpublished rights reserved. * * No part of this work may be used or reproduced in any form or by any * means, or stored in a database or retrieval system, without prior written * permission of BES. * * Use of this work is governed by a license granted by BES. * This work contains confidential and proprietary information of * BES. which is protected by copyright, trade secret, * trademark and other intellectual property rights. * ****************************************************************************/ #if (CHIP_FLASH_CTRL_VER >= 2) #include "cmsis.h" #include "hal_norflaship.h" #include "plat_addr_map.h" #include "plat_types.h" #include "reg_norflaship_v2.h" #ifdef PROGRAMMER #include "task_schedule.h" #else #define TASK_SCHEDULE true #endif //==================================================================================== // Flash IP Operations //==================================================================================== /* Supported Command List (Based on GD25Q32C): parameter WRSR1 = 8'h01 ; parameter PP = 8'h02 ; parameter READ = 8'h03 ; parameter WRDI = 8'h04 ; parameter RDSR1 = 8'h05 ; parameter WREN = 8'h06 ; parameter FREAD = 8'h0B ; parameter WRSR3 = 8'h11 ; parameter RDSR3 = 8'h15 ; parameter SE = 8'h20 ; parameter WRSR2 = 8'h31 ; parameter QPP = 8'h32 ; parameter RDSR2 = 8'h35 ; parameter DOR = 8'h3B ; parameter PSR = 8'h42 ; parameter ESR = 8'h44 ; parameter RSR = 8'h48 ; parameter WEVSR = 8'h50 ; parameter BE32 = 8'h52 ; parameter RSFDP = 8'h5A ; parameter CE = 8'h60 ; parameter RSTE = 8'h66 ; parameter QOR = 8'h6B ; parameter PES = 8'h75 ; parameter SBW = 8'h77 ; parameter PER = 8'h7A ; parameter REMS = 8'h90 ; parameter DREAD_ID = 8'h92 ; parameter QREAD_ID = 8'h94 ; parameter RST = 8'h99 ; parameter RDID = 8'h9F ; parameter HPM = 8'hA3 ; parameter RDI = 8'hAB ; parameter DP = 8'hB9 ; parameter DIOR = 8'hBB ; parameter BE64 = 8'hD8 ; parameter QIOWR = 8'hE7 ; parameter QIOR = 8'hEB ; parameter FPP = 8'hF2 ; */ static struct NORFLASH_CTRL_T *const norflash = (struct NORFLASH_CTRL_T *)FLASH_CTRL_BASE; #if 0 static const uint8_t line_mode[8] = { NEW_CMD_LINE_1X, NEW_CMD_LINE_1X, NEW_CMD_LINE_2X, NEW_CMD_LINE_1X, NEW_CMD_LINE_4X, NEW_CMD_LINE_1X, NEW_CMD_LINE_1X, NEW_CMD_LINE_1X, }; #endif uint8_t norflaship_continuous_read_mode_bit(uint8_t mode_bit) { norflaship_busy_wait(); norflash->REG_004 = SET_BITFIELD(norflash->REG_004, REG_004_MODEBIT, mode_bit); return 0; } uint8_t norflaship_continuous_read_off(void) { norflaship_busy_wait(); norflash->REG_004 &= ~REG_004_CONTINUOUS_MODE; return 0; } uint8_t norflaship_continuous_read_on(void) { norflaship_busy_wait(); norflash->REG_004 |= REG_004_CONTINUOUS_MODE; return 0; } uint8_t norflaship_read_txfifo_empty_count(void) { return GET_BITFIELD(norflash->REG_00C, REG_00C_TXFIFO_EMPCNT); } uint32_t norflaship_write_txfifo(const uint8_t *val, uint32_t len) { uint32_t avail = norflaship_read_txfifo_empty_count(); while (len > 0 && avail > 0) { #if 0 if (len >= 4 && ((uint32_t)val & 3) == 0) { norflash->REG_008.TXWORD = *(uint32_t *)val; val += 4; len -= 4; } else if (len >= 2 && ((uint32_t)val & 1) == 0) { norflash->REG_008.TXHALFWORD = *(uint16_t *)val; val += 2; len -= 2; } else #endif { norflash->REG_008.TXBYTE = *(uint8_t *)val; val += 1; len -= 1; } avail -= 1; } return len; } uint8_t norflaship_read_rxfifo_count(void) { return GET_BITFIELD(norflash->REG_00C, REG_00C_RXFIFO_COUNT); } uint8_t norflaship_read_rxfifo(void) { return norflash->REG_010; } void norflaship_blksize(uint32_t blksize) { norflash->REG_004 = SET_BITFIELD(norflash->REG_004, REG_004_BLOCK_SIZE, blksize); } void norflaship_cmd_addr(uint8_t cmd, uint32_t address) { norflaship_busy_wait(); norflash->REG_004 &= ~REG_004_NEW_CMD_EN; norflash->REG_000 = REG_000_CMD(cmd) | REG_000_ADDR(address); } void norflaship_ext_tx_cmd(uint8_t cmd, uint32_t tx_len) { norflaship_busy_wait(); norflash->REG_004 = SET_BITFIELD(norflash->REG_004, REG_004_BLOCK_SIZE, tx_len) | REG_004_NEW_CMD_EN; norflash->REG_000 = REG_000_CMD(cmd); } void norflaship_ext_rx_cmd(uint8_t cmd, uint32_t tx_len, uint32_t rx_len) { norflaship_busy_wait(); norflash->REG_004 = SET_BITFIELD(norflash->REG_004, REG_004_BLOCK_SIZE, tx_len) | REG_004_NEW_CMD_EN; norflash->REG_000 = REG_000_CMD(cmd) | REG_000_NEW_CMD_RX_EN | REG_000_NEW_CMD_RX_LEN(rx_len); } void norflaship_cmd_done(void) { norflaship_busy_wait(); norflash->REG_004 &= ~REG_004_NEW_CMD_EN; } void norflaship_rxfifo_count_wait(uint8_t cnt) { while ((norflaship_read_rxfifo_count() < cnt) && TASK_SCHEDULE) ; } void norflaship_rxfifo_empty_wait(void) { while ((norflash->REG_00C & REG_00C_RXFIFO_EMPTY) && TASK_SCHEDULE) ; } int norflaship_txfifo_is_full(void) { return !!(norflash->REG_00C & REG_00C_TXFIFO_FULL); } void norflaship_busy_wait(void) { while ((norflash->REG_00C & REG_00C_BUSY) && TASK_SCHEDULE) ; } int norflaship_is_busy(void) { return !!(norflash->REG_00C & REG_00C_BUSY); } void norflaship_clear_fifos(void) { norflaship_busy_wait(); norflash->REG_018 = REG_018_TXFIFOCLR | REG_018_RXFIFOCLR; norflaship_busy_wait(); } void norflaship_clear_rxfifo(void) { norflaship_busy_wait(); norflash->REG_018 = REG_018_RXFIFOCLR; norflaship_busy_wait(); } void norflaship_clear_txfifo(void) { norflaship_busy_wait(); norflash->REG_018 = REG_018_TXFIFOCLR; norflaship_busy_wait(); } void norflaship_div(uint32_t div) { norflaship_busy_wait(); #ifdef CHIP_BEST2300P norflash->REG_014 = SET_BITFIELD(norflash->REG_014, REG_014_CLKDIV, div) | EXTRA_TCHSH_EN_O; #else norflash->REG_014 = SET_BITFIELD(norflash->REG_014, REG_014_CLKDIV, div); #endif } uint32_t norflaship_get_div(void) { return GET_BITFIELD(norflash->REG_014, REG_014_CLKDIV); } void norflaship_cmdquad(uint32_t v) { norflaship_busy_wait(); #ifdef CHIP_BEST2300P if (v) { norflash->REG_014 |= REG_014_CMDQUAD | EXTRA_TCHSH_EN_O; } else { norflash->REG_014 = (norflash->REG_014 & ~REG_014_CMDQUAD) | EXTRA_TCHSH_EN_O; } #else if (v) { norflash->REG_014 |= REG_014_CMDQUAD; } else { norflash->REG_014 &= ~REG_014_CMDQUAD; } #endif } uint32_t norflaship_get_samdly(void) { return GET_BITFIELD(norflash->REG_014, REG_014_SAMPLESEL); } void norflaship_samdly(uint32_t v) { norflaship_busy_wait(); #ifdef CHIP_BEST2300P norflash->REG_014 = SET_BITFIELD(norflash->REG_014, REG_014_SAMPLESEL, v) | EXTRA_TCHSH_EN_O; #else norflash->REG_014 = SET_BITFIELD(norflash->REG_014, REG_014_SAMPLESEL, v); #endif } void norflaship_dual_mode(uint32_t v) { norflaship_busy_wait(); #ifdef CHIP_BEST2300P if (v) { norflash->REG_014 |= REG_014_RAM_DUALMODE | EXTRA_TCHSH_EN_O; } else { norflash->REG_014 = (norflash->REG_014 & ~REG_014_RAM_DUALMODE) | EXTRA_TCHSH_EN_O; } #else if (v) { norflash->REG_014 |= REG_014_RAM_DUALMODE; } else { norflash->REG_014 &= ~REG_014_RAM_DUALMODE; } #endif } void norflaship_hold_pin(uint32_t v) { #ifdef CHIP_BEST2300P if (v) { norflash->REG_014 |= REG_014_HOLDPIN | EXTRA_TCHSH_EN_O; } else { norflash->REG_014 = (norflash->REG_014 & ~REG_014_HOLDPIN) | EXTRA_TCHSH_EN_O; } #else if (v) { norflash->REG_014 |= REG_014_HOLDPIN; } else { norflash->REG_014 &= ~REG_014_HOLDPIN; } #endif } void norflaship_wpr_pin(uint32_t v) { #ifdef CHIP_BEST2300P if (v) { norflash->REG_014 |= REG_014_WPROPIN | EXTRA_TCHSH_EN_O; } else { norflash->REG_014 = (norflash->REG_014 & ~REG_014_WPROPIN) | EXTRA_TCHSH_EN_O; } #else if (v) { norflash->REG_014 |= REG_014_WPROPIN; } else { norflash->REG_014 &= ~REG_014_WPROPIN; } #endif } void norflaship_quad_mode(uint32_t v) { norflaship_busy_wait(); #ifdef CHIP_BEST2300P if (v) { norflash->REG_014 |= REG_014_RAM_QUADMODE | EXTRA_TCHSH_EN_O; } else { norflash->REG_014 = (norflash->REG_014 & ~REG_014_RAM_QUADMODE) | EXTRA_TCHSH_EN_O; } #else if (v) { norflash->REG_014 |= REG_014_RAM_QUADMODE; } else { norflash->REG_014 &= ~REG_014_RAM_QUADMODE; } #endif } void norflaship_addrbyte4(uint32_t v) { #ifdef CHIP_BEST2300P if (v) { norflash->REG_014 |= REG_014_FOUR_BYTE_ADDR_EN | EXTRA_TCHSH_EN_O; } else { norflash->REG_014 = (norflash->REG_014 & ~REG_014_FOUR_BYTE_ADDR_EN) | EXTRA_TCHSH_EN_O; } #else if (v) { norflash->REG_014 |= REG_014_FOUR_BYTE_ADDR_EN; } else { norflash->REG_014 &= ~REG_014_FOUR_BYTE_ADDR_EN; } #endif } void norflaship_ruen(uint32_t v) { norflash->REG_034 = SET_BITFIELD(norflash->REG_034, REG_034_SPI_RUEN, v); } void norflaship_rden(uint32_t v) { norflash->REG_034 = SET_BITFIELD(norflash->REG_034, REG_034_SPI_RDEN, v); } void norflaship_dualiocmd(uint32_t v) { norflash->REG_020 = SET_BITFIELD(norflash->REG_020, REG_020_DUALCMD, v); } void norflaship_rdcmd(uint32_t v) { norflash->REG_020 = SET_BITFIELD(norflash->REG_020, REG_020_READCMD, v); } void norflaship_frdcmd(uint32_t v) { norflash->REG_020 = SET_BITFIELD(norflash->REG_020, REG_020_FREADCMD, v); } void norflaship_qrdcmd(uint32_t v) { norflash->REG_020 = SET_BITFIELD(norflash->REG_020, REG_020_QUADCMD, v); } uint32_t norflaship_get_rdcmd(void) { return GET_BITFIELD(norflash->REG_020, REG_020_READCMD); } void norflaship_set_idle_io_dir(uint32_t v) { #ifdef NORFLASHIP_HAS_IDLE_IO_CTRL norflash->REG_034 = SET_BITFIELD(norflash->REG_034, REG_034_SPI_IOEN, v); #endif } void norflaship_sleep(void) { #ifndef NORFLASHIP_HAS_IDLE_IO_CTRL norflash->REG_034 |= REG_034_SPI_IORES(1 << 2); #endif } void norflaship_wakeup(void) { #ifndef NORFLASHIP_HAS_IDLE_IO_CTRL norflash->REG_034 &= ~REG_034_SPI_IORES(1 << 2); #endif } void norflaship_dec_index(uint32_t idx) { #ifdef NORFLASHIP_HAS_SECURITY norflash->REG_058 = SET_BITFIELD(norflash->REG_058, REG_058_IDX, idx); #endif } void norflaship_dec_saddr(uint32_t addr) { #ifdef NORFLASHIP_HAS_SECURITY norflash->REG_060 = ((addr & 0x000000ff) << 24) | ((addr & 0x0000ff00) << 8) | ((addr & 0x00ff0000) >> 8) | ((addr & 0xff000000) >> 24); #endif } void norflaship_dec_eaddr(uint32_t addr) { #ifdef NORFLASHIP_HAS_SECURITY norflash->REG_064 = ((addr & 0x000000ff) << 24) | ((addr & 0x0000ff00) << 8) | ((addr & 0x00ff0000) >> 8) | ((addr & 0xff000000) >> 24); #endif } void norflaship_dec_enable(void) { #ifdef NORFLASHIP_HAS_SECURITY norflash->REG_06C |= REG_06C_DEC_ENABLE; #endif } void norflaship_dec_disable(void) { #ifdef NORFLASHIP_HAS_SECURITY norflash->REG_06C &= ~REG_06C_DEC_ENABLE; #endif } void norflaship_man_wrap_width(uint32_t width) { #ifdef NORFLASHIP_HAS_SECURITY int bits = 0; if (width == 8) bits = 0; else if (width == 16) bits = 1; else if (width == 32) bits = 2; else if (width == 64) bits = 3; else bits = 1; norflash->REG_038 = SET_BITFIELD(norflash->REG_038, REG_038_MAN_WRAP_BITS, bits); #endif } void norflaship_man_wrap_enable(void) { #ifdef NORFLASHIP_HAS_SECURITY norflash->REG_038 |= REG_038_MAN_WRAP_ENABLE; #endif } void norflaship_man_wrap_disable(void) { #ifdef NORFLASHIP_HAS_SECURITY norflash->REG_038 &= ~REG_038_MAN_WRAP_ENABLE; #endif } void norflaship_auto_wrap_cmd(uint32_t cmd) { #ifdef NORFLASHIP_HAS_SECURITY norflash->REG_038 = SET_BITFIELD(norflash->REG_038, REG_038_AUTO_WRAP_CMD, cmd); #endif } void norflaship_man_mode_enable(void) { #ifdef NORFLASHIP_HAS_SECURITY norflash->REG_038 |= REG_038_WRAP_MODE_SEL; #endif } void norflaship_man_mode_disable(void) { #ifdef NORFLASHIP_HAS_SECURITY norflash->REG_038 &= ~REG_038_WRAP_MODE_SEL; #endif } int norflaship_config_remap_section(uint32_t id, uint32_t addr, uint32_t len, uint32_t new_addr) { #ifdef NORFLASHIP_HAS_REMAP __IO uint32_t *start, *end, *to; if (id >= 4) { return 1; } if (len == 0) { norflash->REG_0B0 &= ~(REG_0B0_ADDR0_REMAP_EN << id); return 0; } if (addr & (REMAP_SECTOR_SIZE - 1)) { return 2; } if (new_addr & (REMAP_SECTOR_SIZE - 1)) { return 3; } if (len < REMAP_SECTOR_SIZE) { return 4; } #ifdef CHIP_BEST2300P if (len & (len - 1)) { return 5; } uint32_t len_idx; len_idx = __CLZ(__RBIT(len)) - 9; norflash->REG_0A0 = (norflash->REG_0A0 & ~(REG_0A0_LEN_WIDTH0_MASK << (id * REG_0A0_LEN_WIDTH1_SHIFT))) | (REG_0A0_LEN_WIDTH0(len_idx) << (id * REG_0A0_LEN_WIDTH1_SHIFT)); #else if (len & (REMAP_SECTOR_SIZE - 1)) { return 5; } #endif start = &norflash->REG_070 + id; end = &norflash->REG_080 + id; to = &norflash->REG_090 + id; *start = addr; *end = addr + len - 1; *to = new_addr; norflash->REG_0B0 |= (REG_0B0_ADDR0_REMAP_EN << id); return 0; #else return -1; #endif } void norflaship_enable_remap(void) { #ifdef NORFLASHIP_HAS_REMAP norflash->REG_0B0 |= REG_0B0_GLB_REMAP_EN; #endif } void norflaship_disable_remap(void) { #ifdef NORFLASHIP_HAS_REMAP norflash->REG_0B0 &= ~REG_0B0_GLB_REMAP_EN; #endif } int norflaship_get_remap_status(void) { #ifdef NORFLASHIP_HAS_REMAP return (norflash->REG_0B0 & REG_0B0_GLB_REMAP_EN) ? true : false; #else return false; #endif } #if (CHIP_FLASH_CTRL_VER >= 3) void norflaship_dummy_others(uint32_t v) { norflash->REG_150 = REG_150_DUMMY_OTHERS(v); } #endif void norflaship_fetch_disable() { norflash->REG_02C &= ~REG_02C_FETCH_EN; } #endif