aboutsummaryrefslogtreecommitdiff
path: root/product/rddanielxlr/module
diff options
context:
space:
mode:
authorAditya Angadi <aditya.angadi@arm.com>2020-01-13 13:41:33 +0530
committerjimqui01 <54316584+jimqui01@users.noreply.github.com>2020-04-15 13:50:41 +0100
commitb44fa4a280284cacf1c87331fb4784863fbf596e (patch)
treea0f8d6052ce1f17b03a2e01a9380697563e6659f /product/rddanielxlr/module
parentb098fe7119d16d06ecef3bcd5fc57db1986199e2 (diff)
product/rddanielxlr: add rddanielxlr system module
The system module performs the function of initializing the SYSTOP domain, turning on the primary core, setting up of the SCMI services and SDS messaging stack. Change-Id: If344a8b2254dedf76f24c8ee23d2526cbeb9a990 Signed-off-by: Aditya Angadi <aditya.angadi@arm.com>
Diffstat (limited to 'product/rddanielxlr/module')
-rw-r--r--product/rddanielxlr/module/rddanielxlr_system/include/mod_rddanielxlr_system.h64
-rw-r--r--product/rddanielxlr/module/rddanielxlr_system/src/Makefile11
-rw-r--r--product/rddanielxlr/module/rddanielxlr_system/src/mod_rddanielxlr_system.c388
3 files changed, 463 insertions, 0 deletions
diff --git a/product/rddanielxlr/module/rddanielxlr_system/include/mod_rddanielxlr_system.h b/product/rddanielxlr/module/rddanielxlr_system/include/mod_rddanielxlr_system.h
new file mode 100644
index 00000000..cc7d62e4
--- /dev/null
+++ b/product/rddanielxlr/module/rddanielxlr_system/include/mod_rddanielxlr_system.h
@@ -0,0 +1,64 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Description:
+ * RD-Daniel System Support
+ */
+
+#ifndef MOD_RDDANIELXLR_SYSTEM_H
+#define MOD_RDDANIELXLR_SYSTEM_H
+
+#include <mod_power_domain.h>
+
+/*!
+ * \addtogroup GroupRDDANIELXLRModule RDDANIELXLR Product Modules
+ * @{
+ */
+
+/*!
+ * \defgroup GroupRDDANIELXLRSystem RDDANIELXLR System Support
+ * @{
+ */
+
+/*!
+ * \brief Additional RDDANIELXLR system power states.
+ */
+enum mod_rddanielxlr_system_power_states {
+ MOD_RDDANIELXLR_SYSTEM_POWER_STATE_SLEEP0 = MOD_PD_STATE_COUNT,
+ MOD_RDDANIELXLR_SYSTEM_POWER_STATE_SLEEP1,
+ MOD_RDDANIELXLR_SYSTEM_POWER_STATE_COUNT
+};
+
+/*!
+ * \brief System power state masks.
+ */
+enum mod_rddanielxlr_system_power_state_masks {
+ MOD_RDDANIELXLR_SYSTEM_POWER_STATE_SLEEP0_MASK =
+ (1 << MOD_RDDANIELXLR_SYSTEM_POWER_STATE_SLEEP0),
+ MOD_RDDANIELXLR_SYSTEM_POWER_STATE_SLEEP1_MASK =
+ (1 << MOD_RDDANIELXLR_SYSTEM_POWER_STATE_SLEEP1),
+};
+
+/*!
+ * \brief Indices of the interfaces exposed by the module.
+ */
+enum mod_rddanielxlr_system_api_idx {
+ /*! API index for the driver interface of the SYSTEM POWER module */
+ MOD_RDDANIELXLR_SYSTEM_API_IDX_SYSTEM_POWER_DRIVER,
+
+ /*! Number of exposed interfaces */
+ MOD_RDDANIELXLR_SYSTEM_API_COUNT
+};
+
+/*!
+ * @}
+ */
+
+/*!
+ * @}
+ */
+
+#endif /* MOD_RDDANIELXLR_SYSTEM_H */
diff --git a/product/rddanielxlr/module/rddanielxlr_system/src/Makefile b/product/rddanielxlr/module/rddanielxlr_system/src/Makefile
new file mode 100644
index 00000000..68b74082
--- /dev/null
+++ b/product/rddanielxlr/module/rddanielxlr_system/src/Makefile
@@ -0,0 +1,11 @@
+#
+# Arm SCP/MCP Software
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BS_LIB_NAME := RDDANIELXLR SYSTEM
+BS_LIB_SOURCES = mod_rddanielxlr_system.c
+
+include $(BS_DIR)/lib.mk
diff --git a/product/rddanielxlr/module/rddanielxlr_system/src/mod_rddanielxlr_system.c b/product/rddanielxlr/module/rddanielxlr_system/src/mod_rddanielxlr_system.c
new file mode 100644
index 00000000..748c8d92
--- /dev/null
+++ b/product/rddanielxlr/module/rddanielxlr_system/src/mod_rddanielxlr_system.c
@@ -0,0 +1,388 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Description:
+ * RD-Daniel System Support.
+ */
+
+#include "clock_soc.h"
+#include "rddanielxlr_core.h"
+#include "rddanielxlr_scmi.h"
+#include "rddanielxlr_sds.h"
+#include "scp_css_mmap.h"
+#include "scp_pik.h"
+#include "scp_rddanielxlr_irq.h"
+
+#include <mod_clock.h>
+#include <mod_power_domain.h>
+#include <mod_ppu_v1.h>
+#include <mod_rddanielxlr_system.h>
+#include <mod_scmi.h>
+#include <mod_sds.h>
+#include <mod_system_info.h>
+#include <mod_system_power.h>
+
+#include <fwk_assert.h>
+#include <fwk_event.h>
+#include <fwk_id.h>
+#include <fwk_interrupt.h>
+#include <fwk_log.h>
+#include <fwk_macros.h>
+#include <fwk_module.h>
+#include <fwk_module_idx.h>
+#include <fwk_notification.h>
+#include <fwk_status.h>
+
+#include <fmw_cmsis.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/* SCMI services required to enable the messaging stack */
+static unsigned int scmi_notification_table[] = {
+ SCP_RDDANIELXLR_SCMI_SERVICE_IDX_PSCI,
+};
+
+/* Module context */
+struct rddanielxlr_system_ctx {
+ /* Pointer to the SCP PIK registers */
+ struct pik_scp_reg *pik_scp_reg;
+
+ /* Pointer to the Interrupt Service Routine API of the PPU_V1 module */
+ const struct ppu_v1_isr_api *ppu_v1_isr_api;
+
+ /* Power domain module restricted API pointer */
+ struct mod_pd_restricted_api *mod_pd_restricted_api;
+
+ /* System Information HAL API pointer */
+ struct mod_system_info_get_info_api *system_info_api;
+ /* SDS API pointer */
+ const struct mod_sds_api *sds_api;
+};
+
+struct rddanielxlr_system_isr {
+ unsigned int interrupt;
+ void (*handler)(void);
+};
+
+static struct rddanielxlr_system_ctx rddanielxlr_system_ctx;
+const struct fwk_module_config config_rddanielxlr_system = { 0 };
+
+static const uint32_t feature_flags = (RDDANIELXLR_SDS_FEATURE_FIRMWARE_MASK |
+ RDDANIELXLR_SDS_FEATURE_DMC_MASK |
+ RDDANIELXLR_SDS_FEATURE_MESSAGING_MASK);
+
+static fwk_id_t sds_feature_availability_id =
+ FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SDS, 3);
+
+/*
+ * SCMI Messaging stack
+ */
+
+static int messaging_stack_ready(void)
+{
+ const struct mod_sds_structure_desc *sds_structure_desc =
+ fwk_module_get_data(sds_feature_availability_id);
+
+ /*
+ * Write SDS Feature Availability to signal the completion of the messaging
+ * stack
+ */
+ return rddanielxlr_system_ctx.sds_api->struct_write(sds_structure_desc->id,
+ 0, (void *)(&feature_flags), sds_structure_desc->size);
+}
+
+/*
+ * PPU Interrupt Service Routines for cluster and core power domains
+ */
+
+static void ppu_cores_isr(unsigned int first, uint32_t status)
+{
+ unsigned int core_idx;
+
+ while (status != 0) {
+ core_idx = __builtin_ctz(status);
+ status &= ~(1 << core_idx);
+
+ if ((first + core_idx) >= rddanielxlr_core_get_core_count())
+ continue;
+
+ rddanielxlr_system_ctx.ppu_v1_isr_api->ppu_interrupt_handler(
+ FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, first + core_idx));
+ }
+}
+
+static void ppu_cores_isr_0(void)
+{
+ ppu_cores_isr(0,
+ rddanielxlr_system_ctx.pik_scp_reg->CPU_PPU_INT_STATUS[0]);
+ ppu_cores_isr(128,
+ rddanielxlr_system_ctx.pik_scp_reg->CPU_PPU_INT_STATUS[4]);
+}
+
+static void ppu_cores_isr_1(void)
+{
+ ppu_cores_isr(32,
+ rddanielxlr_system_ctx.pik_scp_reg->CPU_PPU_INT_STATUS[1]);
+ ppu_cores_isr(160,
+ rddanielxlr_system_ctx.pik_scp_reg->CPU_PPU_INT_STATUS[5]);
+}
+
+static void ppu_cores_isr_2(void)
+{
+ ppu_cores_isr(64,
+ rddanielxlr_system_ctx.pik_scp_reg->CPU_PPU_INT_STATUS[2]);
+ ppu_cores_isr(192,
+ rddanielxlr_system_ctx.pik_scp_reg->CPU_PPU_INT_STATUS[6]);
+}
+
+static void ppu_cores_isr_3(void)
+{
+ ppu_cores_isr(96,
+ rddanielxlr_system_ctx.pik_scp_reg->CPU_PPU_INT_STATUS[3]);
+ ppu_cores_isr(224,
+ rddanielxlr_system_ctx.pik_scp_reg->CPU_PPU_INT_STATUS[7]);
+}
+
+static void ppu_clusters_isr(void)
+{
+ uint32_t status = rddanielxlr_system_ctx.pik_scp_reg->CLUS_PPU_INT_STATUS;
+ unsigned int cluster_idx;
+
+ while (status != 0) {
+ cluster_idx = __builtin_ctz(status);
+
+ rddanielxlr_system_ctx.ppu_v1_isr_api->ppu_interrupt_handler(
+ FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1,
+ rddanielxlr_core_get_core_count() + cluster_idx));
+
+ status &= ~(1 << cluster_idx);
+ }
+}
+
+/*
+ * PPU Interrupt Service Routine table
+ */
+
+static struct rddanielxlr_system_isr isrs[] = {
+ [0] = { .interrupt = PPU_CORES0_IRQ,
+ .handler = ppu_cores_isr_0 },
+ [1] = { .interrupt = PPU_CORES1_IRQ,
+ .handler = ppu_cores_isr_1 },
+ [2] = { .interrupt = PPU_CORES2_IRQ,
+ .handler = ppu_cores_isr_2 },
+ [3] = { .interrupt = PPU_CORES3_IRQ,
+ .handler = ppu_cores_isr_3 },
+ [4] = { .interrupt = PPU_CLUSTERS_IRQ,
+ .handler = ppu_clusters_isr },
+};
+
+/*
+ * System power's driver API
+ */
+
+static int rddanielxlr_system_shutdown(
+ enum mod_pd_system_shutdown system_shutdown)
+{
+ NVIC_SystemReset();
+
+ return FWK_E_DEVICE;
+}
+
+static const struct mod_system_power_driver_api
+ rddanielxlr_system_system_power_driver_api = {
+ .system_shutdown = rddanielxlr_system_shutdown,
+};
+
+/*
+ * Functions fulfilling the framework's module interface
+ */
+
+static int rddanielxlr_system_mod_init(fwk_id_t module_id, unsigned int unused,
+ const void *unused2)
+{
+ int status;
+ unsigned int idx;
+ struct rddanielxlr_system_isr *isr;
+
+ for (idx = 0; idx < FWK_ARRAY_SIZE(isrs); idx++) {
+ isr = &isrs[idx];
+ status = fwk_interrupt_set_isr(isr->interrupt, isr->handler);
+ if (status != FWK_SUCCESS)
+ return status;
+ }
+
+ rddanielxlr_system_ctx.pik_scp_reg = (struct pik_scp_reg *)SCP_PIK_SCP_BASE;
+
+ return FWK_SUCCESS;
+}
+
+static int rddanielxlr_system_bind(fwk_id_t id, unsigned int round)
+{
+ int status;
+
+ if (round > 0)
+ return FWK_SUCCESS;
+
+ status = fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_POWER_DOMAIN),
+ FWK_ID_API(FWK_MODULE_IDX_POWER_DOMAIN, MOD_PD_API_IDX_RESTRICTED),
+ &rddanielxlr_system_ctx.mod_pd_restricted_api);
+ if (status != FWK_SUCCESS)
+ return status;
+
+ status = fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_PPU_V1),
+ FWK_ID_API(FWK_MODULE_IDX_PPU_V1, MOD_PPU_V1_API_IDX_ISR),
+ &rddanielxlr_system_ctx.ppu_v1_isr_api);
+ if (status != FWK_SUCCESS)
+ return status;
+ status = fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_SYSTEM_INFO),
+ FWK_ID_API(FWK_MODULE_IDX_SYSTEM_INFO,
+ MOD_SYSTEM_INFO_GET_API_IDX),
+ &rddanielxlr_system_ctx.system_info_api);
+ if (status != FWK_SUCCESS)
+ return status;
+
+
+ return fwk_module_bind(fwk_module_id_sds,
+ FWK_ID_API(FWK_MODULE_IDX_SDS, 0),
+ &rddanielxlr_system_ctx.sds_api);
+}
+
+static int rddanielxlr_system_process_bind_request(fwk_id_t requester_id,
+ fwk_id_t pd_id, fwk_id_t api_id, const void **api)
+{
+ *api = &rddanielxlr_system_system_power_driver_api;
+ return FWK_SUCCESS;
+}
+
+static int rddanielxlr_system_start(fwk_id_t id)
+{
+ int status;
+ unsigned int i;
+
+ status = fwk_notification_subscribe(
+ mod_clock_notification_id_state_changed,
+ FWK_ID_ELEMENT(FWK_MODULE_IDX_CLOCK, CLOCK_IDX_INTERCONNECT),
+ id);
+ if (status != FWK_SUCCESS)
+ return status;
+
+ FWK_LOG_INFO(
+ "[RD-DANIELXLR SYSTEM] Requesting SYSTOP initialization...\n");
+
+ /*
+ * Subscribe to these SCMI channels in order to know when they have all
+ * initialized.
+ * At that point we can consider the SCMI stack to be initialized from
+ * the point of view of the PSCI agent.
+ */
+ for (i = 0; i < FWK_ARRAY_SIZE(scmi_notification_table); i++) {
+ status = fwk_notification_subscribe(
+ mod_scmi_notification_id_initialized,
+ fwk_id_build_element_id(fwk_module_id_scmi,
+ scmi_notification_table[i]),
+ id);
+ if (status != FWK_SUCCESS)
+ return status;
+ }
+
+ /*
+ * Subscribe to the SDS initialized notification so we can correctly let the
+ * PSCI agent know that the SCMI stack is initialized.
+ */
+ status = fwk_notification_subscribe(
+ mod_sds_notification_id_initialized,
+ fwk_module_id_sds,
+ id);
+ if (status != FWK_SUCCESS)
+ return status;
+
+ return
+ rddanielxlr_system_ctx.mod_pd_restricted_api->set_composite_state_async(
+ FWK_ID_ELEMENT(FWK_MODULE_IDX_POWER_DOMAIN, 0), false,
+ MOD_PD_COMPOSITE_STATE(MOD_PD_LEVEL_2, 0, MOD_PD_STATE_ON,
+ MOD_PD_STATE_OFF, MOD_PD_STATE_OFF));
+}
+
+int rddanielxlr_system_process_notification(const struct fwk_event *event,
+ struct fwk_event *resp_event)
+{
+ int status;
+ struct clock_notification_params *params;
+ struct mod_pd_restricted_api *mod_pd_restricted_api;
+ static unsigned int scmi_notification_count;
+ static bool sds_notification_received;
+ const struct mod_system_info *system_info;
+ uint8_t chip_id = 0;
+
+ status = rddanielxlr_system_ctx.system_info_api->get_system_info(
+ &system_info);
+ if (status == FWK_SUCCESS)
+ chip_id = system_info->chip_id;
+
+ assert(fwk_id_is_type(event->target_id, FWK_ID_TYPE_MODULE));
+
+ if (fwk_id_is_equal(event->id, mod_clock_notification_id_state_changed)) {
+ params = (struct clock_notification_params *)event->params;
+
+ /*
+ * Initialize primary core when the system is initialized for the first
+ * time only
+ */
+ if (params->new_state == MOD_CLOCK_STATE_RUNNING && chip_id == 0) {
+ FWK_LOG_INFO(
+ "[RD-DANIELXLR SYSTEM] Initializing the primary core...\n");
+
+ mod_pd_restricted_api =
+ rddanielxlr_system_ctx.mod_pd_restricted_api;
+
+ status = mod_pd_restricted_api->set_composite_state_async(
+ FWK_ID_ELEMENT(FWK_MODULE_IDX_POWER_DOMAIN, 0),
+ false,
+ MOD_PD_COMPOSITE_STATE(MOD_PD_LEVEL_2, 0, MOD_PD_STATE_ON,
+ MOD_PD_STATE_ON, MOD_PD_STATE_ON));
+ if (status != FWK_SUCCESS)
+ return status;
+
+ /* Unsubscribe to the notification */
+ return fwk_notification_unsubscribe(event->id, event->source_id,
+ event->target_id);
+ } else
+ FWK_LOG_INFO(
+ "[RD-DANIELXLR SYSTEM] Detected as Slave chip: %d, "
+ "wait for SCMI\n", chip_id);
+
+ return FWK_SUCCESS;
+ } else if (fwk_id_is_equal(event->id,
+ mod_scmi_notification_id_initialized)) {
+ scmi_notification_count++;
+ } else if (fwk_id_is_equal(event->id,
+ mod_sds_notification_id_initialized)) {
+ sds_notification_received = true;
+ } else
+ return FWK_E_PARAM;
+
+ if ((scmi_notification_count == FWK_ARRAY_SIZE(scmi_notification_table)) &&
+ sds_notification_received) {
+ messaging_stack_ready();
+
+ scmi_notification_count = 0;
+ sds_notification_received = false;
+ }
+
+ return FWK_SUCCESS;
+}
+
+const struct fwk_module module_rddanielxlr_system = {
+ .name = "RDDANIELXLR_SYSTEM",
+ .type = FWK_MODULE_TYPE_DRIVER,
+ .api_count = MOD_RDDANIELXLR_SYSTEM_API_COUNT,
+ .init = rddanielxlr_system_mod_init,
+ .bind = rddanielxlr_system_bind,
+ .process_bind_request = rddanielxlr_system_process_bind_request,
+ .process_notification = rddanielxlr_system_process_notification,
+ .start = rddanielxlr_system_start,
+};