From ef3c8507a6ba056da7bc6a6eee0b686800493f20 Mon Sep 17 00:00:00 2001 From: Tim Lin Date: Fri, 25 Dec 2020 18:23:44 +0800 Subject: [PATCH] ite: drivers/flash: add flash driver for it8xxx2 Add flash driver for it8xxx2. The driver can implement flash read, write and erase that will be mapped to the ram section for executing. TEST="flash write 0x80000 0x10 0x20 0x30 0x40 ..." "flash read 0x80000 0x100" "flash erase 0x80000 0x1000" Signed-off-by: Tim Lin --- .../riscv/it8xxx2_evb/it8xxx2_evb_defconfig | 1 + drivers/flash/CMakeLists.txt | 1 + drivers/flash/Kconfig | 2 + drivers/flash/Kconfig.it8xxx2 | 20 + drivers/flash/flash_ite_it8xxx2.c | 597 ++++++++++++++++++ dts/riscv/it8xxx2.dtsi | 8 +- include/arch/riscv/common/linker.ld | 8 + soc/riscv/riscv-ite/common/chip_chipregs.h | 40 ++ 8 files changed, 673 insertions(+), 4 deletions(-) create mode 100644 drivers/flash/Kconfig.it8xxx2 create mode 100644 drivers/flash/flash_ite_it8xxx2.c diff --git a/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig b/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig index 65990932c20..57ca792693b 100644 --- a/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig +++ b/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig @@ -31,3 +31,4 @@ CONFIG_GPIO_ITE_IT8XXX2=y CONFIG_I2C=y CONFIG_I2C_ITE_IT8XXX2=y CONFIG_ADC_ITE_IT8XXX2=y +CONFIG_SOC_FLASH_ITE_IT8XXX2=y diff --git a/drivers/flash/CMakeLists.txt b/drivers/flash/CMakeLists.txt index 33cfe0dff25..9e6f4416830 100644 --- a/drivers/flash/CMakeLists.txt +++ b/drivers/flash/CMakeLists.txt @@ -6,6 +6,7 @@ zephyr_library_sources_ifdef(CONFIG_SPI_NOR spi_nor.c) zephyr_library_sources_ifdef(CONFIG_NORDIC_QSPI_NOR nrf_qspi_nor.c) zephyr_library_sources_ifdef(CONFIG_FLASH_SIMULATOR flash_simulator.c) zephyr_library_sources_ifdef(CONFIG_SPI_FLASH_AT45 spi_flash_at45.c) +zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_ITE_IT8XXX2 flash_ite_it8xxx2.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NRF soc_flash_nrf.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NRF_RADIO_SYNC_TICKER soc_flash_nrf_ticker.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_MCUX soc_flash_mcux.c) diff --git a/drivers/flash/Kconfig b/drivers/flash/Kconfig index fed4509de16..bb8421d1052 100644 --- a/drivers/flash/Kconfig +++ b/drivers/flash/Kconfig @@ -62,6 +62,8 @@ source "drivers/flash/Kconfig.at45" source "drivers/flash/Kconfig.esp32" +source "drivers/flash/Kconfig.it8xxx2" + source "drivers/flash/Kconfig.nrf" source "drivers/flash/Kconfig.lpc" diff --git a/drivers/flash/Kconfig.it8xxx2 b/drivers/flash/Kconfig.it8xxx2 new file mode 100644 index 00000000000..b74c7b0b489 --- /dev/null +++ b/drivers/flash/Kconfig.it8xxx2 @@ -0,0 +1,20 @@ +# FLASH configuration options + +# Copyright (c) 2021 ITE Corporation. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FLASH_ITE_IT8XXX2 + bool "ITE IT8XXX2 flash driver" + depends on SOC_FAMILY_RISCV_ITE + select SOC_FLASH_RAMCODE_SECTION + help + The flash driver includes support for read, write and + erase flash operations. It also supports protection. + The it8xxx2 flash size is 1M byte. + +config SOC_FLASH_RAMCODE_SECTION + bool + help + Enable this config to map the __ram_code section + operations of flash(flash_it8xxx2_erase, + flash_it8xxx2_write, flash_it8xxx2_read) to RAM. diff --git a/drivers/flash/flash_ite_it8xxx2.c b/drivers/flash/flash_ite_it8xxx2.c new file mode 100644 index 00000000000..a01d1c4afa1 --- /dev/null +++ b/drivers/flash/flash_ite_it8xxx2.c @@ -0,0 +1,597 @@ +/* + * Copyright (c) 2021 ITE Corporation. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ite_it8xxx2_flash_controller +#define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash) + +#define FLASH_WRITE_BLK_SZ DT_PROP(SOC_NV_FLASH_NODE, write_block_size) +#define FLASH_ERASE_BLK_SZ DT_PROP(SOC_NV_FLASH_NODE, erase_block_size) + +#include +#include +#include +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_FLASH_LOG_LEVEL +#include +LOG_MODULE_REGISTER(flash_ite_it8xxx2); + +/* RAM code start address */ +extern char _ram_code_start; +#define FLASH_RAMCODE_START ((uint32_t)&_ram_code_start) +#define FLASH_RAMCODE_START_BIT19 BIT(19) +/* RAM code section */ +#define __ram_code __attribute__((section(".__ram_code"))) + +#define FLASH_IT8XXX2_REG_BASE \ + ((struct flash_it8xxx2_regs *)DT_INST_REG_ADDR(0)) + +#define DEV_DATA(dev) \ + ((struct flash_it8xxx2_dev_data *const)(dev)->data) + +struct flash_it8xxx2_dev_data { + struct k_sem sem; + int all_protected; + int flash_static_cache_enabled; +}; + +/* + * One page program instruction allows maximum 256 bytes (a page) of data + * to be programmed. + */ +#define CHIP_FLASH_WRITE_PAGE_MAX_SIZE 256 +/* Program is run directly from storage */ +#define CHIP_MAPPED_STORAGE_BASE DT_REG_ADDR(DT_NODELABEL(flash0)) +/* flash size */ +#define CHIP_FLASH_SIZE_BYTES DT_REG_SIZE(DT_NODELABEL(flash0)) +/* protect bank size */ +#define CHIP_FLASH_BANK_SIZE 0x00001000 +/* base+0000h~base+0FFF */ +#define CHIP_RAMCODE_BASE 0x80100000 + +/* + * This is the block size of the ILM on the it8xxx2 chip. + * The ILM for static code cache, CPU fetch instruction from + * ILM(ILM -> CPU)instead of flash(flash -> I-Cache -> CPU) if enabled. + */ +#define IT8XXX2_ILM_BLOCK_SIZE 0x00001000 + +/* page program command */ +#define FLASH_CMD_PAGE_WRITE 0x2 +/* ector erase command (erase size is 4KB) */ +#define FLASH_CMD_SECTOR_ERASE 0x20 +/* command for flash write */ +#define FLASH_CMD_WRITE FLASH_CMD_PAGE_WRITE +/* Write status register */ +#define FLASH_CMD_WRSR 0x01 +/* Write disable */ +#define FLASH_CMD_WRDI 0x04 +/* Write enable */ +#define FLASH_CMD_WREN 0x06 +/* Read status register */ +#define FLASH_CMD_RS 0x05 + +/* Set FSCE# as high level by writing 0 to address xfff_fe00h */ +#define FLASH_FSCE_HIGH_ADDRESS 0x0FFFFE00 +/* Set FSCE# as low level by writing data to address xfff_fd00h */ +#define FLASH_FSCE_LOW_ADDRESS 0x0FFFFD00 + +#define FWP_REG(bank) (bank / 8) +#define FWP_MASK(bank) (1 << (bank % 8)) + +enum flash_wp_interface { + FLASH_WP_HOST = 0x01, + FLASH_WP_DBGR = 0x02, + FLASH_WP_EC = 0x04, +}; + +enum flash_status_mask { + FLASH_SR_NO_BUSY = 0, + /* Internal write operation is in progress */ + FLASH_SR_BUSY = 0x01, + /* Device is memory Write enabled */ + FLASH_SR_WEL = 0x02, + + FLASH_SR_ALL = (FLASH_SR_BUSY | FLASH_SR_WEL), +}; + +enum flash_transaction_cmd { + CMD_CONTINUE, + CMD_END, +}; + +static const struct flash_parameters flash_it8xxx2_parameters = { + .write_block_size = FLASH_WRITE_BLK_SZ, + .erase_value = 0xff, +}; + +void __ram_code ramcode_reset_i_cache(void) +{ + /* I-Cache tag sram reset */ + IT83XX_GCTRL_MCCR |= IT83XX_GCTRL_ICACHE_RESET; + /* Make sure the I-Cache is reset */ + __asm__ volatile ("fence.i" ::: "memory"); + + IT83XX_GCTRL_MCCR &= ~IT83XX_GCTRL_ICACHE_RESET; + __asm__ volatile ("fence.i" ::: "memory"); +} + +void __ram_code ramcode_flash_follow_mode(void) +{ + struct flash_it8xxx2_regs *const flash_regs = FLASH_IT8XXX2_REG_BASE; + /* + * ECINDAR3-0 are EC-indirect memory address registers. + * + * Enter follow mode by writing 0xf to low nibble of ECINDAR3 register, + * and set high nibble as 0x4 to select internal flash. + */ + flash_regs->SMFI_ECINDAR3 = (EC_INDIRECT_READ_INTERNAL_FLASH | + ((FLASH_FSCE_HIGH_ADDRESS >> 24) & GENMASK(3, 0))); + + /* Set FSCE# as high level by writing 0 to address xfff_fe00h */ + flash_regs->SMFI_ECINDAR2 = (FLASH_FSCE_HIGH_ADDRESS >> 16) & GENMASK(7, 0); + flash_regs->SMFI_ECINDAR1 = (FLASH_FSCE_HIGH_ADDRESS >> 8) & GENMASK(7, 0); + flash_regs->SMFI_ECINDAR0 = FLASH_FSCE_HIGH_ADDRESS & GENMASK(7, 0); + + /* Writing 0 to EC-indirect memory data register */ + flash_regs->SMFI_ECINDDR = 0x00; +} + +void __ram_code ramcode_flash_follow_mode_exit(void) +{ + struct flash_it8xxx2_regs *const flash_regs = FLASH_IT8XXX2_REG_BASE; + + /* Exit follow mode, and keep the setting of selecting internal flash */ + flash_regs->SMFI_ECINDAR3 = EC_INDIRECT_READ_INTERNAL_FLASH; + flash_regs->SMFI_ECINDAR2 = 0x00; +} + +void __ram_code ramcode_flash_fsce_high(void) +{ + struct flash_it8xxx2_regs *const flash_regs = FLASH_IT8XXX2_REG_BASE; + + /* FSCE# high level */ + flash_regs->SMFI_ECINDAR1 = (FLASH_FSCE_HIGH_ADDRESS >> 8) & GENMASK(7, 0); + + /* Writing 0 to EC-indirect memory data register */ + flash_regs->SMFI_ECINDDR = 0x00; +} + +void __ram_code ramcode_flash_write_dat(uint8_t wdata) +{ + struct flash_it8xxx2_regs *const flash_regs = FLASH_IT8XXX2_REG_BASE; + + /* Write data to FMOSI */ + flash_regs->SMFI_ECINDDR = wdata; +} + +void __ram_code ramcode_flash_transaction(int wlen, uint8_t *wbuf, int rlen, + uint8_t *rbuf, + enum flash_transaction_cmd cmd_end) +{ + struct flash_it8xxx2_regs *const flash_regs = FLASH_IT8XXX2_REG_BASE; + int i; + + /* FSCE# with low level */ + flash_regs->SMFI_ECINDAR1 = (FLASH_FSCE_LOW_ADDRESS >> 8) & GENMASK(7, 0); + /* Write data to FMOSI */ + for (i = 0; i < wlen; i++) { + flash_regs->SMFI_ECINDDR = wbuf[i]; + } + /* Read data from FMISO */ + for (i = 0; i < rlen; i++) { + rbuf[i] = flash_regs->SMFI_ECINDDR; + } + /* FSCE# high level if transaction done */ + if (cmd_end == CMD_END) { + ramcode_flash_fsce_high(); + } +} + +void __ram_code ramcode_flash_cmd_read_status(enum flash_status_mask mask, + enum flash_status_mask target) +{ + uint8_t status[1]; + uint8_t cmd_rs[] = {FLASH_CMD_RS}; + + /* + * We prefer no timeout here. We can always get the status + * we want, or wait for watchdog triggered to check + * e-flash's status instead of breaking loop. + * This will avoid fetching unknown instruction from e-flash + * and causing exception. + */ + while (1) { + /* read status */ + ramcode_flash_transaction(sizeof(cmd_rs), cmd_rs, 1, status, CMD_END); + /* only bit[1:0] valid */ + if ((status[0] & mask) == target) { + break; + } + } +} + +void __ram_code ramcode_flash_cmd_write_enable(void) +{ + uint8_t cmd_we[] = {FLASH_CMD_WREN}; + + /* enter EC-indirect follow mode */ + ramcode_flash_follow_mode(); + /* send write enable command */ + ramcode_flash_transaction(sizeof(cmd_we), cmd_we, 0, NULL, CMD_END); + /* read status and make sure busy bit cleared and write enabled. */ + ramcode_flash_cmd_read_status(FLASH_SR_ALL, FLASH_SR_WEL); + /* exit EC-indirect follow mode */ + ramcode_flash_follow_mode_exit(); +} + +void __ram_code ramcode_flash_cmd_write_disable(void) +{ + uint8_t cmd_wd[] = {FLASH_CMD_WRDI}; + + /* enter EC-indirect follow mode */ + ramcode_flash_follow_mode(); + /* send write disable command */ + ramcode_flash_transaction(sizeof(cmd_wd), cmd_wd, 0, NULL, CMD_END); + /* make sure busy bit cleared. */ + ramcode_flash_cmd_read_status(FLASH_SR_ALL, FLASH_SR_NO_BUSY); + /* exit EC-indirect follow mode */ + ramcode_flash_follow_mode_exit(); +} + +int __ram_code ramcode_flash_verify(int addr, int size, const char *data) +{ + int i; + uint8_t *wbuf = (uint8_t *)data; + uint8_t *flash = (uint8_t *)addr; + + /* verify for erase */ + if (data == NULL) { + for (i = 0; i < size; i++) { + if (flash[i] != 0xFF) { + return -EINVAL; + } + } + /* verify for write */ + } else { + for (i = 0; i < size; i++) { + if (flash[i] != wbuf[i]) { + return -EINVAL; + } + } + } + + return 0; +} + +void __ram_code ramcode_flash_cmd_write(int addr, int wlen, uint8_t *wbuf) +{ + int i; + uint8_t flash_write[] = {FLASH_CMD_WRITE, ((addr >> 16) & 0xFF), + ((addr >> 8) & 0xFF), (addr & 0xFF)}; + + /* enter EC-indirect follow mode */ + ramcode_flash_follow_mode(); + /* send flash write command (aai word or page program) */ + ramcode_flash_transaction(sizeof(flash_write), flash_write, 0, NULL, CMD_CONTINUE); + + for (i = 0; i < wlen; i++) { + /* send data byte */ + ramcode_flash_write_dat(wbuf[i]); + + /* + * we want to restart the write sequence every IDEAL_SIZE + * chunk worth of data. + */ + if (!(++addr % CHIP_FLASH_WRITE_PAGE_MAX_SIZE)) { + uint8_t w_en[] = {FLASH_CMD_WREN}; + + ramcode_flash_fsce_high(); + /* make sure busy bit cleared. */ + ramcode_flash_cmd_read_status(FLASH_SR_BUSY, FLASH_SR_NO_BUSY); + /* send write enable command */ + ramcode_flash_transaction(sizeof(w_en), w_en, 0, NULL, CMD_END); + /* make sure busy bit cleared and write enabled. */ + ramcode_flash_cmd_read_status(FLASH_SR_ALL, FLASH_SR_WEL); + /* re-send write command */ + flash_write[1] = (addr >> 16) & GENMASK(7, 0); + flash_write[2] = (addr >> 8) & GENMASK(7, 0); + flash_write[3] = addr & GENMASK(7, 0); + ramcode_flash_transaction(sizeof(flash_write), flash_write, + 0, NULL, CMD_CONTINUE); + } + } + ramcode_flash_fsce_high(); + /* make sure busy bit cleared. */ + ramcode_flash_cmd_read_status(FLASH_SR_BUSY, FLASH_SR_NO_BUSY); + /* exit EC-indirect follow mode */ + ramcode_flash_follow_mode_exit(); +} + +void __ram_code ramcode_flash_write(int addr, int wlen, const char *wbuf) +{ + ramcode_flash_cmd_write_enable(); + ramcode_flash_cmd_write(addr, wlen, (uint8_t *)wbuf); + ramcode_flash_cmd_write_disable(); +} + +void __ram_code ramcode_flash_cmd_erase(int addr, int cmd) +{ + uint8_t cmd_erase[] = {cmd, ((addr >> 16) & 0xFF), + ((addr >> 8) & 0xFF), (addr & 0xFF)}; + + /* enter EC-indirect follow mode */ + ramcode_flash_follow_mode(); + /* send erase command */ + ramcode_flash_transaction(sizeof(cmd_erase), cmd_erase, 0, NULL, CMD_END); + /* make sure busy bit cleared. */ + ramcode_flash_cmd_read_status(FLASH_SR_BUSY, FLASH_SR_NO_BUSY); + /* exit EC-indirect follow mode */ + ramcode_flash_follow_mode_exit(); +} + +void __ram_code ramcode_flash_erase(int addr, int cmd) +{ + ramcode_flash_cmd_write_enable(); + ramcode_flash_cmd_erase(addr, cmd); + ramcode_flash_cmd_write_disable(); +} + +/** + * Protect flash banks until reboot. + * + * @param start_bank Start bank to protect + * @param bank_count Number of banks to protect + */ +static void flash_protect_banks(int start_bank, int bank_count, + enum flash_wp_interface wp_if) +{ + int bank; + + for (bank = start_bank; bank < start_bank + bank_count; bank++) { + if (wp_if & FLASH_WP_EC) { + IT83XX_GCTRL_EWPR0PFEC(FWP_REG(bank)) |= FWP_MASK(bank); + } + if (wp_if & FLASH_WP_HOST) { + IT83XX_GCTRL_EWPR0PFH(FWP_REG(bank)) |= FWP_MASK(bank); + } + if (wp_if & FLASH_WP_DBGR) { + IT83XX_GCTRL_EWPR0PFD(FWP_REG(bank)) |= FWP_MASK(bank); + } + } +} + +/* Read data from flash */ +static int __ram_code flash_it8xxx2_read(const struct device *dev, off_t offset, + void *data, size_t len) +{ + struct flash_it8xxx2_regs *const flash_regs = FLASH_IT8XXX2_REG_BASE; + uint8_t *data_t = data; + int i; + + for (i = 0; i < len; i++) { + flash_regs->SMFI_ECINDAR3 = EC_INDIRECT_READ_INTERNAL_FLASH; + flash_regs->SMFI_ECINDAR2 = (offset >> 16) & GENMASK(7, 0); + flash_regs->SMFI_ECINDAR1 = (offset >> 8) & GENMASK(7, 0); + flash_regs->SMFI_ECINDAR0 = (offset & GENMASK(7, 0)); + + /* + * Read/Write to this register will access one byte on the + * flash with the 32-bit flash address defined in ECINDAR3-0 + */ + data_t[i] = flash_regs->SMFI_ECINDDR; + + offset++; + } + + return 0; +} + +/* Write data to the flash, page by page */ +static int __ram_code flash_it8xxx2_write(const struct device *dev, off_t offset, + const void *src_data, size_t len) +{ + struct flash_it8xxx2_dev_data *data = DEV_DATA(dev); + int ret = -EINVAL; + unsigned int key; + + /* + * Check that the offset and length are multiples of the write + * block size. + */ + if ((offset % FLASH_WRITE_BLK_SZ) != 0) { + return -EINVAL; + } + if ((len % FLASH_WRITE_BLK_SZ) != 0) { + return -EINVAL; + } + if (data->flash_static_cache_enabled == 0) { + return -EACCES; + } + if (data->all_protected) { + return -EACCES; + } + + k_sem_take(&data->sem, K_FOREVER); + /* + * CPU can't fetch instruction from flash while use + * EC-indirect follow mode to access flash, interrupts need to be + * disabled. + */ + key = irq_lock(); + + ramcode_flash_write(offset, len, src_data); + ramcode_reset_i_cache(); + /* Get the ILM address of a flash offset. */ + offset |= CHIP_MAPPED_STORAGE_BASE; + ret = ramcode_flash_verify(offset, len, src_data); + + irq_unlock(key); + + k_sem_give(&data->sem); + + return ret; +} + +/* Erase multiple blocks */ +static int __ram_code flash_it8xxx2_erase(const struct device *dev, + off_t offset, size_t len) +{ + struct flash_it8xxx2_dev_data *data = DEV_DATA(dev); + int v_size = len, v_addr = offset, ret = -EINVAL; + unsigned int key; + + /* + * Check that the offset and length are multiples of the write + * erase block size. + */ + if ((offset % FLASH_ERASE_BLK_SZ) != 0) { + return -EINVAL; + } + if ((len % FLASH_ERASE_BLK_SZ) != 0) { + return -EINVAL; + } + if (data->flash_static_cache_enabled == 0) { + return -EACCES; + } + if (data->all_protected) { + return -EACCES; + } + + k_sem_take(&data->sem, K_FOREVER); + /* + * CPU can't fetch instruction from flash while use + * EC-indirect follow mode to access flash, interrupts need to be + * disabled. + */ + key = irq_lock(); + + /* Always use sector erase command */ + for (; len > 0; len -= FLASH_ERASE_BLK_SZ) { + ramcode_flash_erase(offset, FLASH_CMD_SECTOR_ERASE); + offset += FLASH_ERASE_BLK_SZ; + } + ramcode_reset_i_cache(); + /* get the ILM address of a flash offset. */ + v_addr |= CHIP_MAPPED_STORAGE_BASE; + ret = ramcode_flash_verify(v_addr, v_size, NULL); + + irq_unlock(key); + + k_sem_give(&data->sem); + + return ret; +} + +/* Enable or disable the write protection */ +static int flash_it8xxx2_write_protection(const struct device *dev, + bool enable) +{ + struct flash_it8xxx2_dev_data *data = DEV_DATA(dev); + + if (enable) { + /* Protect the entire flash */ + flash_protect_banks(0, CHIP_FLASH_SIZE_BYTES / + CHIP_FLASH_BANK_SIZE, FLASH_WP_EC); + data->all_protected = 1; + } else { + data->all_protected = 0; + } + + /* + * bit[0], eflash protect lock register which can only be write 1 and + * only be cleared by power-on reset. + */ + IT83XX_GCTRL_EPLR |= IT83XX_GCTRL_EPLR_ENABLE; + + return 0; +} + +static const struct flash_parameters * +flash_it8xxx2_get_parameters(const struct device *dev) +{ + ARG_UNUSED(dev); + + return &flash_it8xxx2_parameters; +} + +static void flash_code_static_cache(const struct device *dev) +{ + struct flash_it8xxx2_regs *const flash_regs = FLASH_IT8XXX2_REG_BASE; + struct flash_it8xxx2_dev_data *data = DEV_DATA(dev); + unsigned int key; + + /* Make sure no interrupt while enable static cache */ + key = irq_lock(); + + /* invalid static cache first */ + IT83XX_GCTRL_RVILMCR0 &= ~ILMCR_ILM0_ENABLE; + + flash_regs->SMFI_SCAR0H = IT8XXX2_SMFI_SCAR0H_ENABLE; + + memcpy((void *)CHIP_RAMCODE_BASE, (const void *)FLASH_RAMCODE_START, + IT8XXX2_ILM_BLOCK_SIZE); + + /* RISCV ILM 0 Enable */ + IT83XX_GCTRL_RVILMCR0 |= ILMCR_ILM0_ENABLE; + + /* Enable ILM */ + flash_regs->SMFI_SCAR0L = FLASH_RAMCODE_START & GENMASK(7, 0); + flash_regs->SMFI_SCAR0M = (FLASH_RAMCODE_START >> 8) & GENMASK(7, 0); + flash_regs->SMFI_SCAR0H = (FLASH_RAMCODE_START >> 16) & GENMASK(2, 0); + + if (FLASH_RAMCODE_START & FLASH_RAMCODE_START_BIT19) { + flash_regs->SMFI_SCAR0H |= IT8XXX2_SMFI_SC0A19; + } else { + flash_regs->SMFI_SCAR0H &= ~IT8XXX2_SMFI_SC0A19; + } + + data->flash_static_cache_enabled = 0x01; + + irq_unlock(key); +} + +static int flash_it8xxx2_init(const struct device *dev) +{ + struct flash_it8xxx2_regs *const flash_regs = FLASH_IT8XXX2_REG_BASE; + struct flash_it8xxx2_dev_data *data = DEV_DATA(dev); + + /* By default, select internal flash for indirect fast read. */ + flash_regs->SMFI_ECINDAR3 = EC_INDIRECT_READ_INTERNAL_FLASH; + + /* + * If the embedded flash's size of this part number is larger + * than 256K-byte, enable the page program cycle constructed + * by EC-Indirect Follow Mode. + */ + flash_regs->SMFI_FLHCTRL6R |= IT8XXX2_SMFI_MASK_ECINDPP; + + /* Initialize mutex for flash controller */ + k_sem_init(&data->sem, 1, 1); + + flash_code_static_cache(dev); + + return 0; +} + +static const struct flash_driver_api flash_it8xxx2_api = { + .write_protection = flash_it8xxx2_write_protection, + .erase = flash_it8xxx2_erase, + .write = flash_it8xxx2_write, + .read = flash_it8xxx2_read, + .get_parameters = flash_it8xxx2_get_parameters, +}; + +static struct flash_it8xxx2_dev_data flash_it8xxx2_data; + +DEVICE_DT_INST_DEFINE(0, flash_it8xxx2_init, NULL, + &flash_it8xxx2_data, NULL, + PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, + &flash_it8xxx2_api); diff --git a/dts/riscv/it8xxx2.dtsi b/dts/riscv/it8xxx2.dtsi index 4a34d760641..9b58fefd642 100644 --- a/dts/riscv/it8xxx2.dtsi +++ b/dts/riscv/it8xxx2.dtsi @@ -30,9 +30,9 @@ #size-cells = <1>; ranges; - flashctrl: flash-controller@80000000 { + flashctrl: flash-controller@f01000 { compatible = "ite,it8xxx2-flash-controller"; - reg = <0x80000000 0x100>; + reg = <0x00f01000 0x100>; label = "fspi"; #address-cells = <1>; #size-cells = <1>; @@ -226,9 +226,9 @@ 0 0 0 0 >; #pinctrl-cells = <2>; }; - sram0: memory@80100000 { + sram0: memory@80101000 { compatible = "mmio-sram"; - reg = <0x80100000 DT_SIZE_K(60)>; + reg = <0x80101000 DT_SIZE_K(56)>; }; intc: interrupt-controller@f03f00 { #interrupt-cells = <2>; diff --git a/include/arch/riscv/common/linker.ld b/include/arch/riscv/common/linker.ld index 86b92f46e5a..06eab0162f4 100644 --- a/include/arch/riscv/common/linker.ld +++ b/include/arch/riscv/common/linker.ld @@ -140,6 +140,14 @@ SECTIONS *(".text.*") *(.gnu.linkonce.t.*) #include +#ifdef CONFIG_SOC_FLASH_RAMCODE_SECTION + . = ALIGN(0x1000); + _ram_code_start = .; + KEEP(*(.__ram_code)) + __ram_code_size = . - _ram_code_start; + ASSERT((__ram_code_size <= 0x1000), + "__ram_code_size <= 4k bytes"); +#endif } GROUP_LINK_IN(ROMABLE_REGION) _image_text_end = .; diff --git a/soc/riscv/riscv-ite/common/chip_chipregs.h b/soc/riscv/riscv-ite/common/chip_chipregs.h index cb9bcd395c6..87434a42ded 100644 --- a/soc/riscv/riscv-ite/common/chip_chipregs.h +++ b/soc/riscv/riscv-ite/common/chip_chipregs.h @@ -1672,6 +1672,44 @@ struct wdt_it8xxx2_regs { #define CE_RNG ECREG(EC_REG_BASE_ADDR + 0x3C20) +/* Shared Memory Flash Interface Bridge (SMFI) registers */ + +#ifndef __ASSEMBLER__ +struct flash_it8xxx2_regs { + volatile uint8_t reserved1[59]; + /* 0x3B: EC-Indirect memory address 0 */ + volatile uint8_t SMFI_ECINDAR0; + /* 0x3C: EC-Indirect memory address 1 */ + volatile uint8_t SMFI_ECINDAR1; + /* 0x3D: EC-Indirect memory address 2 */ + volatile uint8_t SMFI_ECINDAR2; + /* 0x3E: EC-Indirect memory address 3 */ + volatile uint8_t SMFI_ECINDAR3; + /* 0x3F: EC-Indirect memory data */ + volatile uint8_t SMFI_ECINDDR; + /* 0x40: Scratch SRAM 0 address low byte */ + volatile uint8_t SMFI_SCAR0L; + /* 0x41: Scratch SRAM 0 address middle byte */ + volatile uint8_t SMFI_SCAR0M; + /* 0x42: Scratch SRAM 0 address high byte */ + volatile uint8_t SMFI_SCAR0H; + volatile uint8_t reserved2[95]; + /* 0xA2: Flash control 6 */ + volatile uint8_t SMFI_FLHCTRL6R; +}; +#endif /* !__ASSEMBLER__ */ + +/* SMFI register fields */ + +/* EC-Indirect read internal flash */ +#define EC_INDIRECT_READ_INTERNAL_FLASH BIT(6) +/* Enable EC-indirect page program command */ +#define IT8XXX2_SMFI_MASK_ECINDPP BIT(3) +/* Scratch SRAM 0 address(BIT(19)) */ +#define IT8XXX2_SMFI_SC0A19 BIT(7) +/* Scratch SRAM enable */ +#define IT8XXX2_SMFI_SCAR0H_ENABLE BIT(3) + /* --- GPIO --- */ #define IT8XXX2_GPIO_BASE 0x00F01600 #define IT8XXX2_GPIO2_BASE 0x00F03E00 @@ -1829,9 +1867,11 @@ struct adc_it8xxx2_regs { #define IT83XX_GCTRL_SPISLVPFE BIT(6) #define IT83XX_GCTRL_RSTC5 ECREG(IT83XX_GCTRL_BASE + 0x21) #define IT83XX_GCTRL_MCCR ECREG(IT83XX_GCTRL_BASE + 0x30) +#define IT83XX_GCTRL_ICACHE_RESET BIT(4) #define IT83XX_GCTRL_PMER1 ECREG(IT83XX_GCTRL_BASE + 0x32) #define IT83XX_GCTRL_PMER2 ECREG(IT83XX_GCTRL_BASE + 0x33) #define IT83XX_GCTRL_EPLR ECREG(IT83XX_GCTRL_BASE + 0x37) +#define IT83XX_GCTRL_EPLR_ENABLE BIT(0) #define IT83XX_GCTRL_IVTBAR ECREG(IT83XX_GCTRL_BASE + 0x41) #define IT83XX_GCTRL_MCCR2 ECREG(IT83XX_GCTRL_BASE + 0x44) #define IT83XX_GCTRL_PIN_MUX0 ECREG(IT83XX_GCTRL_BASE + 0x46)