Browse Source

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 <tim2.lin@ite.corp-partner.google.com>
pull/88290/head
Tim Lin 8 months ago committed by Benjamin Cabé
parent
commit
7a06df9cc3
  1. 18
      dts/riscv/ite/it51526aw.dtsi
  2. 70
      dts/riscv/ite/it51xxx.dtsi
  3. 3
      soc/ite/ec/common/soc_common.h
  4. 6
      soc/ite/ec/it51xxx/CMakeLists.txt
  5. 33
      soc/ite/ec/it51xxx/Kconfig
  6. 37
      soc/ite/ec/it51xxx/Kconfig.defconfig.series
  7. 22
      soc/ite/ec/it51xxx/Kconfig.soc
  8. 301
      soc/ite/ec/it51xxx/chip_chipregs.h
  9. 469
      soc/ite/ec/it51xxx/linker.ld
  10. 119
      soc/ite/ec/it51xxx/soc.c
  11. 12
      soc/ite/ec/it51xxx/soc.h
  12. 56
      soc/ite/ec/it51xxx/vector.S
  13. 5
      soc/ite/ec/soc.yml

18
dts/riscv/ite/it51526aw.dtsi

@ -0,0 +1,18 @@ @@ -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>;
};
};
};

70
dts/riscv/ite/it51xxx.dtsi

@ -0,0 +1,70 @@ @@ -0,0 +1,70 @@
/*
* Copyright (c) 2025 ITE Corporation. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <mem.h>
#include <zephyr/dt-bindings/dt-util.h>
/ {
#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>;
};
};
};

3
soc/ite/ec/common/soc_common.h

@ -43,11 +43,10 @@ uint32_t chip_get_pll_freq(void); @@ -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 */

6
soc/ite/ec/it51xxx/CMakeLists.txt

@ -0,0 +1,6 @@ @@ -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}"
)

33
soc/ite/ec/it51xxx/Kconfig

@ -0,0 +1,33 @@ @@ -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

37
soc/ite/ec/it51xxx/Kconfig.defconfig.series

@ -0,0 +1,37 @@ @@ -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

22
soc/ite/ec/it51xxx/Kconfig.soc

@ -0,0 +1,22 @@ @@ -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

301
soc/ite/ec/it51xxx/chip_chipregs.h

@ -0,0 +1,301 @@ @@ -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 <zephyr/sys/util.h>
#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 */

469
soc/ite/ec/it51xxx/linker.ld

@ -0,0 +1,469 @@ @@ -0,0 +1,469 @@
/*
* Copyright (c) 2025 ITE Corporation. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <soc.h>
#include <zephyr/devicetree.h>
#include <zephyr/linker/sections.h>
#include <zephyr/linker/devicetree_regions.h>
#include <zephyr/linker/linker-defs.h>
#include <zephyr/linker/linker-tool.h>
#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 <zephyr/linker/linker-devnull.h>
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 <zephyr/linker/rel-sections.ld>
#ifdef CONFIG_LLEXT
#include <zephyr/linker/llext-sections.ld>
#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 <snippets-rom-start.ld>
} GROUP_LINK_IN(ROMABLE_REGION)
#ifdef CONFIG_CODE_DATA_RELOCATION
#include <linker_relocate.ld>
#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 <zephyr/linker/kobject-text.ld>
} GROUP_LINK_IN(ROMABLE_REGION)
__text_region_end = .;
__rodata_region_start = .;
#include <zephyr/linker/common-rom.ld>
/* Located in generated directory. This file is populated by calling
* zephyr_linker_sources(ROM_SECTIONS ...). Useful for grouping iterable RO structs.
*/
#include <snippets-rom-sections.ld>
#include <zephyr/linker/thread-local-storage.ld>
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 <snippets-rodata.ld>
#include <zephyr/linker/kobject-rom.ld>
. = ALIGN(4);
} GROUP_LINK_IN(ROMABLE_REGION)
#include <zephyr/linker/cplusplus-rom.ld>
__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 <snippets-ram-sections.ld>
#if defined(CONFIG_USERSPACE)
#define APP_SHARED_ALIGN MPU_MIN_SIZE_ALIGN
#define SMEM_PARTITION_ALIGN MPU_ALIGN
#include <app_smem.ld>
_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 <linker_sram_bss_relocate.ld>
#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 <zephyr/linker/common-noinit.ld>
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 <snippets-rwdata.ld>
#ifdef CONFIG_CODE_DATA_RELOCATION
#include <linker_sram_data_relocate.ld>
#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 <zephyr/linker/common-ram.ld>
#include <zephyr/linker/kobject-data.ld>
#include <zephyr/linker/cplusplus-ram.ld>
/* Located in generated directory. This file is populated by the
* zephyr_linker_sources() Cmake function.
*/
#include <snippets-data-sections.ld>
__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 <snippets-itcm-section.ld>
__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 <snippets-dtcm-section.ld>
__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 <snippets-sections.ld>
#define LAST_RAM_ALIGN MPU_MIN_SIZE_ALIGN
#include <zephyr/linker/ram-end.ld>
GROUP_END(RAMABLE_REGION)
#include <zephyr/linker/debug-sections.ld>
/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
}

119
soc/ite/ec/it51xxx/soc.c

@ -0,0 +1,119 @@ @@ -0,0 +1,119 @@
/*
* Copyright (c) 2025 ITE Corporation. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <soc_common.h>
#include <zephyr/kernel.h>
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;
}

12
soc/ite/ec/it51xxx/soc.h

@ -0,0 +1,12 @@ @@ -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 <soc_common.h>
#endif /* __RISCV_ITE_SOC_H_ */

56
soc/ite/ec/it51xxx/vector.S

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
/*
* Copyright (c) 2025 ITE Corporation. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/toolchain.h>
/* 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

5
soc/ite/ec/soc.yml

@ -15,3 +15,8 @@ family: @@ -15,3 +15,8 @@ family:
- name: it82302ax
- name: it82202bw
- name: it82302bw
- name: ite_ec
series:
- name: it51xxx
socs:
- name: it51526aw

Loading…
Cancel
Save