diff --git a/bsp_sedi/soc/intel_ish/include/sedi_soc_regs.h b/bsp_sedi/soc/intel_ish/include/sedi_soc_regs.h index d6bec90..aedfff9 100644 --- a/bsp_sedi/soc/intel_ish/include/sedi_soc_regs.h +++ b/bsp_sedi/soc/intel_ish/include/sedi_soc_regs.h @@ -115,9 +115,15 @@ SEDI_IREG_BASE_DEFINE(IPC, PMC, 0x4111000); #define SEDI_PMU_BASE (0x04200000) #define SEDI_CCU_BASE 0x04300000 +#ifdef CONFIG_SOC_INTEL_ISH_5_8_0 +#define SEDI_IRQ_RESET_PREP (8) +#define SEDI_IRQ_PCIEDEV (11) +#define SEDI_IRQ_PMU2IOAPIC (12) +#else #define SEDI_IRQ_RESET_PREP (6) #define SEDI_IRQ_PCIEDEV (9) #define SEDI_IRQ_PMU2IOAPIC (10) +#endif /****** APIC *****/ #define SEDI_IOAPIC_BASE 0xFEC00000 diff --git a/bsp_sedi/soc/intel_ish/pm/aon/aon_task.c b/bsp_sedi/soc/intel_ish/pm/aon/aon_task.c index 100efb9..c6c1e8a 100644 --- a/bsp_sedi/soc/intel_ish/pm/aon/aon_task.c +++ b/bsp_sedi/soc/intel_ish/pm/aon/aon_task.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Intel Corporation + * Copyright (c) 2023-2024 Intel Corporation * * SPDX-License-Identifier: BSD-3-Clause */ @@ -312,7 +312,11 @@ static int restore_main_fw(void) /* SRAM needs time to enter retention mode */ #define CYCLES_PER_US 100 +#ifdef CONFIG_SOC_INTEL_ISH_5_8_0 +#define SRAM_RETENTION_US_DELAY 20 +#else #define SRAM_RETENTION_US_DELAY 5 +#endif #define SRAM_RETENTION_CYCLES_DELAY (SRAM_RETENTION_US_DELAY * CYCLES_PER_US) #ifdef CONFIG_SOC_INTEL_ISH_5_6_0 @@ -384,16 +388,34 @@ static void sram_power(int on) /** * check SRAM bank i power gated status in PMU_SRAM_PG_EN register + * 2 bits for one bank on ISH5.8, 1 bit on ISH5.4 * 1: power gated 0: not power gated */ -#define BANK_PG_STATUS(i) (read32(PMU_SRAM_PG_EN) & (0x1 << (i))) +#ifndef CONFIG_SOC_INTEL_ISH_5_8_0 +/* SRAM needs time to warm up after power on */ +#define SRAM_WARM_UP_DELAY_CNT 10 +#define SRAM_PG_BITS(i) (1 << i) +#else +/* SRAM needs time to warm up after power on */ +#define SRAM_WARM_UP_DELAY_CNT 2000 +#define SRAM_PG_BITS(i) (0x3 << (2 * i)) +/** + * check SRAM bank i power status in PMU_SRAM_PWR_STATUS register + * one bank has two tiles, 2 bits for one bank + * 1: ready for operation 0: not ready for operation + */ +#define BANK_PWR_STATUS(i) (read32(PMU_SRAM_PWR_STATUS) & SRAM_PG_BITS(i)) +#endif + +#define BANK_PG_STATUS(i) (read32(PMU_SRAM_PG_EN) & SRAM_PG_BITS(i)) /* enable power gate of a SRAM bank */ -#define BANK_PG_ENABLE(i) (write32(PMU_SRAM_PG_EN, (read32(PMU_SRAM_PG_EN) | (0x1 << (i))))) +#define BANK_PG_ENABLE(i) \ + (write32(PMU_SRAM_PG_EN, (read32(PMU_SRAM_PG_EN) | SRAM_PG_BITS(i)))) /* disable power gate of a SRAM bank */ -#define BANK_PG_DISABLE(i) \ - (write32(PMU_SRAM_PG_EN, (read32(PMU_SRAM_PG_EN) & (~(0x1 << (i)))))) +#define BANK_PG_DISABLE(i) \ + (write32(PMU_SRAM_PG_EN, (read32(PMU_SRAM_PG_EN) & (~SRAM_PG_BITS(i))))) /** * check SRAM bank i disabled status in ISH_SRAM_CTRL_CSFGR register @@ -411,9 +433,6 @@ static void sram_power(int on) (write32(ISH_SRAM_CTRL_CSFGR, \ (read32(ISH_SRAM_CTRL_CSFGR) | (0x1 << ((i) + 4))))) -/* SRAM needs time to warm up after power on */ -#define SRAM_WARM_UP_DELAY_CNT 10 - static void sram_power(int on) { int i; @@ -433,11 +452,15 @@ static void sram_power(int on) for (i = 0; i < SRAM_POWER_OFF_BANKS; i++) { - if (on && (BANK_PG_STATUS(i))) { + if (on) { /* power on and enable a bank */ BANK_PG_DISABLE(i); +#ifdef CONFIG_SOC_INTEL_ISH_5_8_0 + while (!BANK_PWR_STATUS(i)) + ; +#endif delay(SRAM_WARM_UP_DELAY_CNT); /* erase a bank */ @@ -451,6 +474,12 @@ static void sram_power(int on) } else { /* disable and power off a bank */ BANK_PG_ENABLE(i); + +#ifdef CONFIG_SOC_INTEL_ISH_5_8_0 + while (BANK_PWR_STATUS(i)) + ; +#endif + delay(SRAM_WARM_UP_DELAY_CNT); } /** @@ -565,65 +594,91 @@ static inline void clear_vnnred_aoncg(void) write32(CCU_AONCG_EN, 0); } -#ifdef CONFIG_SOC_INTEL_ISH_5_6_0 -#define STRINGIFY(x) #x -#define SLINE(num) STRINGIFY(num) -#define RETENTION_EXIT_CYCLES_DELAY 5 +/* SRAM needs 5 clock cycles to avoid power strike when out of retention */ +#define RETENTION_EXTRA_CYCLES_DELAY (5) + +#ifdef CONFIG_SOC_INTEL_ISH_5_8_0 +/* enable deep sleep of a SRAM bank */ +#define BANK_DS_ENABLE(i) \ + (write32(PMU_SRAM_DEEPSLEEP, read32(PMU_SRAM_DEEPSLEEP) | (0x3 << (2 * i)))) + +/* disable deep sleep of a SRAM bank */ +#define BANK_DS_DISABLE(i) \ + (write32(PMU_SRAM_DEEPSLEEP, read32(PMU_SRAM_DEEPSLEEP) & ~(0x3 << (2 * i)))) -static void sram_enter_sleep_mode(void) +/** + * check SRAM bank i power status in PMU_SRAM_PWR_STATUS register + * one bank has two tiles, 2 bit for one bank + * 1: ready for operation 0: not ready for operation + */ +#define BANK_PWR_STATUS(i) (read32(PMU_SRAM_PWR_STATUS) & (0x3 << (2 * i))) +#endif + +static void sram_retention(int out) { +#if defined(CONFIG_SOC_INTEL_ISH_5_6_0) uint32_t val, sum_mask, mask; sum_mask = mask = 0x1; val = read32(PMU_SRAM_DEEPSLEEP); while (sum_mask <= CONFIG_RAM_BANK_TILE_MASK) { - if (!(val & mask)) { - write32(PMU_SRAM_DEEPSLEEP, val | sum_mask); - while (read32(PMU_SRAM_PWR_STATUS) & mask) - ; + if (out) { + if ((val & mask)) { + write32(PMU_SRAM_DEEPSLEEP, val & ~sum_mask); + while (!(read32(PMU_SRAM_PWR_STATUS) & mask)) + ; + delay(RETENTION_EXTRA_CYCLES_DELAY); + } + } else { + if (!(val & mask)) { + write32(PMU_SRAM_DEEPSLEEP, val | sum_mask); + while (read32(PMU_SRAM_PWR_STATUS) & mask) + ; + } } mask <<= 1; sum_mask += mask; } -} - -static void sram_exit_sleep_mode(void) -{ - uint32_t val, sum_mask, mask; - - sum_mask = mask = 0x1; - val = read32(PMU_SRAM_DEEPSLEEP); - while (sum_mask <= CONFIG_RAM_BANK_TILE_MASK) { - if ((val & mask)) { - write32(PMU_SRAM_DEEPSLEEP, val & ~sum_mask); - while (!(read32(PMU_SRAM_PWR_STATUS) & mask)) +#elif defined(CONFIG_SOC_INTEL_ISH_5_8_0) + for (int i = 0; i < SRAM_POWER_OFF_BANKS; i++) { + if (out && !BANK_PWR_STATUS(i)) { + /* exit deep sleep on a bank */ + BANK_DS_DISABLE(i); + delay(RETENTION_EXTRA_CYCLES_DELAY); + while (!BANK_PWR_STATUS(i)) + ; + } else if (!out) { + /* enter deep sleep on a bank */ + BANK_DS_ENABLE(i); + while (BANK_PWR_STATUS(i)) ; - __asm__ volatile ( - "movl $"SLINE(RETENTION_EXIT_CYCLES_DELAY)", %%ecx;" - "loop .;\n\t" - : - : - : "ecx" - ); } - mask <<= 1; - sum_mask += mask; } -} +#else + if (out) { + /* set main SRAM into normal mode */ + write32(PMU_LDO_CTRL, PMU_LDO_ENABLE_BIT); + + /* + * poll LDO_READY status to make sure SRAM LDO is on + * (exited retention mode) + */ + while (!(read32(PMU_LDO_CTRL) & PMU_LDO_READY_BIT)) + continue; + } else { + /* set main SRAM into retention mode */ + write32(PMU_LDO_CTRL, (PMU_LDO_ENABLE_BIT + | PMU_LDO_RETENTION_BIT)); + } #endif +} static void handle_d0i2(void) { pg_exit_save_ctx(); aon_share.pg_exit = 0; -#ifdef CONFIG_SOC_INTEL_ISH_5_6_0 - sram_enter_sleep_mode(); -#else - /* set main SRAM into retention mode*/ - write32(PMU_LDO_CTRL, (PMU_LDO_ENABLE_BIT - | PMU_LDO_RETENTION_BIT)); -#endif + sram_retention(0); /* delay some cycles before halt */ delay(SRAM_RETENTION_CYCLES_DELAY); @@ -646,19 +701,7 @@ static void handle_d0i2(void) clear_vnnred_aoncg(); -#ifdef CONFIG_SOC_INTEL_ISH_5_6_0 - sram_exit_sleep_mode(); -#else - /* set main SRAM intto normal mode */ - write32(PMU_LDO_CTRL, PMU_LDO_ENABLE_BIT); - - /** - * poll LDO_READY status to make sure SRAM LDO is on - * (exited retention mode) - */ - while (!(read32(PMU_LDO_CTRL) & PMU_LDO_READY_BIT)) - continue; -#endif + sram_retention(1); if (read32(PMU_RST_PREP) & PMU_RST_PREP_AVAIL) handle_reset(ISH_PM_STATE_RESET_PREP); diff --git a/bsp_sedi/soc/intel_ish/pm/ish_dma.c b/bsp_sedi/soc/intel_ish/pm/ish_dma.c index 1535b7f..c3dd129 100644 --- a/bsp_sedi/soc/intel_ish/pm/ish_dma.c +++ b/bsp_sedi/soc/intel_ish/pm/ish_dma.c @@ -1,11 +1,98 @@ /* - * Copyright (c) 2023 Intel Corporation + * Copyright (c) 2023-2024 Intel Corporation * * SPDX-License-Identifier: BSD-3-Clause */ #include "ish_dma.h" +#ifdef CONFIG_SOC_INTEL_ISH_5_8_0 +void ish_dma_set_msb(uint32_t chan, uint32_t dst_msb, uint32_t src_msb) +{ + /* nothing to do */ + (void)chan; + (void)dst_msb; + (void)src_msb; +} + +int ish_dma_copy(uint32_t chan, uint64_t dst, uint64_t src, uint32_t length, + enum dma_mode mode) +{ + int rc = DMA_RC_OK; + uint32_t src_osr_lmt = (mode & SRC_IS_DRAM) ? DMA_OSR_LMT_DRAM : DMA_OSR_LMT_SRAM; + uint32_t dst_osr_lmt = (mode & DST_IS_DRAM) ? DMA_OSR_LMT_DRAM : DMA_OSR_LMT_SRAM; + + if (!length) { + return DMA_RC_OK; + } + + /* Bringup VNN power rail for accessing SoC fabric */ + write32(PMU_VNN_REQ, (1 << VNN_ID_DMA(chan))); + while (!(read32(PMU_VNN_REQ_ACK) & PMU_VNN_REQ_ACK_STATUS)) + continue; + + write64(DMAC_CFG_REG, DMAC_CFG_EN); + mode |= RD_NON_SNOOP | WR_NON_SNOOP; + write32(MISC_DMA_CTL_REG(chan), mode); + write64(DMA_CH_CTRL_REG(chan), DMA_CH_CTRL_VAL); + write64(DMA_CH_CFG2_REG(chan), DMA_CFG_H_VAL(dst_osr_lmt, src_osr_lmt)); + write64(DMA_CH_LLP_REG(chan), 0x0); + write64(DMA_CH_INT_EN_REG(chan), DMA_CH_INT_EN_VAL); + write64(DMA_CH_INT_CLR_REG(chan), read64(DMA_CH_INT_STS_REG(chan))); + + while (length) { + uint32_t chunk = (length > DMA_MAX_BLOCK_SIZE) ? + DMA_MAX_BLOCK_SIZE : length; + uint32_t block_ts = chunk >> DMA_SRC_TR_WIDTH; + + if (chunk % block_ts) { + block_ts++; + } + write64(DMA_CH_BLOCK_TS_REG(chan), block_ts - 1); + + write64(DMA_CH_SAR_REG(chan), src); + write64(DMA_CH_DAR_REG(chan), dst); + + write64(DMAC_CHEN_REG, DMAC_CHEN_CH_BITS(chan)); + while (read64(DMAC_CHEN_REG) & DMAC_CHEN_CH_BITS(chan)) { + ; + } + + if (read64(DMA_CH_INT_STS_REG(chan)) != DMA_INT_XFER_DONE) { + write64(DMA_CH_INT_CLR_REG(chan), read64(DMA_CH_INT_STS_REG(chan))); + rc = DMA_RC_HW; + break; + } + src += chunk; + dst += chunk; + length -= chunk; + write64(DMA_CH_INT_CLR_REG(chan), read64(DMA_CH_INT_STS_REG(chan))); + } + + /* Mark the DMA VNN power rail as no longer needed */ + write32(PMU_VNN_REQ, (1 << VNN_ID_DMA(chan))); + + return rc; +} + +void ish_dma_disable(void) +{ + /* Based on [ROM FAS], 2.1.3 "DMA Controller initialization". */ + uint32_t counter = 0; + + do { + ++counter; + } while ((uint8_t)read64(DMAC_CHEN_REG) && (counter < (UINT32_MAX / 64))); + + if ((uint8_t)read64(DMAC_CHEN_REG)) + write64(DMAC_RESET_REG, 1); + + write64(DMAC_INTSTS_EN_REG, 0); + write64(DMAC_INTSIG_EN_REG, 0); + write64(DMAC_INT_CLR_REG, read64(DMAC_INT_STAT_REG)); + write64(DMAC_CFG_REG, 0); +} +#else static int dma_init_called; /* If ish_dma_init is called */ static int dma_poll(uint32_t addr, uint32_t expected, uint32_t mask) @@ -71,7 +158,7 @@ void ish_dma_init(void) dma_init_called = 1; } -int ish_dma_copy(uint32_t chan, uint32_t dst, uint32_t src, uint32_t length, +int ish_dma_copy(uint32_t chan, uint64_t dst, uint64_t src, uint32_t length, enum dma_mode mode) { uint32_t chan_reg = DMA_REG_BASE + (DMA_CH_REGS_SIZE * chan); @@ -120,8 +207,8 @@ int ish_dma_copy(uint32_t chan, uint32_t dst, uint32_t src, uint32_t length, eflags = interrupt_lock(); write32(MISC_CHID_CFG_REG, chan); /* Set channel to configure */ write32(DMA_CTL_HIGH(chan_reg), chunk); /* Set number of bytes to transfer */ - write32(DMA_DAR(chan_reg), dst); /* Destination address */ - write32(DMA_SAR(chan_reg), src); /* Source address */ + write32(DMA_DAR(chan_reg), (uint32_t)dst); /* Destination address */ + write32(DMA_SAR(chan_reg), (uint32_t)src); /* Source address */ write32(DMA_EN_REG, DMA_CH_EN_BIT(chan) | DMA_CH_EN_WE_BIT(chan)); /* Enable the channel */ interrupt_unlock(eflags); @@ -178,3 +265,4 @@ void ish_dma_set_msb(uint32_t chan, uint32_t dst_msb, uint32_t src_msb) write32(MISC_DST_FILLIN_DMA(chan), dst_msb); interrupt_unlock(eflags); } +#endif diff --git a/bsp_sedi/soc/intel_ish/pm/ish_dma.h b/bsp_sedi/soc/intel_ish/pm/ish_dma.h index 3d3e41f..ebceae5 100644 --- a/bsp_sedi/soc/intel_ish/pm/ish_dma.h +++ b/bsp_sedi/soc/intel_ish/pm/ish_dma.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Intel Corporation + * Copyright (c) 2023-2024 Intel Corporation * * SPDX-License-Identifier: BSD-3-Clause */ @@ -22,6 +22,8 @@ #define DST_IS_DRAM BIT(0) #define SRC_IS_DRAM BIT(1) #define NON_SNOOP BIT(2) +#define RD_NON_SNOOP BIT(8) +#define WR_NON_SNOOP BIT(9) /* ISH5 and on */ #define RS0 0x0 @@ -59,7 +61,7 @@ void ish_dma_init(void); * @param mode Transfer mode * @return DMA_RC_OK, or non-zero if error. */ -int ish_dma_copy(uint32_t chan, uint32_t dst, uint32_t src, uint32_t length, +int ish_dma_copy(uint32_t chan, uint64_t dst, uint64_t src, uint32_t length, enum dma_mode mode); /** * Set upper 32 bits address for DRAM diff --git a/bsp_sedi/soc/intel_ish/pm/ish_pm.c b/bsp_sedi/soc/intel_ish/pm/ish_pm.c index cf20ba1..dfa60e3 100644 --- a/bsp_sedi/soc/intel_ish/pm/ish_pm.c +++ b/bsp_sedi/soc/intel_ish/pm/ish_pm.c @@ -14,6 +14,7 @@ #include #include #include +#include /* defined in link script: soc/x86/intel_ish/scripts/ish_linker.ld */ extern uint32_t __text_region_start; @@ -37,6 +38,43 @@ extern uint32_t _image_ram_end; static sedi_uart_config_t uart0_cfg, uart1_cfg, uart2_cfg; +struct { + sedi_devid_t id; + uint32_t reg; + uint32_t bits; +} static pm_cg_info[] = { + { + .id = SEDI_DEVID_UART0, + .reg = CCU_BCG_UART, + .bits = CCU_BCG_BIT_UART0, + }, + { + .id = SEDI_DEVID_UART1, + .reg = CCU_BCG_UART, + .bits = CCU_BCG_BIT_UART1, + }, + { + .id = SEDI_DEVID_UART2, + .reg = CCU_BCG_UART, + .bits = CCU_BCG_BIT_UART2, + }, + { + .id = SEDI_DEVID_I2C0, + .reg = CCU_BCG_I2C, + .bits = CCU_BCG_BIT_I2C0, + }, + { + .id = SEDI_DEVID_I2C1, + .reg = CCU_BCG_I2C, + .bits = CCU_BCG_BIT_I2C1, + }, + { + .id = SEDI_DEVID_I2C2, + .reg = CCU_BCG_I2C, + .bits = CCU_BCG_BIT_I2C2, + }, +}; + static void uart_to_idle(void) { sedi_uart_get_config(SEDI_UART_0, &uart0_cfg); @@ -70,8 +108,8 @@ static void pg_exit_restore_hw(void) write32(LAPIC_SPUR, LAPIC_ENABLE | LAPIC_SPUR_RESET); write32(CCU_RST_HST, read32(CCU_RST_HST)); - write32(CCU_TCG_ENABLE, 0); - write32(CCU_BCG_ENABLE, 0); + write32(CCU_TCG_DISABLE, 0); + write32(CCU_BCG_DISABLE, 0); write32(CCU_BCG_MIA, 0); write32(CCU_BCG_DMA, 0); @@ -253,13 +291,21 @@ static void init_aon_task(void) aon_share->main_fw_ro_size = (uint32_t)&__rodata_region_end - (uint32_t)&__text_region_start; +#ifdef CONFIG_SOC_INTEL_ISH_5_8_0 + aon_share->main_fw_rw_addr = (uint32_t)&__rodata_region_end; + aon_share->main_fw_rw_size = (uint32_t)&_image_ram_end - + (uint32_t)&__rodata_region_end; +#else aon_share->main_fw_rw_addr = (uint32_t)&_image_ram_start; aon_share->main_fw_rw_size = (uint32_t)&_image_ram_end - (uint32_t)&_image_ram_start; +#endif +#ifndef CONFIG_SOC_INTEL_ISH_5_8_0 aon_share->uma_msb = read32(IPC_UMA_RANGE_LOWER_1); ish_dma_init(); +#endif } static inline void check_aon_task_status(void) @@ -514,11 +560,32 @@ static void pre_setting_d0ix(void) { write32(PMU_VNN_REQ, read32(PMU_VNN_REQ)); uart_to_idle(); + + /* clear registers */ + write32(PMU_CG_PG_STATUS, read32(PMU_CG_PG_STATUS)); + write32(PMU_WAKE_EVENT1, read32(PMU_WAKE_EVENT1)); + write32(PMU_WAKE_EVENT2, read32(PMU_WAKE_EVENT2)); } static void post_setting_d0ix(void) { + uint32_t cg_pg_status, wk_event_1, wk_event_2, fabric_idle_timeout_snapshot; + uart_port_restore(); + + cg_pg_status = read32(PMU_CG_PG_STATUS); + wk_event_1 = read32(PMU_WAKE_EVENT1); + wk_event_2 = read32(PMU_WAKE_EVENT2); + if (cg_pg_status & PMU_STATUS_CG_ABORT) { + PM_LOG("CG_PG_STATUS: 0x%x, Wake_event_1: 0x%x, Wake_event_2: 0x%x\n", + cg_pg_status, wk_event_1, wk_event_2); + fabric_idle_timeout_snapshot = read32(PMU_FABRIC_SNAPSHOT); + if (fabric_idle_timeout_snapshot) { + PM_LOG("FABRIC_IDLE_TIMEOUT_SNAPSHOT: 0x%x\n", + fabric_idle_timeout_snapshot); + write32(PMU_FABRIC_SNAPSHOT, fabric_idle_timeout_snapshot); + } + } } void sedi_pm_enter_power_state(int state) @@ -616,6 +683,8 @@ void sedi_pm_init(void) /* clear reset history register in CCU */ write32(CCU_RST_HST, read32(CCU_RST_HST)); + write32(CCU_TCG_DISABLE, 0); + write32(CCU_BCG_DISABLE, 0); /* disable TCG and disable BCG */ write32(CCU_TCG_EN, 0); reset_bcg(); @@ -711,3 +780,55 @@ void command_idle_stats(void) PM_LOG(" error counts: %u\n", aon_share->error_count); } } + +/** + * Reset low power idle statistics + */ +void reset_pm_stats(void) +{ + memset(&pm_stats, 0, sizeof(pm_stats)); +} + +static int pm_get_cg_info(sedi_devid_t id, uint32_t *reg, uint32_t *reg_bits) +{ + *reg = 0x0; + *reg_bits = 0x0; + + for (int i = 0; i < ARRAY_SIZE(pm_cg_info); i++) { + if (pm_cg_info[i].id == id) { + *reg = pm_cg_info[i].reg; + *reg_bits = pm_cg_info[i].bits; + return SEDI_DRIVER_OK; + } + } + + return (*reg != 0x0) ? SEDI_DRIVER_OK : SEDI_DRIVER_ERROR; +} + +static void pm_change_cg_state(sedi_devid_t id, bool perform_cg) +{ + uint32_t bits, bcg_reg; + uint32_t old_val, new_val; + + if (pm_get_cg_info(id, &bcg_reg, &bits) != SEDI_DRIVER_OK) + return; + + while (1) { + old_val = read32(bcg_reg); + + if (perform_cg) + new_val = old_val | bits; + else + new_val = old_val & ~bits; + + if (atomic_cas((atomic_t *)bcg_reg, (atomic_val_t)old_val, (atomic_val_t)new_val)) + break; + } +} + +void sedi_pm_set_device_power(IN sedi_devid_t id, IN sedi_power_state_t state) +{ + if ((id >= SEDI_DEVID_FIRST) && (id < SEDI_DEVID_TOP)) { + pm_change_cg_state(id, (state != SEDI_POWER_FULL)); + } +} diff --git a/bsp_sedi/soc/intel_ish/pm/ish_pm.h b/bsp_sedi/soc/intel_ish/pm/ish_pm.h index 9994c9f..0aa3969 100644 --- a/bsp_sedi/soc/intel_ish/pm/ish_pm.h +++ b/bsp_sedi/soc/intel_ish/pm/ish_pm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Intel Corporation + * Copyright (c) 2023-2024 Intel Corporation * * SPDX-License-Identifier: BSD-3-Clause */ @@ -47,7 +47,10 @@ static inline void ish_mia_halt(void) { /* make sure interrupts are enabled before halting */ __asm__ volatile("sti;\n" - "hlt;"); + "hlt;\n" + "nop;\n" + "nop;\n" + "cli;"); } /* reset ISH mintue-ia cpu core */ diff --git a/bsp_sedi/soc/intel_ish/pm/pm_regs.h b/bsp_sedi/soc/intel_ish/pm/pm_regs.h index f0ecf2b..2b1c31e 100644 --- a/bsp_sedi/soc/intel_ish/pm/pm_regs.h +++ b/bsp_sedi/soc/intel_ish/pm/pm_regs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Intel Corporation + * Copyright (c) 2023-2024 Intel Corporation * * SPDX-License-Identifier: BSD-3-Clause */ @@ -88,13 +88,19 @@ #define PMU_LDO_CALIBRATION_BIT BIT(2) #define PMU_LDO_READY_BIT BIT(3) +#define PMU_CG_PG_STATUS (SEDI_PMU_BASE + 0x68) +#define PMU_STATUS_CG_ABORT BIT(1) +#define PMU_WAKE_EVENT1 (SEDI_PMU_BASE + 0xc) +#define PMU_WAKE_EVENT2 (SEDI_PMU_BASE + 0x48) +#define PMU_FABRIC_SNAPSHOT (SEDI_PMU_BASE + 0x60) + /* CCU Registers */ #define CCU_TCG_EN (SEDI_CCU_BASE + 0x0) #define CCU_BCG_EN (SEDI_CCU_BASE + 0x4) #define CCU_WDT_CD (SEDI_CCU_BASE + 0x7c) #define CCU_RST_HST (SEDI_CCU_BASE + 0x3c) -#define CCU_TCG_ENABLE (SEDI_CCU_BASE + 0x40) -#define CCU_BCG_ENABLE (SEDI_CCU_BASE + 0x44) +#define CCU_TCG_DISABLE (SEDI_CCU_BASE + 0x40) +#define CCU_BCG_DISABLE (SEDI_CCU_BASE + 0x44) #define CCU_BCG_MIA (SEDI_CCU_BASE + 0x4) #define CCU_BCG_UART (SEDI_CCU_BASE + 0x8) #define CCU_BCG_I2C (SEDI_CCU_BASE + 0xc) @@ -103,17 +109,13 @@ #define CCU_BCG_DMA (SEDI_CCU_BASE + 0x28) #define CCU_AONCG_EN (SEDI_CCU_BASE + 0xdc) #define CCU_BCG_BIT_MIA BIT(0) -#define CCU_BCG_BIT_DMA BIT(1) -#define CCU_BCG_BIT_I2C0 BIT(2) -#define CCU_BCG_BIT_I2C1 BIT(3) -#define CCU_BCG_BIT_SPI BIT(4) -#define CCU_BCG_BIT_SRAM BIT(5) -#define CCU_BCG_BIT_HPET BIT(6) -#define CCU_BCG_BIT_UART BIT(7) -#define CCU_BCG_BIT_GPIO BIT(8) -#define CCU_BCG_BIT_I2C2 BIT(9) -#define CCU_BCG_BIT_SPI2 BIT(10) -#define CCU_BCG_BIT_ALL (0x7ff) + +#define CCU_BCG_BIT_I2C0 BIT(0) +#define CCU_BCG_BIT_I2C1 BIT(1) +#define CCU_BCG_BIT_I2C2 BIT(2) +#define CCU_BCG_BIT_UART0 BIT(0) +#define CCU_BCG_BIT_UART1 BIT(1) +#define CCU_BCG_BIT_UART2 BIT(2) #define CCU_SW_RST BIT(0) #define CCU_WDT_RST BIT(1) @@ -134,6 +136,81 @@ #define MISC_ISH_RTC_COUNTER1 (MISC_REG_BASE + 0x74) /* DMA registers */ +#ifdef CONFIG_SOC_INTEL_ISH_5_8_0 +/* DMA controller global interface */ +#define DMAC_CFG_REG (DMA_REG_BASE + 0x10) +#define DMAC_CFG_EN BIT(0) +#define DMAC_CFG_INT_EN BIT(1) +#define DMAC_CHEN_REG (DMA_REG_BASE + 0x18) +#define DMAC_CHEN_CH_BITS(chan) ((0x1 << (chan)) | (0x1 << (8 + (chan)))) +#define DMAC_INT_CLR_REG (DMA_REG_BASE + 0x38) +#define DMAC_INTSTS_EN_REG (DMA_REG_BASE + 0x40) +#define DMAC_INTSIG_EN_REG (DMA_REG_BASE + 0x48) +#define DMAC_INT_STAT_REG (DMA_REG_BASE + 0x50) +#define DMAC_RESET_REG (DMA_REG_BASE + 0x58) + +#define DMA_CH_SAR_REG(ch) (DMA_REG_BASE + (ch + 1) * 0x100 + 0x0) +#define DMA_CH_DAR_REG(ch) (DMA_REG_BASE + (ch + 1) * 0x100 + 0x8) +#define DMA_CH_BLOCK_TS_REG(ch) (DMA_REG_BASE + (ch + 1) * 0x100 + 0x10) +#define DMA_CH_CTRL_REG(ch) (DMA_REG_BASE + (ch + 1) * 0x100 + 0x18) +#define DMA_CH_CFG2_REG(ch) (DMA_REG_BASE + (ch + 1) * 0x100 + 0x20) +#define DMA_CH_LLP_REG(ch) (DMA_REG_BASE + (ch + 1) * 0x100 + 0x28) +#define DMA_CH_INT_EN_REG(ch) (DMA_REG_BASE + (ch + 1) * 0x100 + 0x80) +#define DMA_CH_INT_STS_REG(ch) (DMA_REG_BASE + (ch + 1) * 0x100 + 0x88) +#define DMA_CH_INT_CLR_REG(ch) (DMA_REG_BASE + (ch + 1) * 0x100 + 0x98) + +#define DMA_INT_XFER_DONE BIT(1) +#define DMA_INT_SRC_DECERR BIT(5) +#define DMA_INT_DST_DECERR BIT(6) +#define DMA_INT_SRC_SLVERR BIT(7) +#define DMA_INT_DST_SLVERR BIT(8) +#define DMA_INT_CH_DISABLE BIT(30) +#define DMA_INT_CH_ABORT BIT(31) + +#define DMA_INT_ERR_L \ + (DMA_INT_SRC_SLVERR | DMA_INT_DST_SLVERR \ + | DMA_INT_SRC_DECERR | DMA_INT_DST_DECERR) + +#define DMA_INT_STOP (DMA_INT_CH_ABORT | DMA_INT_CH_DISABLE | DMA_INT_XFER_DONE) + +#define DMA_CH_INT_EN_VAL ((uint64_t)(DMA_INT_STOP | DMA_INT_ERR_L)) + +#define DMA_MAX_BLOCK_TS (4096) +#define DMA_SRC_MSIZE (3) +#define DMA_SRC_MSIZE_OFF (14) +#define DMA_DST_MSIZE (3) +#define DMA_DST_MSIZE_OFF (18) +#define DMA_SRC_TR_WIDTH (3) +#define DMA_DST_TR_WIDTH (3) +#define DMA_MAX_BLOCK_SIZE (DMA_MAX_BLOCK_TS << DMA_SRC_TR_WIDTH) + +#define AR_CACHE_OFF 22 +#define AR_CACHE_VAL 0 +#define AW_CACHE_OFF 26 +#define AW_CACHE_VAL 3 +#define NONPOSTED_LASTWRITE_EN (1 << 30) + +#define DMA_CH_CTRL_VAL \ + ((DMA_DST_MSIZE << DMA_DST_MSIZE_OFF) \ + | (DMA_SRC_MSIZE << DMA_SRC_MSIZE_OFF) \ + | (DMA_SRC_TR_WIDTH << 8) | (DMA_DST_TR_WIDTH << 11) \ + | (AR_CACHE_VAL << AR_CACHE_OFF) | (AW_CACHE_VAL << AW_CACHE_OFF) \ + | NONPOSTED_LASTWRITE_EN) + +/* 3 outstanding request for SRAM */ +#define DMA_OSR_LMT_SRAM 2 +/* 16 outstanding request for DRAM */ +#define DMA_OSR_LMT_DRAM 0xF + +#define DMA_CFG_DST_OSR_LMT_OFF 27 +#define DMA_CFG_SRC_OSR_LMT_OFF 23 + +#define DMA_CFG_DST_OSR_LMT(val) ((val) << DMA_CFG_DST_OSR_LMT_OFF) +#define DMA_CFG_SRC_OSR_LMT(val) ((val) << DMA_CFG_SRC_OSR_LMT_OFF) + +#define DMA_CFG_H_VAL(dst, src) \ + (DMA_CFG_DST_OSR_LMT(dst) | DMA_CFG_SRC_OSR_LMT(src)) +#else #define DMA_CH_REGS_SIZE 0x58 #define DMA_CLR_BLOCK_REG (DMA_REG_BASE + 0x340) #define DMA_CLR_ERR_REG (DMA_REG_BASE + 0x358) @@ -170,6 +247,7 @@ #define SRC_BURST_SIZE 3 #define DEST_TR_WIDTH 2 #define DEST_BURST_SIZE 3 +#endif /* GPIO Registers */ #define ISH_GPIO_BASE SEDI_IREG_BASE(GPIO, 0) diff --git a/zephyr/iut_test/prj.conf b/zephyr/iut_test/prj.conf index c7d3216..98019ab 100644 --- a/zephyr/iut_test/prj.conf +++ b/zephyr/iut_test/prj.conf @@ -4,6 +4,14 @@ # SPDX-License-Identifier: Apache-2.0 # +# kernel +CONFIG_TICKLESS_KERNEL=y +CONFIG_TIMESLICING=n + +# stack +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_IDLE_STACK_SIZE=1024 + CONFIG_MAIN_THREAD_PRIORITY=14 # basic @@ -45,3 +53,12 @@ CONFIG_GPIO=y CONFIG_SPI=y CONFIG_ASSERT=y + +# uart +CONFIG_SERIAL=y +CONFIG_UART_SEDI=y +CONFIG_UART_INTERRUPT_DRIVEN=y + +# PM +CONFIG_PM=y +CONFIG_PM_DEVICE=y diff --git a/zephyr/iut_test/src/shell_iut.c b/zephyr/iut_test/src/shell_iut.c index 55a0bc8..128e0c3 100644 --- a/zephyr/iut_test/src/shell_iut.c +++ b/zephyr/iut_test/src/shell_iut.c @@ -1,13 +1,14 @@ /* - * Copyright (c) 2023 Intel Corporation. + * Copyright (c) 2023-2024 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ #include #include -#include "iut.h" #include +#include +#include "iut.h" extern int iut_trigger(size_t argc, char **argv); @@ -56,8 +57,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_iut, SHELL_CMD_REGISTER(iut, &sub_iut, "IUT commands", NULL); -#ifdef _CONFIG_PM -static const struct shell_uart *sh_uart; +#ifdef CONFIG_PM +static SHELL_UART_STRUCT * sh_uart; void iut_shell_suspend(void) { @@ -71,22 +72,29 @@ void iut_shell_suspend(void) } /*get shell uart backend*/ - sh_uart = (const struct shell_uart *)shell_ptr->iface->ctx; + sh_uart = (SHELL_UART_STRUCT *)shell_ptr->iface->ctx; if (sh_uart == NULL) { iut_print("get shell UART pointer error!!!\n"); return; } } - - k_timer_stop(sh_uart->timer); +#ifdef CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN + uart_irq_rx_disable(sh_uart->common.dev); +#else + k_timer_stop(&sh_uart->rx_timer); +#endif } void iut_shell_resume(void) { if (sh_uart) { - k_timer_start(sh_uart->timer, K_NO_WAIT, +#ifdef CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN + uart_irq_rx_enable(sh_uart->common.dev); +#else + k_timer_start(&sh_uart->rx_timer, K_NO_WAIT, K_MSEC(CONFIG_SHELL_BACKEND_SERIAL_RX_POLL_PERIOD)); +#endif } } #endif diff --git a/zephyr/iut_test/test_zephyr/CMakeLists.txt b/zephyr/iut_test/test_zephyr/CMakeLists.txt index 125ea56..8ffc8e1 100644 --- a/zephyr/iut_test/test_zephyr/CMakeLists.txt +++ b/zephyr/iut_test/test_zephyr/CMakeLists.txt @@ -15,5 +15,9 @@ if(CONFIG_GPIO_SEDI) target_sources(app PRIVATE gpio/test_gpio.c) endif() +if(CONFIG_PM) + target_sources(app PRIVATE pm/test_pm.c) +endif() + target_sources(app PRIVATE x86/test_fatal.c) target_sources(app PRIVATE timer/test_sys_clock.c) diff --git a/zephyr/iut_test/test_zephyr/pm/test_pm.c b/zephyr/iut_test/test_zephyr/pm/test_pm.c new file mode 100644 index 0000000..c6a11fd --- /dev/null +++ b/zephyr/iut_test/test_zephyr/pm/test_pm.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2021-2024 Intel Corporation. All Rights Reserved. + * + * This software and the related documents are Intel copyrighted materials, + * and your use of them is governed by the express license under which they + * were provided to you ("License"). Unless the License provides otherwise, + * you may not use, modify, copy, publish, distribute, disclose or transmit + * this software or the related documents without Intel's prior written + * permission. + * + * This software and the related documents are provided as is, with no express + * or implied warranties, other than those that are expressly stated in the + * License. + */ + +#include +#include +#include +#include "iut.h" + +#define TEST_PM_D0I0_MS_SLEEP (1) +#define TEST_PM_D0I1_MS_SLEEP (3) +#define TEST_PM_D0I2_MS_SLEEP (1000) +#define TEST_PM_D0I3_MS_SLEEP (5000) + +#define PM_ENTER_D0 0 +#define PM_ENTER_D0i1 1 +#define PM_ENTER_D0i2 2 +#define PM_ENTER_D0i3 3 + +extern void iut_shell_suspend(void); +extern void iut_shell_resume(void); +extern void reset_pm_stats(void); +extern void command_idle_stats(void); + +/* usage: iut_run test_pm [pm level: 0-D0, 1-D0i1, 2-D0i2, 3-D0i3] [ms_sleep]*/ +static int test_pm_d0ix(int argc, char **argv); +DEFINE_IUT_CASE(pm_d0ix, test_pm, IUT_ATTRI_NONE); + +static int test_pm_d0i3(int argc, char **argv); +DEFINE_IUT_CASE(pm_d0i3, test_pm, IUT_ATTRI_AUTORUN); + +static int test_pm_d0i2(int argc, char **argv); +DEFINE_IUT_CASE(pm_d0i2, test_pm, IUT_ATTRI_NONE); + +static int test_pm_d0i1(int argc, char **argv); +DEFINE_IUT_CASE(pm_d0i1, test_pm, IUT_ATTRI_NONE); + +static int test_pm_d0(int argc, char **argv); +DEFINE_IUT_CASE(pm_d0, test_pm, IUT_ATTRI_NONE); + +static int test_pm_stress(int argc, char **argv); +DEFINE_IUT_CASE(pm_stress, test_pm, IUT_ATTRI_NONE); + +static const char *const pm_level_str[PM_ENTER_D0i3 + 1] = { + "D0", + "D0i1", + "D0i2", + "D0i3", +}; + +static inline void clear_pm_stats(void) +{ + reset_pm_stats(); +} + +static void dump_pm_stats(uint32_t ms_sleep) +{ + ARG_UNUSED(ms_sleep); + command_idle_stats(); +} + +static void _test_pm(uint32_t pm_level, uint32_t ms_sleep) +{ + clear_pm_stats(); + + iut_case_print("test [%s]: going to sleep %u ms\n", + pm_level_str[pm_level], ms_sleep); + + iut_shell_suspend(); + + k_msleep(ms_sleep); + + iut_shell_resume(); + + dump_pm_stats(ms_sleep); +} + +static inline int _test_pm_d0(uint32_t ms_sleep) +{ + _test_pm(PM_ENTER_D0, ms_sleep); + TEST_ASSERT_TRUE(1); + + return IUT_ERR_OK; +} + +static int test_pm_d0(int argc, char **argv) +{ + return _test_pm_d0(TEST_PM_D0I0_MS_SLEEP); +} + +static inline int _test_pm_d0i1(uint32_t ms_sleep) +{ + _test_pm(PM_ENTER_D0i1, ms_sleep); + TEST_ASSERT_TRUE(1); + + return IUT_ERR_OK; +} + +static int test_pm_d0i1(int argc, char **argv) +{ + return _test_pm_d0i1(TEST_PM_D0I1_MS_SLEEP); +} + +static inline int _test_pm_d0i2(uint32_t ms_sleep) +{ + _test_pm(PM_ENTER_D0i2, ms_sleep); + TEST_ASSERT_TRUE(1); + + return IUT_ERR_OK; +} + +static int test_pm_d0i2(int argc, char **argv) +{ + return _test_pm_d0i2(TEST_PM_D0I2_MS_SLEEP); +} + +static inline int _test_pm_d0i3(uint32_t ms_sleep) +{ + _test_pm(PM_ENTER_D0i3, ms_sleep); + TEST_ASSERT_TRUE(1); + + return IUT_ERR_OK; +} + +static int test_pm_d0i3(int argc, char **argv) +{ + return _test_pm_d0i3(TEST_PM_D0I3_MS_SLEEP); +} + +static int test_pm_d0ix(int argc, char **argv) +{ + uint32_t ms_sleep = TEST_PM_D0I3_MS_SLEEP; + uint32_t pm_level = PM_ENTER_D0i3; + + if (argc) { + pm_level = (uint32_t)strtoul(argv[0], NULL, 0); + } + if (argc > 1) { + ms_sleep = (uint32_t)strtoul(argv[1], NULL, 0); + } + + switch (pm_level) { + case PM_ENTER_D0: + _test_pm_d0(ms_sleep); + break; + case PM_ENTER_D0i1: + _test_pm_d0i1(ms_sleep); + break; + case PM_ENTER_D0i2: + _test_pm_d0i2(ms_sleep); + break; + case PM_ENTER_D0i3: + _test_pm_d0i3(ms_sleep); + break; + default: + iut_case_print("wrong pm_level %u out of (0 - 3), exit\n", + pm_level); + TEST_ASSERT_TRUE(0); + } + + return IUT_ERR_OK; +} + +typedef int (*pm_test_fn)(int argc, char **argv); +static pm_test_fn pm_test_funcs[] = { + &test_pm_d0i1, + &test_pm_d0i2, + &test_pm_d0i3, +}; + +#define PM_TEST_FUNC_NUM (ARRAY_SIZE(pm_test_funcs)) + +static int test_pm_stress(int argc, char **argv) +{ + uint32_t round = 5; + + if (argc) { + round = (uint32_t)strtoul(argv[0], NULL, 0); + } + while (round--) { + uint32_t idx = (uint32_t)z_tsc_read() % PM_TEST_FUNC_NUM; + + k_msleep(1000); + pm_test_funcs[idx](0, NULL); + } + + return IUT_ERR_OK; +}