summaryrefslogtreecommitdiff
path: root/lib/utils
diff options
context:
space:
mode:
Diffstat (limited to 'lib/utils')
-rw-r--r--lib/utils/cache/fdt_andes_llcache.c23
-rw-r--r--lib/utils/cppc/fdt_cppc_rpmi.c44
-rw-r--r--lib/utils/hsm/fdt_hsm_andes_atcsmu.c64
-rw-r--r--lib/utils/mpxy/fdt_mpxy_rpmi_logging.c2
-rw-r--r--lib/utils/mpxy/fdt_mpxy_rpmi_mm.c9
-rw-r--r--lib/utils/reset/Kconfig4
-rw-r--r--lib/utils/reset/fdt_reset_metanoia.c72
-rw-r--r--lib/utils/reset/objects.mk3
-rw-r--r--lib/utils/suspend/fdt_suspend_andes_atcsmu.c70
9 files changed, 224 insertions, 67 deletions
diff --git a/lib/utils/cache/fdt_andes_llcache.c b/lib/utils/cache/fdt_andes_llcache.c
index 490503ee..7a61b6ab 100644
--- a/lib/utils/cache/fdt_andes_llcache.c
+++ b/lib/utils/cache/fdt_andes_llcache.c
@@ -5,8 +5,11 @@
*/
#include <sbi/riscv_io.h>
+#include <sbi/sbi_domain.h>
#include <sbi/sbi_error.h>
+#include <sbi/sbi_hart.h>
#include <sbi/sbi_heap.h>
+#include <sbi/sbi_scratch.h>
#include <sbi_utils/cache/fdt_cache.h>
#include <sbi_utils/fdt/fdt_driver.h>
#include <sbi_utils/hsm/fdt_hsm_andes_atcsmu.h>
@@ -102,7 +105,10 @@ static int andes_llcache_enable(struct cache_device *dev, bool enable)
}
llcache_ctrl = readl(ctrl_addr);
- return enable == EXTRACT_FIELD(llcache_ctrl, LLCACHE_REG_CTRL_EN_MASK);
+ if (enable != EXTRACT_FIELD(llcache_ctrl, LLCACHE_REG_CTRL_EN_MASK))
+ return SBI_EFAIL;
+
+ return SBI_OK;
}
static struct cache_ops andes_llcache_ops = {
@@ -113,13 +119,13 @@ static struct cache_ops andes_llcache_ops = {
static int andes_llcache_probe(const void *fdt, int nodeoff, const struct fdt_match *match)
{
int rc;
- u64 llcache_base = 0;
+ u64 llcache_base = 0, size;
struct andes_llcache *llcache;
struct cache_device *dev;
uint32_t llcache_cfg;
- rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &llcache_base, NULL);
- if (rc < 0 || !llcache_base)
+ rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &llcache_base, &size);
+ if (rc < 0 || !llcache_base || !size)
return SBI_ENODEV;
llcache = sbi_zalloc(sizeof(*llcache));
@@ -148,6 +154,15 @@ static int andes_llcache_probe(const void *fdt, int nodeoff, const struct fdt_ma
llcache->status_core_stride = 4;
}
+ if (sbi_hart_has_extension(sbi_scratch_thishart_ptr(), SBI_HART_EXT_SMEPMP)) {
+ rc = sbi_domain_root_add_memrange(
+ (unsigned long)llcache->base, (unsigned long)size, PAGE_SIZE,
+ SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_SHARED_SURW_MRW);
+ if (rc)
+ return rc;
+ }
+
/* Wait for the hardware initialization done */
while (!andes_llcache_init_done(llcache))
;
diff --git a/lib/utils/cppc/fdt_cppc_rpmi.c b/lib/utils/cppc/fdt_cppc_rpmi.c
index 7bd3b0f9..15c89351 100644
--- a/lib/utils/cppc/fdt_cppc_rpmi.c
+++ b/lib/utils/cppc/fdt_cppc_rpmi.c
@@ -12,6 +12,7 @@
#include <sbi/sbi_cppc.h>
#include <sbi/sbi_ecall_interface.h>
#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_timer.h>
#include <sbi_utils/fdt/fdt_driver.h>
#include <sbi_utils/fdt/fdt_helper.h>
#include <sbi_utils/mailbox/fdt_mailbox.h>
@@ -39,6 +40,8 @@ struct rpmi_cppc {
ulong fc_db_addr;
u64 fc_db_setmask;
u64 fc_db_preservemask;
+ u64 prev_time_csr;
+ u64 prev_delivered_counter;
};
static unsigned long rpmi_cppc_offset;
@@ -107,6 +110,7 @@ static void rpmi_cppc_fc_db_trigger(struct rpmi_cppc *cppc)
static int rpmi_cppc_read(unsigned long reg, u64 *val)
{
+ u64 curr_freq, curr_time_csr, time_csr_delta, freq;
int rc = SBI_SUCCESS;
struct rpmi_cppc_read_reg_req req;
struct rpmi_cppc_read_reg_resp resp;
@@ -116,12 +120,38 @@ static int rpmi_cppc_read(unsigned long reg, u64 *val)
req.reg_id = reg;
cppc = rpmi_cppc_get_pointer(req.hart_id);
- rc = rpmi_normal_request_with_status(
- cppc->chan, RPMI_CPPC_SRV_READ_REG,
- &req, rpmi_u32_count(req), rpmi_u32_count(req),
- &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
- if (rc)
- return rc;
+ if ((reg == SBI_CPPC_DELIVERED_CTR) && cppc->fc_supported) {
+#if __riscv_xlen != 32
+ curr_freq = readq((void *)cppc->fc_perf_feedback_addr);
+#else
+ curr_freq = readl((void *)cppc->fc_perf_feedback_addr + 4);
+ curr_freq <<= 32;
+ curr_freq |= readl((void *)cppc->fc_perf_feedback_addr);
+#endif
+ curr_time_csr = sbi_timer_value();
+ time_csr_delta = curr_time_csr - cppc->prev_time_csr;
+ cppc->prev_time_csr = curr_time_csr;
+
+ freq = sbi_timer_frequency();
+ if (freq)
+ cppc->prev_delivered_counter +=
+ curr_freq * (time_csr_delta / freq) +
+ (curr_freq * (time_csr_delta % freq)) / freq;
+
+ resp.data_lo = cpu_to_le32(cppc->prev_delivered_counter & UINT32_MAX);
+ resp.data_hi = cpu_to_le32(cppc->prev_delivered_counter >> 32);
+ } else if (reg == SBI_CPPC_REFERENCE_CTR) {
+ curr_time_csr = sbi_timer_value();
+ resp.data_lo = cpu_to_le32(curr_time_csr & UINT32_MAX);
+ resp.data_hi = cpu_to_le32(curr_time_csr >> 32);
+ } else {
+ rc = rpmi_normal_request_with_status(
+ cppc->chan, RPMI_CPPC_SRV_READ_REG,
+ &req, rpmi_u32_count(req), rpmi_u32_count(req),
+ &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
+ if (rc)
+ return rc;
+ }
#if __riscv_xlen == 32
*val = resp.data_lo;
@@ -276,6 +306,8 @@ static int rpmi_cppc_update_hart_scratch(struct mbox_chan *chan)
if (!cppc)
return SBI_ENOSYS;
+ cppc->prev_time_csr = 0;
+ cppc->prev_delivered_counter = 0;
cppc->chan = chan;
cppc->mode = cppc_mode;
cppc->fc_supported = fc_supported;
diff --git a/lib/utils/hsm/fdt_hsm_andes_atcsmu.c b/lib/utils/hsm/fdt_hsm_andes_atcsmu.c
index 115916d5..2885a983 100644
--- a/lib/utils/hsm/fdt_hsm_andes_atcsmu.c
+++ b/lib/utils/hsm/fdt_hsm_andes_atcsmu.c
@@ -56,7 +56,7 @@ bool atcsmu_support_sleep_mode(u32 sleep_type, u32 hartid)
void atcsmu_set_command(u32 pcs_ctl, u32 hartid)
{
- writel_relaxed(pcs_ctl, (char *)atcsmu_base + PCSm_CTL_OFFSET(hartid));
+ writel(pcs_ctl, (char *)atcsmu_base + PCSm_CTL_OFFSET(hartid));
}
int atcsmu_set_reset_vector(u64 wakeup_addr, u32 hartid)
@@ -94,42 +94,24 @@ u32 atcsmu_read_scratch(void)
return readl_relaxed((char *)atcsmu_base + SCRATCH_PAD_OFFSET);
}
-bool atcsmu_pcs_is_sleep(u32 hartid, bool deep_sleep)
+bool atcsmu_hart_is_sleep(void *opaque)
{
- u32 pcs_status = readl_relaxed((char *)atcsmu_base + PCSm_STATUS_OFFSET(hartid));
- u32 pd_status = deep_sleep ? PD_STATUS_DEEP_SLEEP : PD_STATUS_LIGHT_SLEEP;
+ struct atcsmu_sleep_arg *arg = opaque;
- if (EXTRACT_FIELD(pcs_status, PD_TYPE_MASK) != PD_TYPE_SLEEP) {
- sbi_printf("ATCSMU: hart%d (PCS%d): failed to sleep\n", hartid, hartid + 3);
- return false;
- }
-
- if (EXTRACT_FIELD(pcs_status, PD_STATUS_MASK) != pd_status) {
- sbi_printf("ATCSMU: hart%d (PCS%d): failed to enter %s sleep\n",
- hartid, hartid + 3, deep_sleep ? "deep" : "light");
- return false;
- }
+ u32 pcs_status = readl_relaxed((char *)atcsmu_base +
+ PCSm_STATUS_OFFSET(arg->hartid));
+ u32 pd_status = arg->deep_sleep ? PD_STATUS_DEEP_SLEEP :
+ PD_STATUS_LIGHT_SLEEP;
- return true;
+ return EXTRACT_FIELD(pcs_status, PD_TYPE_MASK) == PD_TYPE_SLEEP &&
+ EXTRACT_FIELD(pcs_status, PD_STATUS_MASK) == pd_status;
}
static int ae350_hart_start(u32 hartid, ulong saddr)
{
u32 hartindex = sbi_hartid_to_hartindex(hartid);
- u32 sleep_type = atcsmu_get_sleep_type(hartid);
-
- /*
- * Don't send wakeup command when:
- * 1) boot time
- * 2) the target hart is non-sleepable 25-series hart0
- * 3) light sleep
- */
- if (!sbi_init_count(hartindex) || (is_andes(25) && hartid == 0) ||
- sleep_type == SBI_SUSP_AE350_LIGHT_SLEEP)
- return sbi_ipi_raw_send(hartindex, false);
- atcsmu_set_command(WAKEUP_CMD, hartid);
- return 0;
+ return sbi_ipi_raw_send(hartindex, false);
}
static int ae350_hart_stop(void)
@@ -152,18 +134,19 @@ static int ae350_hart_stop(void)
/* Prevent the core leaving the WFI mode unexpectedly */
csr_write(CSR_MIE, 0);
+ atcsmu_set_wakeup_events(PCS_WAKEUP_MSIP_MASK | PCS_WAKEUP_MEIP_MASK, hartid);
if (sleep_type == SBI_SUSP_AE350_LIGHT_SLEEP) {
- csr_write(CSR_MIE, MIP_MSIP);
- atcsmu_set_wakeup_events(PCS_WAKEUP_MSIP_MASK, hartid);
+ /* Clock-gated only: needs MSI or MEI set to resume past the WFI */
+ csr_set(CSR_MIE, MIP_MSIP | MIP_MEIP);
atcsmu_set_command(LIGHT_SLEEP_CMD, hartid);
} else if (sleep_type == SBI_SUSP_SLEEP_TYPE_SUSPEND) {
- atcsmu_set_wakeup_events(0x0, hartid);
- atcsmu_set_command(DEEP_SLEEP_CMD, hartid);
+ /* Power-gated: SMU wakes it via cold reset, interrupts not needed */
rc = atcsmu_set_reset_vector((ulong)ae350_enable_coherency_warmboot, hartid);
if (rc)
return SBI_EFAIL;
ae350_non_ret_save(sbi_scratch_thishart_ptr());
+ atcsmu_set_command(DEEP_SLEEP_CMD, hartid);
}
ae350_disable_coherency();
@@ -184,18 +167,27 @@ static const struct sbi_hsm_device hsm_andes_atcsmu = {
static int hsm_andes_atcsmu_probe(const void *fdt, int nodeoff, const struct fdt_match *match)
{
int poff, rc;
- u64 addr;
+ u64 addr, size;
/* Need to find the parent for the address property */
poff = fdt_parent_offset(fdt, nodeoff);
if (poff < 0)
return SBI_EINVAL;
- rc = fdt_get_node_addr_size(fdt, poff, 0, &addr, NULL);
- if (rc < 0 || !addr)
+ rc = fdt_get_node_addr_size(fdt, poff, 0, &addr, &size);
+ if (rc < 0 || !addr || !size)
return SBI_ENODEV;
- atcsmu_base = addr;
+ if (sbi_hart_has_extension(sbi_scratch_thishart_ptr(), SBI_HART_EXT_SMEPMP)) {
+ rc = sbi_domain_root_add_memrange(
+ (unsigned long)addr, (unsigned long)size, PAGE_SIZE,
+ SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_SHARED_SURW_MRW);
+ if (rc)
+ return rc;
+ }
+
+ atcsmu_base = addr;
sbi_hsm_set_device(&hsm_andes_atcsmu);
return 0;
}
diff --git a/lib/utils/mpxy/fdt_mpxy_rpmi_logging.c b/lib/utils/mpxy/fdt_mpxy_rpmi_logging.c
index e8f085eb..1e92053d 100644
--- a/lib/utils/mpxy/fdt_mpxy_rpmi_logging.c
+++ b/lib/utils/mpxy/fdt_mpxy_rpmi_logging.c
@@ -11,7 +11,7 @@
static struct mpxy_rpmi_service_data logging_services[] = {
[0] = {
- .id = RPMI_MM_SRV_ENABLE_NOTIFICATION,
+ .id = RPMI_LOGGING_SRV_ENABLE_NOTIFICATION,
.min_tx_len = sizeof(struct rpmi_enable_notification_req),
.max_tx_len = sizeof(struct rpmi_enable_notification_req),
.min_rx_len = sizeof(struct rpmi_enable_notification_resp),
diff --git a/lib/utils/mpxy/fdt_mpxy_rpmi_mm.c b/lib/utils/mpxy/fdt_mpxy_rpmi_mm.c
index d7176aca..7185f3f3 100644
--- a/lib/utils/mpxy/fdt_mpxy_rpmi_mm.c
+++ b/lib/utils/mpxy/fdt_mpxy_rpmi_mm.c
@@ -15,13 +15,20 @@ static struct rpmi_mm_get_attributes_rsp rsp;
static struct mpxy_rpmi_service_data mm_srvcdata[] = {
[0] = {
+ .id = RPMI_MM_SRV_ENABLE_NOTIFICATION,
+ .min_tx_len = sizeof(struct rpmi_enable_notification_req),
+ .max_tx_len = sizeof(struct rpmi_enable_notification_req),
+ .min_rx_len = sizeof(struct rpmi_enable_notification_resp),
+ .max_rx_len = sizeof(struct rpmi_enable_notification_resp),
+ },
+ [1] = {
.id = RPMI_MM_SRV_GET_ATTRIBUTES,
.min_tx_len = 0,
.max_tx_len = 0,
.min_rx_len = sizeof(struct rpmi_mm_get_attributes_rsp),
.max_rx_len = sizeof(struct rpmi_mm_get_attributes_rsp),
},
- [1] = {
+ [2] = {
.id = RPMI_MM_SRV_COMMUNICATE,
.min_tx_len = sizeof(struct rpmi_mm_communicate_req),
.max_tx_len = sizeof(struct rpmi_mm_communicate_req),
diff --git a/lib/utils/reset/Kconfig b/lib/utils/reset/Kconfig
index b2ac120e..8988548c 100644
--- a/lib/utils/reset/Kconfig
+++ b/lib/utils/reset/Kconfig
@@ -29,6 +29,10 @@ config FDT_RESET_LITEX
depends on FDT_GPIO
default n
+config FDT_RESET_METANOIA
+ bool "Metanoia FDT reset driver"
+ default n
+
config FDT_RESET_RPMI
bool "RPMI FDT reset driver"
depends on FDT_MAILBOX && RPMI_MAILBOX
diff --git a/lib/utils/reset/fdt_reset_metanoia.c b/lib/utils/reset/fdt_reset_metanoia.c
new file mode 100644
index 00000000..6f75a893
--- /dev/null
+++ b/lib/utils/reset/fdt_reset_metanoia.c
@@ -0,0 +1,72 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Metanoia Communications Inc.
+ *
+ */
+
+#include <sbi/riscv_io.h>
+#include <sbi/sbi_platform.h>
+#include <sbi/sbi_system.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/fdt/fdt_driver.h>
+
+#define SWRSTREQ_CTRL_REG_OFFSET 0x00
+#define SWRSTREQ_REG_OFFSET 0x04
+
+struct reset_metanoia_data {
+ u8 *reg_base;
+};
+
+static struct reset_metanoia_data reset_data;
+
+static int metanoia_system_reset_check(u32 type, u32 reason)
+{
+ switch (type) {
+ case SBI_SRST_RESET_TYPE_WARM_REBOOT:
+ case SBI_SRST_RESET_TYPE_COLD_REBOOT:
+ return 1;
+ case SBI_SRST_RESET_TYPE_SHUTDOWN:
+ default:
+ return 0;
+ }
+}
+
+static void metanoia_system_reset(u32 type, u32 reason)
+{
+ writew(0x1, reset_data.reg_base + SWRSTREQ_CTRL_REG_OFFSET);
+ writew(0x1, reset_data.reg_base + SWRSTREQ_REG_OFFSET);
+}
+
+static struct sbi_system_reset_device metanoia_reset = {
+ .name = "metanoia-mt2824-reboot",
+ .system_reset_check = metanoia_system_reset_check,
+ .system_reset = metanoia_system_reset,
+};
+
+static int metanoia_reset_init(const void *fdt, int nodeoff,
+ const struct fdt_match *match)
+{
+ u64 reg_addr;
+ int rc;
+
+ rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &reg_addr, NULL);
+ if (rc < 0 || !reg_addr)
+ return SBI_ENODEV;
+
+ reset_data.reg_base = (u8 *)(ulong)reg_addr;
+
+ sbi_system_reset_add_device(&metanoia_reset);
+
+ return 0;
+}
+
+static const struct fdt_match metanoia_reset_match[] = {
+ { .compatible = "metanoia,mt2824-reboot" },
+ { /* sentinel */ }
+};
+
+const struct fdt_driver fdt_reset_metanoia = {
+ .match_table = metanoia_reset_match,
+ .init = metanoia_reset_init,
+};
diff --git a/lib/utils/reset/objects.mk b/lib/utils/reset/objects.mk
index 38b4e306..a9b6edad 100644
--- a/lib/utils/reset/objects.mk
+++ b/lib/utils/reset/objects.mk
@@ -20,6 +20,9 @@ libsbiutils-objs-$(CONFIG_FDT_RESET_HTIF) += reset/fdt_reset_htif.o
carray-fdt_early_drivers-$(CONFIG_FDT_RESET_LITEX) += fdt_reset_litex
libsbiutils-objs-$(CONFIG_FDT_RESET_LITEX) += reset/fdt_reset_litex.o
+carray-fdt_early_drivers-$(CONFIG_FDT_RESET_METANOIA) += fdt_reset_metanoia
+libsbiutils-objs-$(CONFIG_FDT_RESET_METANOIA) += reset/fdt_reset_metanoia.o
+
carray-fdt_early_drivers-$(CONFIG_FDT_RESET_SG2042_HWMON_MCU) += fdt_reset_sg2042_mcu
libsbiutils-objs-$(CONFIG_FDT_RESET_SG2042_HWMON_MCU) += reset/fdt_reset_sg2042_hwmon_mcu.o
diff --git a/lib/utils/suspend/fdt_suspend_andes_atcsmu.c b/lib/utils/suspend/fdt_suspend_andes_atcsmu.c
index 072accc0..86cdf955 100644
--- a/lib/utils/suspend/fdt_suspend_andes_atcsmu.c
+++ b/lib/utils/suspend/fdt_suspend_andes_atcsmu.c
@@ -12,22 +12,37 @@
#include <sbi/sbi_ecall_interface.h>
#include <sbi/sbi_hart.h>
#include <sbi/sbi_system.h>
+#include <sbi/sbi_timer.h>
#include <sbi_utils/cache/fdt_cmo_helper.h>
#include <sbi_utils/fdt/fdt_driver.h>
#include <sbi_utils/fdt/fdt_helper.h>
#include <sbi_utils/hsm/fdt_hsm_andes_atcsmu.h>
-static int check_secondary_harts_sleep(u32 hartid, bool deep_sleep)
+#define HART_SLEEP_TIMEOUT_MS 1000
+
+static int wait_secondary_harts_sleep(u32 hartid, bool deep_sleep)
{
const struct sbi_domain *dom = &root;
unsigned long i;
u32 target;
+ struct atcsmu_sleep_arg arg;
+
+ arg.deep_sleep = deep_sleep;
- /* Ensure the secondary harts entering the corresponding sleep state */
+ /* Wait for the secondary harts entering the corresponding sleep state */
sbi_hartmask_for_each_hartindex(i, dom->possible_harts) {
target = sbi_hartindex_to_hartid(i);
- if (target != hartid && !atcsmu_pcs_is_sleep(target, deep_sleep))
- return SBI_EFAIL;
+ if (target == hartid)
+ continue;
+
+ arg.hartid = target;
+ if (!sbi_timer_waitms_until(atcsmu_hart_is_sleep, &arg,
+ HART_SLEEP_TIMEOUT_MS)) {
+ sbi_printf("ATCSMU: hart%u (PCS%u): timed out waiting for %s sleep\n",
+ target, target + 3,
+ deep_sleep ? "deep" : "light");
+ return SBI_ETIMEOUT;
+ }
}
return SBI_OK;
@@ -42,39 +57,45 @@ static int ae350_system_suspend_check(u32 sleep_type)
static int ae350_system_suspend(u32 sleep_type, unsigned long addr)
{
u32 hartid = current_hartid();
+ unsigned long saved_mie;
int rc;
/* Prevent the core leaving the WFI mode unexpectedly */
+ saved_mie = csr_read(CSR_MIE);
csr_write(CSR_MIE, 0);
- /*
- * Only allow the S-mode external interrupts (UART2 and RTC alarm) to
- * wake up the primary hart
- */
- csr_set(CSR_SIE, MIP_SEIP);
+ /* SMU wakes the primary hart on RTC alarm / UART2 */
atcsmu_set_wakeup_events(PCS_WAKEUP_RTC_ALARM_MASK | PCS_WAKEUP_UART2_MASK, hartid);
if (sleep_type == SBI_SUSP_AE350_LIGHT_SLEEP) {
- rc = check_secondary_harts_sleep(hartid, false);
+ rc = wait_secondary_harts_sleep(hartid, false);
if (rc)
- return rc;
+ goto err_restore_mie;
+ /* Clock-gated only: enable SEI to resume past the WFI */
+ csr_set(CSR_MIE, MIP_SEIP);
atcsmu_set_command(LIGHT_SLEEP_CMD, hartid);
} else if (sleep_type == SBI_SUSP_SLEEP_TYPE_SUSPEND) {
- rc = check_secondary_harts_sleep(hartid, true);
+ rc = wait_secondary_harts_sleep(hartid, true);
if (rc)
- return rc;
+ goto err_restore_mie;
- atcsmu_set_command(DEEP_SLEEP_CMD, hartid);
rc = atcsmu_set_reset_vector((ulong)ae350_enable_coherency_warmboot, hartid);
if (rc)
- return rc;
+ goto err_restore_mie;
ae350_non_ret_save(sbi_scratch_thishart_ptr());
- fdt_cmo_llc_enable(false);
+
+ /* No LLC is fine; only fail on real errors */
+ rc = fdt_cmo_llc_enable(false);
+ if (rc && rc != SBI_ENODEV)
+ goto err_discard_save;
+
rc = fdt_cmo_llc_flush_all();
- if (rc)
- return rc;
+ if (rc && rc != SBI_ENODEV)
+ goto err_enable_llc;
+
+ atcsmu_set_command(DEEP_SLEEP_CMD, hartid);
}
ae350_disable_coherency();
@@ -84,6 +105,15 @@ static int ae350_system_suspend(u32 sleep_type, unsigned long addr)
ae350_enable_coherency();
return SBI_OK;
+
+err_enable_llc:
+ fdt_cmo_llc_enable(true);
+err_discard_save:
+ ae350_non_ret_discard(sbi_scratch_thishart_ptr());
+err_restore_mie:
+ csr_write(CSR_MIE, saved_mie);
+
+ return rc;
}
static void ae350_system_resume(void)
@@ -91,8 +121,10 @@ static void ae350_system_resume(void)
u32 hartid = current_hartid();
u32 sleep_type = atcsmu_get_sleep_type(hartid);
- if (sleep_type == SBI_SUSP_SLEEP_TYPE_SUSPEND)
+ if (sleep_type == SBI_SUSP_SLEEP_TYPE_SUSPEND) {
fdt_cmo_llc_enable(true);
+ ae350_non_ret_restore(sbi_scratch_thishart_ptr());
+ }
}
static struct sbi_system_suspend_device suspend_andes_atcsmu = {