From 7a06df9cc392f0993fe997886fe70398a19ed0dc Mon Sep 17 00:00:00 2001 From: Tim Lin Date: Fri, 8 Nov 2024 19:07:06 +0800 Subject: [PATCH] soc: ITE: Add ITE it51xxx SoC Add support for ITE it51xxx SoC. NOTE: it51526aw is not support RISCV_ISA_EXT_C. Signed-off-by: Tim Lin --- dts/riscv/ite/it51526aw.dtsi | 18 + dts/riscv/ite/it51xxx.dtsi | 70 +++ soc/ite/ec/common/soc_common.h | 3 +- soc/ite/ec/it51xxx/CMakeLists.txt | 6 + soc/ite/ec/it51xxx/Kconfig | 33 ++ soc/ite/ec/it51xxx/Kconfig.defconfig.series | 37 ++ soc/ite/ec/it51xxx/Kconfig.soc | 22 + soc/ite/ec/it51xxx/chip_chipregs.h | 301 +++++++++++++ soc/ite/ec/it51xxx/linker.ld | 469 ++++++++++++++++++++ soc/ite/ec/it51xxx/soc.c | 119 +++++ soc/ite/ec/it51xxx/soc.h | 12 + soc/ite/ec/it51xxx/vector.S | 56 +++ soc/ite/ec/soc.yml | 5 + 13 files changed, 1149 insertions(+), 2 deletions(-) create mode 100644 dts/riscv/ite/it51526aw.dtsi create mode 100644 dts/riscv/ite/it51xxx.dtsi create mode 100644 soc/ite/ec/it51xxx/CMakeLists.txt create mode 100644 soc/ite/ec/it51xxx/Kconfig create mode 100644 soc/ite/ec/it51xxx/Kconfig.defconfig.series create mode 100644 soc/ite/ec/it51xxx/Kconfig.soc create mode 100644 soc/ite/ec/it51xxx/chip_chipregs.h create mode 100644 soc/ite/ec/it51xxx/linker.ld create mode 100644 soc/ite/ec/it51xxx/soc.c create mode 100644 soc/ite/ec/it51xxx/soc.h create mode 100644 soc/ite/ec/it51xxx/vector.S diff --git a/dts/riscv/ite/it51526aw.dtsi b/dts/riscv/ite/it51526aw.dtsi new file mode 100644 index 00000000000..b03cfc22e1b --- /dev/null +++ b/dts/riscv/ite/it51526aw.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 ITE Corporation. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + cpus { + cpu0: cpu@0 { + compatible = "ite,riscv-ite", "riscv"; + riscv,isa = "rv32imb_zifencei"; + device_type = "cpu"; + reg = <0>; + clock-frequency = <32768>; + cpu-power-states = <&standby>; + }; + }; +}; diff --git a/dts/riscv/ite/it51xxx.dtsi b/dts/riscv/ite/it51xxx.dtsi new file mode 100644 index 00000000000..b69fb4fcc7f --- /dev/null +++ b/dts/riscv/ite/it51xxx.dtsi @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025 ITE Corporation. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "ite,riscv-ite", "riscv"; + riscv,isa = "rv32imcb_zifencei"; + device_type = "cpu"; + reg = <0>; + clock-frequency = <32768>; + cpu-power-states = <&standby>; + }; + + power-states { + standby: standby { + compatible = "zephyr,power-state"; + power-state-name = "standby"; + min-residency-us = <500>; + }; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + flashctrl: flash-controller@f01000 { + compatible = "ite,it51xxx-flash-controller"; + reg = <0x00f01000 0x100>; + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + reg = <0 DT_SIZE_M(1)>; + erase-block-size = <4096>; + write-block-size = <4>; + }; + }; + + sram0: memory@800000 { + compatible = "mmio-sram"; + reg = <0x800000 DT_SIZE_K(128)>; + }; + + gpiogcr: gpio-gcr@f01600 { + compatible = "ite,it51xxx-gpiogcr"; + reg = <0x00f01600 0x100>; + }; + + gctrl: general-control@f02000 { + compatible = "ite,it51xxx-gctrl"; + reg = <0x00f02000 0x100>; + }; + }; +}; diff --git a/soc/ite/ec/common/soc_common.h b/soc/ite/ec/common/soc_common.h index b7e0cdd5e55..577d43b5381 100644 --- a/soc/ite/ec/common/soc_common.h +++ b/soc/ite/ec/common/soc_common.h @@ -43,11 +43,10 @@ uint32_t chip_get_pll_freq(void); void chip_pll_ctrl(enum chip_pll_mode mode); void riscv_idle(enum chip_pll_mode mode, unsigned int key); -#ifdef CONFIG_SOC_IT8XXX2_CPU_IDLE_GATING +/* Functions for managing the CPU idle state */ void chip_permit_idle(void); void chip_block_idle(void); bool cpu_idle_not_allowed(void); -#endif #endif /* !_ASMLANGUAGE */ diff --git a/soc/ite/ec/it51xxx/CMakeLists.txt b/soc/ite/ec/it51xxx/CMakeLists.txt new file mode 100644 index 00000000000..f9ea7b8d84e --- /dev/null +++ b/soc/ite/ec/it51xxx/CMakeLists.txt @@ -0,0 +1,6 @@ +zephyr_sources(soc.c vector.S) +zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld + CACHE INTERNAL "SoC Linker script ${SOC_NAME}" +) diff --git a/soc/ite/ec/it51xxx/Kconfig b/soc/ite/ec/it51xxx/Kconfig new file mode 100644 index 00000000000..35923428dca --- /dev/null +++ b/soc/ite/ec/it51xxx/Kconfig @@ -0,0 +1,33 @@ +# Copyright (c) 2025 ITE Corporation. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_IT51XXX + select HAS_PM + select ARCH_HAS_CUSTOM_CPU_IDLE + select ARCH_HAS_CUSTOM_CPU_ATOMIC_IDLE + select SOC_PREP_HOOK + +if SOC_SERIES_IT51XXX + +config SOC_IT51XXX + select RISCV + select ATOMIC_OPERATIONS_C + select RISCV_ISA_RV32I + select RISCV_ISA_EXT_ZICSR + select RISCV_ISA_EXT_ZIFENCEI + select RISCV_ISA_EXT_M + select RISCV_ISA_EXT_C if !SOC_IT51526AW + select RISCV_ISA_EXT_ZBA + select RISCV_ISA_EXT_ZBB + select RISCV_ISA_EXT_ZBS + select FLASH + imply XIP + +config SOC_IT51XXX_CPU_IDLE_GATING + bool + help + This option determines whether the entering CPU idle mode can be + gated by individual drivers. When this option is disabled, CPU idle + mode is always permitted. + +endif # SOC_SERIES_IT51XXX diff --git a/soc/ite/ec/it51xxx/Kconfig.defconfig.series b/soc/ite/ec/it51xxx/Kconfig.defconfig.series new file mode 100644 index 00000000000..1672798b8a5 --- /dev/null +++ b/soc/ite/ec/it51xxx/Kconfig.defconfig.series @@ -0,0 +1,37 @@ +# Copyright (c) 2025 ITE Corporation. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_IT51XXX + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_node_int_prop_int,/cpus/cpu@0,clock-frequency) + +config SYS_CLOCK_TICKS_PER_SEC + default 4096 + +config UART_NS16550_WA_ISR_REENABLE_INTERRUPT + default y + depends on UART_NS16550 + +config FLASH_INIT_PRIORITY + default 0 + +config NUM_IRQS + default 225 + +config DYNAMIC_INTERRUPTS + default y + +config GEN_ISR_TABLES + default y + +config GEN_IRQ_START_VECTOR + default 0 + +config GEN_SW_ISR_TABLE + default y + +config RISCV_SOC_INTERRUPT_INIT + default y + +endif # SOC_SERIES_IT51XXX diff --git a/soc/ite/ec/it51xxx/Kconfig.soc b/soc/ite/ec/it51xxx/Kconfig.soc new file mode 100644 index 00000000000..dccc1678d27 --- /dev/null +++ b/soc/ite/ec/it51xxx/Kconfig.soc @@ -0,0 +1,22 @@ +# Copyright (c) 2025 ITE Corporation. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_IT51XXX + bool + select SOC_FAMILY_ITE_EC + help + Enable support for ITE IT51XXX + +config SOC_IT51XXX + bool + select SOC_SERIES_IT51XXX + +config SOC_IT51526AW + bool + select SOC_IT51XXX + +config SOC_SERIES + default "it51xxx" if SOC_SERIES_IT51XXX + +config SOC + default "it51526aw" if SOC_IT51526AW diff --git a/soc/ite/ec/it51xxx/chip_chipregs.h b/soc/ite/ec/it51xxx/chip_chipregs.h new file mode 100644 index 00000000000..8ad65446753 --- /dev/null +++ b/soc/ite/ec/it51xxx/chip_chipregs.h @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2025 ITE Corporation. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef CHIP_CHIPREGS_H +#define CHIP_CHIPREGS_H + +#include + +#ifdef _ASMLANGUAGE +#define ECREG(x) x +#else + +/* + * Macros for hardware registers access. + */ +#define ECREG(x) (*((volatile unsigned char *)(x))) +#define ECREG_u16(x) (*((volatile unsigned short *)(x))) +#define ECREG_u32(x) (*((volatile unsigned long *)(x))) + +#endif /* _ASMLANGUAGE */ + +/** + * + * (10xxh) Shared Memory Flash Interface Bridge (SMFI) registers + * + */ +#ifndef __ASSEMBLER__ +struct smfi_it51xxx_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 reserved1_1[23]; + /* 0x5A: Host RAM Window Control */ + volatile uint8_t SMFI_HRAMWC; + /* 0x5B: Host RAM Window 0 Base Address [11:4] */ + volatile uint8_t SMFI_HRAMW0BA; + /* 0x5C: Host RAM Window 1 Base Address [11:4] */ + volatile uint8_t SMFI_HRAMW1BA; + /* 0x5D: Host RAM Window 0 Access Allow Size */ + volatile uint8_t SMFI_HRAMW0AAS; + /* 0x5E: Host RAM Window 1 Access Allow Size */ + volatile uint8_t SMFI_HRAMW1AAS; + volatile uint8_t reserved2[67]; + /* 0xA2: Flash control 6 */ + volatile uint8_t SMFI_FLHCTRL6R; + volatile uint8_t reserved3[46]; +}; +#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 IT51XXX_SMFI_MASK_ECINDPP BIT(3) + +/** + * + * (16xxh) General Purpose I/O Port (GPIO) registers + * + */ +#define GPIO_IT51XXX_REGS_BASE ((struct gpio_it51xxx_regs *)DT_REG_ADDR(DT_NODELABEL(gpiogcr))) + +#ifndef __ASSEMBLER__ +struct gpio_it51xxx_regs { + /* 0x00: General Control */ + volatile uint8_t GPIO_GCR; + /* 0x01-CF: Reserved_01_cf */ + volatile uint8_t reserved_01_cf[207]; + /* 0xD0: General Control 31 */ + volatile uint8_t GPIO_GCR31; + /* 0xD1: General Control 32 */ + volatile uint8_t GPIO_GCR32; + /* 0xD2: Reserved_d2 */ + volatile uint8_t reserved_d2[1]; + /* 0xD3: General Control 34 */ + volatile uint8_t GPIO_GCR34; + /* 0xD4: GPA Voltage Selection */ + volatile uint8_t GPIO_GPAVSR; + /* 0xD5: GPB Voltage Selection */ + volatile uint8_t GPIO_GPBVSR; + /* 0xD6: GPC Voltage Selection */ + volatile uint8_t GPIO_GPCVSR; + /* 0xD7: GPD Voltage Selection */ + volatile uint8_t GPIO_GPDVSR; + /* 0xD8: GPE Voltage Selection */ + volatile uint8_t GPIO_GPEVSR; + /* 0xD9: GPF Voltage Selection */ + volatile uint8_t GPIO_GPFVSR; + /* 0xDA: GPG Voltage Selection */ + volatile uint8_t GPIO_GPGVSR; + /* 0xDB: GPH Voltage Selection */ + volatile uint8_t GPIO_GPHVSR; + /* 0xDC: GPI Voltage Selection */ + volatile uint8_t GPIO_GPIVSR; + /* 0xDD: GPJ Voltage Selection */ + volatile uint8_t GPIO_GPJVSR; + /* 0xDE: GP I3C Control */ + volatile uint8_t GPIO_GPI3CCR; + /* 0xDF: Reserved_df */ + volatile uint8_t reserved_df[1]; + /* 0xE0: General Control 16 */ + volatile uint8_t GPIO_GCR16; + /* 0xE1: General Control 17 */ + volatile uint8_t GPIO_GCR17; + /* 0xE2: General Control 18 */ + volatile uint8_t GPIO_GCR18; + /* 0xE3: Reserved_e3 */ + volatile uint8_t reserved_e3; + /* 0xE4: General Control 19 */ + volatile uint8_t GPIO_GCR19; + /* 0xE5: General Control 20 */ + volatile uint8_t GPIO_GCR20; + /* 0xE6: General Control 21 */ + volatile uint8_t GPIO_GCR21; + /* 0xE7: General Control 22 */ + volatile uint8_t GPIO_GCR22; + /* 0xE8: Reserved_e8 */ + volatile uint8_t reserved_e8[1]; + /* 0xE9: General Control 24 */ + volatile uint8_t GPIO_GCR24; + /* 0xEA: General Control 25 */ + volatile uint8_t GPIO_GCR25; + /* 0xEB: General Control 26 */ + volatile uint8_t GPIO_GCR26; + /* 0xEC: Reserved_ec */ + volatile uint8_t reserved_ec[1]; + /* 0xED: General Control 28 */ + volatile uint8_t GPIO_GCR28; + /* 0xEE-0xEF: Reserved_ee_ef */ + volatile uint8_t reserved_ee_ef[2]; + /* 0xF0: General Control 1 */ + volatile uint8_t GPIO_GCR1; + /* 0xF1: General Control 2 */ + volatile uint8_t GPIO_GCR2; + /* 0xF2: General Control 3 */ + volatile uint8_t GPIO_GCR3; + /* 0xF3: General Control 4 */ + volatile uint8_t GPIO_GCR4; + /* 0xF4: General Control 5 */ + volatile uint8_t GPIO_GCR5; + /* 0xF5: General Control 6 */ + volatile uint8_t GPIO_GCR6; + /* 0xF6: General Control 7 */ + volatile uint8_t GPIO_GCR7; + /* 0xF7: General Control 8 */ + volatile uint8_t GPIO_GCR8; + /* 0xF8: General Control 9 */ + volatile uint8_t GPIO_GCR9; + /* 0xF9: General Control 10 */ + volatile uint8_t GPIO_GCR10; + /* 0xFA: General Control 11 */ + volatile uint8_t GPIO_GCR11; + /* 0xFB: General Control 12 */ + volatile uint8_t GPIO_GCR12; + /* 0xFC: General Control 13 */ + volatile uint8_t GPIO_GCR13; + /* 0xFD: General Control 14 */ + volatile uint8_t GPIO_GCR14; + /* 0xFE: General Control 15 */ + volatile uint8_t GPIO_GCR15; + /* 0xFF: Power Good Watch Control */ + volatile uint8_t GPIO_PGWCR; +}; +#endif /* !__ASSEMBLER__ */ + +/* GPIO register fields */ +/* 0x00: General Control */ +#define IT51XXX_GPIO_LPCRSTEN (BIT(2) | BIT(1)) +#define IT51XXX_GPIO_GCR_ESPI_RST_D2 0x2 +#define IT51XXX_GPIO_GCR_ESPI_RST_POS 1 +#define IT51XXX_GPIO_GCR_ESPI_RST_EN_MASK (0x3 << IT51XXX_GPIO_GCR_ESPI_RST_POS) +/* 0xF0: General Control 1 */ +#define IT51XXX_GPIO_U2CTRL_SIN1_SOUT1_EN BIT(2) +#define IT51XXX_GPIO_U1CTRL_SIN0_SOUT0_EN BIT(0) +/* 0xE6: General Control 21 */ +#define IT51XXX_GPIO_GPH1VS BIT(1) +#define IT51XXX_GPIO_GPH2VS BIT(0) + +#define KSIX_KSOX_KBS_GPIO_MODE BIT(7) +#define KSIX_KSOX_GPIO_OUTPUT BIT(6) +#define KSIX_KSOX_GPIO_PULLUP BIT(2) +#define KSIX_KSOX_GPIO_PULLDOWN BIT(1) + +#define GPCR_PORT_PIN_MODE_INPUT BIT(7) +#define GPCR_PORT_PIN_MODE_OUTPUT BIT(6) +#define GPCR_PORT_PIN_MODE_PULLUP BIT(2) +#define GPCR_PORT_PIN_MODE_PULLDOWN BIT(1) + +/* + * If both PULLUP and PULLDOWN are set to 1b, the corresponding port would be + * configured as tri-state. + */ +#define GPCR_PORT_PIN_MODE_TRISTATE \ + (GPCR_PORT_PIN_MODE_INPUT | GPCR_PORT_PIN_MODE_PULLUP | GPCR_PORT_PIN_MODE_PULLDOWN) + +/** + * + * (1Exxh) PLL Control Mode + * + */ +#ifndef __ASSEMBLER__ +enum chip_pll_mode { + CHIP_PLL_DOZE = 0, + CHIP_PLL_SLEEP = 1, + CHIP_PLL_DEEP_DOZE = 3, +}; +#endif + +/** + * + * (20xxh) General Control (GCTRL) registers + * + */ +#define GCTRL_IT51XXX_REGS_BASE ((struct gctrl_it51xxx_regs *)DT_REG_ADDR(DT_NODELABEL(gctrl))) + +#ifndef __ASSEMBLER__ +struct gctrl_it51xxx_regs { + /* 0x00-0x01: Reserved_00_01 */ + volatile uint8_t reserved_00_01[2]; + /* 0x02: Chip Version */ + volatile uint8_t GCTRL_ECHIPVER; + /* 0x03-0x05: Reserved_03_05 */ + volatile uint8_t reserved_03_05[3]; + /* 0x06: Reset Status */ + volatile uint8_t GCTRL_RSTS; + /* 0x07-0x09: Reserved_07_09 */ + volatile uint8_t reserved_07_09[3]; + /* 0x0A: Base Address Select */ + volatile uint8_t GCTRL_BADRSEL; + /* 0x0B: Wait Next Clock Rising */ + volatile uint8_t GCTRL_WNCKR; + /* 0x0C: Special Control 5 */ + volatile uint8_t GCTRL_SPCTRL5; + /* 0x0D: Special Control 1 */ + volatile uint8_t GCTRL_SPCTRL1; + /* 0x0E-0x0F: reserved_0e_0f */ + volatile uint8_t reserved_0e_0f[2]; + /* 0x10: Reset Control DMM */ + volatile uint8_t GCTRL_RSTDMMC; + /* 0x11: Reset Control 4 */ + volatile uint8_t GCTRL_RSTC4; + /* 0x12-0x1B: reserved_12_1b */ + volatile uint8_t reserved_12_1b[10]; + /* 0x1C: Special Control 4 */ + volatile uint8_t GCTRL_SPCTRL4; + /* 0x1D-0x1F: reserved_1d_1f */ + volatile uint8_t reserved_1d_1f[3]; + /* 0x20: Reset Control 5 */ + volatile uint8_t GCTRL_RSTC5; + /* 0x21-0x37: reserved_21_37 */ + volatile uint8_t reserved_21_37[23]; + /* 0x38: Special Control 9 */ + volatile uint8_t GCTRL_SPCTRL9; + /* 0x39-0x84: reserved_39_84 */ + volatile uint8_t reserved_39_84[76]; + /* 0x85: Chip ID Byte 1 */ + volatile uint8_t GCTRL_ECHIPID1; + /* 0x86: Chip ID Byte 2 */ + volatile uint8_t GCTRL_ECHIPID2; + /* 0x87: Chip ID Byte 3 */ + volatile uint8_t GCTRL_ECHIPID3; +}; +#endif /* !__ASSEMBLER__ */ + +/* GCTRL register fields */ +/* 0x06: Reset Status */ +#define IT51XXX_GCTRL_LRS (BIT(1) | BIT(0)) +#define IT51XXX_GCTRL_IWDTR BIT(1) +/* 0x0B: Wait Next 65K Rising */ +#define IT51XXX_GCTRL_WN65K 0x00 +/* 0x10: Reset Control DMM */ +#define IT51XXX_GCTRL_UART1SD BIT(3) +#define IT51XXX_GCTRL_UART2SD BIT(2) +/* 0x11: Reset Control 4 */ +#define IT51XXX_GCTRL_RPECI BIT(4) +#define IT51XXX_GCTRL_RUART BIT(2) +/* 0x1C: Special Control 4 */ +#define IT51XXX_GCTRL_LRSIWR BIT(2) +#define IT51XXX_GCTRL_LRSIPWRSWTR BIT(1) +#define IT51XXX_GCTRL_LRSIPGWR BIT(0) +/* 0x38: Special Control 9 */ +#define IT51XXX_GCTRL_ALTIE BIT(4) + +#endif /* CHIP_CHIPREGS_H */ diff --git a/soc/ite/ec/it51xxx/linker.ld b/soc/ite/ec/it51xxx/linker.ld new file mode 100644 index 00000000000..c1000628324 --- /dev/null +++ b/soc/ite/ec/it51xxx/linker.ld @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2025 ITE Corporation. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include + +#include +#include + +#ifdef CONFIG_XIP +#define ROMABLE_REGION ROM +#else +#define ROMABLE_REGION RAM +#endif +#define RAMABLE_REGION RAM + +#define _EXCEPTION_SECTION_NAME exceptions +#define _RESET_SECTION_NAME reset + +#if defined(CONFIG_ROM_END_OFFSET) +#define ROM_END_OFFSET CONFIG_ROM_END_OFFSET +#else +#define ROM_END_OFFSET 0 +#endif + +#if defined(CONFIG_FLASH_LOAD_OFFSET) +#define FLASH_LOAD_OFFSET CONFIG_FLASH_LOAD_OFFSET +#else +#define FLASH_LOAD_OFFSET 0 +#endif + +#ifdef CONFIG_XIP + +#if CONFIG_FLASH_LOAD_SIZE > 0 +#define ROM_SIZE (CONFIG_FLASH_LOAD_SIZE - ROM_END_OFFSET) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_CHOSEN(zephyr_flash), soc_nv_flash, okay) +#define ROM_BASE (DT_REG_ADDR(DT_CHOSEN(zephyr_flash)) + FLASH_LOAD_OFFSET) +#ifndef ROM_SIZE +#define ROM_SIZE (DT_REG_SIZE(DT_CHOSEN(zephyr_flash)) - ROM_END_OFFSET) +#endif + +#elif DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_flash), jedec_spi_nor) +/* For jedec,spi-nor we expect the spi controller to memory map the flash + * and for that mapping to be on the register with the name flash_mmap and if a register with that + * name doesn't exists, we expect it to be in the second register property of the spi controller. + */ +#define SPI_CTRL DT_PARENT(DT_CHOSEN(zephyr_flash)) +#define FLASH_MMAP_NAME flash_mmap +#define ROM_BASE \ + (DT_REG_ADDR_BY_NAME_OR(SPI_CTRL, FLASH_MMAP_NAME, DT_REG_ADDR_BY_IDX(SPI_CTRL, 1)) + \ + FLASH_LOAD_OFFSET) +#ifndef ROM_SIZE +#define ROM_SIZE \ + (DT_REG_SIZE_BY_NAME_OR(SPI_CTRL, FLASH_MMAP_NAME, DT_REG_SIZE_BY_IDX(SPI_CTRL, 1)) - \ + ROM_END_OFFSET) +#endif + +#else /* Use Kconfig to cover the remaining cases */ +#define ROM_BASE (CONFIG_FLASH_BASE_ADDRESS + FLASH_LOAD_OFFSET) +#ifndef ROM_SIZE +#define ROM_SIZE (CONFIG_FLASH_SIZE * 1024 - FLASH_LOAD_OFFSET - ROM_END_OFFSET) +#endif + +#endif /* DT_NODE_HAS_COMPAT_STATUS */ + +#else /* CONFIG_XIP */ +#define ROM_BASE CONFIG_SRAM_BASE_ADDRESS +#define ROM_SIZE (KB(CONFIG_SRAM_SIZE) - ROM_END_OFFSET) +#endif /* CONFIG_XIP */ + +#define RAM_BASE CONFIG_SRAM_BASE_ADDRESS +#define RAM_SIZE KB(CONFIG_SRAM_SIZE) + +#ifdef CONFIG_RISCV_PMP + #define MPU_MIN_SIZE CONFIG_PMP_GRANULARITY + #define MPU_MIN_SIZE_ALIGN . = ALIGN(MPU_MIN_SIZE); + #if defined(CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT) + #define MPU_ALIGN(region_size) \ + . = ALIGN(MPU_MIN_SIZE); \ + . = ALIGN( 1 << LOG2CEIL(region_size)) + #else + #define MPU_ALIGN(region_size) \ + . = ALIGN(MPU_MIN_SIZE) + #endif +#else + #define MPU_MIN_SIZE_ALIGN + #define MPU_ALIGN(region_size) . = ALIGN(4) +#endif + +#include + +MEMORY +{ +#ifdef CONFIG_XIP + ROM (rx) : ORIGIN = ROM_BASE, LENGTH = ROM_SIZE +#endif + RAM (rwx) : ORIGIN = RAM_BASE, LENGTH = RAM_SIZE + +#if defined(CONFIG_LINKER_DEVNULL_MEMORY) + DEVNULL_ROM (rx) : ORIGIN = DEVNULL_ADDR, LENGTH = DEVNULL_SIZE +#endif + + LINKER_DT_REGIONS() + + /* Used by and documented in include/linker/intlist.ld */ + IDT_LIST (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K +} + +ENTRY(CONFIG_KERNEL_ENTRY) + +SECTIONS + { + +#include + +#ifdef CONFIG_LLEXT +#include +#endif + + /* + * The .plt and .iplt are here according to + * 'riscv32-zephyr-elf-ld --verbose', before text section. + */ + SECTION_PROLOGUE(.plt,,) + { + *(.plt) + } + + SECTION_PROLOGUE(.iplt,,) + { + *(.iplt) + } + + GROUP_START(ROMABLE_REGION) + __rom_region_start = ROM_BASE; + + SECTION_PROLOGUE(rom_start,,) + { + . = ALIGN(16); +/* Located in generated directory. This file is populated by calling + * zephyr_linker_sources(ROM_START ...). + */ +#include + } GROUP_LINK_IN(ROMABLE_REGION) + +#ifdef CONFIG_CODE_DATA_RELOCATION +#include +#endif + + SECTION_PROLOGUE(_RESET_SECTION_NAME,,) + { + KEEP(*(.reset.*)) + } GROUP_LINK_IN(ROMABLE_REGION) + + SECTION_PROLOGUE(_EXCEPTION_SECTION_NAME,,) + { + . = ALIGN(256); + KEEP(*(".exception.entry.*")) + *(".exception.other.*") + } GROUP_LINK_IN(ROMABLE_REGION) + + SECTION_PROLOGUE(_TEXT_SECTION_NAME,,) + { + . = ALIGN(4); + KEEP(*(.openocd_debug)) + KEEP(*(".openocd_debug.*")) + + __text_region_start = .; + + *(.text) + *(".text.*") + *(.gnu.linkonce.t.*) +#include + } GROUP_LINK_IN(ROMABLE_REGION) + + __text_region_end = .; + + __rodata_region_start = .; +#include +/* Located in generated directory. This file is populated by calling + * zephyr_linker_sources(ROM_SECTIONS ...). Useful for grouping iterable RO structs. + */ +#include +#include + + SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) + { + . = ALIGN(4); + *(.srodata) + *(".srodata.*") + *(.rodata) + *(".rodata.*") + *(.gnu.linkonce.r.*) + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include +#include + . = ALIGN(4); + } GROUP_LINK_IN(ROMABLE_REGION) + +#include + __rodata_region_end = .; + + /* For non-XIP system, __rom_region_end symbol should be set to + * the end of common ROMABLE_REGIONs (text and rodata) instead of + * the linker script end, so it wouldn't mistakenly contain + * RAMABLE_REGION in it. + */ +#ifndef CONFIG_XIP +#ifdef CONFIG_RISCV_PMP + SECTION_PROLOGUE(rom_mpu_padding,,) + { + MPU_ALIGN(__rodata_region_end - __rom_region_start); +#ifdef CONFIG_QEMU_TARGET + /* + * QEMU doesn't vet each instruction fetch individually. + * Instead, it grabs a whole page and perform dynamic + * translation on it in a batch. It therefore validates + * PMP permissions using page-sized and -aligned chunks. + */ + . = ALIGN(0x1000); +#endif + } GROUP_LINK_IN(ROMABLE_REGION) +#endif /* CONFIG_RISCV_PMP */ + + __rom_region_end = .; + __rom_region_size = __rom_region_end - __rom_region_start; +#endif /* CONFIG_XIP */ + GROUP_END(ROMABLE_REGION) + + GROUP_START(RAMABLE_REGION) + + . = RAM_BASE; + _image_ram_start = .; +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + +#if defined(CONFIG_USERSPACE) +#define APP_SHARED_ALIGN MPU_MIN_SIZE_ALIGN +#define SMEM_PARTITION_ALIGN MPU_ALIGN + +#include + + _app_smem_size = _app_smem_end - _app_smem_start; + _app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME); +#endif /* CONFIG_USERSPACE */ + + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + MPU_MIN_SIZE_ALIGN + /* + * For performance, BSS section is assumed to be 4 byte aligned and + * a multiple of 4 bytes + */ + . = ALIGN(4); + __bss_start = .; + __kernel_ram_start = .; + *(.sbss) + *(".sbss.*") + *(.bss) + *(".bss.*") + COMMON_SYMBOLS + +#ifdef CONFIG_CODE_DATA_RELOCATION +#include +#endif + + /* + * As memory is cleared in words only, it is simpler to ensure the BSS + * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes. + */ + __bss_end = ALIGN(4); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) + +#include + + SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,) + { + . = ALIGN(4); + /* _image_ram_start = .; */ + __data_region_start = .; + __data_start = .; + + *(.data) + *(".data.*") + +#ifdef CONFIG_RISCV_GP + /* + * RISC-V architecture has 12-bit signed immediate offsets in the + * instructions. If we can put the most commonly accessed globals + * in a special 4K span of memory addressed by the GP register, then + * we can access those values in a single instruction, saving both + * codespace and runtime. + * + * Since these immediate offsets are signed, place gp 0x800 past the + * beginning of .sdata so that we can use both positive and negative + * offsets. + */ + . = ALIGN(8); + PROVIDE (__global_pointer$ = . + 0x800); +#endif + + *(.sdata .sdata.* .gnu.linkonce.s.*) + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + +#ifdef CONFIG_CODE_DATA_RELOCATION +#include +#endif + + __data_end = .; + + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + __data_size = __data_end - __data_start; + __data_load_start = LOADADDR(_DATA_SECTION_NAME); + + __data_region_load_start = LOADADDR(_DATA_SECTION_NAME); + +#include +#include +#include + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + + __data_region_end = .; + + __kernel_ram_end = .; + __kernel_ram_size = __kernel_ram_end - __kernel_ram_start; + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay) +GROUP_START(ITCM) + + SECTION_PROLOGUE(_ITCM_SECTION_NAME,,SUBALIGN(8)) + { + __itcm_start = .; + *(.itcm) + *(".itcm.*") + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. */ +#include + + __itcm_end = .; + } GROUP_LINK_IN(ITCM AT> ROMABLE_REGION) + + __itcm_size = __itcm_end - __itcm_start; + __itcm_load_start = LOADADDR(_ITCM_SECTION_NAME); + +GROUP_END(ITCM) +#endif + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay) +GROUP_START(DTCM) + + SECTION_PROLOGUE(_DTCM_BSS_SECTION_NAME, (NOLOAD),SUBALIGN(8)) + { + __dtcm_start = .; + __dtcm_bss_start = .; + *(.dtcm_bss) + *(".dtcm_bss.*") + __dtcm_bss_end = .; + } GROUP_LINK_IN(DTCM) + + SECTION_PROLOGUE(_DTCM_NOINIT_SECTION_NAME, (NOLOAD),SUBALIGN(8)) + { + __dtcm_noinit_start = .; + *(.dtcm_noinit) + *(".dtcm_noinit.*") + __dtcm_noinit_end = .; + } GROUP_LINK_IN(DTCM) + + SECTION_PROLOGUE(_DTCM_DATA_SECTION_NAME,,SUBALIGN(8)) + { + __dtcm_data_start = .; + *(.dtcm_data) + *(".dtcm_data.*") + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. */ +#include + + __dtcm_data_end = .; + } GROUP_LINK_IN(DTCM AT> ROMABLE_REGION) + + __dtcm_end = .; + + __dtcm_data_load_start = LOADADDR(_DTCM_DATA_SECTION_NAME); + +GROUP_END(DTCM) +#endif + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + +#define LAST_RAM_ALIGN MPU_MIN_SIZE_ALIGN + +#include + + GROUP_END(RAMABLE_REGION) + +#include + + /DISCARD/ : { *(.note.GNU-stack) } + + SECTION_PROLOGUE(.riscv.attributes, 0,) + { + KEEP(*(.riscv.attributes)) + KEEP(*(.gnu.attributes)) + } + +/* Output section descriptions are needed for these sections to suppress + * warnings when "--orphan-handling=warn" is set for lld. + */ +#if defined(CONFIG_LLVM_USE_LLD) + SECTION_PROLOGUE(.symtab, 0,) { *(.symtab) } + SECTION_PROLOGUE(.strtab, 0,) { *(.strtab) } + SECTION_PROLOGUE(.shstrtab, 0,) { *(.shstrtab) } +#endif + + /* Sections generated from 'zephyr,memory-region' nodes */ + LINKER_DT_SECTIONS() + +/* Because ROMABLE_REGION != RAMABLE_REGION in XIP-system, it is valid + * to set __rom_region_end symbol at the end of linker script and + * doesn't mistakenly contain the RAMABLE_REGION in it. + */ +#ifdef CONFIG_XIP +/* Must be last in romable region */ +SECTION_PROLOGUE(.last_section,,) +{ +#ifdef CONFIG_LINKER_LAST_SECTION_ID + /* Fill last section with a word to ensure location counter and actual rom + * region data usage match. */ + LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN) + /* __rom_region_size is used when configuring the PMP entry of the ROM region. + * Addresses (pmpaddr) in PMP registers need to be aligned to 4. Align + * __rom_region_size to 4 to meet that requirement. */ + MPU_MIN_SIZE_ALIGN +#endif +} GROUP_LINK_IN(ROMABLE_REGION) + +/* To provide the image size as a const expression, + * calculate this value here. */ +__rom_region_end = LOADADDR(.last_section) + SIZEOF(.last_section); +__rom_region_size = __rom_region_end - __rom_region_start; +#endif + +} diff --git a/soc/ite/ec/it51xxx/soc.c b/soc/ite/ec/it51xxx/soc.c new file mode 100644 index 00000000000..2f3c435228a --- /dev/null +++ b/soc/ite/ec/it51xxx/soc.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2025 ITE Corporation. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +static mm_reg_t ecpm_base = DT_REG_ADDR(DT_NODELABEL(ecpm)); +/* it51xxx ECPM registers definition */ +/* 0x03: PLL Control */ +#define ECPM_PLLCTRL 0x03 + +void chip_pll_ctrl(enum chip_pll_mode mode) +{ + volatile uint8_t _pll_ctrl __unused; + + sys_write8(mode, ecpm_base + ECPM_PLLCTRL); + /* + * for deep doze / sleep mode + * This load operation will ensure PLL setting is taken into + * control register before wait for interrupt instruction. + */ + _pll_ctrl = sys_read8(ecpm_base + ECPM_PLLCTRL); +} + +#ifdef CONFIG_SOC_IT51XXX_CPU_IDLE_GATING +/* Preventing CPU going into idle mode during command queue. */ +static atomic_t cpu_idle_disabled; + +void chip_permit_idle(void) +{ + atomic_dec(&cpu_idle_disabled); +} + +void chip_block_idle(void) +{ + atomic_inc(&cpu_idle_disabled); +} + +bool cpu_idle_not_allowed(void) +{ + return atomic_get(&cpu_idle_disabled); +} +#endif + +/* The routine must be called with interrupts locked */ +void riscv_idle(enum chip_pll_mode mode, unsigned int key) +{ + /* + * The routine is called with interrupts locked (in kernel/idle()). + * But on kernel/context test_kernel_cpu_idle test, the routine will be + * called without interrupts locked. Hence we disable M-mode external + * interrupt here to protect the below content. + */ + csr_clear(mie, MIP_MEIP); + sys_trace_idle(); + + /* Chip doze after wfi instruction */ + chip_pll_ctrl(mode); + + /* Wait for interrupt */ + __asm__ volatile("wfi"); + + /* + * Enable M-mode external interrupt + * An interrupt can not be fired yet until we enable global interrupt + */ + csr_set(mie, MIP_MEIP); + + /* Restore global interrupt lockout state */ + irq_unlock(key); +} + +void arch_cpu_idle(void) +{ +#ifdef CONFIG_SOC_IT51XXX_CPU_IDLE_GATING + /* + * The EC processor(CPU) cannot be in the k_cpu_idle() during + * the transactions with the CQ mode(DMA mode). Otherwise, + * the EC processor would be clock gated. + */ + if (cpu_idle_not_allowed()) { + /* Restore global interrupt lockout state */ + irq_unlock(MSTATUS_IEN); + } else { +#endif + riscv_idle(CHIP_PLL_DOZE, MSTATUS_IEN); +#ifdef CONFIG_SOC_IT51XXX_CPU_IDLE_GATING + } +#endif +} + +void arch_cpu_atomic_idle(unsigned int key) +{ + riscv_idle(CHIP_PLL_DOZE, key); +} + +void soc_prep_hook(void) +{ + struct gpio_ite_ec_regs *const gpio_regs = GPIO_ITE_EC_REGS_BASE; + struct gctrl_ite_ec_regs *const gctrl_regs = GCTRL_ITE_EC_REGS_BASE; + + /* Scratch ROM0 is 4kb size */ + gctrl_regs->GCTRL_SCR0SZR = IT51XXX_GCTRL_SCRSIZE_4K; + + /* bit4: wake up CPU if it is in low power mode and an interrupt is pending. */ + gctrl_regs->GCTRL_SPCTRL9 |= IT51XXX_GCTRL_ALTIE; + + /* UART1 and UART2 board init */ + /* bit3: UART1 and UART2 belong to the EC side. */ + gctrl_regs->GCTRL_RSTDMMC |= IT51XXX_GCTRL_UART1SD | IT51XXX_GCTRL_UART2SD; + /* Reset UART before config it */ + gctrl_regs->GCTRL_RSTC4 = IT51XXX_GCTRL_RUART; + /* Switch UART1 and UART2 on without hardware flow control */ + gpio_regs->GPIO_GCR1 |= + IT51XXX_GPIO_U1CTRL_SIN0_SOUT0_EN | IT51XXX_GPIO_U2CTRL_SIN1_SOUT1_EN; +} diff --git a/soc/ite/ec/it51xxx/soc.h b/soc/ite/ec/it51xxx/soc.h new file mode 100644 index 00000000000..869206638dc --- /dev/null +++ b/soc/ite/ec/it51xxx/soc.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2025 ITE Corporation. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __RISCV_ITE_SOC_H_ +#define __RISCV_ITE_SOC_H_ + +#include + +#endif /* __RISCV_ITE_SOC_H_ */ diff --git a/soc/ite/ec/it51xxx/vector.S b/soc/ite/ec/it51xxx/vector.S new file mode 100644 index 00000000000..74d33f894c7 --- /dev/null +++ b/soc/ite/ec/it51xxx/vector.S @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025 ITE Corporation. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* exports */ +GTEXT(__start) + +/* imports */ +GTEXT(__initialize) +GTEXT(_isr_wrapper) + +SECTION_FUNC(vectors, __start) +#ifdef CONFIG_RISCV_GP + .option push + .option norelax + /* Configure the GP register */ + la gp, __global_pointer$ + .option pop +#endif + + .option norvc; + /* + * Set mtvec (Machine Trap-Vector Base-Address Register) + * to _isr_wrapper. + */ + la t0, _isr_wrapper + csrw mtvec, t0 + csrwi mie, 0 + /* Jump to __initialize */ + tail __initialize + +/* + * eflash signature used to enable specific function after power-on reset. + * (HW mechanism) + * The content of 16-bytes must be the following and at offset 0x40 of binary. + * ---------------------------------------------------------------------------- + * 1st 2nd 3rd 4th 5th 6th 7th 8th 9th 10th 11th 12th 13th 14th 15th 16th + * ---------------------------------------------------------------------------- + * A5h A5h A5h A5h A5h A5h [host] [flag] 85h 12h 5Ah 5Ah AAh AAh 55h 55h + * ---------------------------------------------------------------------------- + * 7th [host]: A4h = enable eSPI, A5h = enable LPC + */ +.org 0x40 +.balign 16 +.global eflash_sig +eflash_sig: +.byte 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5 +/* Enable eSPI */ +.byte 0xA4 +/* Flag of signature. Enable internal clock generator */ +.byte 0xB4 +.byte 0x85, 0x12, 0x5A, 0x5A, 0xAA, 0xAA, 0x55, 0x55 diff --git a/soc/ite/ec/soc.yml b/soc/ite/ec/soc.yml index b73270535f9..b0cba7d8eae 100644 --- a/soc/ite/ec/soc.yml +++ b/soc/ite/ec/soc.yml @@ -15,3 +15,8 @@ family: - name: it82302ax - name: it82202bw - name: it82302bw + - name: ite_ec + series: + - name: it51xxx + socs: + - name: it51526aw