From patchwork Tue Aug 6 07:33:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anup Patel X-Patchwork-Id: 1969363 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=Uq4m8s5v; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=ventanamicro.com header.i=@ventanamicro.com header.a=rsa-sha256 header.s=google header.b=CW6pVbKz; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=opensbi-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=patchwork.ozlabs.org) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WdQ6r3Fnmz1yYD for ; Tue, 6 Aug 2024 17:34:28 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Lh+/CyfsH46jtO7wThWp9b84eRFm/9E1g9hSqXH2DFA=; b=Uq4m8s5vCKrsXl gYJ8Yp8IKqqLFAYzHYiXwzAjil3pNt6i3ljzUVuKz12JVvRfz4GvvpPGXNn5SZZJpBqFbqCqDEB/z 1zFr8zqR1kk7Sya5aIzL+rtd6ptHIFtDJOiCTG5o/xA3KSMkZLk9LZNIGW0ktE25/yMA1/U+KtPCB 1pzTCtNDNtp0WxIbJdrgFmBMvFulDhRTaziz3YRTA9SNJLWpTsQgBL8Yn0iAnhgRwPosdHc0pPack fyH8t2XZ7OcgHkAuqIw0QXanKiO9kBZzj2Pl+mztozGUewDAtwKcVg03TFTxJqrmnSSowNorAJt15 oCBG1sTVLvyGvzb0R75w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sbEi5-00000000o1x-0E4x; Tue, 06 Aug 2024 07:34:21 +0000 Received: from mail-pf1-x42e.google.com ([2607:f8b0:4864:20::42e]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sbEhy-00000000nxZ-3q7y for opensbi@lists.infradead.org; Tue, 06 Aug 2024 07:34:18 +0000 Received: by mail-pf1-x42e.google.com with SMTP id d2e1a72fcca58-70d23caf8ddso286213b3a.0 for ; Tue, 06 Aug 2024 00:34:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1722929654; x=1723534454; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Y7TPRnaFrAtCNWpiTJtHiv13r5RgdBoonWPDPgXEYpU=; b=CW6pVbKz3Dq4Hd/A+7rJAHs/6hpcA7GDf5UMeylcp+YS3zfjKuViYFjrW3eJRbSp9C hA7jKChMjXIcSazAXRkULFPMJN0Q0ylk6lqX7jr3WWE7pphcZp/tkYBshkhxnBoc0sXy m35UIYJJSexbUF0EJVXxBcz5rZrdhi8kv5otSDWYRWV4W8/OUro7prPNS9rB7w5+XXTK mMJsa/t9KJQQ4e23iX0v5D/zkoQvRNtqhjqO8v6SA8NQc4zk7fxrgWLQgzFYf0tYMVfs a6uXhQfr1Bx7QlOqs98Ztyp8PwPwwK7wN39TZcdc82BOUO8g7KsrHLxMhuAuv7isYpyl 9hhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722929654; x=1723534454; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Y7TPRnaFrAtCNWpiTJtHiv13r5RgdBoonWPDPgXEYpU=; b=gP5THyxLpNTLGniGD/hronR8QMmbwZYeCgjpM7C4mxdzILtKobKn+a7dWIaSX6ae6C nnmJ/H8bbEuIBu2ZPfFDA6bJXuoYzOM9Q/E/5FL3Iy2s/b1cbb0RLkKdBzJZXF4p6o3T GrsuSc6FGU/mcUro9+aAFipHcDifhoVVDtDe6U8phlWKIVGBKIxe5gtBiHyGUDZlRFaY yK3i541quWMhd7MGKbjJsz+1ldihNiKG8NGonGB0vuxubGiwlaktL1KmZtwaI/b9k0+6 qbkfgNbAYXm02vrC5/Wq7/+PJOGzmkpfdbHNHQKkseBmEWarjr8IlsRjFOhnzKOH18w+ BpNw== X-Forwarded-Encrypted: i=1; AJvYcCXhsGGP70BJeajW/JuIhILWYPtMGnHf2uhcgbLUZ9hCZna9vv+PCDaDOo6rD9MqCymWesd2tcZfdq/HsWJEkZs4MS5nHJHUrDb3JCM= X-Gm-Message-State: AOJu0YweaG4xf3lU2WQDVfghCMtPHPs77ZlK2ELrHgpAokLx939w8vpI jTt5mIB+C+O2SW0b3YrXUUQ485VNUwO1XwYx1ScOC25Kch3vn7wPeR02SeLf3v8= X-Google-Smtp-Source: AGHT+IFpx6P438yryYcjQSQ7maQjngJJqU1ql1ykiOxF+ZM0O4g83oEKmLeB18fu+3K4yGne0RIG3g== X-Received: by 2002:a05:6a00:1912:b0:707:ffa4:de3f with SMTP id d2e1a72fcca58-7106cfcfd8dmr19561944b3a.17.1722929653554; Tue, 06 Aug 2024 00:34:13 -0700 (PDT) Received: from anup-ubuntu-vm.localdomain ([223.185.134.124]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7106ed2de28sm6455011b3a.191.2024.08.06.00.34.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Aug 2024 00:34:13 -0700 (PDT) From: Anup Patel To: Atish Patra Cc: Andrew Jones , Anup Patel , opensbi@lists.infradead.org, Subrahmanya Lingappa , Anup Patel Subject: [PATCH 10/16] lib: utils/hsm: Add RPMI HSM driver Date: Tue, 6 Aug 2024 13:03:32 +0530 Message-Id: <20240806073338.1856901-11-apatel@ventanamicro.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240806073338.1856901-1-apatel@ventanamicro.com> References: <20240806073338.1856901-1-apatel@ventanamicro.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240806_003415_559930_1D0661DB X-CRM114-Status: GOOD ( 22.15 ) X-Spam-Score: -2.1 (--) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Subrahmanya Lingappa The RPMI HSM service group provides set of routine to query and control power states of a Hart. Add RPMI based Hart State Management (HSM) driver. Content analysis details: (-2.1 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:42e listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-BeenThere: opensbi@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "opensbi" Errors-To: opensbi-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Subrahmanya Lingappa The RPMI HSM service group provides set of routine to query and control power states of a Hart. Add RPMI based Hart State Management (HSM) driver. Signed-off-by: Subrahmanya Lingappa Signed-off-by: Anup Patel --- include/sbi_utils/mailbox/rpmi_msgprot.h | 91 ++++++ lib/utils/hsm/Kconfig | 9 + lib/utils/hsm/fdt_hsm_rpmi.c | 351 +++++++++++++++++++++++ lib/utils/hsm/objects.mk | 3 + platform/generic/configs/defconfig | 1 + 5 files changed, 455 insertions(+) create mode 100644 lib/utils/hsm/fdt_hsm_rpmi.c diff --git a/include/sbi_utils/mailbox/rpmi_msgprot.h b/include/sbi_utils/mailbox/rpmi_msgprot.h index a2403c90..efe35aee 100644 --- a/include/sbi_utils/mailbox/rpmi_msgprot.h +++ b/include/sbi_utils/mailbox/rpmi_msgprot.h @@ -151,6 +151,7 @@ enum rpmi_servicegroup_id { RPMI_SRVGRP_BASE = 0x00001, RPMI_SRVGRP_SYSTEM_RESET = 0x00002, RPMI_SRVGRP_SYSTEM_SUSPEND = 0x00003, + RPMI_SRVGRP_HSM = 0x00004, RPMI_SRVGRP_ID_MAX_COUNT, }; @@ -243,4 +244,94 @@ struct rpmi_syssusp_suspend_resp { s32 status; }; +/** RPMI HSM State Management ServiceGroup Service IDs */ +enum rpmi_cpu_hsm_service_id { + RPMI_HSM_SRV_ENABLE_NOTIFICATION = 0x01, + RPMI_HSM_SRV_HART_START = 0x02, + RPMI_HSM_SRV_HART_STOP = 0x03, + RPMI_HSM_SRV_HART_SUSPEND = 0x04, + RPMI_HSM_SRV_GET_HART_STATUS = 0x05, + RPMI_HSM_SRV_GET_HART_LIST = 0x06, + RPMI_HSM_SRV_GET_SUSPEND_TYPES = 0x07, + RPMI_HSM_SRV_GET_SUSPEND_INFO = 0x08, + RPMI_HSM_SRV_ID_MAX_COUNT, +}; + +/* HSM service group request and response structs */ +struct rpmi_hsm_hart_start_req { + u32 hartid; + u32 start_addr_lo; + u32 start_addr_hi; +}; + +struct rpmi_hsm_hart_start_resp { + s32 status; +}; + +struct rpmi_hsm_hart_stop_req { + u32 hartid; +}; + +struct rpmi_hsm_hart_stop_resp { + s32 status; +}; + +struct rpmi_hsm_hart_susp_req { + u32 hartid; + u32 suspend_type; + u32 resume_addr_lo; + u32 resume_addr_hi; +}; + +struct rpmi_hsm_hart_susp_resp { + s32 status; +}; + +struct rpmi_hsm_get_hart_status_req { + u32 hartid; +}; + +struct rpmi_hsm_get_hart_status_resp { + s32 status; + u32 hart_status; +}; + +struct rpmi_hsm_get_hart_list_req { + u32 start_index; +}; + +struct rpmi_hsm_get_hart_list_resp { + s32 status; + u32 remaining; + u32 returned; + /* remaining space need to be adjusted for the above 3 u32's */ + u32 hartid[(RPMI_MSG_DATA_SIZE(RPMI_SLOT_SIZE_MIN) - (sizeof(u32) * 3)) / sizeof(u32)]; +}; + +struct rpmi_hsm_get_susp_types_req { + u32 start_index; +}; + +struct rpmi_hsm_get_susp_types_resp { + s32 status; + u32 remaining; + u32 returned; + /* remaining space need to be adjusted for the above 3 u32's */ + u32 types[(RPMI_MSG_DATA_SIZE(RPMI_SLOT_SIZE_MIN) - (sizeof(u32) * 3)) / sizeof(u32)]; +}; + +struct rpmi_hsm_get_susp_info_req { + u32 suspend_type; +}; + +struct rpmi_hsm_get_susp_info_resp { + s32 status; + u32 flags; +#define RPMI_HSM_FLAGS_LOCAL_TIME_STOP (1U << 31) + u32 entry_latency_us; + u32 exit_latency_us; + u32 wakeup_latency_us; + u32 min_residency_us; +}; + #endif /* !__RPMI_MSGPROT_H__ */ diff --git a/lib/utils/hsm/Kconfig b/lib/utils/hsm/Kconfig index 31506116..1ad7958f 100644 --- a/lib/utils/hsm/Kconfig +++ b/lib/utils/hsm/Kconfig @@ -7,4 +7,13 @@ config FDT_HSM depends on FDT default n +if FDT_HSM + +config FDT_HSM_RPMI + bool "FDT RPMI HSM driver" + depends on FDT_MAILBOX && RPMI_MAILBOX + default n + +endif + endmenu diff --git a/lib/utils/hsm/fdt_hsm_rpmi.c b/lib/utils/hsm/fdt_hsm_rpmi.c new file mode 100644 index 00000000..e598901d --- /dev/null +++ b/lib/utils/hsm/fdt_hsm_rpmi.c @@ -0,0 +1,351 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Ventana Micro Systems Inc. + * + * Authors: + * Subrahmanya Lingappa + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_HSM_SUPSEND_STATE_NAMELEN 16 + +struct rpmi_hsm_suspend { + u32 num_states; + struct sbi_cpu_idle_state *states; +}; + +struct rpmi_hsm { + struct mbox_chan *chan; + struct rpmi_hsm_suspend *susp; +}; + +static unsigned long rpmi_hsm_offset; + +static struct rpmi_hsm *rpmi_hsm_get_pointer(u32 hartid) +{ + struct sbi_scratch *scratch; + + scratch = sbi_hartid_to_scratch(hartid); + if (!scratch || !rpmi_hsm_offset) + return NULL; + + return sbi_scratch_offset_ptr(scratch, rpmi_hsm_offset); +} + +static int rpmi_hsm_start(u32 hartid, ulong resume_addr) +{ + struct rpmi_hsm_hart_start_req req; + struct rpmi_hsm_hart_start_resp resp; + struct rpmi_hsm *rpmi = rpmi_hsm_get_pointer(hartid); + + if (!rpmi) + return SBI_ENOSYS; + + req.hartid = hartid; + req.start_addr_lo = resume_addr; + req.start_addr_hi = (u64)resume_addr >> 32; + + return rpmi_normal_request_with_status( + rpmi->chan, RPMI_HSM_SRV_HART_START, + &req, rpmi_u32_count(req), rpmi_u32_count(req), + &resp, rpmi_u32_count(resp), rpmi_u32_count(resp)); +} + +static int rpmi_hsm_stop(void) +{ + int rc; + struct rpmi_hsm_hart_stop_req req; + struct rpmi_hsm_hart_stop_resp resp; + void (*jump_warmboot)(void) = + (void (*)(void))sbi_scratch_thishart_ptr()->warmboot_addr; + struct rpmi_hsm *rpmi = rpmi_hsm_get_pointer(current_hartid()); + + if (!rpmi) + return SBI_ENOSYS; + + req.hartid = current_hartid(); + + rc = rpmi_normal_request_with_status( + rpmi->chan, RPMI_HSM_SRV_HART_STOP, + &req, rpmi_u32_count(req), rpmi_u32_count(req), + &resp, rpmi_u32_count(resp), rpmi_u32_count(resp)); + if (rc) + return rc; + + /* Wait for interrupt */ + wfi(); + + jump_warmboot(); + + return 0; +} + +static bool is_rpmi_hsm_susp_supported(struct rpmi_hsm_suspend *susp, u32 type) +{ + int i; + + for (i = 0; i < susp->num_states; i++) + if (type == susp->states[i].suspend_param) + return true; + + return false; +} + +static int rpmi_hsm_suspend(u32 type, ulong resume_addr) +{ + int rc; + struct rpmi_hsm_hart_susp_req req; + struct rpmi_hsm_hart_susp_resp resp; + struct rpmi_hsm *rpmi = rpmi_hsm_get_pointer(current_hartid()); + + if (!rpmi) + return SBI_ENOSYS; + + /* check if harts support this suspend type */ + if (!is_rpmi_hsm_susp_supported(rpmi->susp, type)) + return SBI_EINVAL; + + req.hartid = current_hartid(); + req.suspend_type = type; + req.resume_addr_lo = resume_addr; + req.resume_addr_hi = (u64)resume_addr >> 32; + + rc = rpmi_normal_request_with_status( + rpmi->chan, RPMI_HSM_SRV_HART_SUSPEND, + &req, rpmi_u32_count(req), rpmi_u32_count(req), + &resp, rpmi_u32_count(resp), rpmi_u32_count(resp)); + if (rc) + return rc; + + /* Wait for interrupt */ + wfi(); + + return 0; +} + +static struct sbi_hsm_device sbi_hsm_rpmi = { + .name = "rpmi-hsm", + .hart_start = rpmi_hsm_start, + .hart_stop = rpmi_hsm_stop, + .hart_suspend = rpmi_hsm_suspend, +}; + +static int rpmi_hsm_fixup(void *fdt) +{ + struct rpmi_hsm *rpmi = rpmi_hsm_get_pointer(current_hartid()); + + if (!rpmi || !rpmi->susp || !rpmi->susp->num_states) + return 0; + + return fdt_add_cpu_idle_states(fdt, rpmi->susp->states); +} + +static int rpmi_hsm_get_num_suspend_states(struct mbox_chan *chan, + struct rpmi_hsm_suspend *susp) +{ + int rc; + struct rpmi_hsm_get_susp_types_req req; + struct rpmi_hsm_get_susp_types_resp resp; + + req.start_index = 0; + rc = rpmi_normal_request_with_status( + chan, RPMI_HSM_SRV_GET_SUSPEND_TYPES, + &req, rpmi_u32_count(req), rpmi_u32_count(req), + &resp, rpmi_u32_count(resp), rpmi_u32_count(resp)); + if (rc) + return rc; + + susp->num_states = resp.returned + resp.remaining; + return 0; +} + +static int rpmi_hsm_get_suspend_states(struct mbox_chan *chan, + struct rpmi_hsm_suspend *susp) +{ + int rc, i, cnt = 0; + struct rpmi_hsm_get_susp_types_req req; + struct rpmi_hsm_get_susp_types_resp resp; + struct rpmi_hsm_get_susp_info_req dreq; + struct rpmi_hsm_get_susp_info_resp dresp; + struct sbi_cpu_idle_state *state; + + if (!susp->num_states) + return 0; + + req.start_index = 0; + do { + rc = rpmi_normal_request_with_status( + chan, RPMI_HSM_SRV_GET_SUSPEND_TYPES, + &req, rpmi_u32_count(req), rpmi_u32_count(req), + &resp, rpmi_u32_count(resp), rpmi_u32_count(resp)); + if (rc) + return rc; + + for (i = 0; i < resp.returned && cnt < susp->num_states; i++) + susp->states[cnt++].suspend_param = resp.types[i]; + req.start_index = i; + } while (resp.remaining); + + for (i = 0; i < susp->num_states; i++) { + state = &susp->states[i]; + + dreq.suspend_type = state->suspend_param; + rc = rpmi_normal_request_with_status( + chan, RPMI_HSM_SRV_GET_SUSPEND_INFO, + &dreq, rpmi_u32_count(dreq), rpmi_u32_count(dreq), + &dresp, rpmi_u32_count(dresp), rpmi_u32_count(dresp)); + if (rc) + return rc; + + state->entry_latency_us = dresp.entry_latency_us; + state->exit_latency_us = dresp.exit_latency_us; + state->wakeup_latency_us = dresp.wakeup_latency_us; + state->min_residency_us = dresp.min_residency_us; + } + + return 0; +} + +static int rpmi_hsm_update_hart_scratch(struct mbox_chan *chan, + struct rpmi_hsm_suspend *susp) +{ + int rc, i; + struct rpmi_hsm_get_hart_list_req req; + struct rpmi_hsm_get_hart_list_resp resp; + struct rpmi_hsm *rpmi = rpmi_hsm_get_pointer(current_hartid()); + + req.start_index = 0; + do { + rc = rpmi_normal_request_with_status( + chan, RPMI_HSM_SRV_GET_HART_LIST, + &req, rpmi_u32_count(req), rpmi_u32_count(req), + &resp, rpmi_u32_count(resp), rpmi_u32_count(resp)); + if (rc) + return rc; + + for (i = 0; i < resp.returned; i++) { + rpmi = rpmi_hsm_get_pointer(resp.hartid[i]); + if (!rpmi) + return SBI_ENOSYS; + + rpmi->chan = chan; + rpmi->susp = susp; + } + + req.start_index += resp.returned; + } while (resp.remaining); + + return 0; +} + +static int rpmi_hsm_cold_init(void *fdt, int nodeoff, + const struct fdt_match *match) +{ + int rc, i; + struct mbox_chan *chan; + struct rpmi_hsm_suspend *susp; + + if (!rpmi_hsm_offset) { + rpmi_hsm_offset = + sbi_scratch_alloc_type_offset(struct rpmi_hsm); + if (!rpmi_hsm_offset) + return SBI_ENOMEM; + } + + /* + * If channel request failed then other end does not support + * HSM service group so do nothing. + */ + rc = fdt_mailbox_request_chan(fdt, nodeoff, 0, &chan); + if (rc) + return 0; + + /* Allocate context for HART suspend states */ + susp = sbi_zalloc(sizeof(*susp)); + if (!susp) + return SBI_ENOMEM; + + /* Get number of HART suspend states */ + rc = rpmi_hsm_get_num_suspend_states(chan, susp); + if (rc) + goto fail_free_susp; + + /* Skip HART suspend state discovery for zero HART suspend states */ + if (!susp->num_states) + goto skip_suspend_states; + + /* Allocate array of HART suspend states */ + susp->states = sbi_calloc(susp->num_states + 1, sizeof(*susp->states)); + if (!susp->states) { + rc = SBI_ENOMEM; + goto fail_free_susp; + } + + /* Allocate name of each HART suspend state */ + for (i = 0; i < susp->num_states; i++) { + susp->states[i].name = + sbi_zalloc(MAX_HSM_SUPSEND_STATE_NAMELEN); + if (!susp->states[i].name) { + do { + i--; + sbi_free((void *)susp->states[i].name); + } while (i > 0); + + rc = SBI_ENOMEM; + goto fail_free_susp_states; + } + sbi_snprintf((char *)susp->states[i].name, + MAX_HSM_SUPSEND_STATE_NAMELEN, "cpu-susp%d", i); + } + + /* Get details about each HART suspend state */ + rc = rpmi_hsm_get_suspend_states(chan, susp); + if (rc) + goto fail_free_susp_state_names; + +skip_suspend_states: + /* Update per-HART scratch space */ + rc = rpmi_hsm_update_hart_scratch(chan, susp); + if (rc) + goto fail_free_susp_state_names; + + /* Register HSM device */ + if (!susp->num_states) + sbi_hsm_rpmi.hart_suspend = NULL; + sbi_hsm_set_device(&sbi_hsm_rpmi); + + return 0; + +fail_free_susp_state_names: + for (i = 0; i < susp->num_states; i++) + sbi_free((void *)susp->states[i].name); +fail_free_susp_states: + if (susp->num_states) + sbi_free(susp->states); +fail_free_susp: + sbi_free(susp); + return rc; +} + +static const struct fdt_match rpmi_hsm_match[] = { + { .compatible = "riscv,rpmi-hsm" }, + {}, +}; + +struct fdt_hsm fdt_hsm_rpmi = { + .match_table = rpmi_hsm_match, + .fdt_fixup = rpmi_hsm_fixup, + .cold_init = rpmi_hsm_cold_init, +}; diff --git a/lib/utils/hsm/objects.mk b/lib/utils/hsm/objects.mk index 49337bf5..b54b6f6c 100644 --- a/lib/utils/hsm/objects.mk +++ b/lib/utils/hsm/objects.mk @@ -9,3 +9,6 @@ libsbiutils-objs-$(CONFIG_FDT_HSM) += hsm/fdt_hsm.o libsbiutils-objs-$(CONFIG_FDT_HSM) += hsm/fdt_hsm_drivers.carray.o + +carray-fdt_hsm_drivers-$(CONFIG_FDT_HSM_RPMI) += fdt_hsm_rpmi +libsbiutils-objs-$(CONFIG_FDT_HSM_RPMI) += hsm/fdt_hsm_rpmi.o diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig index 2efc7136..78fc96b6 100644 --- a/platform/generic/configs/defconfig +++ b/platform/generic/configs/defconfig @@ -11,6 +11,7 @@ CONFIG_FDT_GPIO_DESIGNWARE=y CONFIG_FDT_GPIO_SIFIVE=y CONFIG_FDT_GPIO_STARFIVE=y CONFIG_FDT_HSM=y +CONFIG_FDT_HSM_RPMI=y CONFIG_FDT_I2C=y CONFIG_FDT_I2C_SIFIVE=y CONFIG_FDT_I2C_DW=y