summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Feng <li1.feng@intel.com>2022-11-03 09:59:18 -0700
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-11-15 00:23:15 +0000
commit8b3da602888d0013db6fb38617d707f89c0565f9 (patch)
tree5884765420a31549c1332824ef70a1a13a49028b
parent9d21e1334139db03bc68a560bf1814bc5ac4bcde (diff)
downloadchrome-ec-8b3da602888d0013db6fb38617d707f89c0565f9.tar.gz
chip/ish: fix system shutdown in D0i3
ISH should set PMC LTR(Latency Tolerance Reporting) for DMA operation. Without doing this, we observed system shutdown during D0i3. This CL set LTR to 2ms before DMA operation and set LTR to a large number after DMA operation is completed to enable SOC to go into the lowest possible power state. BUG=b:234136500 BRANCH=none TEST=on Nirwen platform, ISH enter D0i3 host loading case, and also stitching to coreboot case; S0i3 is hit and no shutdown. Signed-off-by: Leifu Zhao <leifu.zhao@intel.com> Signed-off-by: Li Feng <li1.feng@intel.com> Change-Id: Ib0fe907470774998dda29a40197d6c18ad6372f1 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4003320 Code-Coverage: Haribalaraman Ramasubramanian <haribalaraman.r@intel.corp-partner.google.com> Reviewed-by: Kyoung Kim <kyoung.il.kim@gmail.com> Reviewed-by: Haribalaraman Ramasubramanian <haribalaraman.r@intel.corp-partner.google.com> Commit-Queue: Kangheui Won <khwon@chromium.org> Tested-by: Haribalaraman Ramasubramanian <haribalaraman.r@intel.corp-partner.google.com> Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com> Reviewed-by: Kangheui Won <khwon@chromium.org>
-rw-r--r--chip/ish/aontaskfw/ish_aontask.c71
-rw-r--r--chip/ish/dma.c40
-rw-r--r--chip/ish/ish_dma.h41
-rw-r--r--chip/ish/registers.h54
4 files changed, 166 insertions, 40 deletions
diff --git a/chip/ish/aontaskfw/ish_aontask.c b/chip/ish/aontaskfw/ish_aontask.c
index d167f3f5df..58d62d1891 100644
--- a/chip/ish/aontaskfw/ish_aontask.c
+++ b/chip/ish/aontaskfw/ish_aontask.c
@@ -91,6 +91,56 @@
static void handle_reset(enum ish_pm_state pm_state);
+#if defined(CHIP_VARIANT_ISH5P4)
+static void sb_upstream_write_raw_base(uint32_t addr, uint32_t attr,
+ uint32_t data, uint32_t sairs,
+ uint8_t addr48, uint16_t addr_hi)
+{
+ uint32_t eflags;
+ uint32_t addr_hi_32;
+
+ addr_hi_32 = addr_hi | (1 << 31);
+
+ eflags = interrupt_lock();
+
+ PMU_VNN_REQ = (1 << VNN_ID_SIDEBAND);
+ while (!(PMU_VNN_REQ_ACK & PMU_VNN_REQ_ACK_STATUS))
+ continue;
+
+ if (dma_poll(SBEP_REG_UP_MSG_STATUS_ADDR, 0, UP_STATUS_BUSY_MASK) ==
+ DMA_RC_OK) {
+ SBEP_REG_UP_MSG_REQ_ADDR_LOW = addr;
+
+ if (addr48) {
+ SBEP_REG_UP_MSG_REQ_ADDR_HIGH = addr_hi_32;
+ } else {
+ SBEP_REG_UP_MSG_REQ_ADDR_HIGH = 0;
+ }
+
+ SBEP_REG_UP_MSG_REQ_ATTR = attr;
+ SBEP_REG_UP_MSG_REQ_DATA = data;
+ SBEP_REG_UP_MSG_REQ_EH = sairs;
+ SBEP_REG_UP_MSG_COMMAND = SBEP_CMD_WRITE;
+
+ dma_poll(SBEP_REG_UP_MSG_STATUS_ADDR, 0, UP_STATUS_BUSY_MASK);
+ dma_poll(SBEP_REG_UP_MSG_STATUS_ADDR, UP_STATUS_MSG_SENT_MASK,
+ UP_STATUS_MSG_SENT_MASK);
+ SBEP_REG_UP_MSG_STATUS = UP_STATUS_MSG_SENT_CLR;
+ }
+
+ PMU_VNN_REQ = (1 << VNN_ID_SIDEBAND);
+ interrupt_unlock(eflags);
+}
+
+static void sb_upstream_write_raw(uint32_t addr, uint32_t attr, uint32_t data,
+ uint32_t sairs)
+{
+ addr = addr & 0x0000FFFF;
+
+ sb_upstream_write_raw_base(addr, attr, data, sairs, 0, 0);
+}
+#endif
+
/* ISR for PMU wakeup interrupt */
static void pmu_wakeup_isr(void)
{
@@ -670,6 +720,13 @@ static void handle_d0i3(void)
aon_share.pg_exit = 0;
}
+#if defined(CHIP_VARIANT_ISH5P4)
+ /* Set PMC LTR to 2ms before DMA copy */
+ if (IS_ENABLED(CONFIG_ISH_NEW_PM))
+ sb_upstream_write_raw(0, LTR_CMD_ATTR, LTR_CMD_DATA_2MS,
+ SBEP_PMC_SAIRS_VAL);
+#endif
+
/* store main FW 's context to IMR DDR from main SRAM */
ret = store_main_fw();
@@ -680,6 +737,13 @@ static void handle_d0i3(void)
/* power off main SRAM */
sram_power(0);
+#if defined(CHIP_VARIANT_ISH5P4)
+ /* Set LTR to a large number after DMA copy done */
+ if (IS_ENABLED(CONFIG_ISH_NEW_PM))
+ sb_upstream_write_raw(0, LTR_CMD_ATTR, LTR_CMD_DATA_INFINITE,
+ SBEP_PMC_SAIRS_VAL);
+#endif
+
set_vnnred_aoncg();
if (IS_ENABLED(CONFIG_ISH_IPAPG) && is_ipapg_allowed()) {
@@ -712,6 +776,13 @@ static void handle_d0i3(void)
aon_share.uma_msb);
}
+#if defined(CHIP_VARIANT_ISH5P4)
+ /* Set PMC LTR to 2ms before DMA copy */
+ if (IS_ENABLED(CONFIG_ISH_NEW_PM))
+ sb_upstream_write_raw(0, LTR_CMD_ATTR, LTR_CMD_DATA_2MS,
+ SBEP_PMC_SAIRS_VAL);
+#endif
+
/* restore main FW 's context to main SRAM from IMR DDR */
ret = restore_main_fw();
diff --git a/chip/ish/dma.c b/chip/ish/dma.c
index 48a27a0463..e2f1aba8ed 100644
--- a/chip/ish/dma.c
+++ b/chip/ish/dma.c
@@ -13,28 +13,6 @@
static int dma_init_called; /* If ish_dma_init is called */
-static int dma_poll(uint32_t addr, uint32_t expected, uint32_t mask)
-{
- int retval = -1;
- uint32_t counter = 0;
-
- /*
- * The timeout is approximately 2.2 seconds according to
- * value of UINT32_MAX, 120MHZ ISH clock frequency and
- * instruction count which is around 4.
- */
- while (counter < (UINT32_MAX / 64)) {
- /* test condition */
- if ((REG32(addr) & mask) == expected) {
- retval = DMA_RC_OK;
- break;
- }
- counter++;
- }
-
- return retval;
-}
-
void ish_dma_ocp_timeout_disable(void)
{
if (!IS_ENABLED(CONFIG_ISH_NEW_PM)) {
@@ -44,24 +22,6 @@ void ish_dma_ocp_timeout_disable(void)
}
}
-static inline uint32_t interrupt_lock(void)
-{
- uint32_t eflags = 0;
- __asm__ volatile("pushfl;" /* save eflag value */
- "popl %0;"
- "cli;"
- : "=r"(eflags)); /* shut off interrupts */
- return eflags;
-}
-
-static inline void interrupt_unlock(uint32_t eflags)
-{
- __asm__ volatile("pushl %0;" /* restore elfag values */
- "popfl;"
- :
- : "r"(eflags));
-}
-
void dma_configure_psize(void)
{
/* Give chan0 512 bytes for high performance, and chan1 128 bytes. */
diff --git a/chip/ish/ish_dma.h b/chip/ish/ish_dma.h
index fb9c4f4f06..89d6cb7342 100644
--- a/chip/ish/ish_dma.h
+++ b/chip/ish/ish_dma.h
@@ -27,6 +27,47 @@
#define PAGE_SIZE 4096
+static inline uint32_t interrupt_lock(void)
+{
+ uint32_t eflags = 0;
+
+ __asm__ volatile("pushfl;" /* save eflag value */
+ "popl %0;"
+ "cli;"
+ : "=r"(eflags)); /* shut off interrupts */
+ return eflags;
+}
+
+static inline void interrupt_unlock(uint32_t eflags)
+{
+ __asm__ volatile("pushl %0;" /* restore elfag values */
+ "popfl;"
+ :
+ : "r"(eflags));
+}
+
+static inline int dma_poll(uint32_t addr, uint32_t expected, uint32_t mask)
+{
+ int retval = -1;
+ uint32_t counter = 0;
+
+ /*
+ * The timeout is approximately 2.2 seconds according to
+ * value of UINT32_MAX, 120MHZ ISH clock frequency and
+ * instruction count which is around 4.
+ */
+ while (counter < (UINT32_MAX / 64)) {
+ /* test condition */
+ if ((REG32(addr) & mask) == expected) {
+ retval = DMA_RC_OK;
+ break;
+ }
+ counter++;
+ }
+
+ return retval;
+}
+
/**
* SRAM: ISH local static ram
* UMA: Protected system DRAM region dedicated for ISH
diff --git a/chip/ish/registers.h b/chip/ish/registers.h
index ba83b7bef8..7fe5d2c5ab 100644
--- a/chip/ish/registers.h
+++ b/chip/ish/registers.h
@@ -136,6 +136,59 @@ enum ish_i2c_port {
#define SB_CLK_GATE_EN_TRUNK_CLK_GATE BIT(1)
#endif
+#define SBEP_REG_UP_MSG_STATUS_ADDR (ISH_SBEP_BASE + 0x0040)
+#define SBEP_REG_UP_MSG_STATUS REG32(ISH_SBEP_BASE + 0x0040)
+#define SBEP_REG_UP_MSG_COMMAND REG32(ISH_SBEP_BASE + 0x0044)
+#define SBEP_REG_UP_MSG_REQ_ADDR_LOW REG32(ISH_SBEP_BASE + 0x0048)
+#define SBEP_REG_UP_MSG_REQ_ADDR_HIGH REG32(ISH_SBEP_BASE + 0x004C)
+#define SBEP_REG_UP_MSG_REQ_DATA REG32(ISH_SBEP_BASE + 0x0050)
+#define SBEP_REG_UP_MSG_REQ_ATTR REG32(ISH_SBEP_BASE + 0x0054)
+#define SBEP_REG_UP_MSG_REQ_EH REG32(ISH_SBEP_BASE + 0x0058)
+
+#define UP_STATUS_BUSY_MASK 0x01
+#define UP_STATUS_MSG_SENT_MASK 0x02
+#define UP_STATUS_MSG_SENT_CLR 0x02
+
+#define SBEP_CMD_ACTION 0x1
+#define SBEP_CMD_TYPE_WRITE 0x0
+#define SBEP_CMD_TYPE_READ 0x1
+#define SBEP_CMD_POSTED 0x1
+#define SBEP_CMD_NON_POSTED 0x0
+#define SBEP_CMD_INT_ENABLED 0x1
+#define SBEP_CMD_ACTION_OFF 0
+#define SBEP_CMD_TYPE_OFF 1
+#define SBEP_CMD_POSTED_OFF 2
+#define SBEP_CMD_INT_OFF 3
+
+#define SBEP_CMD_WRITE \
+ ((SBEP_CMD_ACTION << SBEP_CMD_ACTION_OFF) | \
+ (SBEP_CMD_TYPE_WRITE << SBEP_CMD_TYPE_OFF) | \
+ (SBEP_CMD_POSTED << SBEP_CMD_POSTED_OFF) | \
+ (SBEP_CMD_INT_ENABLED << SBEP_CMD_INT_OFF))
+
+#define SBEP_ATTR_LTR_OPCODE 0x43
+#define SBEP_ATTR_PMC_DEST_ID 0xCC
+#define SBEP_ATTR_DEST_ID_OFF 0
+#define SBEP_ATTR_OPCODE_OFF 8
+#define SBEP_ATTR_WRITE_ALL_BYTES 0xF
+#define SBEP_ATTR_BYTE_ENABLE_OFF 16
+#define LTR_CMD_ATTR \
+ ((SBEP_ATTR_PMC_DEST_ID << SBEP_ATTR_DEST_ID_OFF) | \
+ (SBEP_ATTR_LTR_OPCODE << SBEP_ATTR_OPCODE_OFF) | \
+ (SBEP_ATTR_WRITE_ALL_BYTES << SBEP_ATTR_BYTE_ENABLE_OFF))
+#define LTR_CMD_DATA_2MS 0x90029002
+#define LTR_CMD_DATA_INFINITE 0
+
+#define SBEP_SAIRS_ROOT_SPACE_PMC 0
+
+#define SBEP_SAIRS_EH_PRESENT 1
+#define SBEP_SAIRS_ROOT_SPACE_OFF 16
+#define SBEP_SAIRS_EH_PRESENT_OFF 31
+
+#define SBEP_PMC_SAIRS_VAL \
+ ((SBEP_SAIRS_ROOT_SPACE_PMC << SBEP_SAIRS_ROOT_SPACE_OFF) | \
+ (SBEP_SAIRS_EH_PRESENT << SBEP_SAIRS_EH_PRESENT_OFF))
+
/* APIC interrupt vectors */
#define ISH_TS_VECTOR 0x20 /* Task switch vector */
#define LAPIC_LVT_ERROR_VECTOR 0x21 /* Clears IOAPIC/LAPIC sync errors */
@@ -269,6 +322,7 @@ enum ish_i2c_port {
#define VNN_ID_DMA0 4
#define VNN_ID_DMA(chan) (VNN_ID_DMA0 + chan)
+#define VNN_ID_SIDEBAND 21
/* OCP registers */
#define OCP_IOSF2OCP_BRIDGE (ISH_OCP_BASE + 0x9400)