aboutsummaryrefslogtreecommitdiff
path: root/module/psu/src
diff options
context:
space:
mode:
authorRonald Cron <ronald.cron@arm.com>2018-06-05 09:31:39 +0200
committerRonald Cron <ronald.cron@arm.com>2018-06-08 11:46:47 +0200
commitb151958dbb2f37383f4d9a1f7802c36008d9fef2 (patch)
treefe20ebfb8c10facbfd028edefe601462ae3ee64c /module/psu/src
parentfd3027b6fd17a4a33a685adb73f2acfcae9a2ced (diff)
Add support for SGM-775
Co-authored-by: Filipe Rinaldi <filipe.rinaldi@arm.com> Co-authored-by: Paul Beesley <paul.beesley@arm.com> Co-authored-by: Chris Kay <chris.kay@arm.com> Co-authored-by: Elieva Pignat <elieva.pignat@arm.com> Co-authored-by: Pedro Custodio <pedro.krewinkelcustodio@arm.com> Change-Id: Ic7524ad58a7c15d5b055e88a9719b2feee437f1d Signed-off-by: Ronald Cron <ronald.cron@arm.com>
Diffstat (limited to 'module/psu/src')
-rw-r--r--module/psu/src/Makefile14
-rw-r--r--module/psu/src/mod_psu_device_api.c224
-rw-r--r--module/psu/src/mod_psu_device_api_private.h16
-rw-r--r--module/psu/src/mod_psu_event.c98
-rw-r--r--module/psu/src/mod_psu_event_private.h29
-rw-r--r--module/psu/src/mod_psu_module.c128
-rw-r--r--module/psu/src/mod_psu_module_private.h28
-rw-r--r--module/psu/src/mod_psu_private.h16
8 files changed, 553 insertions, 0 deletions
diff --git a/module/psu/src/Makefile b/module/psu/src/Makefile
new file mode 100644
index 00000000..da070113
--- /dev/null
+++ b/module/psu/src/Makefile
@@ -0,0 +1,14 @@
+#
+# Arm SCP/MCP Software
+# Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BS_LIB_NAME := psu
+BS_LIB_SOURCES := \
+ mod_psu_device_api.c \
+ mod_psu_event.c \
+ mod_psu_module.c
+
+include $(BS_DIR)/lib.mk
diff --git a/module/psu/src/mod_psu_device_api.c b/module/psu/src/mod_psu_device_api.c
new file mode 100644
index 00000000..f3500d7a
--- /dev/null
+++ b/module/psu/src/mod_psu_device_api.c
@@ -0,0 +1,224 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <fwk_mm.h>
+#include <fwk_module.h>
+#include <fwk_module_idx.h>
+#include <fwk_thread.h>
+#include <mod_psu_private.h>
+
+static int api_get_enabled(fwk_id_t device_id, bool *enabled)
+{
+ int status;
+ const struct mod_psu_device_ctx *ctx;
+
+ /* This API call cannot target another module */
+ if (fwk_id_get_module_idx(device_id) != FWK_MODULE_IDX_PSU)
+ return FWK_E_PARAM;
+
+ /* Ensure the identifier refers to a valid element */
+ if (!fwk_module_is_valid_element_id(device_id))
+ return FWK_E_PARAM;
+
+ /* Validate the API call */
+ status = fwk_module_check_call(device_id);
+ if (status != FWK_SUCCESS)
+ return FWK_E_STATE;
+
+ ctx = __mod_psu_get_valid_device_ctx(device_id);
+ if (ctx == NULL)
+ return FWK_E_PARAM;
+
+ /* Get the enabled state from the driver */
+ status = ctx->apis.driver->get_enabled(ctx->config->driver_id, enabled);
+ if (status != FWK_SUCCESS)
+ return FWK_E_HANDLER;
+
+ return FWK_SUCCESS;
+}
+
+static int api_set_enabled(fwk_id_t device_id, bool enable)
+{
+ int status;
+ const struct mod_psu_device_ctx *ctx;
+
+ /* This API call cannot target another module */
+ if (fwk_id_get_module_idx(device_id) != FWK_MODULE_IDX_PSU)
+ return FWK_E_PARAM;
+
+ /* Ensure the identifier refers to a valid element */
+ if (!fwk_module_is_valid_element_id(device_id))
+ return FWK_E_PARAM;
+
+ /* Validate the API call */
+ status = fwk_module_check_call(device_id);
+ if (status != FWK_SUCCESS)
+ return FWK_E_STATE;
+
+ ctx = __mod_psu_get_valid_device_ctx(device_id);
+ if (ctx == NULL)
+ return FWK_E_PARAM;
+
+ /* Set the enabled state through the driver */
+ status = ctx->apis.driver->set_enabled(ctx->config->driver_id, enable);
+ if (status != FWK_SUCCESS)
+ return FWK_E_HANDLER;
+
+ return FWK_SUCCESS;
+}
+
+static int api_set_enabled_async(fwk_id_t device_id, bool enable)
+{
+ int status;
+ struct fwk_event event;
+ struct mod_psu_event_params_set_enabled *params;
+
+ /* This API call cannot target another module */
+ if (fwk_id_get_module_idx(device_id) != FWK_MODULE_IDX_PSU)
+ return FWK_E_PARAM;
+
+ /* Ensure the identifier refers to an existing element */
+ if (fwk_module_is_valid_element_id(device_id))
+ return FWK_E_PARAM;
+
+ /* Validate the API call */
+ status = fwk_module_check_call(device_id);
+ if (status != FWK_SUCCESS)
+ return FWK_E_STATE;
+
+ /* Build and submit the event */
+ event = (struct fwk_event) {
+ .id = mod_psu_event_id_set_enabled,
+ .target_id = device_id,
+ .response_requested = true,
+ };
+
+ params = (void *)&event.params;
+ *params = (struct mod_psu_event_params_set_enabled) {
+ .enable = enable,
+ };
+
+ /* Submit the event for processing */
+ status = fwk_thread_put_event(&event);
+ if (status == FWK_E_NOMEM)
+ return FWK_E_NOMEM;
+ else if (status != FWK_SUCCESS)
+ return FWK_E_PANIC;
+
+ return FWK_SUCCESS;
+}
+
+static int api_get_voltage(fwk_id_t device_id, uintmax_t *voltage)
+{
+ int status;
+ const struct mod_psu_device_ctx *ctx;
+
+ /* This API call cannot target another module */
+ if (fwk_id_get_module_idx(device_id) != FWK_MODULE_IDX_PSU)
+ return FWK_E_PARAM;
+
+ /* Ensure the identifier refers to a valid element */
+ if (!fwk_module_is_valid_element_id(device_id))
+ return FWK_E_PARAM;
+
+ /* Validate the API call */
+ status = fwk_module_check_call(device_id);
+ if (status != FWK_SUCCESS)
+ return FWK_E_STATE;
+
+ ctx = __mod_psu_get_valid_device_ctx(device_id);
+ if (ctx == NULL)
+ return FWK_E_PARAM;
+
+ /* Get the voltage from the driver */
+ status = ctx->apis.driver->get_voltage(ctx->config->driver_id, voltage);
+ if (status != FWK_SUCCESS)
+ return FWK_E_HANDLER;
+
+ return FWK_SUCCESS;
+}
+
+static int api_set_voltage(fwk_id_t device_id, uintmax_t voltage)
+{
+ int status;
+ const struct mod_psu_device_ctx *ctx;
+
+ /* This API call cannot target another module */
+ if (fwk_id_get_module_idx(device_id) != FWK_MODULE_IDX_PSU)
+ return FWK_E_PARAM;
+
+ /* Ensure the identifier refers to a valid element */
+ if (!fwk_module_is_valid_element_id(device_id))
+ return FWK_E_PARAM;
+
+ /* Validate the API call */
+ status = fwk_module_check_call(device_id);
+ if (status != FWK_SUCCESS)
+ return FWK_E_STATE;
+
+ ctx = __mod_psu_get_valid_device_ctx(device_id);
+ if (ctx == NULL)
+ return FWK_E_PARAM;
+
+ /* Set the voltage state through the driver */
+ status = ctx->apis.driver->set_voltage(ctx->config->driver_id, voltage);
+ if (status != FWK_SUCCESS)
+ return FWK_E_HANDLER;
+
+ return FWK_SUCCESS;
+}
+
+static int api_set_voltage_async(fwk_id_t device_id, uintmax_t voltage)
+{
+ int status;
+ struct fwk_event event;
+ struct mod_psu_event_params_set_voltage *params;
+
+ /* This API call cannot target another module */
+ if (fwk_id_get_module_idx(device_id) != FWK_MODULE_IDX_PSU)
+ return FWK_E_PARAM;
+
+ /* Ensure the identifier refers to an existing element */
+ if (fwk_module_is_valid_element_id(device_id))
+ return FWK_E_PARAM;
+
+ /* Validate the API call */
+ status = fwk_module_check_call(device_id);
+ if (status != FWK_SUCCESS)
+ return FWK_E_STATE;
+
+ /* Build and submit the event */
+ event = (struct fwk_event) {
+ .id = mod_psu_event_id_set_enabled,
+ .target_id = device_id,
+ .response_requested = true,
+ };
+
+ params = (void *)&event.params;
+ *params = (struct mod_psu_event_params_set_voltage) {
+ .voltage = voltage,
+ };
+
+ status = fwk_thread_put_event(&event);
+ if (status == FWK_E_NOMEM)
+ return FWK_E_NOMEM;
+ else if (status != FWK_SUCCESS)
+ return FWK_E_PANIC;
+
+ return FWK_SUCCESS;
+}
+
+/* Module API implementation */
+const struct mod_psu_device_api __mod_psu_device_api = {
+ .get_enabled = api_get_enabled,
+ .set_enabled = api_set_enabled,
+ .set_enabled_async = api_set_enabled_async,
+ .get_voltage = api_get_voltage,
+ .set_voltage = api_set_voltage,
+ .set_voltage_async = api_set_voltage_async,
+};
diff --git a/module/psu/src/mod_psu_device_api_private.h b/module/psu/src/mod_psu_device_api_private.h
new file mode 100644
index 00000000..6959f594
--- /dev/null
+++ b/module/psu/src/mod_psu_device_api_private.h
@@ -0,0 +1,16 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MOD_PSU_DEVICE_API_PRIVATE_H
+#define MOD_PSU_DEVICE_API_PRIVATE_H
+
+#include <mod_psu.h>
+
+/* Module API implementation */
+extern const struct mod_psu_device_api __mod_psu_device_api;
+
+#endif /* MOD_PSU_DEVICE_API_PRIVATE_H */
diff --git a/module/psu/src/mod_psu_event.c b/module/psu/src/mod_psu_event.c
new file mode 100644
index 00000000..104045a6
--- /dev/null
+++ b/module/psu/src/mod_psu_event.c
@@ -0,0 +1,98 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <fwk_macros.h>
+#include <fwk_module.h>
+#include <fwk_module_idx.h>
+#include <mod_psu_private.h>
+
+int mod_psu_event_set_enabled(
+ const struct fwk_event *event,
+ struct fwk_event *response)
+{
+ const struct mod_psu_device_ctx *ctx;
+ const struct mod_psu_event_params_set_enabled *params;
+ struct mod_psu_event_params_set_enabled_response *response_params;
+
+ /* These conditions were checked when we submitted the event */
+ assert(fwk_id_get_module_idx(event->target_id) == FWK_MODULE_IDX_PSU);
+ assert(fwk_module_is_valid_element_id(event->target_id));
+
+ /* Explicitly cast to our parameter types */
+ params = (void *)&event->params;
+ response_params = (void *)&response->params;
+
+ ctx = __mod_psu_get_device_ctx(event->target_id);
+
+ /* Set the enabled state through the driver */
+ response_params->status = ctx->apis.driver->set_enabled(
+ ctx->config->driver_id,
+ params->enable);
+
+ return FWK_SUCCESS;
+}
+
+int mod_psu_event_set_voltage(
+ const struct fwk_event *event,
+ struct fwk_event *response)
+{
+ const struct mod_psu_device_ctx *ctx;
+ const struct mod_psu_event_params_set_voltage *params;
+ struct mod_psu_event_params_set_voltage_response *response_params;
+
+ /* These conditions were checked when we submitted the event */
+ assert(fwk_id_get_module_idx(event->target_id) == FWK_MODULE_IDX_PSU);
+ assert(fwk_module_is_valid_element_id(event->target_id));
+
+ /* Explicitly cast to our parameter types */
+ params = (void *)&event->params;
+ response_params = (void *)&response->params;
+
+ ctx = __mod_psu_get_device_ctx(event->target_id);
+
+ /* Set the voltage through the driver */
+ response_params->status = ctx->apis.driver->set_voltage(
+ ctx->config->driver_id,
+ params->voltage);
+
+ return FWK_SUCCESS;
+}
+
+int __mod_psu_process_event(
+ const struct fwk_event *event,
+ struct fwk_event *response)
+{
+ typedef int (*handler_t)(
+ const struct fwk_event *event,
+ struct fwk_event *response);
+
+ static const handler_t handlers[] = {
+ [MOD_PSU_EVENT_IDX_SET_ENABLED] = mod_psu_event_set_enabled,
+ [MOD_PSU_EVENT_IDX_SET_VOLTAGE] = mod_psu_event_set_voltage,
+ };
+
+ unsigned int event_idx;
+ handler_t handler;
+
+ /* We only handle the events defined by us */
+ if (fwk_id_get_module_idx(event->id) != FWK_MODULE_IDX_PSU)
+ return FWK_E_PARAM;
+
+ /* Ensure the event index is within bounds we can handle */
+ event_idx = fwk_id_get_event_idx(event->id);
+ if (event_idx >= FWK_ARRAY_SIZE(handlers))
+ return FWK_E_PARAM;
+
+ /* Ensure we have an implemented handler for this event */
+ handler = handlers[event_idx];
+ if (handler == NULL)
+ return FWK_E_PARAM;
+
+ /* Delegate event handling to the relevant handler */
+ return handler(event, response);
+}
diff --git a/module/psu/src/mod_psu_event_private.h b/module/psu/src/mod_psu_event_private.h
new file mode 100644
index 00000000..e451c8ac
--- /dev/null
+++ b/module/psu/src/mod_psu_event_private.h
@@ -0,0 +1,29 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MOD_PSU_EVENT_PRIVATE_H
+#define MOD_PSU_EVENT_PRIVATE_H
+
+#include <fwk_event.h>
+#include <fwk_id.h>
+
+/* "Set enabled" event */
+struct mod_psu_event_params_set_enabled {
+ bool enable;
+};
+
+/* "Set voltage" event */
+struct mod_psu_event_params_set_voltage {
+ uintmax_t voltage;
+};
+
+/* Event handler */
+int __mod_psu_process_event(
+ const struct fwk_event *event,
+ struct fwk_event *response);
+
+#endif /* MOD_PSU_EVENT_PRIVATE_H */
diff --git a/module/psu/src/mod_psu_module.c b/module/psu/src/mod_psu_module.c
new file mode 100644
index 00000000..9eab2f1d
--- /dev/null
+++ b/module/psu/src/mod_psu_module.c
@@ -0,0 +1,128 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <fwk_macros.h>
+#include <fwk_mm.h>
+#include <fwk_module.h>
+#include <fwk_module_idx.h>
+#include <mod_psu_private.h>
+
+/* Device context table */
+static struct mod_psu_device_ctx (*device_ctx)[];
+
+static int psu_init(
+ fwk_id_t module_id,
+ unsigned int element_count,
+ const void *data)
+{
+ device_ctx = fwk_mm_calloc(
+ element_count,
+ sizeof((*device_ctx)[0]));
+ if (device_ctx == NULL)
+ return FWK_E_NOMEM;
+
+ return FWK_SUCCESS;
+}
+
+static int psu_element_init(
+ fwk_id_t device_id,
+ unsigned int sub_element_count,
+ const void *data)
+{
+ assert(sub_element_count == 0);
+
+ __mod_psu_get_device_ctx(device_id)->config = data;
+
+ return FWK_SUCCESS;
+}
+
+static int psu_bind_element(fwk_id_t device_id, unsigned int round)
+{
+ int status;
+ const struct mod_psu_device_ctx *ctx;
+
+ /* Only handle the first round */
+ if (round > 0)
+ return FWK_SUCCESS;
+
+ ctx = __mod_psu_get_device_ctx(device_id);
+
+ /* Bind to the driver */
+ status = fwk_module_bind(
+ ctx->config->driver_id,
+ ctx->config->driver_api_id,
+ &ctx->apis.driver);
+ if (status != FWK_SUCCESS) {
+ assert(false);
+
+ return FWK_E_PANIC;
+ }
+
+ assert(ctx->apis.driver->set_enabled != NULL);
+ assert(ctx->apis.driver->get_enabled != NULL);
+ assert(ctx->apis.driver->set_voltage != NULL);
+ assert(ctx->apis.driver->get_voltage != NULL);
+
+ return FWK_SUCCESS;
+}
+
+static int psu_bind(fwk_id_t id, unsigned int round)
+{
+ /* We only need to handle element binding */
+ if (fwk_id_is_type(id, FWK_ID_TYPE_ELEMENT))
+ return psu_bind_element(id, round);
+
+ return FWK_SUCCESS;
+}
+
+static int psu_process_bind_request(
+ fwk_id_t source_id,
+ fwk_id_t target_id,
+ fwk_id_t api_id,
+ const void **api)
+{
+ /* Only accept binds to the elements */
+ if (!fwk_id_is_type(target_id, FWK_ID_TYPE_ELEMENT))
+ return FWK_E_PARAM;
+
+ /* Only expose the device API */
+ if (!fwk_id_is_equal(api_id, mod_psu_api_id_psu_device))
+ return FWK_E_PARAM;
+
+ *api = &__mod_psu_device_api;
+
+ return FWK_SUCCESS;
+}
+
+struct mod_psu_device_ctx *__mod_psu_get_device_ctx(fwk_id_t device_id)
+{
+ unsigned int element_idx = fwk_id_get_element_idx(device_id);
+
+ return &(*device_ctx)[element_idx];
+}
+
+struct mod_psu_device_ctx *__mod_psu_get_valid_device_ctx(fwk_id_t device_id)
+{
+ if (fwk_module_check_call(device_id) != FWK_SUCCESS)
+ return NULL;
+
+ return __mod_psu_get_device_ctx(device_id);
+}
+
+/* Module description */
+const struct fwk_module module_psu = {
+ .name = "PSU",
+ .type = FWK_MODULE_TYPE_HAL,
+ .init = psu_init,
+ .element_init = psu_element_init,
+ .bind = psu_bind,
+ .process_bind_request = psu_process_bind_request,
+ .process_event = __mod_psu_process_event,
+ .api_count = MOD_PSU_API_IDX_COUNT,
+ .event_count = MOD_PSU_EVENT_IDX_COUNT,
+};
diff --git a/module/psu/src/mod_psu_module_private.h b/module/psu/src/mod_psu_module_private.h
new file mode 100644
index 00000000..adf01784
--- /dev/null
+++ b/module/psu/src/mod_psu_module_private.h
@@ -0,0 +1,28 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MOD_PSU_DEVICE_CTX_PRIVATE_H
+#define MOD_PSU_DEVICE_CTX_PRIVATE_H
+
+#include <fwk_id.h>
+#include <mod_psu.h>
+
+/* Device context */
+struct mod_psu_device_ctx {
+ /* Device configuration */
+ const struct mod_psu_device_config *config;
+
+ struct {
+ /* Driver API */
+ const struct mod_psu_driver_api *driver;
+ } apis;
+};
+
+struct mod_psu_device_ctx *__mod_psu_get_device_ctx(fwk_id_t device_id);
+struct mod_psu_device_ctx *__mod_psu_get_valid_device_ctx(fwk_id_t device_id);
+
+#endif /* MOD_PSU_DEVICE_CTX_PRIVATE_H */
diff --git a/module/psu/src/mod_psu_private.h b/module/psu/src/mod_psu_private.h
new file mode 100644
index 00000000..446e9f63
--- /dev/null
+++ b/module/psu/src/mod_psu_private.h
@@ -0,0 +1,16 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MOD_PSU_PRIVATE_H
+#define MOD_PSU_PRIVATE_H
+
+#include <fwk_id.h>
+#include <mod_psu_device_api_private.h>
+#include <mod_psu_event_private.h>
+#include <mod_psu_module_private.h>
+
+#endif /* MOD_PSU_PRIVATE_H */