diff --git a/.gitlab/templates/build-test.yml b/.gitlab/templates/build-test.yml index c6fcfec7f3a96435e7c549465c0f7ffe058187d6..2da117f5e4b098c89e30162a68627f3a491162da 100644 --- a/.gitlab/templates/build-test.yml +++ b/.gitlab/templates/build-test.yml @@ -38,7 +38,7 @@ matrix: - BUILD_PRODUCT: [host, juno, morello, n1sdp, rcar, rdv3, rdv1, rdv1mc, rdn1e1, rdn2, - sgi575, sgm775, sgm776, synquacer, tc2] + sgi575, sgm775, sgm776, synquacer, tc2, rd1ae] .build-products-all-products-all-log-levels: extends: .build-products @@ -46,7 +46,7 @@ matrix: - BUILD_PRODUCT: [host, juno, morello, n1sdp, rcar, rdv3, rdv1, rdv1mc, rdn1e1, rdn2, - sgi575, sgm775, sgm776, synquacer, tc2] + sgi575, sgm775, sgm776, synquacer, tc2, rd1ae] BUILD_PRODUCTS_LOG_LEVEL: [DEBUG, INFO, WARN, ERROR, CRIT, DISABLED] diff --git a/maintainers.md b/maintainers.md index d41e435cc62d7b433785024858279fea1ff37f12..c496c5f63b91fb6c25e38c38fa7aa2e8c883a886 100644 --- a/maintainers.md +++ b/maintainers.md @@ -39,6 +39,12 @@ contributions. Arm platforms typically come under the maintainership of the project core maintainers. The platforms listed here represent the exceptions to this rule. +#### Automotive RD platforms (rd1ae) + +- [Diego Sueiro](https://gitlab.arm.com/Diego.Sueiro) +- [Peter Hoyes](https://gitlab.arm.com/Peter.Hoyes) +- [Ziad Elhanafy](https://gitlab.arm.com/Ziad.Elhanafy) + #### Morello (morello) - [Deepak Pandey](https://gitlab.arm.com/Deepak.Pandey) diff --git a/module/noc_s3/src/noc_s3_discovery.c b/module/noc_s3/src/noc_s3_discovery.c index f07bf311e2b90c22733154e6e44e9cbd34d9f12d..ee0d9810a96747cb253b15506b2146880bb47d9b 100644 --- a/module/noc_s3/src/noc_s3_discovery.c +++ b/module/noc_s3/src/noc_s3_discovery.c @@ -344,8 +344,9 @@ int noc_s3_get_subfeature_offset( } FWK_LOG_ERR( - MOD_NAME "Subfeature(%d) not supported by the Node[Type: %" PRId32 - "][ID: %" PRId32 "]", + MOD_NAME + "Subfeature(%d) not supported by the Node[Type: %lu" + "][ID: %lu]", subfeature_type, GET_NODE_TYPE(component_hdr->node_type), GET_NODE_ID(component_hdr->node_type)); diff --git a/product/automotive-rd/rd1ae/include/syscnt_impdef.h b/product/automotive-rd/rd1ae/include/syscnt_impdef.h new file mode 100644 index 0000000000000000000000000000000000000000..bd17249c0bcd2ba4533e33ec703d08fe1dc10ae0 --- /dev/null +++ b/product/automotive-rd/rd1ae/include/syscnt_impdef.h @@ -0,0 +1,21 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * System counter implementation specific register defnitions. + */ + +#ifndef RD1AE_SYSCNT_IMPDEF_H +#define RD1AE_SYSCNT_IMPDEF_H + +/* + * Offsets of the system counter implementation defined registers found on + * RD1AE. + */ +#define RD1AE_SYSCNT_IMPDEF0_CNTENCR 0xC0U +#define RD1AE_SYSCNT_IMPDEF0_CNTINCR 0xD0U + +#endif /* RD1AE_SYSCNT_IMPDEF_H */ diff --git a/product/automotive-rd/rd1ae/interface/io_block/doc/io_block.md b/product/automotive-rd/rd1ae/interface/io_block/doc/io_block.md new file mode 100644 index 0000000000000000000000000000000000000000..0e76beb4e384bf2d2883b968bec0058b6c640506 --- /dev/null +++ b/product/automotive-rd/rd1ae/interface/io_block/doc/io_block.md @@ -0,0 +1,28 @@ +# IO Block Interface + +Copyright (c) 2024, Arm Limited. All rights reserved. + +## Overview +The IO Block interface provides a standard API to be implemented by multiple +modules (IO Block drivers). + +This will allow multiple modules to have the same interface. +but having different internal implementations. +i.e. It abstracts the knowledge of the API user from the implementation, + which makes it more flexible and platform-agnostic. + +## Use + To use the IO Block interface it requires to add the include path in the + respective module `CMakeLists.txt` file. + ``` CMAKE + target_include_directories(${SCP_MODULE_TARGET} PUBLIC + "${CMAKE_SOURCE_DIR}/product/automotive-rd/rd1ae/interface/io_block/") + ``` + Then simply include `interface_io_block.h` file to use all IO Block + interface definitions. + +### Example + ```C + /* `api` holds the concrete implementation of the interface. */ + api->map_region(struct interface_io_block_setup_mmap *mmap); + ``` diff --git a/product/automotive-rd/rd1ae/interface/io_block/interface_io_block.h b/product/automotive-rd/rd1ae/interface/io_block/interface_io_block.h new file mode 100644 index 0000000000000000000000000000000000000000..a0662ea375431113495cdcd7e5fb9580379510ac --- /dev/null +++ b/product/automotive-rd/rd1ae/interface/io_block/interface_io_block.h @@ -0,0 +1,118 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef INTERFACE_IO_BLOCK +#define INTERFACE_IO_BLOCK + +#include +#include + +/*! + * \addtogroup GroupInterfaces Interfaces + * @{ + */ + +/*! + * \defgroup GroupIoBlock IO Block module interface + * + * \brief Interface definition for IO Block drivers. + * + * \details This provides an generic interface for the modules to bind to a + * platform specific IO Block driver module. + * @{ + */ + +/*! + * \brief List the types of carveouts supported by the IO Blocks. + */ +enum interface_io_block_carveout_type { + /*! IO Block carveout type ECAM. */ + INTERFACE_IO_BLOCK_CARVEOUT_TYPE_ECAM, + /*! IO Block carveout type MMIOL. */ + INTERFACE_IO_BLOCK_CARVEOUT_TYPE_MMIOL, + /*! IO Block carveout type MMIOH. */ + INTERFACE_IO_BLOCK_CARVEOUT_TYPE_MMIOH, + /*! Maximum number of carveouts types. */ + INTERFACE_IO_BLOCK_CARVEOUT_TYPE_MAX, +}; + +/*! + * \brief List the types of access allowed on the mapped carveouts. + */ +enum interface_io_block_access_type { + /*! IO Block Access type Non secure. */ + INTERFACE_IO_BLOCK_ACCESS_TYPE_NS, + /*! IO Block Access type Secure. */ + INTERFACE_IO_BLOCK_ACCESS_TYPE_S, + /*! IO Block Access type Realm. */ + INTERFACE_IO_BLOCK_ACCESS_TYPE_RL, + /*! IO Block Access type Root. */ + INTERFACE_IO_BLOCK_ACCESS_TYPE_RT, + /*! Maximum numbers of access types. */ + INTERFACE_IO_BLOCK_ACCESS_TYPE_MAX +}; + +/*! + * \brief Defines base address and size of carveout. + */ +struct interface_io_block_carveout_info { + /*! Start of the carveout. */ + uint64_t base; + /*! Size of the carveout. */ + uint64_t size; + /*! Carveout type: ECAM, MMIOL, MMIOH. */ + enum interface_io_block_carveout_type carveout_type; + /*! Type of access allowed on the carveout. */ + enum interface_io_block_access_type access_type; + /*! + * Target node id. The rootport node to be programmed when bifurcation mode + * is enabled. + */ + uint16_t target_id; + /*! Index of mapped carveout region. */ + uint8_t region_id; +}; + +struct interface_io_block_setup_mmap { + /*! Base register address for the IO Block. */ + uint64_t io_block_address; + /*! Regions to be mapped in the IO Block. */ + struct interface_io_block_carveout_info *carveout_info; + /*! Number of regions. */ + size_t region_count; + /*! Source node ID. Regions are programmed in source node. */ + uint16_t source_id; +}; + +/*! + * \brief IO Block interface to manage mappings in the NCI block. + */ +struct interface_io_block_memmap_api { + /*! + * \brief Program the given memory carveout in the IO Block. + * + * \param mmap Memory map information of the regions to be mapped in the IO + * Block. + * + * \retval ::FWK_SUCCESS on successfully mapping the region. + * \retval ::FWK_E_DATA if mapping region is invalid. + * \return One of the standard framework status codes. + */ + int (*map_region)(struct interface_io_block_setup_mmap *mmap); + /*! + * \brief Remove the careout mapping from the IO block. + * + * \param mmap Memory map information of the regions mapped in the IO Block. + * + * \retval ::FWK_SUCCESS on successfully mapping the region. + * \retval ::FWK_E_DATA if mapping region is invalid. + * \return One of the standard framework status codes. + */ + int (*unmap_region)(struct interface_io_block_setup_mmap *mmap); +}; + +#endif /* INTERFACE_IO_BLOCK */ diff --git a/product/automotive-rd/rd1ae/module/io_block/CMakeLists.txt b/product/automotive-rd/rd1ae/module/io_block/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5da6fd5546a017476fc32415e95a70c29244184a --- /dev/null +++ b/product/automotive-rd/rd1ae/module/io_block/CMakeLists.txt @@ -0,0 +1,17 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +add_library(${SCP_MODULE_TARGET} SCP_MODULE) + +target_include_directories(${SCP_MODULE_TARGET} + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" + PUBLIC "${CMAKE_SOURCE_DIR}/product/automotive-rd/rd1ae/interface/io_block/" + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src") + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_io_block.c") + +target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-noc-s3 module-atu) diff --git a/product/automotive-rd/rd1ae/module/io_block/Module.cmake b/product/automotive-rd/rd1ae/module/io_block/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..18e14f8900cd59009e92f07c68d077c9758c8765 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/io_block/Module.cmake @@ -0,0 +1,10 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "io-block") + +set(SCP_MODULE_TARGET "module-io-block") diff --git a/product/automotive-rd/rd1ae/module/io_block/include/mod_io_block.h b/product/automotive-rd/rd1ae/module/io_block/include/mod_io_block.h new file mode 100644 index 0000000000000000000000000000000000000000..4f964aaeda17e04530fa486d4987445d5589107b --- /dev/null +++ b/product/automotive-rd/rd1ae/module/io_block/include/mod_io_block.h @@ -0,0 +1,97 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * IO Block driver module to define IO block configuration.. + */ + +#ifndef MOD_IO_BLOCK_H +#define MOD_IO_BLOCK_H + +#include + +#include + +#include +#include + +/*! + * \addtogroup GroupModules Modules + * \{ + */ + +/*! + * \ingroup GroupModules Modules + * \defgroup GroupModuleIOBlock IO Block + * + * \brief IO Block module. + * + * \details This module implements IO Block layout for the platform. + * \{ + */ + +/*! + * \brief Module API indices + */ +enum mod_io_block_api_idx { + /*! Interface to configure a region in the target IO block */ + MOD_IO_BLOCK_API_IDX_MAP_REGION, + /*! Total API count */ + MOD_IO_BLOCK_API_IDX_MAX, +}; + +/*! + * \brief Info of each IO block and regions to be programmed in it. + */ +struct mod_io_block_element_config { + /*! Number of mapping for the IO Block */ + uint32_t region_mem_maps_count; + /*! List of the mapping to be done for the IO Block */ + struct interface_io_block_setup_mmap *region_mem_maps; +}; + +/*! + * \brief Used for capturing notification ID and source ID of the platform + * module. + */ +struct mod_io_block_platform_notification { + /*! Identifier of the notification id */ + const fwk_id_t notification_id; + /*! Identifier of the module sending the notification */ + const fwk_id_t source_id; +}; + +/*! + * \brief IO Block module configuration data + */ +struct mod_io_block_config { + /*! NCI module ID */ + fwk_id_t nci_id; + /*! NCI module address mapping API ID */ + fwk_id_t nci_api_id; + /*! ATU module ID */ + fwk_id_t atu_id; + /*! ATU module address mapping API ID */ + fwk_id_t atu_api_id; + /*! Platform notification and source ID */ + struct mod_io_block_platform_notification plat_notification; + /*! + * Logical address used to map 64 bit IO Block register address to a 32 bit + * window + */ + uintptr_t logical_region_base; + /*! size of the region */ + size_t logical_region_size; +}; + +/*! + * \} + */ + +/*! + * \} + */ +#endif /* MOD_IO_BLOCK_H */ diff --git a/product/automotive-rd/rd1ae/module/io_block/src/mod_io_block.c b/product/automotive-rd/rd1ae/module/io_block/src/mod_io_block.c new file mode 100644 index 0000000000000000000000000000000000000000..bdff7aaf531f043ea15703678c0626630f9f4a32 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/io_block/src/mod_io_block.c @@ -0,0 +1,371 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * IO Block module. + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MOD_NAME "[IO_BLOCK] " + +/* Module Context */ +struct io_block_context { + /*! IO block module config. */ + const struct mod_io_block_config *config; + /*! IO block element config. */ + const struct mod_io_block_element_config **element_config; + /*! NCI driver map/unmap APIs. */ + struct mod_noc_s3_memmap_api *nci_memmap_api; + /*! ATU map/unmap APIs. */ + struct mod_atu_api *atu_api; +}; + +static struct io_block_context ctx; + +static int map_region_in_nci( + uint64_t base, + uint32_t target_id, + uint32_t source_id, + uint64_t address, + uint64_t size, + uint8_t *region_idx) +{ + struct mod_noc_s3_psam_region psam_regions = { + .target_id = target_id, + .base_address = address, + .size = size, + }; + struct mod_noc_s3_comp_config comp_config = { + .type = MOD_NOC_S3_NODE_TYPE_ASNI, + .id = source_id, + .psam_regions = &psam_regions, + .psam_region_count = 1, + }; + struct mod_noc_s3_dev dev = { + .periphbase = base, + }; + + return ctx.nci_memmap_api->map_region_in_psam( + &dev, &comp_config, region_idx); +} + +static int unmap_region_in_nci( + uint64_t base, + uint32_t source_id, + uint8_t region_idx) +{ + struct mod_noc_s3_dev dev = { + .periphbase = ctx.config->logical_region_base, + }; + struct mod_noc_s3_comp_config comp_config = { + .type = MOD_NOC_S3_NODE_TYPE_ASNI, + .id = source_id, + }; + + return ctx.nci_memmap_api->unmap_region_in_psam( + &dev, &comp_config, region_idx); +} + +static int map_region(struct interface_io_block_setup_mmap *mmap) +{ + struct atu_region_map atu_map = { + .region_owner_id = FWK_ID_MODULE(FWK_MODULE_IDX_IO_BLOCK), + .attributes = ATU_ENCODE_ATTRIBUTES_ROOT_PAS, + .log_addr_base = ctx.config->logical_region_base, + .region_size = ctx.config->logical_region_size, + }; + uint8_t region_idx; + size_t idx; + int status; + + if (mmap == NULL) { + return FWK_E_PARAM; + } + atu_map.phy_addr_base = mmap->io_block_address; + + status = ctx.atu_api->add_region( + &atu_map, FWK_ID_ELEMENT(FWK_MODULE_IDX_ATU, 0), ®ion_idx); + if (status != FWK_SUCCESS) { + return status; + } + + for (idx = 0; idx < mmap->region_count; idx++) { + status = map_region_in_nci( + atu_map.log_addr_base, + mmap->carveout_info[idx].target_id, + mmap->source_id, + mmap->carveout_info[idx].base, + mmap->carveout_info[idx].size, + &mmap->carveout_info[idx].region_id); + if (status != FWK_SUCCESS) { + return status; + } + } + + status = ctx.atu_api->remove_region( + region_idx, + FWK_ID_ELEMENT(FWK_MODULE_IDX_ATU, 0), + atu_map.region_owner_id); + + return status; +} + +static int unmap_region(struct interface_io_block_setup_mmap *mmap) +{ + struct atu_region_map atu_map = { + .region_owner_id = FWK_ID_MODULE(FWK_MODULE_IDX_IO_BLOCK), + .attributes = ATU_ENCODE_ATTRIBUTES_ROOT_PAS, + .log_addr_base = ctx.config->logical_region_base, + .region_size = ctx.config->logical_region_size, + }; + uint8_t region_idx; + size_t idx; + int status; + + if (mmap == NULL) { + return FWK_E_PARAM; + } + atu_map.phy_addr_base = mmap->io_block_address; + + status = ctx.atu_api->add_region( + &atu_map, FWK_ID_ELEMENT(FWK_MODULE_IDX_ATU, 0), ®ion_idx); + if (status != FWK_SUCCESS) { + return status; + } + + for (idx = 0; idx < mmap->region_count; idx++) { + status = unmap_region_in_nci( + atu_map.log_addr_base, + mmap->source_id, + mmap->carveout_info[idx].region_id); + if (status != FWK_SUCCESS) { + return status; + } + } + + status = ctx.atu_api->remove_region( + region_idx, + FWK_ID_ELEMENT(FWK_MODULE_IDX_ATU, 0), + atu_map.region_owner_id); + + return status; +} + +static struct interface_io_block_memmap_api memmap_api = { + .map_region = map_region, + .unmap_region = unmap_region, +}; + +static int map_static_mappings(unsigned int element_idx) +{ + const struct mod_io_block_element_config *element_config; + struct atu_region_map atu_map; + uint32_t mapping_idx; + + atu_map.region_owner_id = FWK_ID_MODULE(FWK_MODULE_IDX_IO_BLOCK); + atu_map.attributes = ATU_ENCODE_ATTRIBUTES_ROOT_PAS; + atu_map.log_addr_base = ctx.config->logical_region_base; + atu_map.region_size = ctx.config->logical_region_size; + + element_config = ctx.element_config[element_idx]; + + for (mapping_idx = 0; mapping_idx < element_config->region_mem_maps_count; + mapping_idx++) { + struct interface_io_block_setup_mmap *mapping; + uint32_t region_idx; + uint8_t atu_region_idx; + uint8_t nci_region_idx; + int status; + + atu_map.phy_addr_base = + element_config->region_mem_maps[mapping_idx].io_block_address; + + status = ctx.atu_api->add_region( + &atu_map, FWK_ID_ELEMENT(FWK_MODULE_IDX_ATU, 0), &atu_region_idx); + if (status != FWK_SUCCESS) { + return status; + } + + mapping = &element_config->region_mem_maps[mapping_idx]; + for (region_idx = 0; region_idx < mapping->region_count; region_idx++) { + status = map_region_in_nci( + atu_map.log_addr_base, + mapping->carveout_info[region_idx].target_id, + mapping->source_id, + mapping->carveout_info[region_idx].base, + mapping->carveout_info[region_idx].size, + &nci_region_idx); + if (status != FWK_SUCCESS) { + return status; + } + } + + status = ctx.atu_api->remove_region( + atu_region_idx, + FWK_ID_ELEMENT(FWK_MODULE_IDX_ATU, 0), + atu_map.region_owner_id); + if (status != FWK_SUCCESS) { + return status; + } + } + + return FWK_SUCCESS; +} + +/* + * Framework Handlers. + */ +static int mod_io_block_init( + fwk_id_t module_id, + unsigned int element_count, + const void *config) +{ + ctx.config = config; + if (element_count == 0) { + return FWK_SUCCESS; + } + + ctx.element_config = fwk_mm_calloc( + element_count, sizeof(struct mod_io_block_element_config)); + + return FWK_SUCCESS; +} + +static int mod_io_block_element_init( + fwk_id_t element_id, + unsigned int unused, + const void *data) +{ + const struct mod_io_block_element_config *element_config; + + element_config = (struct mod_io_block_element_config *)data; + if ((element_config->region_mem_maps_count == 0) || + (element_config->region_mem_maps == NULL)) { + fwk_unexpected(); + return FWK_E_DATA; + } + + ctx.element_config[fwk_id_get_element_idx(element_id)] = element_config; + + return FWK_SUCCESS; +} + +static int mod_io_block_bind(fwk_id_t id, unsigned int round) +{ + int status; + + status = fwk_module_bind( + ctx.config->atu_id, ctx.config->atu_api_id, &ctx.atu_api); + if (status != FWK_SUCCESS) { + return status; + } + + return fwk_module_bind( + ctx.config->nci_id, ctx.config->nci_api_id, &ctx.nci_memmap_api); +} + +static int mod_io_block_start(fwk_id_t id) +{ + /* Nothing to be done for module start call */ + if (fwk_id_get_type(id) == FWK_ID_TYPE_MODULE) { + return FWK_SUCCESS; + } + + if (fwk_id_type_is_valid(ctx.config->plat_notification.source_id)) { + /* + * Bind to the platform notification that is needed to start module + * configuration. + */ + return fwk_notification_subscribe( + ctx.config->plat_notification.notification_id, + ctx.config->plat_notification.source_id, + id); + } + + return map_static_mappings(fwk_id_get_element_idx(id)); +} + +static int mod_io_block_process_bind_request( + fwk_id_t requester_id, + fwk_id_t id, + fwk_id_t api_id, + const void **api) +{ + int status; + enum mod_io_block_api_idx api_idx; + + status = FWK_SUCCESS; + api_idx = (enum mod_io_block_api_idx)fwk_id_get_api_idx(api_id); + + switch (api_idx) { + case MOD_IO_BLOCK_API_IDX_MAP_REGION: + *api = &memmap_api; + break; + default: + status = FWK_E_PARAM; + break; + }; + + return status; +} + +static int mod_io_block_process_notification( + const struct fwk_event *event, + struct fwk_event *resp_event) +{ + unsigned int element_idx; + int status; + + if (fwk_id_is_type(event->target_id, FWK_ID_TYPE_MODULE)) { + return FWK_E_PARAM; + } + + if (fwk_id_is_equal( + event->id, ctx.config->plat_notification.notification_id)) { + status = fwk_notification_unsubscribe( + event->id, event->source_id, event->target_id); + if (status != FWK_SUCCESS) { + return status; + } + + element_idx = fwk_id_get_element_idx(event->target_id); + status = map_static_mappings(element_idx); + if (status != FWK_SUCCESS) { + return status; + } + } + + return FWK_SUCCESS; +} + +const struct fwk_module module_io_block = { + .type = FWK_MODULE_TYPE_HAL, + .init = mod_io_block_init, + .api_count = MOD_IO_BLOCK_API_IDX_MAX, + .element_init = mod_io_block_element_init, + .bind = mod_io_block_bind, + .start = mod_io_block_start, + .process_bind_request = mod_io_block_process_bind_request, + .process_notification = mod_io_block_process_notification, +}; diff --git a/product/automotive-rd/rd1ae/module/pcie_discovery/CMakeLists.txt b/product/automotive-rd/rd1ae/module/pcie_discovery/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b7ad3a93050d1df2dfd113296f6882ccc6ac0921 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/pcie_discovery/CMakeLists.txt @@ -0,0 +1,16 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +add_library(${SCP_MODULE_TARGET} SCP_MODULE) + +target_include_directories( + ${SCP_MODULE_TARGET} + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") + +target_sources( + ${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_pcie_discovery.c") diff --git a/product/automotive-rd/rd1ae/module/pcie_discovery/Module.cmake b/product/automotive-rd/rd1ae/module/pcie_discovery/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..e37e66bb20bfc92bb7b5b936694b9d33b587d2d7 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/pcie_discovery/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "pcie_discovery") +set(SCP_MODULE_TARGET "module-pcie_discovery") diff --git a/product/automotive-rd/rd1ae/module/pcie_discovery/include/mod_pcie_discovery.h b/product/automotive-rd/rd1ae/module/pcie_discovery/include/mod_pcie_discovery.h new file mode 100644 index 0000000000000000000000000000000000000000..faf3987b0b5a1168da20764171ab00edae09659f --- /dev/null +++ b/product/automotive-rd/rd1ae/module/pcie_discovery/include/mod_pcie_discovery.h @@ -0,0 +1,112 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_PCIE_DISCOVERY_H +#define MOD_PCIE_DISCOVERY_H + +#include + +#include +#include + +/*! + * \brief Module API indices + */ +enum mod_pcie_discovery_api_idx { + /*! + * Interface to calculate ECAM, MMIOL and MMIOH resource size by doing PCIe + * Bus Walk. + */ + MOD_PCIE_DISCOVERY_API_IDX_CALCULATE_RESOURCES, + /*! Total API Count */ + MOD_PCIE_DISCOVERY_API_IDX_MAP +}; + +/*! + * \brief APIs to perform memory read and write operations. + */ +struct pcie_discovery_rw_api { + /*! + * \brief Read a byte from the given memory address + * + * \param addr Memory address + * + * \return byte value read from the memory address + */ + uint8_t (*read8)(uint64_t addr); + + /*! + * \brief Write a byte to the given memory address + * + * \param addr Memory address. + * \param value Byte value to be written. + */ + void (*write8)(uint64_t addr, uint8_t value); + + /*! + * \brief Read a word from the given memory address + * + * \param addr Memory address + * + * \return word value read from the memory address + */ + uint32_t (*read32)(uint64_t addr); + + /*! + * \brief Write a word to the given memory address + * + * \param addr Memory address. + * \param value Word value to be written. + */ + void (*write32)(uint64_t addr, uint32_t value); +}; + +/*! + * Datastructure to capture the size of memory required by all of the devices + * present under the given host bridge. + */ +struct pcie_mmap_size { + /*! ECAM region size */ + uint64_t ecam; + + /*! 32-bit MMIO space start size */ + uint64_t mmiol; + + /*! 64-bit MMIO space size */ + uint64_t mmioh; + + /*! Range of bus numbers consumed by the Root port */ + uint8_t bus; +}; + +struct mod_pcie_discovery_api { + /*! + * \brief Captures the size of memory required by the devices present in the + * tree. + * This does a depth first search, identify the device and then + * capture the memory required by the device in ECAM, MMIOL and MMIOH + * regions. + * + * \param ecam_base_address Base address of RP's ECAM region + * \param mmap_size Placeholder for filling IO memory carveout sizes + * required by all the endpoints under the given RP. + * \param primary_bus_number Starting bus number. + * \param rw_api Customised APIs use to do MMIO transactions in AP memory + * region. NOTE: The default read/write + * APIs are used this is NULL. + * + * \return FWK_E_PARAM If the ecam address and mmap_size are not valid. + * \return FWK_SUCCESS On successful completion. + */ + int (*calculate_resource)( + uint64_t ecam_base_address, + struct pcie_mmap_size *mmap_size, + uint8_t primary_bus_number, + struct pcie_discovery_rw_api *rw_api); +}; + +#endif /* MOD_PCIE_DISCOVERY_H */ diff --git a/product/automotive-rd/rd1ae/module/pcie_discovery/src/mod_pcie_discovery.c b/product/automotive-rd/rd1ae/module/pcie_discovery/src/mod_pcie_discovery.c new file mode 100644 index 0000000000000000000000000000000000000000..ae12c9c39539873d77b5ec29629250ff89381795 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/pcie_discovery/src/mod_pcie_discovery.c @@ -0,0 +1,341 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +/* PCIe configuration space offset definitions */ +#define PCIE_BAR_OFFSET 0x10 + +#define PCIE_BAR_SIZE 0x4 + +/* + * ECAM space per bus + * 32 devices * 8 functions * 4kB config space = 1MB + */ +#define MAX_ECAM_SPACE_PER_BUS (FWK_MIB) + +/* + * MAX ECAM space + * MAX ECAM space per bus * Max numbers of bus(256) + */ +#define MAX_ECAM_SPACE (256 * MAX_ECAM_SPACE_PER_BUS) + +/* PCIe configuration space offset definitions */ +#define PCIE_HEADER_TYPE_OFFSET 0xE +#define PCIE_PRIMARY_BUS_NUM_OFFSET 0x18 +#define PCIE_SECONDARY_BUS_NUM_OFFSET 0x19 +#define PCIE_SUBORDINATE_BUS_NUM_OFFSET 0x1A + +#define PCIE_HEADER_TYPE_MASK 0x7F +#define PCIE_HEADER_TYPE_ENDPOINT 0 +#define PCIE_HEADER_TYPE_BRIDGE 1 + +/* BDF table offsets for PCIe & CCIX controllers */ +#define PCIE_BDF_TABLE_OFFSET 0 + +/* PCIe standard definitions */ +#define PCIE_BUS_NUM_MAX 0xFF +#define DEVICES_PER_BUS_MAX 32 +#define FUNCTIONS_PER_DEVICE_MAX 8 +#define BRIDGE_BAR_COUNT 2 +#define DEVICE_BAR_COUNT 6 + +#define BDF_ADDR_SHIFT_BUS 20 +#define BDF_ADDR_SHIFT_DEVICE 15 +#define BDF_ADDR_SHIFT_FUNCTION 12 + +#define PCIE_MEM_TYPE_MASK 0x06 +#define PCIE_MEM_TYPE_32 0x00 /* 32 bit address */ +#define PCIE_MEM_TYPE_64 0x04 /* 64 bit address */ +#define PCIE_MEM_MASK ~(0xFULL) + +#define PCIE_GET_MMIO_SIZE64(BAR) (~(BAR & PCIE_MEM_MASK) + 1) +#define PCIE_GET_MMIO_SIZE32(BAR) (~((uint32_t)(BAR & PCIE_MEM_MASK)) + 1) + +#define PCIE_BRIDGE_MEM_WINDOW_ALIGNMENT (1UL << 20) + +/* Default API to do 1 byte read */ +uint8_t read8(uint64_t addr) +{ + return *((volatile uint8_t *)(uint32_t)addr); +} + +/* Default API to do 1 byte write */ +void write8(uint64_t addr, uint8_t value) +{ + *((volatile uint8_t *)(uint32_t)addr) = value; +} + +/* Default API to do 4 byte read */ +uint32_t read32(uint64_t addr) +{ + return *((volatile uint32_t *)(uint32_t)addr); +} + +/* Default API to do 4 byte write */ +void write32(uint64_t addr, uint32_t value) +{ + *((volatile uint32_t *)(uint32_t)addr) = value; +} + +struct pcie_discovery_rw_api default_rw_api = { + .read8 = read8, + .write8 = write8, + .read32 = read32, + .write32 = write32, +}; + +/* The bridge expects the mmio window address to be 1M align */ +static void align_address_for_bridge_window(struct pcie_mmap_size *mmap_size) +{ + mmap_size->mmiol = + FWK_ALIGN_NEXT(mmap_size->mmiol, PCIE_BRIDGE_MEM_WINDOW_ALIGNMENT); + mmap_size->mmioh = + FWK_ALIGN_NEXT(mmap_size->mmioh, PCIE_BRIDGE_MEM_WINDOW_ALIGNMENT); +} + +/* Program sequence to get the configuration size of a PCIe device */ +static void get_mmio_memory_size( + uint64_t ecam_addr, + struct pcie_mmap_size *mmap_size, + struct pcie_discovery_rw_api *rw_api, + uint8_t num_bar) +{ + uint8_t idx; + uint64_t pcie_bar_addr; + uint64_t mmio_size; + + /* + * Write 0xFFFFFFFF to all the BARs sequentially to get the configuration + * size. + */ + pcie_bar_addr = ecam_addr + PCIE_BAR_OFFSET; + for (idx = 0; idx < num_bar; idx++) { + rw_api->write32(pcie_bar_addr, 0xFFFFFFFF); + pcie_bar_addr += PCIE_BAR_SIZE; + } + + /* + * This section treats IO and Memory address space as Memory address space. + */ + pcie_bar_addr = ecam_addr + PCIE_BAR_OFFSET; + for (idx = 0; idx < num_bar; idx++) { + mmio_size = rw_api->read32(pcie_bar_addr); + if ((mmio_size != 0) && (mmio_size != 0xFFFFFFFF)) { + if ((mmio_size & PCIE_MEM_TYPE_MASK) == PCIE_MEM_TYPE_64) { + /* + * Device supports 64 bit addressing. Increase the counter and + * address and read the next 32 bits of 64 bit mmap size. + */ + idx++; + pcie_bar_addr += PCIE_BAR_SIZE; + mmio_size |= ((uint64_t)(rw_api->read32(pcie_bar_addr))) << 32; + mmio_size = PCIE_GET_MMIO_SIZE64(mmio_size); + mmap_size->mmioh = FWK_ALIGN_NEXT(mmap_size->mmioh, mmio_size); + mmap_size->mmioh += mmio_size; + } else { + /* Device supports 32 bit addressing. */ + mmio_size = PCIE_GET_MMIO_SIZE32(mmio_size); + mmap_size->mmiol = FWK_ALIGN_NEXT(mmap_size->mmiol, mmio_size); + mmap_size->mmiol += mmio_size; + } + } + pcie_bar_addr += PCIE_BAR_SIZE; + } +} + +/* + * Procedure to do PCIe bus walk. This will also calculate the total mmio region + * size required for each root port. + */ +static uint8_t pcie_bus_scan( + uint64_t ecam_addr, + uint8_t pri_bnum, + uint8_t sec_bnum, + struct pcie_mmap_size *mmap_size, + struct pcie_discovery_rw_api *rw_api) +{ + int dev_num; + int fn_num; + uint8_t bar_count; + uint8_t header_type; + uint8_t sub_bnum; + uint32_t df_addr; + uint32_t vid; + uint64_t config_addr; + + sub_bnum = pri_bnum; + /* Loop over all devices on pri_bnum bus */ + for (dev_num = 0; dev_num < DEVICES_PER_BUS_MAX; dev_num++) { + /* Loop over all functions on dev_num device */ + for (fn_num = 0; fn_num < FUNCTIONS_PER_DEVICE_MAX; fn_num++) { + df_addr = (dev_num << BDF_ADDR_SHIFT_DEVICE) | + (fn_num << BDF_ADDR_SHIFT_FUNCTION); + config_addr = ecam_addr + df_addr; + + vid = rw_api->read32(config_addr); + /* If function 0 of any device has invalid VID break the loop */ + if ((vid & 0xFFFF) == 0xFFFF) { + if (fn_num == 0) { + break; + } else { + continue; + } + } + + FWK_LOG_LOCAL( + "[PCIE]: Found device: %d:%d:%d\n", pri_bnum, dev_num, fn_num); + + /* + * Read the header type to identify if the device + * is an endpoint or a PCI-PCI bridge. + */ + header_type = rw_api->read8(config_addr + PCIE_HEADER_TYPE_OFFSET); + if ((header_type & PCIE_HEADER_TYPE_MASK) == + PCIE_HEADER_TYPE_BRIDGE) { + /* + * PCI-PCI bridge is identified. Set primary and secondary bus + * numbers. Let subordinate bus number be max possible bus + * number as we need to further identify devices downstream. + */ + rw_api->write8( + config_addr + PCIE_PRIMARY_BUS_NUM_OFFSET, pri_bnum); + rw_api->write8( + config_addr + PCIE_SECONDARY_BUS_NUM_OFFSET, sec_bnum); + rw_api->write8( + config_addr + PCIE_SUBORDINATE_BUS_NUM_OFFSET, + PCIE_BUS_NUM_MAX); + /* + * Recursively call the scan function with incremented + * primary and secondary bus numbers. + */ + sub_bnum = pcie_bus_scan( + ecam_addr + ((sec_bnum - pri_bnum) << BDF_ADDR_SHIFT_BUS), + sec_bnum, + sec_bnum + 1, + mmap_size, + rw_api); + /* + * The recursive call has returned from an endpoint + * identification so use the returned bus number as the + * bridge's subordinate bus number. + */ + rw_api->write8( + config_addr + PCIE_SUBORDINATE_BUS_NUM_OFFSET, sub_bnum); + sec_bnum = sub_bnum + 1; + bar_count = BRIDGE_BAR_COUNT; + /* Memory carveout under bridge should be 1 MB aligned. */ + align_address_for_bridge_window(mmap_size); + } else { + /* + * Endpoint is identified. Proceed to other functions & + * devices in this bus and return to previous recursive call. + */ + sub_bnum = sec_bnum - 1; + bar_count = DEVICE_BAR_COUNT; + } + get_mmio_memory_size(config_addr, mmap_size, rw_api, bar_count); + } + } + /* Return the subordinate bus number to previous recursive call */ + return sub_bnum; +} + +static int calculate_resource( + uint64_t ecam_base_address, + struct pcie_mmap_size *mmap_size, + uint8_t primary_bus_number, + struct pcie_discovery_rw_api *rw_api) +{ + uint8_t pri_bnum; + uint8_t sec_bnum; + uint8_t sub_bnum; + + if ((ecam_base_address == 0) || (mmap_size == NULL) || + (primary_bus_number == UINT8_MAX)) { + return FWK_E_PARAM; + } + + if (rw_api == NULL) { + if (ecam_base_address > UINT32_MAX) { + return FWK_E_PARAM; + } + + rw_api = &default_rw_api; + } + + pri_bnum = primary_bus_number; + sec_bnum = primary_bus_number + 1; + + sub_bnum = + pcie_bus_scan(ecam_base_address, pri_bnum, sec_bnum, mmap_size, rw_api); + + mmap_size->bus = (sub_bnum - pri_bnum) + 1; + mmap_size->ecam = mmap_size->bus * MAX_ECAM_SPACE_PER_BUS; + + /* + * Linux/EDK2 expects the mmiol size to be minumum size of + * (Number of bus * 1M) + */ + mmap_size->mmiol = FWK_ALIGN_NEXT( + mmap_size->mmiol, mmap_size->bus * MAX_ECAM_SPACE_PER_BUS); + + /* Align for host bridge */ + align_address_for_bridge_window(mmap_size); + + return FWK_SUCCESS; +} + +static int pcie_discovery_init( + fwk_id_t module_id, + unsigned int unused, + const void *unused2) +{ + return FWK_SUCCESS; +} + +static struct mod_pcie_discovery_api pcie_discovery_api = { + .calculate_resource = calculate_resource, +}; + +static int pcie_discovery_process_bind_request( + fwk_id_t requester_id, + fwk_id_t id, + fwk_id_t api_id, + const void **api) +{ + enum mod_pcie_discovery_api_idx api_idx; + + api_idx = (enum mod_pcie_discovery_api_idx)fwk_id_get_api_idx(api_id); + if (api_idx != MOD_PCIE_DISCOVERY_API_IDX_CALCULATE_RESOURCES) { + return FWK_E_PARAM; + } + + *api = &pcie_discovery_api; + return FWK_SUCCESS; +} + +const struct fwk_module module_pcie_discovery = { + .type = FWK_MODULE_TYPE_SERVICE, + .api_count = MOD_PCIE_DISCOVERY_API_IDX_MAP, + .init = pcie_discovery_init, + .process_bind_request = pcie_discovery_process_bind_request, +}; + +const struct fwk_module_config config_pcie_discovery = { 0 }; diff --git a/product/automotive-rd/rd1ae/module/pcie_setup/CMakeLists.txt b/product/automotive-rd/rd1ae/module/pcie_setup/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..1e25faaed52e295094c6f65dabe9c13a65695d84 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/pcie_setup/CMakeLists.txt @@ -0,0 +1,19 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +add_library(${SCP_MODULE_TARGET} SCP_MODULE) + +target_include_directories(${SCP_MODULE_TARGET} + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" + PUBLIC "${CMAKE_SOURCE_DIR}/interface/address_remapper/" + PUBLIC "${CMAKE_SOURCE_DIR}/interface/cmn" + PUBLIC "${CMAKE_SOURCE_DIR}/product/automotive-rd/rd1ae/interface/io_block/") + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_pcie_setup.c") + +target_link_libraries(${SCP_MODULE_TARGET} + PRIVATE module-system-info module-pcie_discovery module-sds) diff --git a/product/automotive-rd/rd1ae/module/pcie_setup/Module.cmake b/product/automotive-rd/rd1ae/module/pcie_setup/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..c28f8e2b9e7ae09e4a0a5d250d7f1ced1c300125 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/pcie_setup/Module.cmake @@ -0,0 +1,10 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "pcie-setup") + +set(SCP_MODULE_TARGET "module-pcie-setup") diff --git a/product/automotive-rd/rd1ae/module/pcie_setup/include/mod_pcie_setup.h b/product/automotive-rd/rd1ae/module/pcie_setup/include/mod_pcie_setup.h new file mode 100644 index 0000000000000000000000000000000000000000..2cc72e369cd9b2d89786f1dd276c7d538fba86cb --- /dev/null +++ b/product/automotive-rd/rd1ae/module/pcie_setup/include/mod_pcie_setup.h @@ -0,0 +1,181 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Module for configuring PCIe rootports and its memory map. + */ + +#ifndef MOD_PCIE_SETUP_H +#define MOD_PCIE_SETUP_H + +#include +#include + +#include +#include +#include + +/*! + * \brief PCIe setup notification indices. + */ +enum mod_pcie_setup_notification_idx { + /*! PCIe initialisation completed. */ + MOD_PCIE_SETUP_NOTIFICATION_IDX_INITIALISED, + /*! Number of defined notification. */ + MOD_PCIE_SETUP_NOTIFICATION_IDX_COUNT +}; + +/*! + * \brief Defines base address and size of carveout. + */ + +struct mod_pcie_setup_carveout { + /*! Start of the carveout */ + uint64_t start; + /*! Size of the carveout */ + uint64_t size; +}; + +/*! + * \brief Defines regions for ECAM, MMIOL, MMIOH and Bus. + */ +struct mod_pcie_setup_mmap { + struct mod_pcie_setup_carveout ecam; + struct mod_pcie_setup_carveout mmiol; + struct mod_pcie_setup_carveout mmioh; + struct mod_pcie_setup_carveout bus; + uint64_t interrupt_id; +}; + +/*! + * \brief Placeholder to put ECAM, MMIOL, MMIOH and Bus number info for each RP. + */ +struct mod_pcie_setup_block_mmap { + uint64_t id; + uint64_t segment; + uint64_t translation; + uint64_t smmu_base; + uint64_t ep_count; + struct mod_pcie_setup_mmap ep[]; +}; + +/*! + * \brief Placeholder to put information of all the block present on the + * platform. + */ +struct mod_pcie_setup_block_mmap_list { + uint64_t block_count; + uint64_t table_size; + struct mod_pcie_setup_block_mmap blocks[]; +}; + +/*! + * \brief configuration for a single end point and memory map for non io macro. + */ +struct mod_pcie_setup_ep_config { + /*! Valid flag to indicate if the mapping is valid to program */ + bool valid; + /*! Allow non-secure access + * + * By default only secure accesses are allowed. Set this to true to allow + * non-secure access as well. + */ + bool allow_ns_access; + /*! ID of the Root port node. */ + uint8_t rp_node_id; +}; + +/*! + * \brief Configuration information used for programming IO virtualisation + * block. + */ +struct mod_pcie_setup_config { + /*! NCI GVP base */ + uint64_t reg_base; + /*! ID of the node in the CMN mesh configuration */ + unsigned int cmn_node_id; + /*!* ID of the source node in NCI */ + uint8_t nci_source_node_id; + /*!* ID of the Io Virtualization block. */ + uint8_t block_id; + /*! Identifier of the SDS structure to place PCIE mmap info. */ + uint32_t sds_struct_id; + /*! SMMU base address for the block. */ + uint64_t smmu_base; + /*! End point config for RPs */ + struct mod_pcie_setup_ep_config *ep_config; +}; + +/*! + * \brief Platform notification source and notification id + * + * \details On platforms that require platform configuration to access the SDS + * memory regions, the platform notification can be subscribed. This is + * optional for a platform and if provided as module configuration + * data, the configuration will be done only after this notification is + * processed. + */ +struct mod_pcie_setup_platform_notification { + /*! Identifier of the notification id */ + const fwk_id_t notification_id; + + /*! Identifier of the module sending the notification */ + const fwk_id_t source_id; +}; + +/*! + * \brief Module configuration data used for per chip resource allocation. + */ +struct mod_pcie_setup_resource_info { + /*! ID of concrete implementation of CMN interface. */ + fwk_id_t cmn_id; + /*! ID of concrete implementation of IO Block interface. */ + fwk_id_t io_block_id; + /*! ID of concrete implementation of ATU MMIO. */ + fwk_id_t atu_mmio_id; + /*! ID of CMN map_io_region api. */ + fwk_id_t cmn_api_id; + /*! ID of IO Block io_block_setup api. */ + fwk_id_t io_block_api_id; + /*! ID of IO Block ATU MMIO rw api. */ + fwk_id_t atu_mmio_api_id; + /*! Offset added to the address. */ + uint64_t translation; + /*! Bank for allocating carveouts for ECAM, MMIOL and MMIOH. */ + struct mod_pcie_setup_mmap mmap; + /*! Number of endpoints in each IO Block. */ + uint8_t ep_count; + /*! Platform notification source and notification id */ + struct mod_pcie_setup_platform_notification plat_notification; + /*! Structure ID for PCIe configuration info in SDS table. */ + uint32_t sds_struct_id; + /*! List of the interrupt IDs for the end points. */ + uint64_t *ep_interrupt_ids; +}; + +/*! + * \brief Module configuration. + */ +struct mod_pcie_setup_module_config { + /*! Number of resource information configuration. One per chip. */ + size_t resource_info_count; + /*! + * Resource configuration common for all the IO virtualsation blocks in a + * chip. + */ + struct mod_pcie_setup_resource_info *resource_info; +}; + +/*! + * \brief Identifiers for the ::MOD_PCIE_SETUP_NOTIFICATION_IDX_INITIALISED + * notification. + */ +static const fwk_id_t mod_pcie_setup_notification_initialised = + FWK_ID_NOTIFICATION_INIT( + FWK_MODULE_IDX_PCIE_SETUP, + MOD_PCIE_SETUP_NOTIFICATION_IDX_INITIALISED); + +#endif /* MOD_PCIE_SETUP_H */ diff --git a/product/automotive-rd/rd1ae/module/pcie_setup/src/mod_pcie_setup.c b/product/automotive-rd/rd1ae/module/pcie_setup/src/mod_pcie_setup.c new file mode 100644 index 0000000000000000000000000000000000000000..d2d0e6b0eeed09dbd62b8dab66faa73fa8b25499 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/pcie_setup/src/mod_pcie_setup.c @@ -0,0 +1,734 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * RD-1 AE PCIe Setup. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#define MOD_NAME "[PCIE_SETUP] " + +struct mod_pcie_setup_context { + /* Pointer to the element configuration pointers (table) */ + struct mod_pcie_setup_config **config; + + /* APIs required to do PCIe bus walk and resource discovery */ + struct mod_pcie_discovery_api *pcie_discovery_api; + + /* Pointer to the module config. */ + const void *module_config; + + /* Pointer to the chip specific module info. */ + struct mod_pcie_setup_resource_info resource_info; + + /* Pointer to system info APIs */ + struct mod_system_info_get_info_api *system_info_api; + + /* Pointer to system info configuration. */ + const struct mod_system_info *system_info; + + /* API to program PCIe memory region in GVP NCI. */ + struct interface_io_block_memmap_api *io_block_memmap_api; + + /* APIs to configure CMN moudle. */ + struct interface_cmn_memmap_rnsam_api *cmn_memmap_rnsam_api; + + /* AP remap Address read write APIs */ + struct interface_address_remapper_rw_api *remapper_rw_api; + + /* APIs to program PCIe memory map configuration info in SDS. */ + struct mod_sds_api *sds_api; + + /* + * Size of block config. This depends on the number of rootport in + * the block. + */ + size_t block_config_size; + + /* Number of IO Blocks . */ + size_t block_count; +}; + +static struct mod_pcie_setup_context pcie_setup_context; + +static int pcie_setup_send_initialised_notification(void) +{ + struct fwk_event notification_event = { 0 }; + unsigned int notification_count; + + notification_event.id = mod_pcie_setup_notification_initialised; + notification_event.source_id = fwk_module_id_pcie_setup; + + FWK_LOG_INFO(MOD_NAME + "Sending PCIe initialisation completion notification."); + return fwk_notification_notify(¬ification_event, ¬ification_count); +} + +static int pcie_setup_update_sds( + struct mod_pcie_setup_block_mmap *block_info, + struct mod_pcie_setup_config *config) +{ + static uint32_t offset = sizeof(struct mod_pcie_setup_block_mmap_list); + static uint64_t count = 0; + static uint64_t table_size = sizeof(struct mod_pcie_setup_block_mmap_list); + size_t block_size; + int status; + + count++; + status = pcie_setup_context.sds_api->struct_write( + config->sds_struct_id, + offsetof(struct mod_pcie_setup_block_mmap_list, block_count), + &count, + sizeof(((struct mod_pcie_setup_block_mmap_list *)0)->block_count)); + if (status != FWK_SUCCESS) { + FWK_LOG_ERR("Block count: SDS Update failed, error:%d", status); + return status; + } + + block_size = sizeof(struct mod_pcie_setup_block_mmap) + + (block_info->ep_count * sizeof(struct mod_pcie_setup_mmap)); + + table_size += block_size; + status = pcie_setup_context.sds_api->struct_write( + config->sds_struct_id, + offsetof(struct mod_pcie_setup_block_mmap_list, table_size), + &table_size, + sizeof(((struct mod_pcie_setup_block_mmap_list *)0)->table_size)); + if (status != FWK_SUCCESS) { + FWK_LOG_ERR("Table Size: SDS Update failed, error:%d", status); + return status; + } + + status = pcie_setup_context.sds_api->struct_write( + config->sds_struct_id, offset, block_info, block_size); + offset += block_size; + if (status != FWK_SUCCESS) { + FWK_LOG_ERR("PCIe Table: SDS Update failed, error:%d", status); + } + + return status; +} + +static void allocate_ecam_address( + struct mod_pcie_setup_mmap *mmap, + struct pcie_mmap_size *mmap_size) +{ + struct mod_pcie_setup_resource_info *res_info; + + res_info = &pcie_setup_context.resource_info; + + if (mmap_size->ecam != 0) { + if (mmap_size->ecam > res_info->mmap.ecam.size) { + FWK_LOG_ERR(MOD_NAME "No memory left to allocate for ECAM"); + fwk_unexpected(); + } + mmap->ecam.start = res_info->mmap.ecam.start; + mmap->ecam.size = mmap_size->ecam; + res_info->mmap.ecam.start += mmap_size->ecam; + res_info->mmap.ecam.size -= mmap_size->ecam; + } else { + /* + * Reset the values to zero to prevent caller from using garbage values. + */ + mmap->ecam.start = 0; + mmap->ecam.size = 0; + } +} + +static void allocate_mmiol_address( + struct mod_pcie_setup_mmap *mmap, + struct pcie_mmap_size *mmap_size) +{ + struct mod_pcie_setup_resource_info *res_info; + + res_info = &pcie_setup_context.resource_info; + + if (mmap_size->mmiol != 0) { + if (mmap_size->mmiol > res_info->mmap.mmiol.size) { + FWK_LOG_ERR(MOD_NAME "No memory left to allocate for MMIOL"); + fwk_unexpected(); + } + mmap->mmiol.start = res_info->mmap.mmiol.start; + mmap->mmiol.size = mmap_size->mmiol; + res_info->mmap.mmiol.start += mmap_size->mmiol; + res_info->mmap.mmiol.size -= mmap_size->mmiol; + } else { + /* + * Reset the values to zero to prevent caller from using garbage values. + */ + mmap->mmiol.start = 0; + mmap->mmiol.size = 0; + } +} + +static void allocate_mmioh_address( + struct mod_pcie_setup_mmap *mmap, + struct pcie_mmap_size *mmap_size) +{ + struct mod_pcie_setup_resource_info *res_info; + + res_info = &pcie_setup_context.resource_info; + + if (mmap_size->mmioh != 0) { + if (mmap_size->mmioh > res_info->mmap.mmioh.size) { + FWK_LOG_ERR(MOD_NAME "No memory left to allocate for MMIOH"); + fwk_unexpected(); + } + mmap->mmioh.start = res_info->mmap.mmioh.start; + mmap->mmioh.size = mmap_size->mmioh; + res_info->mmap.mmioh.start += mmap_size->mmioh; + res_info->mmap.mmioh.size -= mmap_size->mmioh; + } else { + /* + * Reset the values to zero to prevent caller from using garbage values. + */ + mmap->mmioh.start = 0; + mmap->mmioh.size = 0; + } +} + +static void allocate_bus( + struct mod_pcie_setup_mmap *mmap, + struct pcie_mmap_size *mmap_size) +{ + struct mod_pcie_setup_resource_info *res_info; + + res_info = &pcie_setup_context.resource_info; + + if (mmap_size->bus != 0) { + if (mmap_size->bus > res_info->mmap.bus.size) { + FWK_LOG_ERR(MOD_NAME "No bus left to allocate"); + fwk_unexpected(); + } + mmap->bus.start = res_info->mmap.bus.start; + mmap->bus.size = mmap_size->bus; + res_info->mmap.bus.start += mmap_size->bus; + res_info->mmap.bus.size -= mmap_size->bus; + } else { + /* + * Reset the values to zero to prevent caller from using garbage values. + */ + mmap->bus.start = 0; + mmap->bus.size = 0; + } +} + +/* + * This takes in the size required for each of the region and then allocates + * regions for them from platform provided configuration. + */ +static inline void get_address_range( + struct mod_pcie_setup_mmap *mmap, + struct pcie_mmap_size *mmap_size) +{ + allocate_ecam_address(mmap, mmap_size); + allocate_mmiol_address(mmap, mmap_size); + allocate_mmioh_address(mmap, mmap_size); + allocate_bus(mmap, mmap_size); +} + +static int map_region_in_io_block( + enum interface_io_block_carveout_type carveout_type, + struct mod_pcie_setup_config *config, + uint64_t address, + uint64_t size, + uint8_t index, + uint8_t *region) +{ + struct interface_io_block_carveout_info carveout_info = { + .base = address, + .size = size, + .carveout_type = carveout_type, + .target_id = config->ep_config[index].rp_node_id + }; + struct interface_io_block_setup_mmap mmap_info = { + .io_block_address = config->reg_base, + .carveout_info = &carveout_info, + .region_count = 1, + .source_id = config->nci_source_node_id, + }; + int status; + + status = pcie_setup_context.io_block_memmap_api->map_region(&mmap_info); + if (status == FWK_SUCCESS) { + *region = carveout_info.region_id; + } + + return status; +} + +static int unmap_region_in_io_block( + struct mod_pcie_setup_config *config, + uint8_t region) +{ + struct interface_io_block_carveout_info carveout_info = { + .region_id = region, + }; + struct interface_io_block_setup_mmap mmap_info = { + .io_block_address = config->reg_base, + .carveout_info = &carveout_info, + .region_count = 1, + .source_id = config->nci_source_node_id, + }; + int status; + + status = pcie_setup_context.io_block_memmap_api->unmap_region(&mmap_info); + + return status; +} + +static int discover_and_configure_pcie_device( + struct mod_pcie_setup_config *config, + uint8_t index, + struct mod_pcie_setup_mmap *mmap) +{ + struct interface_address_remapper_rw_api *remapper_rw_api; + struct mod_pcie_discovery_api *pcie_discovery_api; + struct mod_pcie_setup_resource_info *res_info; + struct pcie_discovery_rw_api pcie_rw_api; + struct pcie_mmap_size mmap_size = { 0 }; + uint64_t ecam_adjusted_address; + uint8_t region; + int status; + + res_info = &pcie_setup_context.resource_info; + + status = map_region_in_io_block( + INTERFACE_IO_BLOCK_CARVEOUT_TYPE_ECAM, + config, + res_info->mmap.ecam.start, + res_info->mmap.ecam.size, + index, + ®ion); + if (status != FWK_SUCCESS) { + FWK_LOG_ERR(MOD_NAME "NCI mapping failed"); + return status; + } + + remapper_rw_api = pcie_setup_context.remapper_rw_api; + pcie_rw_api.read8 = remapper_rw_api->read8; + pcie_rw_api.write8 = remapper_rw_api->write8; + pcie_rw_api.read32 = remapper_rw_api->read32; + pcie_rw_api.write32 = remapper_rw_api->write32; + + ecam_adjusted_address = res_info->mmap.ecam.start; + + if (res_info->mmap.ecam.start < res_info->translation) { + ecam_adjusted_address += res_info->translation; + } + pcie_discovery_api = pcie_setup_context.pcie_discovery_api; + pcie_discovery_api->calculate_resource( + ecam_adjusted_address - (res_info->mmap.bus.start * FWK_MIB), + &mmap_size, + res_info->mmap.bus.start, + &pcie_rw_api); + get_address_range(mmap, &mmap_size); + + status = unmap_region_in_io_block(config, region); + if (status != FWK_SUCCESS) { + return status; + } + + if (mmap->ecam.size != 0) { + status = map_region_in_io_block( + INTERFACE_IO_BLOCK_CARVEOUT_TYPE_ECAM, + config, + mmap->ecam.start, + mmap->ecam.size, + index, + ®ion); + if (status != FWK_SUCCESS) { + FWK_LOG_ERR(MOD_NAME "ECAM Mapping in NCI failed"); + return status; + } + } + + if (mmap->mmiol.size != 0) { + status = map_region_in_io_block( + INTERFACE_IO_BLOCK_CARVEOUT_TYPE_MMIOL, + config, + mmap->mmiol.start, + mmap->mmiol.size, + index, + ®ion); + if (status != FWK_SUCCESS) { + FWK_LOG_ERR(MOD_NAME "MMIOL Mapping in NCI failed"); + return status; + } + } + + if (mmap->mmioh.size != 0) { + status = map_region_in_io_block( + INTERFACE_IO_BLOCK_CARVEOUT_TYPE_MMIOH, + config, + mmap->mmioh.start, + mmap->mmioh.size, + index, + ®ion); + if (status != FWK_SUCCESS) { + FWK_LOG_ERR(MOD_NAME "MMIOH Mapping in NCI failed"); + return status; + } + } + + return FWK_SUCCESS; +} + +static int configure_pcie_endpoint( + struct mod_pcie_setup_config *config, + struct mod_pcie_setup_block_mmap *block_mmap) +{ + struct interface_cmn_memmap_rnsam_api *cmn_memmap_rnsam_api; + struct mod_pcie_setup_resource_info *res_info; + uint64_t ecam_start; + uint64_t mmiol_start; + uint64_t mmioh_start; + size_t ecam_size; + size_t mmiol_size; + size_t mmioh_size; + uint8_t index; + int status; + + res_info = &pcie_setup_context.resource_info; + + ecam_start = res_info->mmap.ecam.start; + mmiol_start = res_info->mmap.mmiol.start; + mmioh_start = res_info->mmap.mmioh.start; + ecam_size = 0; + mmiol_size = 0; + mmioh_size = 0; + + cmn_memmap_rnsam_api = pcie_setup_context.cmn_memmap_rnsam_api; + status = cmn_memmap_rnsam_api->map_io_region( + res_info->mmap.ecam.start, + res_info->mmap.ecam.size, + config->cmn_node_id); + if (status != FWK_SUCCESS) { + return status; + } + + for (index = 0; index < res_info->ep_count; index++) { + if (config->ep_config[index].valid) { + struct mod_pcie_setup_mmap *ep_mmap = + &block_mmap->ep[block_mmap->ep_count]; + block_mmap->ep_count++; + status = discover_and_configure_pcie_device(config, index, ep_mmap); + if (status != FWK_SUCCESS) { + return status; + } + ecam_size += ep_mmap->ecam.size; + mmiol_size += ep_mmap->mmiol.size; + mmioh_size += ep_mmap->mmioh.size; + ep_mmap->interrupt_id = res_info->ep_interrupt_ids[index]; + block_mmap->segment = pcie_setup_context.system_info->chip_id; + block_mmap->translation = res_info->translation; + block_mmap->smmu_base = config->smmu_base; + } + } + + status = pcie_setup_update_sds(block_mmap, config); + if (status != FWK_SUCCESS) { + return status; + } + + if (ecam_size != 0) { + status = cmn_memmap_rnsam_api->map_io_region( + ecam_start, ecam_size, config->cmn_node_id); + if (status != FWK_SUCCESS) { + return status; + } + } + + if (mmiol_size != 0) { + status = cmn_memmap_rnsam_api->map_io_region( + mmiol_start, mmiol_size, config->cmn_node_id); + if (status != FWK_SUCCESS) { + return status; + } + } + + if (mmioh_size != 0) { + status = cmn_memmap_rnsam_api->map_io_region( + mmioh_start, mmioh_size, config->cmn_node_id); + if (status != FWK_SUCCESS) { + return status; + } + } + + return FWK_SUCCESS; +} + +static int configure_pcie_ecam_mmio_space( + struct mod_pcie_setup_config *config, + unsigned int element) +{ + struct mod_pcie_setup_block_mmap *block_mmap; + unsigned int chip_id; + int status = FWK_SUCCESS; + + FWK_LOG_INFO(MOD_NAME "Configuring PCIe: %d", element); + block_mmap = fwk_mm_calloc(pcie_setup_context.block_config_size, 1); + if (block_mmap == NULL) { + return FWK_E_NOMEM; + } + chip_id = pcie_setup_context.system_info->chip_id; + block_mmap->id = + config->block_id + (chip_id * pcie_setup_context.block_count); + status = configure_pcie_endpoint(config, block_mmap); + fwk_mm_free(block_mmap); + + if (status != FWK_SUCCESS) { + FWK_LOG_ERR(MOD_NAME "PCIe(%d) Setup Failed.", element); + return status; + } + + if (element == (pcie_setup_context.block_count - 1)) { + status = pcie_setup_send_initialised_notification(); + } + + return status; +} + +/* Framework APIs. */ +static int mod_pcie_setup_init( + fwk_id_t module_id, + unsigned int block_count, + const void *data) +{ + const struct mod_pcie_setup_module_config *module_config; + size_t block_config_size; + + module_config = data; + if ((module_config == NULL) || (module_config->resource_info_count == 0)) { + return FWK_E_PARAM; + } + + /* + * Copy first instance of the resource info for binding. + */ + pcie_setup_context.module_config = data; + memcpy( + &pcie_setup_context.resource_info, + module_config->resource_info, + sizeof(pcie_setup_context.resource_info)); + + if (block_count == 0) { + return FWK_SUCCESS; + } + + pcie_setup_context.block_count = block_count; + pcie_setup_context.config = + fwk_mm_calloc(block_count, sizeof(struct mod_pcie_setup_config *)); + if (pcie_setup_context.config == NULL) { + return FWK_E_NOMEM; + } + + block_config_size = sizeof(struct mod_pcie_setup_block_mmap) + + (sizeof(struct mod_pcie_setup_mmap) * + pcie_setup_context.resource_info.ep_count); + pcie_setup_context.block_config_size = block_config_size; + + return FWK_SUCCESS; +} + +static int mod_pcie_setup_element_init( + fwk_id_t element_id, + unsigned int unused, + const void *data) +{ + struct mod_pcie_setup_config *config; + + config = (struct mod_pcie_setup_config *)data; + if ((config == NULL) || (config->reg_base == 0)) { + fwk_unexpected(); + return FWK_E_DATA; + } + + pcie_setup_context.config[fwk_id_get_element_idx(element_id)] = config; + + return FWK_SUCCESS; +} + +static int mod_pcie_setup_bind(fwk_id_t id, unsigned int round) +{ + struct mod_pcie_setup_resource_info *res_info; + int status; + + res_info = &pcie_setup_context.resource_info; + + status = fwk_module_bind( + res_info->atu_mmio_id, + res_info->atu_mmio_api_id, + &pcie_setup_context.remapper_rw_api); + if (status != FWK_SUCCESS) { + return status; + } + + status = fwk_module_bind( + res_info->cmn_id, + res_info->cmn_api_id, + &pcie_setup_context.cmn_memmap_rnsam_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), + &pcie_setup_context.system_info_api); + if (status != FWK_SUCCESS) { + return status; + } + + status = fwk_module_bind( + res_info->io_block_id, + res_info->io_block_api_id, + &pcie_setup_context.io_block_memmap_api); + if (status != FWK_SUCCESS) { + return status; + } + + status = fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_PCIE_DISCOVERY), + FWK_ID_API( + FWK_MODULE_IDX_PCIE_DISCOVERY, + MOD_PCIE_DISCOVERY_API_IDX_CALCULATE_RESOURCES), + &pcie_setup_context.pcie_discovery_api); + if (status != FWK_SUCCESS) { + return status; + } + + if (pcie_setup_context.sds_api == NULL) { + status = fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_SDS), + FWK_ID_API(FWK_MODULE_IDX_SDS, 0), + &pcie_setup_context.sds_api); + if (status != FWK_SUCCESS) { + return status; + } + } + + return status; +} + +static int mod_pcie_setup_start(fwk_id_t id) +{ + struct mod_pcie_setup_resource_info *res_info; + unsigned int element; + int status; + + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) { + const struct mod_pcie_setup_module_config *module_config; + unsigned int chip_id; + + status = pcie_setup_context.system_info_api->get_system_info( + &pcie_setup_context.system_info); + if (status != FWK_SUCCESS) { + return status; + } + + chip_id = pcie_setup_context.system_info->chip_id; + module_config = pcie_setup_context.module_config; + if (chip_id >= module_config->resource_info_count) { + FWK_LOG_ERR(MOD_NAME "Module configuration not valid."); + return FWK_E_PARAM; + } + + memcpy( + &pcie_setup_context.resource_info, + &module_config->resource_info[chip_id], + sizeof(pcie_setup_context.resource_info)); + + return FWK_SUCCESS; + } + + fwk_assert(fwk_module_is_valid_element_id(id)); + + element = fwk_id_get_element_idx(id); + + res_info = &pcie_setup_context.resource_info; + + if (fwk_id_type_is_valid(res_info->plat_notification.source_id)) { + /* Bind to the platform notification that is needed to start module + * configuration. */ + status = fwk_notification_subscribe( + res_info->plat_notification.notification_id, + res_info->plat_notification.source_id, + id); + } else { + struct mod_pcie_setup_config *config; + config = pcie_setup_context.config[element]; + status = configure_pcie_ecam_mmio_space(config, element); + } + + return status; +} + +static int mod_pcie_setup_process_notification( + const struct fwk_event *event, + struct fwk_event *resp_event) +{ + struct mod_pcie_setup_resource_info *res_info; + struct mod_pcie_setup_config *config; + + fwk_assert(!fwk_id_is_type(event->target_id, FWK_ID_TYPE_MODULE)); + + res_info = &pcie_setup_context.resource_info; + if (fwk_id_is_equal( + event->id, res_info->plat_notification.notification_id)) { + unsigned int element; + int status; + + status = fwk_notification_unsubscribe( + event->id, event->source_id, event->target_id); + if (status != FWK_SUCCESS) { + return status; + } + + element = fwk_id_get_element_idx(event->target_id); + config = pcie_setup_context.config[element]; + status = configure_pcie_ecam_mmio_space(config, element); + if (status != FWK_SUCCESS) { + return status; + } + } + + return FWK_SUCCESS; +} + +const struct fwk_module module_pcie_setup = { + .type = FWK_MODULE_TYPE_DRIVER, + .init = mod_pcie_setup_init, + .element_init = mod_pcie_setup_element_init, + .bind = mod_pcie_setup_bind, + .start = mod_pcie_setup_start, + .notification_count = (unsigned int)MOD_PCIE_SETUP_NOTIFICATION_IDX_COUNT, + .process_notification = mod_pcie_setup_process_notification, +}; diff --git a/product/automotive-rd/rd1ae/module/safety_island_platform/CMakeLists.txt b/product/automotive-rd/rd1ae/module/safety_island_platform/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6393799385b1d5ed7ebb1eb85e24b46d4e6e4887 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/safety_island_platform/CMakeLists.txt @@ -0,0 +1,18 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +add_library(${SCP_MODULE_TARGET} SCP_MODULE) + +target_include_directories(${SCP_MODULE_TARGET} + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_safety_island_platform.c") + +target_link_libraries( + ${SCP_MODULE_TARGET} + PRIVATE module-power-domain module-transport) diff --git a/product/automotive-rd/rd1ae/module/safety_island_platform/Module.cmake b/product/automotive-rd/rd1ae/module/safety_island_platform/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..0b00723b61f627306208080350d5a85e3ca72f5c --- /dev/null +++ b/product/automotive-rd/rd1ae/module/safety_island_platform/Module.cmake @@ -0,0 +1,10 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "safety-island-platform") + +set(SCP_MODULE_TARGET "module-safety-island-platform") diff --git a/product/automotive-rd/rd1ae/module/safety_island_platform/doc/safety_island_platform.md b/product/automotive-rd/rd1ae/module/safety_island_platform/doc/safety_island_platform.md new file mode 100644 index 0000000000000000000000000000000000000000..7157f4eaaaef710eee87e96cd00cd7444f44c793 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/safety_island_platform/doc/safety_island_platform.md @@ -0,0 +1,108 @@ +\ingroup GroupModules Modules +\defgroup GroupSafetyIslandPlatform SafetyIslandPlatform + +# Module Safety Island Platform Architecture + +Copyright (c) 2024, Arm Limited. All rights reserved. + +## Overview + +The Safety Island Platform provides means of receiving inter-processor messages +in order to boot a Safety Island Cluster. + +## Module Design + +``` + +--------+ +---------+ +------------------------+ +--------------+ + | DRIVER | |TRANSPORT| | SAFETY ISLAND PLATFORM | | POWER DOMAIN | + +---+----+ +----+----+ +-----------+------------+ +------+-------+ + | | | | + Interrupt | | | | +----------->+---+ | | | + | | isr() | | | + | | | | | + |<--+ | | | + | signal_message() | | | + +------------------------------->| | | + | | signal_message() | | + | +------------------------------->| | + | | | For each cluster core | + | | | set_state() | + | | +---------------------------------->| + | | | +------+ + | | | | | Set the power domain state of + | | | | | the Safety Island Cluster core + | | | return status |<-----+ + | | |<----------------------------------+ + | | | | + | |transport_release_channel_lock()| | + | |<-------------------------------+ | + | | | | + | | return status | | + | +------------------------------->| | + | | | | + | | return status | | + | return status |<-------------------------------+ | + |<-------------------------------+ | | + | | | | + | | | | +``` + +## Configuration Example + +The following examples demonstrate how to populate the configuration data for +the Safety Island Platform module. + +```config_safety_island_platform.c``` + +```C +static const struct fwk_element + safety_island_platform_element_table[SI_CL_COUNT + 1] = { + [SI_CL0_IDX] = { + .name = "Safety Island Cluster 0", + .data = &((struct safety_island_cluster_config) { + .transport_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_TRANSPORT, + SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS0), + .cluster_layout = {SI_CL0_ID, SI_CL0_CORE_NUM, SI_CL0_CORE_OFS}, + }), + }, + [SI_CL1_IDX] = { + .name = "Safety Island Cluster 1", + .data = &((struct safety_island_cluster_config) { + .transport_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_TRANSPORT, + SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS1), + .cluster_layout = {SI_CL1_ID, SI_CL1_CORE_NUM, SI_CL1_CORE_OFS}, + }), + }, + [SI_CL2_IDX] = { + .name = "Safety Island Cluster 2", + .data = &((struct safety_island_cluster_config) { + .transport_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_TRANSPORT, + SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS2), + .cluster_layout = {SI_CL2_ID, SI_CL2_CORE_NUM, SI_CL2_CORE_OFS}, + }), + }, + [SI_CL_COUNT] = { 0 }, +}; + +static const struct fwk_element *get_safety_island_platform_element_table( + fwk_id_t module_id) +{ + return safety_island_platform_element_table; +} + +const struct fwk_module_config config_safety_island_platform = { + .elements = + FWK_MODULE_DYNAMIC_ELEMENTS(get_safety_island_platform_element_table), +}; +``` + +Configuration data must also be provided for each Safety Island Cluster in +each of the following modules: +1. Power Domain module +2. PPU module +3. Tansport module +4. Communication Driver such as MHU diff --git a/product/automotive-rd/rd1ae/module/safety_island_platform/include/mod_safety_island_platform.h b/product/automotive-rd/rd1ae/module/safety_island_platform/include/mod_safety_island_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..75a14614b50ae3ce9bfa24824769105673708057 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/safety_island_platform/include/mod_safety_island_platform.h @@ -0,0 +1,65 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Safety Island Support + */ + +#ifndef MOD_SAFETY_ISLAND_PLATFORM_H +#define MOD_SAFETY_ISLAND_PLATFORM_H + +#include +#include + +#include + +#include + +/*! + * \brief Indices of the interfaces exposed by the module. + */ +enum mod_safety_island_platform_api_idx { + MOD_SAFETY_ISLAND_PLATFORM_API_IDX_BOOT_CLUSTER, + + /*! Number of exposed interfaces */ + MOD_SAFETY_ISLAND_PLATFORM_API_COUNT +}; + +/*! + * \brief Safety Island cluster layout. + */ +struct safety_island_platform_cluster_layout { + /*! Safety Island cluster ID */ + uint32_t id; + /*! Safety Island cluster number of cores */ + uint32_t num_cores; + /*! Safety Island cluster core offset */ + uint32_t core_offset; +}; + +/*! + * \brief Safety Island cluster configuration data. + */ +struct safety_island_cluster_config { + /*! Safety Island cluster transport channel identifier */ + const fwk_id_t transport_id; + /* Safety Island cluster layout */ + const struct safety_island_platform_cluster_layout cluster_layout; +}; + +/*! + * \brief Safety Island cluster context data. + */ +struct safety_island_cluster_ctx { + /*! Safety Island cluster configuration data */ + struct safety_island_cluster_config *config; + /* Transport API to send/respond to a message */ + struct mod_transport_firmware_api *transport_api; + /* Power Domain restricted API pointer */ + struct mod_pd_restricted_api *pd_restricted_api; +}; + +#endif /* MOD_SAFETY_ISLAND_PLATFORM_H */ diff --git a/product/automotive-rd/rd1ae/module/safety_island_platform/src/mod_safety_island_platform.c b/product/automotive-rd/rd1ae/module/safety_island_platform/src/mod_safety_island_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..0fb19b3e0ee84d9c806986e95e8f880e50f8fdc1 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/safety_island_platform/src/mod_safety_island_platform.c @@ -0,0 +1,244 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Safety Island Platform Module. + */ + +#include "platform_core.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MOD_NAME "[SAFETY_ISLAND_PLATFORM]" + +/* Module context */ +struct safety_island_platform_ctx { + /* Safety Island Cluster config data */ + struct safety_island_cluster_ctx *safety_island_ctx_table; + /* Number of Safety Island clusters */ + uint32_t safety_island_cluster_count; +}; + +static struct safety_island_platform_ctx ctx; + +static int init_si_cluster_cores(fwk_id_t safety_island_cluster_idx) +{ + uint32_t pd_state; + uint32_t core; + struct safety_island_cluster_ctx *safety_island_cluster_ctx = + &ctx.safety_island_ctx_table[fwk_id_get_element_idx( + safety_island_cluster_idx)]; + uint32_t cluster_offset = + safety_island_cluster_ctx->config->cluster_layout.core_offset; + uint32_t num_cores = + safety_island_cluster_ctx->config->cluster_layout.num_cores; + + uint32_t start_id = platform_get_core_count() + + platform_get_cluster_count() + cluster_offset; + + /* Composite Power Domain state to be set for the Safety Island */ + pd_state = MOD_PD_COMPOSITE_STATE( + MOD_PD_LEVEL_1, 0, 0, MOD_PD_STATE_ON, MOD_PD_STATE_ON); + + for (core = 0; core < num_cores; core++) { + fwk_id_t pd_id = + FWK_ID_ELEMENT(FWK_MODULE_IDX_POWER_DOMAIN, start_id + core); + int status = safety_island_cluster_ctx->pd_restricted_api->set_state( + pd_id, false, pd_state); + if (status != FWK_SUCCESS) { + FWK_LOG_ERR( + MOD_NAME "Failed to intialize %s core %lu", + fwk_module_get_element_name(safety_island_cluster_idx), + (unsigned long)core); + return status; + } + } + + return FWK_SUCCESS; +} + +static int signal_error(fwk_id_t safety_island_cluster_idx) +{ + struct safety_island_cluster_ctx *safety_island_cluster_ctx = + &ctx.safety_island_ctx_table[fwk_id_get_element_idx( + safety_island_cluster_idx)]; + FWK_LOG_ERR( + MOD_NAME "Error! Invalid response received to boot %s", + fwk_module_get_element_name(safety_island_cluster_idx)); + safety_island_cluster_ctx->transport_api->release_transport_channel_lock( + safety_island_cluster_ctx->config->transport_id); + + return FWK_SUCCESS; +} + +static int signal_message(fwk_id_t safety_island_cluster_idx) +{ + int status; + struct safety_island_cluster_ctx *safety_island_cluster_ctx = + &ctx.safety_island_ctx_table[fwk_id_get_element_idx( + safety_island_cluster_idx)]; + + FWK_LOG_INFO( + MOD_NAME "Received doorbell event to boot %s", + fwk_module_get_element_name(safety_island_cluster_idx)); + FWK_LOG_INFO( + MOD_NAME "Initializing %s cores...", + fwk_module_get_element_name(safety_island_cluster_idx)); + status = init_si_cluster_cores(safety_island_cluster_idx); + if (status != FWK_SUCCESS) { + FWK_LOG_ERR( + MOD_NAME "Error! Failed to initialize %s cores", + fwk_module_get_element_name(safety_island_cluster_idx)); + fwk_trap(); + } + safety_island_cluster_ctx->transport_api->release_transport_channel_lock( + safety_island_cluster_ctx->config->transport_id); + + return FWK_SUCCESS; +} + +static const struct mod_transport_firmware_signal_api + platform_transport_signal_api = { + .signal_error = signal_error, + .signal_message = signal_message, + }; + +/* + * Framework handlers + */ +static int safety_island_platform_mod_init( + fwk_id_t module_id, + unsigned int safety_island_cluster_count, + const void *unused) +{ + if (safety_island_cluster_count == 0) { + return FWK_E_PARAM; + } + + ctx.safety_island_ctx_table = fwk_mm_calloc( + safety_island_cluster_count, sizeof(ctx.safety_island_ctx_table[0])); + + ctx.safety_island_cluster_count = safety_island_cluster_count; + + return FWK_SUCCESS; +} + +static int safety_island_platform_cluster_init( + fwk_id_t safety_island_cluster_idx, + unsigned int sub_element_count, + const void *data) +{ + struct safety_island_cluster_config *config; + struct safety_island_cluster_ctx *safety_island_cluster_ctx; + + config = (struct safety_island_cluster_config *)data; + + if (config == NULL) { + return FWK_E_DATA; + } + + safety_island_cluster_ctx = + &ctx.safety_island_ctx_table[fwk_id_get_element_idx( + safety_island_cluster_idx)]; + safety_island_cluster_ctx->config = config; + + return FWK_SUCCESS; +} + +static int safety_island_platform_bind(fwk_id_t id, unsigned int round) +{ + struct safety_island_cluster_ctx *safety_island_cluster_ctx; + fwk_id_t transport_api_id; + int status; + + if ((round != 0) || (fwk_id_is_type(id, FWK_ID_TYPE_MODULE))) { + return FWK_SUCCESS; + } + + safety_island_cluster_ctx = + &ctx.safety_island_ctx_table[fwk_id_get_element_idx(id)]; + + transport_api_id = + FWK_ID_API(FWK_MODULE_IDX_TRANSPORT, MOD_TRANSPORT_API_IDX_FIRMWARE); + + status = fwk_module_bind( + safety_island_cluster_ctx->config->transport_id, + transport_api_id, + &safety_island_cluster_ctx->transport_api); + + if (status != FWK_SUCCESS) { + return status; + } + + return fwk_module_bind( + fwk_module_id_power_domain, + mod_pd_api_id_restricted, + &safety_island_cluster_ctx->pd_restricted_api); + + return FWK_SUCCESS; +} + +static int safety_island_platform_process_bind_request( + fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + int status; + enum mod_safety_island_platform_api_idx api_id_type; + struct safety_island_cluster_ctx *safety_island_cluster_ctx; + + if (!fwk_id_is_type(target_id, FWK_ID_TYPE_ELEMENT)) { + /* Only binding to an element is allowed */ + fwk_unexpected(); + return FWK_E_ACCESS; + } + + safety_island_cluster_ctx = + &ctx.safety_island_ctx_table[fwk_id_get_element_idx(target_id)]; + + api_id_type = + (enum mod_safety_island_platform_api_idx)fwk_id_get_api_idx(api_id); + + switch (api_id_type) { + case MOD_SAFETY_ISLAND_PLATFORM_API_IDX_BOOT_CLUSTER: + if (fwk_id_is_equal( + source_id, safety_island_cluster_ctx->config->transport_id)) { + *api = &platform_transport_signal_api; + status = FWK_SUCCESS; + } else { + status = FWK_E_PARAM; + } + break; + default: + status = FWK_E_PARAM; + break; + } + + return status; +} + +const struct fwk_module module_safety_island_platform = { + .type = FWK_MODULE_TYPE_HAL, + .api_count = MOD_SAFETY_ISLAND_PLATFORM_API_COUNT, + .init = safety_island_platform_mod_init, + .element_init = safety_island_platform_cluster_init, + .bind = safety_island_platform_bind, + .process_bind_request = safety_island_platform_process_bind_request, +}; diff --git a/product/automotive-rd/rd1ae/module/safety_island_platform/test/CMakeLists.txt b/product/automotive-rd/rd1ae/module/safety_island_platform/test/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f76a32d9d8421e29cd2a65e84f47744090b6575f --- /dev/null +++ b/product/automotive-rd/rd1ae/module/safety_island_platform/test/CMakeLists.txt @@ -0,0 +1,30 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(TEST_SRC mod_safety_island_platform) +set(TEST_FILE mod_safety_island_platform) + +set(UNIT_TEST_TARGET mod_safety_island_platform_unit_test) + +set(MODULE_SRC ${PRODUCT_ROOT}/${TEST_MODULE}/src) +set(MODULE_INC ${PRODUCT_ROOT}/${TEST_MODULE}/include) + +list(APPEND OTHER_MODULE_INC ${MODULE_ROOT}/power_domain/include) +list(APPEND OTHER_MODULE_INC ${MODULE_ROOT}/transport/include) + +set(MODULE_UT_SRC ${CMAKE_CURRENT_LIST_DIR}) +set(MODULE_UT_INC ${CMAKE_CURRENT_LIST_DIR}) + +list(APPEND MOCK_REPLACEMENTS fwk_id) +list(APPEND MOCK_REPLACEMENTS fwk_module) + +include(${SCP_ROOT}/unit_test/module_common.cmake) + +target_compile_definitions(${UNIT_TEST_TARGET} PUBLIC + "BUILD_HAS_MOD_POWER_DOMAIN") +target_compile_definitions(${UNIT_TEST_TARGET} PUBLIC + "BUILD_HAS_MOD_TRANSPORT") diff --git a/product/automotive-rd/rd1ae/module/safety_island_platform/test/config_safety_island_platform.h b/product/automotive-rd/rd1ae/module/safety_island_platform/test/config_safety_island_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..d640a89b25fcd67dd3ca41fae6a8fa179d93ec66 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/safety_island_platform/test/config_safety_island_platform.h @@ -0,0 +1,82 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'safety_island_platform'. + */ + +#include "config_transport.h" + +#include + +#include +#include +#include + +/* Safety Island Cluster 0 layout */ +#define SI_CL0_ID 0U +#define SI_CL0_CORE_NUM 1U +#define SI_CL0_CORE_OFS SI_CL0_CORE_NUM + +/* Safety Island Cluster 1 layout */ +#define SI_CL1_ID SI_CL0_ID + 1U +#define SI_CL1_CORE_NUM 2U +#define SI_CL1_CORE_OFS SI_CL0_CORE_NUM + SI_CL1_CORE_NUM + +/* Safety Island Cluster 2 layout */ +#define SI_CL2_ID SI_CL1_ID + 1U +#define SI_CL2_CORE_NUM 4U +#define SI_CL2_CORE_OFS SI_CL1_CORE_NUM + SI_CL2_CORE_NUM + +enum safety_island_cluster_idx { + SI_CL0_IDX, + SI_CL1_IDX, + SI_CL2_IDX, + SI_CL_COUNT, +}; + +static const struct fwk_element + safety_island_platform_element_table[SI_CL_COUNT + 1] = { + [SI_CL0_IDX] = { + .name = "Safety Island Cluster 0", + .data = &((struct safety_island_cluster_config) { + .transport_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_TRANSPORT, + SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS0), + .cluster_layout = {SI_CL0_ID, SI_CL0_CORE_NUM, SI_CL0_CORE_OFS}, + }), + }, + [SI_CL1_IDX] = { + .name = "Safety Island Cluster 1", + .data = &((struct safety_island_cluster_config) { + .transport_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_TRANSPORT, + SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS1), + .cluster_layout = {SI_CL1_ID, SI_CL1_CORE_NUM, SI_CL1_CORE_OFS}, + }), + }, + [SI_CL2_IDX] = { + .name = "Safety Island Cluster 2", + .data = &((struct safety_island_cluster_config) { + .transport_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_TRANSPORT, + SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS2), + .cluster_layout = {SI_CL2_ID, SI_CL2_CORE_NUM, SI_CL2_CORE_OFS}, + }), + }, + [SI_CL_COUNT] = { 0 }, +}; + +static const struct fwk_element *get_safety_island_platform_element_table( + fwk_id_t module_id) +{ + return safety_island_platform_element_table; +} + +const struct fwk_module_config config_safety_island_platform = { + .elements = + FWK_MODULE_DYNAMIC_ELEMENTS(get_safety_island_platform_element_table), +}; diff --git a/product/automotive-rd/rd1ae/module/safety_island_platform/test/config_transport.h b/product/automotive-rd/rd1ae/module/safety_island_platform/test/config_transport.h new file mode 100644 index 0000000000000000000000000000000000000000..af9288feaeeabdb30e164ee9d4cee2cdfc7bc834 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/safety_island_platform/test/config_transport.h @@ -0,0 +1,14 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Module 'transport' element indexes */ +enum scp_cfgd_mod_transport_element_idx { + SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS0, + SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS1, + SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS2, + SCP_CFGD_MOD_TRANSPORT_EIDX_COUNT, +}; diff --git a/product/automotive-rd/rd1ae/module/safety_island_platform/test/fwk_module_idx.h b/product/automotive-rd/rd1ae/module/safety_island_platform/test/fwk_module_idx.h new file mode 100644 index 0000000000000000000000000000000000000000..2a77dceca2bd618f0bcf7d30602074475e05f6f6 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/safety_island_platform/test/fwk_module_idx.h @@ -0,0 +1,31 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEST_FWK_MODULE_MODULE_IDX_H +#define TEST_FWK_MODULE_MODULE_IDX_H + +enum fwk_module_idx { + FWK_MODULE_IDX_SAFETY_ISLAND_PLATFORM, + FWK_MODULE_IDX_TRANSPORT, + FWK_MODULE_IDX_POWER_DOMAIN, + FWK_MODULE_IDX_FAKE, + FWK_MODULE_IDX_COUNT, +}; + +static const fwk_id_t fwk_module_id_safety_island_platform = + FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SAFETY_ISLAND_PLATFORM); + +static const fwk_id_t fwk_module_id_transport = + FWK_ID_MODULE_INIT(FWK_MODULE_IDX_TRANSPORT); + +static const fwk_id_t fwk_module_id_power_domain = + FWK_ID_MODULE_INIT(FWK_MODULE_IDX_POWER_DOMAIN); + +static const fwk_id_t fwk_module_id_fake = + FWK_ID_MODULE_INIT(FWK_MODULE_IDX_FAKE); + +#endif /* TEST_FWK_MODULE_MODULE_IDX_H */ diff --git a/product/automotive-rd/rd1ae/module/safety_island_platform/test/mod_safety_island_platform_unit_test.c b/product/automotive-rd/rd1ae/module/safety_island_platform/test/mod_safety_island_platform_unit_test.c new file mode 100644 index 0000000000000000000000000000000000000000..c1b08bd4d68f5d8acf1ef751a29dd5aa0f627bed --- /dev/null +++ b/product/automotive-rd/rd1ae/module/safety_island_platform/test/mod_safety_island_platform_unit_test.c @@ -0,0 +1,312 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "unity.h" + +#include +#include + +#include +#include +#include + +#include + +#include UNIT_TEST_SRC +#include "config_safety_island_platform.h" + +#include +#include +#include + +static int release_transport_channel_lock_success(fwk_id_t channel_id) +{ + return FWK_SUCCESS; +} + +static int pd_set_state_success( + fwk_id_t pd_id, + bool response_requested, + uint32_t state) +{ + return FWK_SUCCESS; +} + +static struct mod_transport_firmware_api transport_api = { + .release_transport_channel_lock = release_transport_channel_lock_success, +}; +static struct mod_pd_restricted_api pd_restricted_api = { + .set_state = pd_set_state_success, +}; + +void setUp(void) +{ + /* Do Nothing */ +} + +void tearDown(void) +{ + /* Do Nothing */ +} + +/*! + * \brief Safety Island Platform unit test: safety_platform_mod_init(), + invalid number of safety island clusters. + * + * \details Handle case in safety_platform_mod_init() where number of + * safety island clusters is passed. + */ +void test_safety_island_platform_mod_init_fail(void) +{ + int status = 0; + + status = safety_island_platform_mod_init( + fwk_module_id_safety_island_platform, 0, NULL); + + TEST_ASSERT_EQUAL(status, FWK_E_PARAM); +} + +/*! + * \brief Safety Island Platform unit test: safety_platform_mod_init(), + valid number of safety island clusters. + * + * \details Handle case in safety_platform_mod_init() where valid number of + * safety island clusters is passed. + */ +void test_safety_island_platform_mod_init_success(void) +{ + int status; + + status = safety_island_platform_mod_init( + fwk_module_id_safety_island_platform, SI_CL_COUNT, NULL); + + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); +} + +/*! + * \brief Safety Island Platform unit test: + * safety_island_platform_cluster_init(), invalid config data. + * + * \details Handle case in safety_island_platform_cluster_init() where invalid + * config data is passed. + */ +void test_safety_island_platform_cluster_init_fail(void) +{ + int status = 0; + + status = safety_island_platform_mod_init( + fwk_module_id_safety_island_platform, SI_CL_COUNT, NULL); + + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); + + status = safety_island_platform_cluster_init( + FWK_ID_ELEMENT(FWK_MODULE_IDX_SAFETY_ISLAND_PLATFORM, 0), 1, NULL); + + TEST_ASSERT_EQUAL(status, FWK_E_DATA); +} + +/*! + * \brief Safety Island Platform unit test: + * safety_island_platform_cluster_init(), valid config data. + * + * \details Handle case in safety_island_platform_cluster_init() where valid + * config data is passed. + */ +void test_safety_island_platform_cluster_init_success(void) +{ + int status = 0; + uint32_t idx; + + status = safety_island_platform_mod_init( + fwk_module_id_safety_island_platform, SI_CL_COUNT, NULL); + + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); + + for (idx = 0; idx < SI_CL_COUNT; idx++) { + fwk_id_t element_id = + FWK_ID_ELEMENT(FWK_MODULE_IDX_SAFETY_ISLAND_PLATFORM, idx); + fwk_id_get_element_idx_ExpectAndReturn(element_id, idx); + status = safety_island_platform_cluster_init( + element_id, + 1, + (const void *)safety_island_platform_element_table[idx].data); + + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); + } +} + +/*! + * \brief Safety Island Platform unit test: safety_island_platform_bind(), + module binding failure. + * + * \details Handle case in safety_island_platform_bind() when module binding + * fails + */ +void test_safety_island_platform_bind_fail(void) +{ + int status; + fwk_id_t element_id = + FWK_ID_ELEMENT(FWK_MODULE_IDX_SAFETY_ISLAND_PLATFORM, 0U); + + fwk_id_is_type_ExpectAndReturn(element_id, FWK_ID_TYPE_MODULE, false); + fwk_id_get_element_idx_ExpectAndReturn(element_id, 0U); + fwk_module_bind_ExpectAnyArgsAndReturn(1); + + status = safety_island_platform_bind(element_id, 0U); + + TEST_ASSERT_NOT_EQUAL(status, FWK_SUCCESS); +} + +/*! + * \brief Safety Island Platform unit test: safety_island_platform_bind(), + valid config data and arguments. + * + * \details Handle case in safety_island_platform_bind() where valid config + * data is passed and arguments are passed. + */ +void test_safety_island_platform_bind_success(void) +{ + int status; + fwk_id_t element_id = + FWK_ID_ELEMENT(FWK_MODULE_IDX_SAFETY_ISLAND_PLATFORM, 0U); + + /* Attempt binding with a non zero round */ + status = safety_island_platform_bind(element_id, 1U); + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); + + /* Attempt binding for the module and not a cluster */ + fwk_id_is_type_ExpectAndReturn( + fwk_module_id_safety_island_platform, FWK_ID_TYPE_MODULE, true); + status = + safety_island_platform_bind(fwk_module_id_safety_island_platform, 0U); + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); + + /* Bind the safety island cluster correctly */ + fwk_id_is_type_ExpectAndReturn(element_id, FWK_ID_TYPE_MODULE, false); + fwk_id_get_element_idx_ExpectAndReturn(element_id, 0U); + fwk_module_bind_IgnoreAndReturn(FWK_SUCCESS); + status = safety_island_platform_bind(element_id, 0U); + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); +} + +/*! + * \brief Safety Island Platform unit test: + safety_island_platform_process_bind_request(), invalid arguments. + * + * \details Handle case in safety_island_platform_process_bind_request() where + * invalid arguments are passed. + */ +void test_safety_island_platform_process_bind_request_fail(void) +{ + int status; + const void *api = NULL; + fwk_id_t api_id = FWK_ID_API( + FWK_MODULE_IDX_SAFETY_ISLAND_PLATFORM, + MOD_SAFETY_ISLAND_PLATFORM_API_COUNT); + fwk_id_is_type_ExpectAndReturn( + fwk_module_id_safety_island_platform, FWK_ID_TYPE_ELEMENT, false); + status = safety_island_platform_process_bind_request( + fwk_module_id_fake, fwk_module_id_safety_island_platform, api_id, &api); + TEST_ASSERT_EQUAL(status, FWK_E_ACCESS); + TEST_ASSERT_NULL(api); +} + +/*! + * \brief Safety Island Platform unit test: + safety_island_platform_process_bind_request(), valid config data + and arguments. + * + * \details Handle case in safety_island_platform_process_bind_request() where + * valid config and arguments are passed. + */ +void test_safety_island_platform_process_bind_request_success(void) +{ + int status; + uint32_t idx; + + /* Initialize the module */ + status = safety_island_platform_mod_init( + fwk_module_id_safety_island_platform, SI_CL_COUNT, NULL); + + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); + + for (idx = 0; idx < SI_CL_COUNT; idx++) { + const struct safety_island_cluster_config *config = + safety_island_platform_element_table[idx].data; + fwk_id_t api_id = FWK_ID_API( + FWK_MODULE_IDX_SAFETY_ISLAND_PLATFORM, + MOD_SAFETY_ISLAND_PLATFORM_API_COUNT); + const struct mod_transport_firmware_signal_api *api; + fwk_id_t element_id = + FWK_ID_ELEMENT(FWK_MODULE_IDX_SAFETY_ISLAND_PLATFORM, idx); + + /* Intiailize the Safety Island cluster */ + fwk_id_get_element_idx_ExpectAndReturn(element_id, idx); + status = safety_island_platform_cluster_init( + element_id, + 1, + (const void *)safety_island_platform_element_table[idx].data); + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); + + /* Bind the safety island cluster */ + fwk_id_is_type_ExpectAndReturn(element_id, FWK_ID_TYPE_MODULE, false); + fwk_id_get_element_idx_ExpectAndReturn(element_id, idx); + fwk_module_bind_IgnoreAndReturn(FWK_SUCCESS); + status = safety_island_platform_bind(element_id, 0U); + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); + + /* Call Process Bind Request on the Safety Island Cluster */ + fwk_id_is_type_ExpectAndReturn(element_id, FWK_ID_TYPE_ELEMENT, true); + fwk_id_get_element_idx_ExpectAndReturn(element_id, idx); + fwk_id_get_api_idx_ExpectAndReturn( + api_id, MOD_SAFETY_ISLAND_PLATFORM_API_IDX_BOOT_CLUSTER); + fwk_id_is_equal_ExpectAndReturn( + fwk_module_id_fake, config->transport_id, true); + + /* Set Transport and Power Domain APIs */ + ctx.safety_island_ctx_table[idx].transport_api = &transport_api; + ctx.safety_island_ctx_table[idx].pd_restricted_api = &pd_restricted_api; + + status = safety_island_platform_process_bind_request( + fwk_module_id_fake, element_id, api_id, (const void **)&api); + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); + TEST_ASSERT_NOT_NULL(api); + + /* Test signal_message */ + fwk_id_get_element_idx_IgnoreAndReturn(idx); + fwk_module_get_element_name_IgnoreAndReturn("Test"); + status = api->signal_message(api_id); + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); + + /* Test signal_error */ + fwk_id_get_element_idx_IgnoreAndReturn(idx); + fwk_module_get_element_name_IgnoreAndReturn("Test"); + status = api->signal_error(api_id); + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); + } +} + +int safety_island_platform_test_main(void) +{ + UNITY_BEGIN(); + + RUN_TEST(test_safety_island_platform_mod_init_fail); + RUN_TEST(test_safety_island_platform_mod_init_success); + RUN_TEST(test_safety_island_platform_cluster_init_fail); + RUN_TEST(test_safety_island_platform_cluster_init_success); + RUN_TEST(test_safety_island_platform_bind_fail); + RUN_TEST(test_safety_island_platform_bind_success); + RUN_TEST(test_safety_island_platform_process_bind_request_fail); + RUN_TEST(test_safety_island_platform_process_bind_request_success); + + return UNITY_END(); +} + +int main(void) +{ + return safety_island_platform_test_main(); +} diff --git a/product/automotive-rd/rd1ae/module/safety_island_platform/test/platform_core.h b/product/automotive-rd/rd1ae/module/safety_island_platform/test/platform_core.h new file mode 100644 index 0000000000000000000000000000000000000000..88dba1a114672729bc2701065f982b79d7fe93b8 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/safety_island_platform/test/platform_core.h @@ -0,0 +1,42 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Platform generic definitions. + */ + +#ifndef PLATFORM_CORE_H +#define PLATFORM_CORE_H + +#include + +#define NUMBER_OF_ROOTPORTS 5 + +#define CORES_PER_CLUSTER 1 +#define NUMBER_OF_CLUSTERS 16 + +#define NUM_PCIE_INTEG_CTRL 4 + +static inline unsigned int platform_get_cluster_count(void) +{ + return NUMBER_OF_CLUSTERS; +} + +static inline unsigned int platform_get_core_per_cluster_count( + unsigned int cluster) +{ + fwk_assert(cluster < platform_get_cluster_count()); + + return CORES_PER_CLUSTER; +} + +static inline unsigned int platform_get_core_count(void) +{ + return platform_get_core_per_cluster_count(0) * + platform_get_cluster_count(); +} + +#endif /* PLATFORM_CORE_H */ diff --git a/product/automotive-rd/rd1ae/module/scp_platform/CMakeLists.txt b/product/automotive-rd/rd1ae/module/scp_platform/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b3a36b7f1639814932796a364e904d53f296a43d --- /dev/null +++ b/product/automotive-rd/rd1ae/module/scp_platform/CMakeLists.txt @@ -0,0 +1,21 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +add_library(${SCP_MODULE_TARGET} SCP_MODULE) + +target_include_directories(${SCP_MODULE_TARGET} + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") + +target_sources( + ${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_scp_platform.c" + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/platform_power_mgmt.c" + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/platform_rse.c") + +target_link_libraries( + ${SCP_MODULE_TARGET} + PRIVATE module-power-domain module-system-power module-scmi + module-system-info module-transport module-timer) diff --git a/product/automotive-rd/rd1ae/module/scp_platform/Module.cmake b/product/automotive-rd/rd1ae/module/scp_platform/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..4faf2676b32d3556e54bb53e41f6de1cbb89246f --- /dev/null +++ b/product/automotive-rd/rd1ae/module/scp_platform/Module.cmake @@ -0,0 +1,10 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "scp-platform") + +set(SCP_MODULE_TARGET "module-scp-platform") diff --git a/product/automotive-rd/rd1ae/module/scp_platform/include/internal/scp_platform.h b/product/automotive-rd/rd1ae/module/scp_platform/include/internal/scp_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..8463a9bcedc36721a2a7bd2017b9e102cbf19d44 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/scp_platform/include/internal/scp_platform.h @@ -0,0 +1,103 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * SCP sub-system support. + */ + +#ifndef SCP_PLATFORM_H +#define SCP_PLATFORM_H + +#include + +#define MOD_NAME "[SCP_PLATFORM]" + +/* SRAM address where AP binary will be preloaded */ +#define AP_BOOT_ADDRESS (0x42000U) + +/* + * RSE communication interface helper functions. + */ + +/*! + * \brief Helper function to return platform system transport signal API. + * + * \param None. + * + * \return Pointer to the scp platform transport signal API. + */ +const void *get_platform_transport_signal_api(void); + +/*! + * \brief Helper function to notify RSE and wait for response. + * + * \details Notify RSE that SYSTOP is powered up so it can enable GPC bypass in + * the system control block. + * + * \param None. + * + * \retval ::FWK_SUCCESS Operation succeeded. + * \return One of the standard error codes for implementation-defined errors. + */ +int notify_rse_and_wait_for_response(void); + +/*! + * \brief Helper function to bind to transport and timer module APIs. + * + * \param config Pointer to the module config data. + * + * \retval ::FWK_SUCCESS Operation succeeded. + * \return One of the standard error codes for implementation-defined errors. + */ +int platform_rse_bind(const struct mod_scp_platform_config *config); + +/* + * Power management interface helper functions. + */ + +/*! + * \brief Helper function to return platform system power driver API. + * + * \param None. + * + * \return Pointer to the scp platform system power driver API. + */ +const void *get_platform_system_power_driver_api(void); + +/* + * SCMI interface helper functions. + */ + +/*! + * \brief Helper function to return platform system SCMI API. + * + * \param None. + * + * \return Pointer to the SCP platform system SCMI API. + */ +const void *get_platform_scmi_power_down_api(void); + +/*! + * \brief Helper function to bind to power domain restricted API. + * + * \param None. + * + * \retval ::FWK_SUCCESS Operation succeeded. + * \return One of the standard error codes for implementation-defined errors. + */ +int platform_power_mgmt_bind(void); + +/*! + * \brief Power on the given AP core. + * + * \param core_idx AP core index. + * + * \retval ::FWK_SUCCESS Operation succeeded. + * \return One of the standard error codes for implementation-defined errors. + */ +int init_ap_core(uint8_t core_idx); + +#endif /* SCP_PLATFORM_H */ diff --git a/product/automotive-rd/rd1ae/module/scp_platform/include/mod_scp_platform.h b/product/automotive-rd/rd1ae/module/scp_platform/include/mod_scp_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..30bf7db10d930a2d5204e2a4cb1c6cd5c75a02d8 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/scp_platform/include/mod_scp_platform.h @@ -0,0 +1,91 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * SCP Platform Support + */ + +#ifndef MOD_SCP_PLATFORM_H +#define MOD_SCP_PLATFORM_H + +#include +#include + +#include + +/*! + * \addtogroup GroupPLATFORMModule PLATFORM Product Modules + * @{ + */ + +/*! + * \defgroup GroupSCPPlatform SCP Platform Support + * @{ + */ + +/*! + * \brief Indices of the interfaces exposed by the module. + */ +enum mod_scp_platform_api_idx { + /*! API index for the powerdown interface of SCMI module */ + MOD_SCP_PLATFORM_API_IDX_SCMI_POWER_DOWN, + + /*! API index for the driver interface of the SYSTEM POWER module */ + MOD_SCP_PLATFORM_API_IDX_SYSTEM_POWER_DRIVER, + + /*! Interface for Transport module */ + MOD_SCP_PLATFORM_API_IDX_TRANSPORT_SIGNAL, + + /*! Number of exposed interfaces */ + MOD_SCP_PLATFORM_API_COUNT +}; + +/*! + * \brief Notification indices. + */ +enum mod_scp_platform_notification_idx { + /*! SCP subsystem initialization completion notification */ + MOD_SCP_PLATFORM_NOTIFICATION_IDX_SUBSYS_INITIALIZED, + + /*! Number of notifications defined by the module */ + MOD_SCP_PLATFORM_NOTIFICATION_COUNT, +}; + +/*! + * \brief Identifier for the + * ::MOD_SCP_PLATFORM_NOTIFICATION_IDX_SUBSYS_INITIALIZED notification. + */ +static const fwk_id_t mod_scp_platform_notification_subsys_init = + FWK_ID_NOTIFICATION_INIT( + FWK_MODULE_IDX_SCP_PLATFORM, + MOD_SCP_PLATFORM_NOTIFICATION_IDX_SUBSYS_INITIALIZED); + +/*! + * \brief SCP platform configuration data. + */ +struct mod_scp_platform_config { + /*! Timer identifier */ + fwk_id_t timer_id; + + /*! Transport channel identifier */ + fwk_id_t transport_id; + + /*! + * Maximum amount of time, in microseconds, to wait for the RSE handshake + * event. + */ + uint32_t rse_sync_wait_us; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_SCP_PLATFORM_H */ diff --git a/product/automotive-rd/rd1ae/module/scp_platform/src/mod_scp_platform.c b/product/automotive-rd/rd1ae/module/scp_platform/src/mod_scp_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..bcd911d7941f716f6ca6192365a4a5ee549d7d03 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/scp_platform/src/mod_scp_platform.c @@ -0,0 +1,207 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * SCP platform sub-system initialization support. + */ + +#include "core_manager.h" +#include "platform_core.h" + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#define L0GPTSZ_SHIFT 0x9 +#define L0GPTSZ_16GB 0x4 + +/* Module context */ +struct scp_platform_ctx { + /* Module config data */ + const struct mod_scp_platform_config *config; + + /* System Information HAL API pointer */ + struct mod_system_info_get_info_api *system_info_api; +}; + +/* Module context data */ +static struct scp_platform_ctx scp_platform_ctx; + +static void platform_update_gpt_size(void) +{ + unsigned int n; + + /* Set Level 0 Granule Protection Table size to 16GB for all cores */ + for (n = 0; n < platform_get_core_count(); n++) { + volatile uint32_t *pe_static_config = + (volatile uint32_t *)(&SCP_CLUSTER_UTILITY_CORE_MANAGER_PTR(n) + ->PE_STATIC_CONFIG); + *pe_static_config |= (L0GPTSZ_16GB << L0GPTSZ_SHIFT); + } +} + +/* Helper function to program the AP Core RVBAR */ +static void program_ap_rvbar() +{ + uint8_t core_idx; + + for (core_idx = 0; core_idx < platform_get_core_count(); core_idx++) { + /* Set RVBAR to boot SRAM address */ + SCP_CLUSTER_UTILITY_CORE_MANAGER_PTR(core_idx)->PE_RVBARADDR_LW = + AP_BOOT_ADDRESS; + SCP_CLUSTER_UTILITY_CORE_MANAGER_PTR(core_idx)->PE_RVBARADDR_UP = 0; + } +} + +/* + * Framework handlers + */ +static int scp_platform_mod_init( + fwk_id_t module_id, + unsigned int unused, + const void *data) +{ + const struct mod_scp_platform_config *config; + + config = (struct mod_scp_platform_config *)data; + + if (!fwk_id_type_is_valid(config->timer_id) || + !fwk_id_type_is_valid(config->transport_id)) { + return FWK_E_DATA; + } + + /* Save the config data in the module context */ + scp_platform_ctx.config = config; + + return FWK_SUCCESS; +} + +static int scp_platform_bind(fwk_id_t id, unsigned int round) +{ + int status; + fwk_id_t mod_system_info_api_id_get_info; + + if (round > 0) { + return FWK_SUCCESS; + } + + /* Bind to modules required to handshake with RSE */ + status = platform_rse_bind(scp_platform_ctx.config); + if (status != FWK_SUCCESS) { + return status; + } + + /* Bind to modules required for power management */ + status = platform_power_mgmt_bind(); + if (status != FWK_SUCCESS) { + return status; + } + + mod_system_info_api_id_get_info = + FWK_ID_API(FWK_MODULE_IDX_SYSTEM_INFO, MOD_SYSTEM_INFO_GET_API_IDX); + + /* Bind to System Info HAL API */ + return fwk_module_bind( + fwk_module_id_system_info, + mod_system_info_api_id_get_info, + &scp_platform_ctx.system_info_api); +} + +static int scp_platform_process_bind_request( + fwk_id_t requester_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + int status; + enum mod_scp_platform_api_idx api_id_type; + + api_id_type = (enum mod_scp_platform_api_idx)fwk_id_get_api_idx(api_id); + + switch (api_id_type) { + case MOD_SCP_PLATFORM_API_IDX_SCMI_POWER_DOWN: + *api = get_platform_scmi_power_down_api(); + status = FWK_SUCCESS; + break; + + case MOD_SCP_PLATFORM_API_IDX_SYSTEM_POWER_DRIVER: + *api = get_platform_system_power_driver_api(); + status = FWK_SUCCESS; + break; + + case MOD_SCP_PLATFORM_API_IDX_TRANSPORT_SIGNAL: + *api = get_platform_transport_signal_api(); + status = FWK_SUCCESS; + break; + + default: + status = FWK_E_PARAM; + } + + return status; +} + +static int scp_platform_start(fwk_id_t id) +{ + int status; + struct fwk_event event = { 0 }; + unsigned int event_count; + + /* Notify RSE that SYSTOP is powered up and wait for RSE doorbell */ + status = notify_rse_and_wait_for_response(); + if (status != FWK_SUCCESS) { + FWK_LOG_ERR(MOD_NAME "Error! SCP-RSE handshake failed"); + return FWK_E_PANIC; + } + + /* SCP subsystem initialization completion notification */ + event.id = mod_scp_platform_notification_subsys_init; + event.source_id = id; + + /* + * RSE has now setup GPC bypass in the system control block. Notify other + * modules that are waiting to access memory regions outside the SCP + * subsystem (which otherwise would have generated a fault). + */ + status = fwk_notification_notify(&event, &event_count); + if (status != FWK_SUCCESS) { + FWK_LOG_ERR(MOD_NAME "Error! Subsystem init notification failed"); + return FWK_E_PANIC; + } + + /* Update L0GPTSZ for all cores */ + platform_update_gpt_size(); + + FWK_LOG_INFO(MOD_NAME "Initializing the primary core..."); + + program_ap_rvbar(); + + status = init_ap_core(0); + if (status != FWK_SUCCESS) { + FWK_LOG_ERR(MOD_NAME "Error! Failed to initialize primary core"); + fwk_trap(); + } + + return FWK_SUCCESS; +} + +const struct fwk_module module_scp_platform = { + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = MOD_SCP_PLATFORM_API_COUNT, + .notification_count = MOD_SCP_PLATFORM_NOTIFICATION_COUNT, + .init = scp_platform_mod_init, + .bind = scp_platform_bind, + .process_bind_request = scp_platform_process_bind_request, + .start = scp_platform_start, +}; diff --git a/product/automotive-rd/rd1ae/module/scp_platform/src/platform_power_mgmt.c b/product/automotive-rd/rd1ae/module/scp_platform/src/platform_power_mgmt.c new file mode 100644 index 0000000000000000000000000000000000000000..12f3a775fb46eb5fc43d2dab5de7a937999bc2ce --- /dev/null +++ b/product/automotive-rd/rd1ae/module/scp_platform/src/platform_power_mgmt.c @@ -0,0 +1,164 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * SCP Platform Support - Power Management + */ + +#include "scp_cfgd_scmi.h" + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +/*! SCMI protocol API */ +static const struct mod_scmi_from_protocol_req_api *scmi_protocol_req_api; + +/* Module 'power_domain' restricted API pointer */ +static struct mod_pd_restricted_api *pd_restricted_api; + +/* System shutdown function */ +static int platform_shutdown(enum mod_pd_system_shutdown system_shutdown) +{ + int status; + fwk_id_t rse_scmi_prot_id = FWK_ID_ELEMENT( + FWK_MODULE_IDX_SCMI, SCP_CFGD_MOD_SCMI_RSE_POWER_DOWN_SEND); + struct scp_cfgd_scmi_sys_power_state_set_payload scp_scmi_payload; + + scp_scmi_payload.flags = 0; + scp_scmi_payload.system_state = (uint32_t)system_shutdown; + + /* + * The current RSE firmware lacks SCMI support, preventing the RSE platform + * firmware from sending SCMI power state notify messages to the SCP or + * subscribing to SCMI notifications. To address this limitation, notify + * the RSE about system power down using the SCMI system power state set + * message. As this message can be decoded in the RSE firmware with minimal + * SCMI message parsing logic. + */ + status = scmi_protocol_req_api->scmi_send_message( + MOD_SCMI_SYS_POWER_STATE_SET, + MOD_SCMI_PROTOCOL_ID_SYS_POWER, + 0, + rse_scmi_prot_id, + (void *)&scp_scmi_payload, + sizeof(scp_scmi_payload), + false); + + if (status != FWK_SUCCESS) { + FWK_LOG_ERR( + "[SCP_PLATFORM] ERROR! Unable to send shutdown request to RSE"); + return status; + } + + while (1) { + __WFI(); + } + + return FWK_E_DEVICE; +} + +/* Module 'system_power' driver interface */ +const struct mod_system_power_driver_api platform_system_pwr_drv_api = { + .system_shutdown = platform_shutdown, +}; + +const void *get_platform_system_power_driver_api(void) +{ + return &platform_system_pwr_drv_api; +} + +/* + * SCMI module -> SCP platform module interface + */ +static int platform_system_get_scmi_protocol_id( + fwk_id_t protocol_id, + uint8_t *scmi_protocol_id) +{ + *scmi_protocol_id = (uint8_t)MOD_SCMI_PROTOCOL_ID_SYS_POWER; + + return FWK_SUCCESS; +} + +/* + * Upon binding the scp_platform module to the SCMI module, the SCMI module + * will also bind back to the scp_platform module, anticipating the presence of + * .get_scmi_protocol_id() and .message_handler() APIs. + * + * In the current implementation of scp_platform module, only sending SCMI + * message is implemented, and the scp_platform module is not intended to + * receive any SCMI messages. Therefore, it is necessary to include a minimal + * .message_handler() API to ensure the successful binding of the SCMI module. + */ +static int platform_system_scmi_message_handler( + fwk_id_t protocol_id, + fwk_id_t service_id, + const uint32_t *payload, + size_t payload_size, + unsigned int message_id) +{ + return FWK_SUCCESS; +} + +/* SCMI driver interface */ +const struct mod_scmi_to_protocol_api platform_system_scmi_api = { + .get_scmi_protocol_id = platform_system_get_scmi_protocol_id, + .message_handler = platform_system_scmi_message_handler, +}; + +const void *get_platform_scmi_power_down_api(void) +{ + return &platform_system_scmi_api; +} + +int platform_power_mgmt_bind(void) +{ + int status; + + /* Bind to SCMI module for RSE communication */ + status = fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_SCMI), + FWK_ID_API(FWK_MODULE_IDX_SCMI, MOD_SCMI_API_IDX_PROTOCOL_REQ), + &scmi_protocol_req_api); + if (status != FWK_SUCCESS) { + return status; + } + + return fwk_module_bind( + fwk_module_id_power_domain, + mod_pd_api_id_restricted, + &pd_restricted_api); +} + +int init_ap_core(uint8_t core_idx) +{ + bool resp_requested; + uint32_t pd_state; + fwk_id_t pd_id; + + pd_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_POWER_DOMAIN, core_idx); + + /* Notification event at the end of request processing is not required */ + resp_requested = false; + + /* Composite Power Domain state to be set for the AP */ + pd_state = MOD_PD_COMPOSITE_STATE( + MOD_PD_LEVEL_2, 0, MOD_PD_STATE_ON, MOD_PD_STATE_ON, MOD_PD_STATE_ON); + + return pd_restricted_api->set_state(pd_id, resp_requested, pd_state); +} diff --git a/product/automotive-rd/rd1ae/module/scp_platform/src/platform_rse.c b/product/automotive-rd/rd1ae/module/scp_platform/src/platform_rse.c new file mode 100644 index 0000000000000000000000000000000000000000..85b529e2879eb66cc882bf7ac34671cd98f5be18 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/scp_platform/src/platform_rse.c @@ -0,0 +1,140 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * SCP Platform Support - implements support for communication with RSE. + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +/* Platform RSE context */ +struct platform_rse_ctx { + /* Pointer to the module config data */ + const struct mod_scp_platform_config *config; + + /* Transport API to send/respond to a message */ + const struct mod_transport_firmware_api *transport_api; + + /* Timer API */ + const struct mod_timer_api *timer_api; + + /* Flag to indicate that the RSE doorbell has been received */ + volatile bool rse_doorbell_received; +}; + +static struct platform_rse_ctx ctx; + +/* Utility function to check if SCP platform has received doorbell from RSE */ +static bool is_rse_doorbell_received(void *unused) +{ + return ctx.rse_doorbell_received; +} + +/* + * Module 'transport' signal interface implementation. + */ +static int signal_error(fwk_id_t unused) +{ + FWK_LOG_ERR(MOD_NAME "Error! Invalid response received from RSE"); + + ctx.transport_api->release_transport_channel_lock(ctx.config->transport_id); + + return FWK_SUCCESS; +} + +static int signal_message(fwk_id_t unused) +{ + FWK_LOG_INFO(MOD_NAME "Received doorbell event from RSE"); + + ctx.transport_api->release_transport_channel_lock(ctx.config->transport_id); + + /* Set the flag to indicate that the RSE initialization is complete */ + ctx.rse_doorbell_received = true; + + return FWK_SUCCESS; +} + +const struct mod_transport_firmware_signal_api platform_transport_signal_api = { + .signal_error = signal_error, + .signal_message = signal_message, +}; + +/* + * Helper function to retrieve the 'transport' module signal API. + */ +const void *get_platform_transport_signal_api(void) +{ + return &platform_transport_signal_api; +} + +/* + * RSE has to be notified that SYSTOP is powered up and so it can enable GPC + * bypass in the system control block. + */ +int notify_rse_and_wait_for_response(void) +{ + int status; + + /* + * Trigger doorbell to RSE to indicate that the SYSTOP domain is ON. + */ + status = ctx.transport_api->trigger_interrupt(ctx.config->transport_id); + if (status != FWK_SUCCESS) { + FWK_LOG_ERR(MOD_NAME + "Error! Failed to send SYSTOP enabled message to RSE"); + return status; + } + + /* + * Wait till a doorbell from RSE is received. This doorbell event indicates + * that the RSE has initialized the GPC adnd completed the peripheral + * NI-Tower setup. + */ + status = ctx.timer_api->wait( + ctx.config->timer_id, + ctx.config->rse_sync_wait_us, + is_rse_doorbell_received, + NULL); + if (status != FWK_SUCCESS) { + FWK_LOG_ERR(MOD_NAME "Error! No response from RSE for SYSTOP sync"); + } + + return status; +} + +/* + * Bind to timer and transport module to communicate with RSE. + */ +int platform_rse_bind(const struct mod_scp_platform_config *config) +{ + int status; + fwk_id_t timer_api_id; + fwk_id_t transport_api_id; + + ctx.config = config; + + timer_api_id = FWK_ID_API(FWK_MODULE_IDX_TIMER, MOD_TIMER_API_IDX_TIMER); + status = fwk_module_bind(config->timer_id, timer_api_id, &ctx.timer_api); + if (status != FWK_SUCCESS) { + return status; + } + + transport_api_id = + FWK_ID_API(FWK_MODULE_IDX_TRANSPORT, MOD_TRANSPORT_API_IDX_FIRMWARE); + return fwk_module_bind( + config->transport_id, transport_api_id, &ctx.transport_api); +} diff --git a/product/automotive-rd/rd1ae/module/system_pik/CMakeLists.txt b/product/automotive-rd/rd1ae/module/system_pik/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5d29f5e651b9c604cc30f3de17c3ba6e384af811 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/system_pik/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +add_library(${SCP_MODULE_TARGET} SCP_MODULE) + +target_include_directories(${SCP_MODULE_TARGET} + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_system_pik.c") diff --git a/product/automotive-rd/rd1ae/module/system_pik/Module.cmake b/product/automotive-rd/rd1ae/module/system_pik/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..cc9d71339f0fbf32a99a5430ce07ac8ce5089d48 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/system_pik/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "system-pik") +set(SCP_MODULE_TARGET "module_system_pik") diff --git a/product/automotive-rd/rd1ae/module/system_pik/include/mod_system_pik.h b/product/automotive-rd/rd1ae/module/system_pik/include/mod_system_pik.h new file mode 100644 index 0000000000000000000000000000000000000000..c3b63ef8db17cf7fcc676a55265b767b7915c2a4 --- /dev/null +++ b/product/automotive-rd/rd1ae/module/system_pik/include/mod_system_pik.h @@ -0,0 +1,25 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_SYSTEM_PIK_H +#define MOD_SYSTEM_PIK_H + +#include "system_pik.h" + +#include + +#define TCU_L0GPTSZ_SHIFT 2UL +#define L0GPTSZ_16GIB 0x04UL + +struct mod_system_pik_device_config { + /*! Base address of the system PIK register */ + uintptr_t system_pik_base; + /*! Level 0 Granule Protection Table size */ + uint32_t l0_gpt_size; +}; + +#endif /* MOD_SYSTEM_PIK_H */ diff --git a/product/automotive-rd/rd1ae/module/system_pik/src/mod_system_pik.c b/product/automotive-rd/rd1ae/module/system_pik/src/mod_system_pik.c new file mode 100644 index 0000000000000000000000000000000000000000..539270917878973da636f9ac8d6b015b1ad26c2f --- /dev/null +++ b/product/automotive-rd/rd1ae/module/system_pik/src/mod_system_pik.c @@ -0,0 +1,55 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * System PIK device driver. + */ + +#include + +#include +#include + +struct mod_system_pik_ctx { + struct system_pik_reg *system_pik_reg; +}; + +/* System PIK module context */ +static struct mod_system_pik_ctx system_pik_ctx; + +/* + * Framework handlers + */ +static int mod_system_pik_init( + fwk_id_t module_id, + unsigned int device_count, + const void *data) +{ + struct mod_system_pik_device_config *config = + (struct mod_system_pik_device_config *)data; + + system_pik_ctx.system_pik_reg = + (struct system_pik_reg *)config->system_pik_base; + + if (config->l0_gpt_size != 0) { + system_pik_ctx.system_pik_reg->IOMACRO_OVERRIDE = + (config->l0_gpt_size << TCU_L0GPTSZ_SHIFT); + } + + return FWK_SUCCESS; +} + +static int mod_system_pik_start(fwk_id_t id) +{ + return FWK_SUCCESS; +} + +/* System PIK module definition */ +const struct fwk_module module_system_pik = { + .type = FWK_MODULE_TYPE_DRIVER, + .init = mod_system_pik_init, + .start = mod_system_pik_start, +}; diff --git a/product/automotive-rd/rd1ae/product.mk b/product/automotive-rd/rd1ae/product.mk new file mode 100644 index 0000000000000000000000000000000000000000..fb857f288d16978d202206ad2ef9aac4aad813be --- /dev/null +++ b/product/automotive-rd/rd1ae/product.mk @@ -0,0 +1,10 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +BS_PRODUCT_NAME := rd1ae +BS_FIRMWARE_LIST := scp_ramfw diff --git a/product/automotive-rd/rd1ae/scp_ramfw/CMakeLists.txt b/product/automotive-rd/rd1ae/scp_ramfw/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3d09d365d16a471b4fb538263b58de76ea263117 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/CMakeLists.txt @@ -0,0 +1,65 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# cmake-lint: disable=E1122 + +# +# Create the firmware target. +# +add_executable(rd1ae-bl2) + +target_include_directories( + rd1ae-bl2 + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_SOURCE_DIR}/../include") + +target_sources( + rd1ae-bl2 + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/config_atu_mmio.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_apcontext.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_armv7m_mpu.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_atu.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_cmn_cyprus.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_gtimer.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_io_block.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_mhu3.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_noc_s3.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_pcie_setup.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_pik_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_pl011.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_power_domain.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_ppu_v1.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_safety_island_platform.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_power_domain.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_system_power.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scp_platform.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_sds.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_sid.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_system_info.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_system_pik.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_system_pll.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_system_power.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_timer.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_transport.c") + +# +# Some of our firmware includes require CMSIS. +# + +target_link_libraries(rd1ae-bl2 PUBLIC cmsis::core-m) + +# +# We explicitly add the CMSIS include directories to our interface include +# directories. Each module target adds these include directories to their own, +# allowing them to include any firmware includes we expose. +# + +target_include_directories( + rd1ae-bl2 + PUBLIC $) diff --git a/product/automotive-rd/rd1ae/scp_ramfw/Firmware.cmake b/product/automotive-rd/rd1ae/scp_ramfw/Firmware.cmake new file mode 100644 index 0000000000000000000000000000000000000000..cc1bcfa35d7e703380186f6da6dacc7fd5dfcb34 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/Firmware.cmake @@ -0,0 +1,76 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# +# Configure the build system. +# + +set(SCP_FIRMWARE "rd1ae-bl2") + +set(SCP_FIRMWARE_TARGET "rd1ae-bl2") + +set(SCP_TOOLCHAIN_INIT "GNU") + +set(SCP_GENERATE_FLAT_BINARY_INIT TRUE) + +set(SCP_ENABLE_NOTIFICATIONS_INIT TRUE) + +# Disable Interprocedural optimization +set(SCP_ENABLE_IPO_INIT FALSE) + +set(SCP_ARCHITECTURE "arm-m") + +set(SCP_ENABLE_NEWLIB_NANO FALSE) + +set(SCP_ENABLE_OUTBAND_MSG_SUPPORT TRUE) + +set(SCP_ENABLE_SCMI_NOTIFICATIONS TRUE) + +set(SCP_ENABLE_ATU_MANAGE TRUE) + +list(PREPEND SCP_MODULE_PATHS + "${CMAKE_CURRENT_LIST_DIR}/../module/io_block" + "${CMAKE_CURRENT_LIST_DIR}/../module/pcie_discovery" + "${CMAKE_CURRENT_LIST_DIR}/../module/pcie_setup" + "${CMAKE_CURRENT_LIST_DIR}/../module/safety_island_platform" + "${CMAKE_CURRENT_LIST_DIR}/../module/scp_platform" + "${CMAKE_CURRENT_LIST_DIR}/../module/system_pik") + + +# The order of the modules in the following list is the order in which the +# modules are initialized, bound, started during the pre-runtime phase. +# Any change in the order will cause firmware initialization errors. +list(APPEND SCP_MODULES "armv7m-mpu") +list(APPEND SCP_MODULES "pl011") +list(APPEND SCP_MODULES "atu") +list(APPEND SCP_MODULES "noc-s3") +list(APPEND SCP_MODULES "atu-mmio") +list(APPEND SCP_MODULES "system-pik") +list(APPEND SCP_MODULES "ppu-v1") +list(APPEND SCP_MODULES "system-power") +list(APPEND SCP_MODULES "power-domain") +list(APPEND SCP_MODULES "system-pll") +list(APPEND SCP_MODULES "pik-clock") +list(APPEND SCP_MODULES "clock") +list(APPEND SCP_MODULES "gtimer") +list(APPEND SCP_MODULES "timer") +list(APPEND SCP_MODULES "cmn-cyprus") +list(APPEND SCP_MODULES "mhu3") +list(APPEND SCP_MODULES "transport") +list(APPEND SCP_MODULES "pcid") +list(APPEND SCP_MODULES "sid") +list(APPEND SCP_MODULES "system-info") +list(APPEND SCP_MODULES "apcontext") +list(APPEND SCP_MODULES "scmi") +list(APPEND SCP_MODULES "sds") +list(APPEND SCP_MODULES "scmi-power-domain") +list(APPEND SCP_MODULES "scmi-system-power") +list(APPEND SCP_MODULES "io-block") +list(APPEND SCP_MODULES "pcie_discovery") +list(APPEND SCP_MODULES "pcie-setup") +list(APPEND SCP_MODULES "scp-platform") +list(APPEND SCP_MODULES "safety-island-platform") diff --git a/product/automotive-rd/rd1ae/scp_ramfw/Toolchain-ArmClang.cmake b/product/automotive-rd/rd1ae/scp_ramfw/Toolchain-ArmClang.cmake new file mode 100755 index 0000000000000000000000000000000000000000..2ab30d85024e75702ada74add5adb0c5ff60a28d --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/Toolchain-ArmClang.cmake @@ -0,0 +1,17 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include_guard() + +set(CMAKE_SYSTEM_PROCESSOR "cortex-m7") + +set(CMAKE_ASM_COMPILER_TARGET "arm-arm-none-eabi") +set(CMAKE_C_COMPILER_TARGET "arm-arm-none-eabi") +set(CMAKE_CXX_COMPILER_TARGET "arm-arm-none-eabi") + +set(CMAKE_TOP_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../..") +include("${CMAKE_TOP_DIR}/cmake/Toolchain/ArmClang-Baremetal.cmake") diff --git a/product/automotive-rd/rd1ae/scp_ramfw/Toolchain-Clang.cmake b/product/automotive-rd/rd1ae/scp_ramfw/Toolchain-Clang.cmake new file mode 100644 index 0000000000000000000000000000000000000000..0d52f02816e4dd4638df817908977f9facecb881 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/Toolchain-Clang.cmake @@ -0,0 +1,17 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include_guard() + +set(CMAKE_SYSTEM_PROCESSOR "cortex-m7") + +set(CMAKE_ASM_COMPILER_TARGET "arm-arm-none-eabi") +set(CMAKE_C_COMPILER_TARGET "arm-arm-none-eabi") +set(CMAKE_CXX_COMPILER_TARGET "arm-arm-none-eabi") + +set(CMAKE_TOP_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../..") +include("${CMAKE_TOP_DIR}/cmake/Toolchain/Clang-Baremetal.cmake") diff --git a/product/automotive-rd/rd1ae/scp_ramfw/Toolchain-GNU.cmake b/product/automotive-rd/rd1ae/scp_ramfw/Toolchain-GNU.cmake new file mode 100755 index 0000000000000000000000000000000000000000..62d475fac140bac1d0517d7d076b39c2a61af26e --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/Toolchain-GNU.cmake @@ -0,0 +1,18 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include_guard() + +set(CMAKE_SYSTEM_PROCESSOR "cortex-m7") +set(CMAKE_TOOLCHAIN_PREFIX "arm-none-eabi-") + +set(CMAKE_ASM_COMPILER_TARGET "arm-none-eabi") +set(CMAKE_C_COMPILER_TARGET "arm-none-eabi") +set(CMAKE_CXX_COMPILER_TARGET "arm-none-eabi") + +set(CMAKE_TOP_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../..") +include("${CMAKE_TOP_DIR}/cmake/Toolchain/GNU-Baremetal.cmake") diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_apcontext.c b/product/automotive-rd/rd1ae/scp_ramfw/config_apcontext.c new file mode 100644 index 0000000000000000000000000000000000000000..833224195f286c190b49fd33074a72920247c5ac --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_apcontext.c @@ -0,0 +1,36 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'apcontext'. + */ + +#include "scp_clock.h" +#include "scp_fw_mmap.h" + +#include +#include + +#include +#include +#include + +static const struct mod_apcontext_config apcontext_data = { + .base = SCP_AP_CONTEXT_BASE, + .size = SCP_AP_CONTEXT_SIZE, + .clock_id = FWK_ID_NONE_INIT, + .platform_notification = { + .notification_id = FWK_ID_NOTIFICATION_INIT( + FWK_MODULE_IDX_SCP_PLATFORM, + MOD_SCP_PLATFORM_NOTIFICATION_IDX_SUBSYS_INITIALIZED), + .source_id = FWK_ID_MODULE_INIT( + FWK_MODULE_IDX_SCP_PLATFORM), + }, +}; + +struct fwk_module_config config_apcontext = { + .data = &apcontext_data, +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_armv7m_mpu.c b/product/automotive-rd/rd1ae/scp_ramfw/config_armv7m_mpu.c new file mode 100644 index 0000000000000000000000000000000000000000..0f0243f392c72d81846b1f50743b19eafcfd52e9 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_armv7m_mpu.c @@ -0,0 +1,84 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'armv7m_mpu'. + */ + +#include "scp_fw_mmap.h" +#include "scp_mmap.h" + +#include + +#include +#include + +#define SCP_MPU_REGION_COUNT 4 + +static const ARM_MPU_Region_t regions[SCP_MPU_REGION_COUNT] = { + { + /* 0x0000_0000 - 0xFFFF_FFFF */ + .RBAR = ARM_MPU_RBAR(0x0UL, 0x00000000UL), + .RASR = ARM_MPU_RASR( + 1, + ARM_MPU_AP_PRIV, + 0, + 1, + 0, + 1, + 0, + ARM_MPU_REGION_SIZE_4GB), + }, + { + /* 0x0000_0000 - 0x0003_FFFF */ + .RBAR = ARM_MPU_RBAR(0x1UL, SCP_ITC_RAM_BASE), + .RASR = ARM_MPU_RASR( + 0, + ARM_MPU_AP_PRO, + 0, + 0, + 1, + 0, + 0, + ARM_MPU_REGION_SIZE_256KB), + }, + { + /* 0x2000_0000 - 0x2003_FFFF */ + .RBAR = ARM_MPU_RBAR(0x2UL, SCP_DTC_RAM_BASE), + .RASR = ARM_MPU_RASR( + 1, + ARM_MPU_AP_PRIV, + 0, + 0, + 1, + 1, + 0, + ARM_MPU_REGION_SIZE_256KB), + }, + { + /* + * 0x7000_0000 - 0x7000_1FFF + * This is mapped to 0x0000_0000 - 0x0000_1FFF in AP memory map. + */ + .RBAR = ARM_MPU_RBAR(0x3UL, SCP_AP_PERIPHERAL_SRAM_TRUSTED_BASE), + .RASR = ARM_MPU_RASR( + 1, + ARM_MPU_AP_PRIV, + 0, + 1, + 1, + 1, + 0, + ARM_MPU_REGION_SIZE_8KB), + }, +}; + +const struct fwk_module_config config_armv7m_mpu = { + .data = &((struct mod_armv7m_mpu_config){ + .region_count = FWK_ARRAY_SIZE(regions), + .regions = regions, + }), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_atu.c b/product/automotive-rd/rd1ae/scp_ramfw/config_atu.c new file mode 100644 index 0000000000000000000000000000000000000000..2beb4e734b8ab465de628453877409a677115034 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_atu.c @@ -0,0 +1,104 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'atu'. + */ + +#include "scp_mmap.h" + +#include +#include + +#include +#include +#include +#include +#include + +/* Indices for ATU module elements */ +enum cfgd_mod_atu_element_idx { + CFGD_MOD_ATU_EIDX_ATU0, + CFGD_MOD_ATU_EIDX_COUNT +}; + +#define MOD_ATU_ELEMENT_COUNT (CFGD_MOD_ATU_EIDX_COUNT + 1) + +/* Indices for translation regions to be configured in the ATU */ +enum atu_regions_idx { + /* ATU region to access CMN CFGM */ + ATU_REGION_IDX_CMN = 0, + /* ATU region to access AP Cluster Utility space */ + ATU_REGION_IDX_CLUSTER_UTIL, + /* ATU region to access AP shared SRAM */ + ATU_REGION_IDX_SHARED_SRAM, + /* ATU region to GPC SMMU register space */ + ATU_REGION_IDX_GPC_SMMU, + /* ATU region to RSM SRAM region */ + ATU_REGION_IDX_RSM_SRAM, + /* ATU region count */ + ATU_REGION_IDX_COUNT, +}; + +const struct atu_region_map atu_regions[ATU_REGION_IDX_COUNT] = { + [ATU_REGION_IDX_CMN] = { + .region_owner_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SCP_PLATFORM), + .log_addr_base = SCP_ATW1_CMN_BASE, + .phy_addr_base = 0x100000000ULL, + .region_size = SCP_ATW1_CMN_SIZE, + .attributes = ATU_ENCODE_ATTRIBUTES_ROOT_PAS, + }, + [ATU_REGION_IDX_CLUSTER_UTIL] = { + .region_owner_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SCP_PLATFORM), + .log_addr_base = SCP_ATW0_CLUSTER_UTILITY_BASE, + .phy_addr_base = 0x200000000ULL, + .region_size = SCP_ATW0_CLUSTER_UTILITY_SIZE, + .attributes = ATU_ENCODE_ATTRIBUTES_ROOT_PAS, + }, + [ATU_REGION_IDX_SHARED_SRAM] = { + .region_owner_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SCP_PLATFORM), + .log_addr_base = SCP_ATW0_AP_PERIPHERAL_SRAM_BASE, + .phy_addr_base = 0x00000000ULL, + .region_size = SCP_ATW0_AP_PERIPHERAL_SRAM_SIZE, + .attributes = ATU_ENCODE_ATTRIBUTES_ROOT_PAS, + }, + [ATU_REGION_IDX_GPC_SMMU] = { + .region_owner_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SCP_PLATFORM), + .log_addr_base = SCP_ATW0_AP_PERIPHERAL_GPC_SMMU_BASE, + .phy_addr_base = 0x300000000ULL, + .region_size = SCP_ATW0_AP_PERIPHERAL_GPC_SMMU_SIZE, + .attributes = ATU_ENCODE_ATTRIBUTES_ROOT_PAS, + }, + [ATU_REGION_IDX_RSM_SRAM] = { + .region_owner_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SCP_PLATFORM), + .log_addr_base = SCP_ATW0_SHARED_SRAM_RSM_BASE, + .phy_addr_base = 0x2F000000ULL, + .region_size = SCP_ATW0_SHARED_SRAM_RSM_SIZE, + .attributes = ATU_ENCODE_ATTRIBUTES_SECURE_PAS, + }, +}; + +static const struct fwk_element element_table[MOD_ATU_ELEMENT_COUNT] = { + [CFGD_MOD_ATU_EIDX_ATU0] = { + .name = "SCP_ATU", + .data = &(struct mod_atu_device_config) { + .is_atu_delegated = false, + .atu_base = SCP_ATU_BASE, + .atu_region_config_table = atu_regions, + .atu_region_count = FWK_ARRAY_SIZE(atu_regions), + }, + }, + [CFGD_MOD_ATU_EIDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_atu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_element_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_atu_mmio.c b/product/automotive-rd/rd1ae/scp_ramfw/config_atu_mmio.c new file mode 100644 index 0000000000000000000000000000000000000000..aec8a480e70e9bd8d4f1c0df8d3c419e0655bc8c --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_atu_mmio.c @@ -0,0 +1,29 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'atu_mmio'. + */ + +#include "scp_mmap.h" + +#include +#include + +#include +#include +#include + +static struct mod_atu_mmio_config atu_mmio_module_config = { + .window_address = SCP_ATW0_ATU_MMIO_BASE, + .map_size = SCP_ATW0_ATU_MMIO_SIZE, + .atu_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_ATU, 0), + .atu_api_id = FWK_ID_API(FWK_MODULE_IDX_ATU, MOD_ATU_API_IDX_ATU), +}; + +struct fwk_module_config config_atu_mmio = { + .data = &atu_mmio_module_config, +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_clock.c b/product/automotive-rd/rd1ae/scp_ramfw/config_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..f67435573d85b215f4743a327cd1977a0bbfe94e --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_clock.c @@ -0,0 +1,103 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'clock'. + */ + +#include "platform_core.h" +#include "scp_cfgd_power_domain.h" +#include "scp_clock.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Module 'clock' element count */ +#define MOD_CLOCK_ELEMENT_COUNT (CFGD_MOD_CLOCK_EIDX_COUNT + 1) + +/* + * Helper macro to instantiate 'clock' module element config data. + */ +#define CFGD_MOD_CLOCK_ELEMENT_CPU(n) \ + [CFGD_MOD_CLOCK_EIDX_CPU##n] = { \ + .name = "CPU" #n, \ + .data = &((struct mod_clock_dev_config){ \ + .driver_id = FWK_ID_ELEMENT_INIT( \ + FWK_MODULE_IDX_PIK_CLOCK, CFGD_MOD_PIK_CLOCK_EIDX_CPU##n), \ + .api_id = FWK_ID_API_INIT( \ + FWK_MODULE_IDX_PIK_CLOCK, MOD_PIK_CLOCK_API_TYPE_CLOCK), \ + .default_on = true, \ + }), \ + } + +/* + * Module 'clock' element configuration data. + */ +static const struct fwk_element clock_dev_table[MOD_CLOCK_ELEMENT_COUNT] = { + CFGD_MOD_CLOCK_ELEMENT_CPU(0), + CFGD_MOD_CLOCK_ELEMENT_CPU(1), + CFGD_MOD_CLOCK_ELEMENT_CPU(2), + CFGD_MOD_CLOCK_ELEMENT_CPU(3), + CFGD_MOD_CLOCK_ELEMENT_CPU(4), + CFGD_MOD_CLOCK_ELEMENT_CPU(5), + CFGD_MOD_CLOCK_ELEMENT_CPU(6), + CFGD_MOD_CLOCK_ELEMENT_CPU(7), + CFGD_MOD_CLOCK_ELEMENT_CPU(8), + CFGD_MOD_CLOCK_ELEMENT_CPU(9), + CFGD_MOD_CLOCK_ELEMENT_CPU(10), + CFGD_MOD_CLOCK_ELEMENT_CPU(11), + CFGD_MOD_CLOCK_ELEMENT_CPU(12), + CFGD_MOD_CLOCK_ELEMENT_CPU(13), + CFGD_MOD_CLOCK_ELEMENT_CPU(14), + CFGD_MOD_CLOCK_ELEMENT_CPU(15), + [CFGD_MOD_CLOCK_EIDX_CMN] = { + .name = "CMN-Cyprus", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PIK_CLOCK, + CFGD_MOD_PIK_CLOCK_EIDX_CMN), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PIK_CLOCK, + MOD_PIK_CLOCK_API_TYPE_CLOCK), + }), + }, + { 0 }, +}; + +static const struct fwk_element *clock_get_dev_desc_table(fwk_id_t module_id) +{ + unsigned int i; + + for (i = 0; i < CFGD_MOD_CLOCK_EIDX_COUNT; i++) { + struct mod_clock_dev_config *dev_config = + (struct mod_clock_dev_config *)clock_dev_table[i].data; + dev_config->pd_source_id = fwk_id_build_element_id( + fwk_module_id_power_domain, + platform_get_core_count() + platform_get_cluster_count() + + PD_STATIC_DEV_IDX_SYSTOP); + } + + return clock_dev_table; +} + +const struct fwk_module_config config_clock = { + .data = + &(struct mod_clock_config){ + .pd_transition_notification_id = FWK_ID_NOTIFICATION_INIT( + FWK_MODULE_IDX_POWER_DOMAIN, + MOD_PD_NOTIFICATION_IDX_POWER_STATE_TRANSITION), + .pd_pre_transition_notification_id = FWK_ID_NOTIFICATION_INIT( + FWK_MODULE_IDX_POWER_DOMAIN, + MOD_PD_NOTIFICATION_IDX_POWER_STATE_PRE_TRANSITION), + }, + + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(clock_get_dev_desc_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_cmn_cyprus.c b/product/automotive-rd/rd1ae/scp_ramfw/config_cmn_cyprus.c new file mode 100644 index 0000000000000000000000000000000000000000..fb97bf7807d3a0b205d888507db8482e0efdc633 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_cmn_cyprus.c @@ -0,0 +1,263 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'cmn_cyprus'. + */ + +#include "cmn_node_id.h" +#include "scp_exp_mmap.h" +#include "scp_mmap.h" + +#include + +#include +#include +#include +#include + +#include + +#define MMAP_TABLE_COUNT 17 +#define SNF_TABLE_COUNT 32 + +static const unsigned int snf_table[SNF_TABLE_COUNT] = { + MEM_CNTRL0_ID, /* Maps to HN-F logical node 0 */ + MEM_CNTRL0_ID, /* Maps to HN-F logical node 1 */ + MEM_CNTRL0_ID, /* Maps to HN-F logical node 2 */ + MEM_CNTRL0_ID, /* Maps to HN-F logical node 3 */ + MEM_CNTRL1_ID, /* Maps to HN-F logical node 4 */ + MEM_CNTRL1_ID, /* Maps to HN-F logical node 5 */ + MEM_CNTRL1_ID, /* Maps to HN-F logical node 6 */ + MEM_CNTRL1_ID, /* Maps to HN-F logical node 7 */ + MEM_CNTRL2_ID, /* Maps to HN-F logical node 8 */ + MEM_CNTRL2_ID, /* Maps to HN-F logical node 9 */ + MEM_CNTRL2_ID, /* Maps to HN-F logical node 10 */ + MEM_CNTRL2_ID, /* Maps to HN-F logical node 11 */ + MEM_CNTRL3_ID, /* Maps to HN-F logical node 12 */ + MEM_CNTRL3_ID, /* Maps to HN-F logical node 13 */ + MEM_CNTRL3_ID, /* Maps to HN-F logical node 14 */ + MEM_CNTRL3_ID, /* Maps to HN-F logical node 15 */ + MEM_CNTRL4_ID, /* Maps to HN-F logical node 16 */ + MEM_CNTRL4_ID, /* Maps to HN-F logical node 17 */ + MEM_CNTRL4_ID, /* Maps to HN-F logical node 18 */ + MEM_CNTRL4_ID, /* Maps to HN-F logical node 19 */ + MEM_CNTRL5_ID, /* Maps to HN-F logical node 20 */ + MEM_CNTRL5_ID, /* Maps to HN-F logical node 21 */ + MEM_CNTRL5_ID, /* Maps to HN-F logical node 22 */ + MEM_CNTRL5_ID, /* Maps to HN-F logical node 23 */ + MEM_CNTRL6_ID, /* Maps to HN-F logical node 24 */ + MEM_CNTRL6_ID, /* Maps to HN-F logical node 25 */ + MEM_CNTRL6_ID, /* Maps to HN-F logical node 26 */ + MEM_CNTRL6_ID, /* Maps to HN-F logical node 27 */ + MEM_CNTRL7_ID, /* Maps to HN-F logical node 28 */ + MEM_CNTRL7_ID, /* Maps to HN-F logical node 29 */ + MEM_CNTRL7_ID, /* Maps to HN-F logical node 30 */ + MEM_CNTRL7_ID, /* Maps to HN-F logical node 31 */ +}; + +static const struct mod_cmn_cyprus_mem_region_map mmap[MMAP_TABLE_COUNT] = { + { + /* + * System cache backed region + * Map: 0x0000_0000_0000 - 0xFFFF_FFFF_FFFF (256 TiB) + */ + .base = UINT64_C(0x000000000000), + .size = UINT64_C(256) * FWK_TIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_SYSCACHE, + .hns_pos_start = { 0, 0, 0 }, + .hns_pos_end = { MESH_SIZE_X - 1, MESH_SIZE_Y - 1, 1 }, + }, + { + /* + * Shared SRAM + * Map: 0x0000_0000_0000 - 0x0000_07FF_FFFF (128 MB) + */ + .base = UINT64_C(0x000000000000), + .size = UINT64_C(128) * FWK_MIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_SYSCACHE_SUB, + .node_id = NODE_ID_SBSX, + }, + { + /* + * Boot Flash + * Map: 0x00_0800_0000 - 0x00_0FFF_FFFF (128 MB) + */ + .base = UINT64_C(0x0008000000), + .size = UINT64_C(128) * FWK_MIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_IO, + .node_id = NODE_ID_HNT1, + }, + { + /* + * Peripherals + * Map: 0x00_1000_0000 - 0x00_2EFF_FFFF (496 MB) + */ + .base = UINT64_C(0x0010000000), + .size = UINT64_C(496) * FWK_MIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_IO, + .node_id = NODE_ID_HND, + }, + { + /* + * Shared SRAM + * Map: 0x00_2F00_0000 - 0x00_2F3F_FFFF (4 MB) + */ + .base = UINT64_C(0x002F000000), + .size = UINT64_C(4) * FWK_MIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_SYSCACHE_SUB, + .node_id = NODE_ID_SBSX, + }, + { + /* + * Peripherals + * Map: 0x00_2F40_0000 - 0x00_5FFF_FFFF (780 MB) + */ + .base = UINT64_C(0x002F400000), + .size = UINT64_C(780) * FWK_MIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_IO, + .node_id = NODE_ID_HND, + }, + { + /* + * CMN_CYPRUS GPV + * Map: 0x01_0000_0000 - 0x01_3FFF_FFFF (1 GB) + */ + .base = UINT64_C(0x0100000000), + .size = UINT64_C(1) * FWK_GIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_IO, + .node_id = NODE_ID_HND, + }, + { + /* + * Cluster Utility Memory region + * Map: 0x2_0000_0000 - 0x2_3FFF_FFFF (1 GB) + */ + .base = UINT64_C(0x200000000), + .size = UINT64_C(1) * FWK_GIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_IO, + .node_id = NODE_ID_HND, + }, + { + /* + * Peripherals - Memory Controller + * Map: 0x2_4000_0000 - 0x2_4FFF_FFFF (256 MB) + */ + .base = UINT64_C(0x240000000), + .size = UINT64_C(256) * FWK_MIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_IO, + .node_id = NODE_ID_HND, + }, + { + /* + * Peripherals, NCI GPV Memory Map 0 + * Map: 0x02_8000_0000 - 0x02_87FF_FFFF (128 MB) + */ + .base = UINT64_C(0x0280000000), + .size = UINT64_C(128) * FWK_MIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_IO, + .node_id = IOVB_NODE_ID0, + }, + { + /* + * Peripherals, NCI GPV Memory Map 1 + * Map: 0x02_8800_0000 - 0x02_8FFF_FFFF (128 MB) + */ + .base = UINT64_C(0x0288000000), + .size = UINT64_C(128) * FWK_MIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_IO, + .node_id = IOVB_NODE_ID1, + }, + { + /* + * Peripherals, NCI GPV Memory Map 2 + * Map: 0x02_9000_0000 - 0x02_97FF_FFFF (128 MB) + */ + .base = UINT64_C(0x0290000000), + .size = UINT64_C(128) * FWK_MIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_IO, + .node_id = IOVB_NODE_ID2, + }, + { + /* + * Peripherals, NCI GPV Memory Map 3 + * Map: 0x02_9800_0000 - 0x02_9FFF_FFFF (128 MB) + */ + .base = UINT64_C(0x0298000000), + .size = UINT64_C(128) * FWK_MIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_IO, + .node_id = IOVB_NODE_ID3, + }, + { + /* + * Peripherals, NCI GPV Memory Map 4 + * Map: 0x02_A000_0000 - 0x02_A7FF_FFFF (128 MB) + */ + .base = UINT64_C(0x02A0000000), + .size = UINT64_C(128) * FWK_MIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_IO, + .node_id = IOVB_NODE_ID4, + }, + { + /* + * GPC_SMMU region + * Map: 0x03_0000_0000 - 0x03_07FF_FFFF (128 MB) + */ + .base = UINT64_C(0x300000000), + .size = UINT64_C(128) * FWK_MIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_IO, + .node_id = NODE_ID_HND, + }, + { + /* + * Non Secure NOR Flash 0/1 + * Map: 0x06_0000_0000 - 0x06_07FF_FFFF (128 MB) + */ + .base = UINT64_C(0x0600000000), + .size = UINT64_C(128) * FWK_MIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_IO, + .node_id = NODE_ID_HND, + }, + { + /* + * Ethernet Controller PL91x + * Map: 0x06_0C00_0000 - 0x06_0FFF_FFFF (64 MB) + */ + .base = UINT64_C(0x060C000000), + .size = UINT64_C(64) * FWK_MIB, + .type = MOD_CMN_CYPRUS_MEM_REGION_TYPE_IO, + .node_id = NODE_ID_HND, + }, +}; + +static struct mod_cmn_cyprus_config cmn_config_table[1] = { + [0] = { + .periphbase = SCP_CMN_BASE, + .mesh_size_x = MESH_SIZE_X, + .mesh_size_y = MESH_SIZE_Y, + .mmap_table = mmap, + .mmap_count = FWK_ARRAY_SIZE(mmap), + .hns_cal_mode = true, + .hnf_sam_config = { + .snf_table = snf_table, + .snf_count = FWK_ARRAY_SIZE(snf_table), + .hnf_sam_mode = MOD_CMN_CYPRUS_HNF_SAM_MODE_DIRECT_MAPPING, + }, + .rnsam_scg_config = { + .scg_hashing_mode = MOD_CMN_CYPRUS_RNSAM_SCG_POWER_OF_TWO_HASHING, + }, + }, +}; + +static struct mod_cmn_cyprus_config_table cmn_config_data = { + .chip_config_data = cmn_config_table, + .chip_count = 1U, + .timer_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_TIMER, 0), +}; + +const struct fwk_module_config config_cmn_cyprus = { + .data = (void *)&cmn_config_data, +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_gtimer.c b/product/automotive-rd/rd1ae/scp_ramfw/config_gtimer.c new file mode 100644 index 0000000000000000000000000000000000000000..7b33857964be7178802221917d59def54f1c7bde --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_gtimer.c @@ -0,0 +1,69 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'gtimer'. + */ + +#include "scp_mmap.h" +#include "syscnt_impdef.h" + +#include + +#include +#include +#include +#include +#include + +#define MOD_GTIMER_ELEMENT_COUNT 2 + +/* REF_CLK input clock speed */ +#define CLOCK_RATE_REFCLK (100UL * FWK_MHZ) + +/* + * System Counter per-tick increment value required for 100MHz clock speed as + * required for SBSA compliance. That is, (100MHz / CLOCK_RATE_REFCLK) = 1. + */ +#define SYSCNT_INCR 1 + +/* + * System counter implementation defined register config data. + */ +static struct mod_gtimer_syscounter_impdef_config syscnt_impdef_cfg[2] = { + [0] = { + .offset = RD1AE_SYSCNT_IMPDEF0_CNTENCR, + .value = 0, + }, + [1] = { + .offset = RD1AE_SYSCNT_IMPDEF0_CNTINCR, + .value = SYSCNT_INCR, + }, +}; + +/* Generic timer driver config */ +static const struct fwk_element gtimer_dev_table[MOD_GTIMER_ELEMENT_COUNT] = { + [0] = { .name = "REFCLK", + .data = &((struct mod_gtimer_dev_config){ + .hw_timer = SCP_REFCLK_CNTBASE0_BASE, + .hw_counter = SCP_REFCLK_CNTCTL_BASE, + .control = SCP_REFCLK_CNTCONTROL_BASE, + .frequency = (CLOCK_RATE_REFCLK * SYSCNT_INCR), + .clock_id = FWK_ID_NONE_INIT, + .syscnt_impdef_cfg = syscnt_impdef_cfg, + .syscnt_impdef_cfg_cnt = FWK_ARRAY_SIZE(syscnt_impdef_cfg), + }) }, + [1] = { 0 }, +}; + +const struct fwk_module_config config_gtimer = { + .elements = FWK_MODULE_STATIC_ELEMENTS_PTR(gtimer_dev_table), +}; + +struct fwk_time_driver fmw_time_driver(const void **ctx) +{ + return mod_gtimer_driver(ctx, config_gtimer.elements.table[0].data); +} diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_io_block.c b/product/automotive-rd/rd1ae/scp_ramfw/config_io_block.c new file mode 100644 index 0000000000000000000000000000000000000000..2e18b2840d0eaf0f3791176fc95ddf8e82fe51d3 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_io_block.c @@ -0,0 +1,86 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'io_block'. + */ + +#include "io_macro_layout.h" +#include "scp_fw_mmap.h" +#include "scp_mmap.h" + +#include +#include +#include +#include + +#include +#include +#include + +#define IO_MACRO_ELEMENT_CONFIG(idx) \ + { \ + .name = "IO Macro " #idx, \ + .data = &((struct mod_io_block_element_config){ \ + .region_mem_maps_count = 2, \ + .region_mem_maps = ((struct interface_io_block_setup_mmap[2]){ \ + [0] = { .io_block_address = NCI_GVP_BLOCK_BASE(idx), \ + .source_id = ASNI_CMN, \ + .region_count = 1, \ + .carveout_info = \ + &((struct interface_io_block_carveout_info){ \ + .base = TCU_REG_BASE(idx), \ + .size = TCU_REG_SIZE, \ + .target_id = AMNI_PMNI_TCU_APB, \ + .region_id = 0, \ + }) }, \ + [1] = { .io_block_address = NCI_GVP_BLOCK_BASE(idx), \ + .source_id = ASNI_CMN, \ + .region_count = 1, \ + .carveout_info = \ + &((struct interface_io_block_carveout_info){ \ + .base = CTRL_REG_BASE(idx), \ + .size = CTRL_REG_SIZE, \ + .target_id = AMNI_PMNI_CTRL_REG_APB, \ + .region_id = 0, \ + }) }, \ + }), \ + }) \ + } + +static struct mod_io_block_config io_block_module_config = { + .nci_id = FWK_ID_MODULE(FWK_MODULE_IDX_NOC_S3), + .nci_api_id = + FWK_ID_API(FWK_MODULE_IDX_NOC_S3, MOD_NOC_S3_API_SETUP_PSAM), + .atu_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_ATU, 0), + .atu_api_id = FWK_ID_API(FWK_MODULE_IDX_ATU, MOD_ATU_API_IDX_ATU), + .plat_notification = { + .notification_id = FWK_ID_NOTIFICATION_INIT( + FWK_MODULE_IDX_SCP_PLATFORM, + MOD_SCP_PLATFORM_NOTIFICATION_IDX_SUBSYS_INITIALIZED), + .source_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SCP_PLATFORM), + }, + .logical_region_base = SCP_ATW0_AP_IO_BLOCK_NCI_BASE, + .logical_region_size = SCP_ATW0_AP_IO_BLOCK_NCI_SIZE +}; + +static const struct fwk_element io_block_element_table[5] = { + [0] = IO_MACRO_ELEMENT_CONFIG(0), + [1] = IO_MACRO_ELEMENT_CONFIG(1), + [2] = IO_MACRO_ELEMENT_CONFIG(2), + [3] = IO_MACRO_ELEMENT_CONFIG(3), + [4] = { 0 }, +}; + +static const struct fwk_element *io_block_get_element_table(fwk_id_t module_id) +{ + return io_block_element_table; +} + +struct fwk_module_config config_io_block = { + .data = &io_block_module_config, + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(io_block_get_element_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_mhu3.c b/product/automotive-rd/rd1ae/scp_ramfw/config_mhu3.c new file mode 100644 index 0000000000000000000000000000000000000000..c9fdbb375c4a8b83fba6e8c6f213c720d654bd04 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_mhu3.c @@ -0,0 +1,95 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'mhu3'. + */ + +#include "scp_cfgd_mhu3.h" +#include "scp_mmap.h" + +#include + +#include +#include +#include + +#include + +#define MOD_MHU3_ELEMENT_COUNT (SCP_CFGD_MOD_MHU3_EIDX_COUNT + 1) + +/* + * Timeout to wait for the receiver to clear the MHUv3 channel status + * register so the channel can become available again. + */ +#define RESP_WAIT_TIMEOUT_US (30 * 1000) + +/* AP<-->SCP Secure MHUv3 doorbell channel configuration */ +struct mod_mhu3_channel_config scp2ap_s_dbch_config[1] = { + /* PBX CH 0, FLAG 0, MBX CH 0, FLAG 0 */ + [0] = MOD_MHU3_INIT_DBCH(0, 0, 0, 0), +}; + +/* SCP<-->RSE Secure MHUv3 Doorbell channel configuration */ +struct mod_mhu3_channel_config scp2rse_s_dbch_config[5] = { + /* PBX CH 0, FLAG 0, MBX CH 0, FLAG 0 */ + [0] = MOD_MHU3_INIT_DBCH(0, 0, 0, 0), + /* PBX CH 1, FLAG 0, MBX CH 1, FLAG 0, used by scp platform for shutdown */ + [1] = MOD_MHU3_INIT_DBCH(1, 0, 1, 0), + /* PBX CH 2, FLAG 0, MBX CH 2, FLAG 0, used by scp platform for SI CL0 boot + */ + [2] = MOD_MHU3_INIT_DBCH(2, 0, 2, 0), + /* PBX CH 2, FLAG 1, MBX CH 2, FLAG 1, used by scp platform for SI CL1 boot + */ + [3] = MOD_MHU3_INIT_DBCH(2, 1, 2, 1), + /* PBX CH 2, FLAG 2, MBX CH 2, FLAG 2, used by scp platform for SI CL2 boot + */ + [4] = MOD_MHU3_INIT_DBCH(2, 2, 2, 2), +}; + +/* AP<-->SCP Secure MHUv3 doorbell channel count */ +#define SCP2AP_S_DBCH_COUNT FWK_ARRAY_SIZE(scp2ap_s_dbch_config) + +/* SCP<-->RSE Secure MHUv3 Doorbell channel count */ +#define SCP2RSE_S_DBCH_COUNT FWK_ARRAY_SIZE(scp2rse_s_dbch_config) + +/* Module element table */ +static const struct fwk_element mhu_element_table[MOD_MHU3_ELEMENT_COUNT] = { + [SCP_CFGD_MOD_MHU3_EIDX_SCP_AP_S] = { + .name = "SCP2AP_S_MHU_DBCH", + .sub_element_count = SCP2AP_S_DBCH_COUNT, + .data = &(struct mod_mhu3_device_config) { + .irq = (unsigned int) MHU3_AP2SCP_IRQ_S, + .in = SCP_AP2SCP_MHUV3_RCV_S_BASE, + .out = SCP_SCP2AP_MHUV3_SEND_S_BASE, + .channels = &scp2ap_s_dbch_config[0], + .timer_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_TIMER, 0), + .resp_wait_timeout_us = RESP_WAIT_TIMEOUT_US, + }, + }, + [SCP_CFGD_MOD_MHU3_EIDX_SCP_RSE_S] = { + .name = "SCP2RSE_S_MHU_DBCH", + .sub_element_count = SCP2RSE_S_DBCH_COUNT, + .data = &(struct mod_mhu3_device_config) { + .irq = (unsigned int) MHU3_RSE2SCP_IRQ_S, + .in = SCP_RSE2SCP_MHUV3_RCV_S_BASE, + .out = SCP_SCP2RSE_MHUV3_SEND_S_BASE, + .channels = &scp2rse_s_dbch_config[0], + .timer_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_TIMER, 0), + .resp_wait_timeout_us = RESP_WAIT_TIMEOUT_US, + }, + }, + [SCP_CFGD_MOD_MHU3_EIDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *get_element_table(fwk_id_t module_id) +{ + return mhu_element_table; +} + +struct fwk_module_config config_mhu3 = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_element_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_noc_s3.c b/product/automotive-rd/rd1ae/scp_ramfw/config_noc_s3.c new file mode 100644 index 0000000000000000000000000000000000000000..307218ab5634068bf5b2bb3049b93aac8e3c6c79 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_noc_s3.c @@ -0,0 +1,18 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'noc_s3'. + */ + +#include + +#include +#include + +struct fwk_module_config config_noc_s3 = { + .elements = FWK_MODULE_STATIC_ELEMENTS({ { 0 } }) +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_pcie_setup.c b/product/automotive-rd/rd1ae/scp_ramfw/config_pcie_setup.c new file mode 100644 index 0000000000000000000000000000000000000000..0d4bc5e4f78cde43735eb4aaf621cb11d13efa24 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_pcie_setup.c @@ -0,0 +1,143 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "cmn_node_id.h" +#include "io_macro_layout.h" +#include "scp_cfgd_sds.h" +#include "scp_fw_mmap.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/* PCIe ECAM and MMIO addresses */ +#define ECAM_SIZE (UINT64_C(256) * FWK_MIB) +#define CHIP_ECAM_OFFSET(idx) (idx * ECAM_SIZE) +#define CHIP_ECAM_BASE_ADDRESS(idx) (0x4000000000ULL + CHIP_ECAM_OFFSET(idx)) + +#define MMIOH_SIZE (UINT64_C(64) * FWK_GIB) +#define CHIP_MMIOH_OFFSET(idx) (idx * MMIOH_SIZE) +#define CHIP_MMIOH_BASE_ADDRESS(idx) (0x4040000000ULL + CHIP_MMIOH_OFFSET(idx)) +#define CHIP_PCIE_BUS_SIZE 256 +#define CHIP_PCIE_MMIOL_SIZE (0x20000000UL) +#define CHIP0_PCIE_MMIOL_BASE (0x60000000UL) +#define CHIP1_PCIE_MMIOL_BASE (CHIP0_PCIE_MMIOL_BASE + CHIP_PCIE_MMIOL_SIZE) +#define CHIP2_PCIE_MMIOL_BASE (CHIP1_PCIE_MMIOL_BASE + CHIP_PCIE_MMIOL_SIZE) +#define NUMBER_OF_ENDPOINTS 5 +#define NUMBER_OF_CHIPS 1 + +#define CHIP_MEMMAP(idx) \ + { \ + .mmap = { \ + .ecam = { \ + .start = CHIP_ECAM_BASE_ADDRESS(idx), \ + .size = ECAM_SIZE, \ + }, \ + .mmiol = { \ + .start = CHIP##idx##_PCIE_MMIOL_BASE, \ + .size = CHIP_PCIE_MMIOL_SIZE, \ + }, \ + .mmioh = { \ + .start = CHIP_MMIOH_BASE_ADDRESS(idx), \ + .size = MMIOH_SIZE \ + }, \ + .bus = { \ + .start = 0, \ + .size = CHIP_PCIE_BUS_SIZE \ + } \ + }, \ + .cmn_id = FWK_ID_MODULE(FWK_MODULE_IDX_CMN_CYPRUS), \ + .io_block_id = FWK_ID_MODULE(FWK_MODULE_IDX_IO_BLOCK), \ + .cmn_api_id = FWK_ID_API(FWK_MODULE_IDX_CMN_CYPRUS, \ + MOD_CMN_CYPRUS_API_IDX_MAP_IO_REGION), \ + .io_block_api_id = FWK_ID_API(FWK_MODULE_IDX_IO_BLOCK, \ + MOD_IO_BLOCK_API_IDX_MAP_REGION), \ + .atu_mmio_id = FWK_ID_MODULE(FWK_MODULE_IDX_ATU_MMIO), \ + .atu_mmio_api_id = FWK_ID_API(FWK_MODULE_IDX_ATU_MMIO, \ + MOD_ATU_MMIO_API_IDX_MEM_RW),\ + .plat_notification = { \ + .notification_id = FWK_ID_NOTIFICATION_INIT( \ + FWK_MODULE_IDX_SCP_PLATFORM, \ + MOD_SCP_PLATFORM_NOTIFICATION_IDX_SUBSYS_INITIALIZED), \ + .source_id = FWK_ID_MODULE_INIT( \ + FWK_MODULE_IDX_SCP_PLATFORM), \ + }, \ + .ep_count = NUMBER_OF_ENDPOINTS, \ + .ep_interrupt_ids = ((uint64_t [NUMBER_OF_ENDPOINTS]) { \ + [0] = 0, \ + [1] = 0x10000U, \ + [2] = 0x20000U, \ + [3] = 0x30000U, \ + [4] = 0x40000U, \ + }), \ + } + +#define IO_MACRO_EP_CONFIG(x1_en, x20_en, x21_en, x4_en, x8_en) \ + ((struct mod_pcie_setup_ep_config[NUMBER_OF_ENDPOINTS]){ \ + [0] = { .valid = x8_en, \ + .allow_ns_access = true, \ + .rp_node_id = AMNI_PCIEX8_0 }, \ + [1] = { .valid = x4_en, \ + .allow_ns_access = true, \ + .rp_node_id = AMNI_PCIEX4_0 }, \ + [2] = { .valid = x21_en, \ + .allow_ns_access = true, \ + .rp_node_id = AMNI_PCIEX2_1 }, \ + [3] = { .valid = x20_en, \ + .allow_ns_access = true, \ + .rp_node_id = AMNI_PCIEX2_0 }, \ + [4] = { .valid = x1_en, \ + .allow_ns_access = true, \ + .rp_node_id = AMNI_PCIEX1_0 }, \ + }) + +#define IO_MACRO_PCIE_ELEMENT_CONFIG(idx, x1_en, x20_en, x21_en, x4_en, x8_en) \ + { \ + .name = "IO Macro " #idx, \ + .data = &((struct mod_pcie_setup_config){ \ + .reg_base = NCI_GVP_BLOCK_BASE(idx), \ + .cmn_node_id = IOVB_NODE_ID##idx, \ + .nci_source_node_id = ASNI_CMN, \ + .block_id = idx, \ + .smmu_base = TCU_REG_BASE(idx), \ + .sds_struct_id = SDS_PCIE_MMAP, \ + .ep_config = \ + IO_MACRO_EP_CONFIG(x1_en, x20_en, x21_en, x4_en, x8_en) }) \ + } + +static const struct fwk_element pcie_setup_element_table[2] = { + [0] = IO_MACRO_PCIE_ELEMENT_CONFIG(0, true, true, true, true, true), + + [1] = { 0 }, +}; + +static struct mod_pcie_setup_resource_info resource_info = CHIP_MEMMAP(0); + +static const struct mod_pcie_setup_module_config module_config = { + .resource_info_count = NUMBER_OF_CHIPS, + .resource_info = (struct mod_pcie_setup_resource_info *)&resource_info, +}; + +static const struct fwk_element *pcie_setup_get_element_table( + fwk_id_t module_id) +{ + return pcie_setup_element_table; +} + +struct fwk_module_config config_pcie_setup = { + .data = &module_config, + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(pcie_setup_get_element_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_pik_clock.c b/product/automotive-rd/rd1ae/scp_ramfw/config_pik_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..5293a696f86617f42ff7317e9bc378e912eb03e1 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_pik_clock.c @@ -0,0 +1,227 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'pik_clock'. + */ + +#include "core_manager.h" +#include "scp_clock.h" +#include "scp_pwrctrl.h" +#include "system_pik.h" + +#include + +#include +#include +#include +#include + +/* Rate table count */ +#define CPU_CLK_RATE_COUNT 1 +#define INT_CLK_RATE_COUNT 1 +#define SCP_CLK_RATE_COUNT 1 +#define GIC_CLK_RATE_COUNT 1 +#define SCP_PIK_CLK_RATE_COUNT 1 +#define SYSPER_CLK_RATE_COUNT 1 +#define UART_CLK_RATE_COUNT 1 + +/* Module 'pik_clock' element count */ +#define MOD_PIK_CLOCK_ELEMENT_COUNT (CFGD_MOD_PIK_CLOCK_EIDX_COUNT + 1) + +#define CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(n) \ + [CFGD_MOD_PIK_CLOCK_EIDX_CPU##n] = { \ + .name = "PIK CLK CPU" #n, \ + .data = &((struct mod_pik_clock_dev_config){ \ + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, \ + .is_group_member = false, \ + .control_reg = \ + &SCP_CLUSTER_UTILITY_CORE_MANAGER_PTR(n)->CORECLK_CTRL, \ + .divext_reg = \ + &SCP_CLUSTER_UTILITY_CORE_MANAGER_PTR(n)->CORECLK_DIV1, \ + .rate_table = rate_table_cpu_clk, \ + .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_clk), \ + .initial_rate = 0, \ + }), \ + } + +/* CPU clock rate table */ +static const struct mod_pik_clock_rate + rate_table_cpu_clk[CPU_CLK_RATE_COUNT] = { + { + .rate = 0, + .source = MOD_PIK_CLOCK_CLUSCLK_SOURCE_PLL0, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT, + .divider = 1, + }, + }; + +/* Cache Coherent Interconnect clock rate table */ +static const struct mod_pik_clock_rate + rate_table_int_clk[INT_CLK_RATE_COUNT] = { + { + .rate = 2000 * FWK_MHZ, + .source = MOD_PIK_CLOCK_INTCLK_SOURCE_INTPLL, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT, + .divider = 1, + }, + }; + +/* SCP CORE clock rate table */ +static const struct mod_pik_clock_rate + rate_table_scp_clk[SCP_CLK_RATE_COUNT] = { + { + .rate = 800 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = CLOCK_RATE_SYSPLLCLK / (800 * FWK_MHZ), + }, + }; + +/* GIC clock rate table */ +static const struct mod_pik_clock_rate + rate_table_gic_clk[GIC_CLK_RATE_COUNT] = { + { + .rate = 1000 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = CLOCK_RATE_SYSPLLCLK / (1000 * FWK_MHZ), + }, + }; + +/* SCP PIK clock rate table */ +static const struct mod_pik_clock_rate + rate_table_scp_pik_clk[SCP_PIK_CLK_RATE_COUNT] = { + { + .rate = 400 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = CLOCK_RATE_SYSPLLCLK / (400 * FWK_MHZ), + }, + }; + +/* System Peripheral clock rate table */ +static const struct mod_pik_clock_rate + rate_table_sysper_clk[SYSPER_CLK_RATE_COUNT] = { + { + .rate = 500 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = CLOCK_RATE_SYSPLLCLK / (500 * FWK_MHZ), + }, + }; + +/* UART clock rate table */ +static const struct mod_pik_clock_rate + rate_table_uart_clk[UART_CLK_RATE_COUNT] = { + { + .rate = 250 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = CLOCK_RATE_SYSPLLCLK / (250 * FWK_MHZ), + }, + }; + +static const struct fwk_element pik_clock_table[MOD_PIK_CLOCK_ELEMENT_COUNT] = { + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(0), + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(1), + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(2), + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(3), + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(4), + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(5), + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(6), + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(7), + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(8), + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(9), + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(10), + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(11), + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(12), + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(13), + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(14), + CFGD_MOD_PIK_CLOCK_ELEMENT_CPU(15), + [CFGD_MOD_PIK_CLOCK_EIDX_CMN] = { + .name = "PIK CLK CMN", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &SYSTEM_PIK_PTR->INTCLK_CTRL, + .divext_reg = &SYSTEM_PIK_PTR->INTCLK_DIV1, + .rate_table = rate_table_int_clk, + .rate_count = FWK_ARRAY_SIZE(rate_table_int_clk), + .initial_rate = 2000 * FWK_MHZ, + }), + }, + [CFGD_MOD_PIK_CLOCK_EIDX_SCP] = { + .name = "PIK CLK SCP", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &SCP_PWRCTRL_PTR->CORECLK_CTRL, + .divsys_reg = &SCP_PWRCTRL_PTR->CORECLK_DIV1, + .rate_table = rate_table_scp_clk, + .rate_count = FWK_ARRAY_SIZE(rate_table_scp_clk), + .initial_rate = 800 * FWK_MHZ, + }), + }, + [CFGD_MOD_PIK_CLOCK_EIDX_GIC] = { + .name = "PIK CLK GIC", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &SYSTEM_PIK_PTR->GICCLK_CTRL, + .divsys_reg = &SYSTEM_PIK_PTR->GICCLK_DIV1, + .rate_table = rate_table_gic_clk, + .rate_count = FWK_ARRAY_SIZE(rate_table_gic_clk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CFGD_MOD_PIK_CLOCK_EIDX_SCP_PIK] = { + .name = "PIK CLK SCP PIK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &SYSTEM_PIK_PTR->SCPPIKCLK_CTRL, + .divsys_reg = &SYSTEM_PIK_PTR->SCPPIKCLK_DIV1, + .rate_table = rate_table_scp_pik_clk, + .rate_count = FWK_ARRAY_SIZE(rate_table_scp_pik_clk), + .initial_rate = 400 * FWK_MHZ, + }), + }, + [CFGD_MOD_PIK_CLOCK_EIDX_SYSPERCLK] = { + .name = "PIK CLK SYSPER", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &SYSTEM_PIK_PTR->SYSPERCLK_CTRL, + .divsys_reg = &SYSTEM_PIK_PTR->SYSPERCLK_DIV1, + .rate_table = rate_table_sysper_clk, + .rate_count = FWK_ARRAY_SIZE(rate_table_sysper_clk), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CFGD_MOD_PIK_CLOCK_EIDX_UARTCLK] = { + .name = "PIK CLK UART", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &SYSTEM_PIK_PTR->APUARTCLK_CTRL, + .divsys_reg = &SYSTEM_PIK_PTR->APUARTCLK_DIV1, + .rate_table = rate_table_uart_clk, + .rate_count = FWK_ARRAY_SIZE(rate_table_uart_clk), + .initial_rate = 250 * FWK_MHZ, + }), + }, + [CFGD_MOD_PIK_CLOCK_EIDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *pik_clock_get_element_table(fwk_id_t module_id) +{ + return pik_clock_table; +} + +const struct fwk_module_config config_pik_clock = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(pik_clock_get_element_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_pl011.c b/product/automotive-rd/rd1ae/scp_ramfw/config_pl011.c new file mode 100644 index 0000000000000000000000000000000000000000..7b94c4db343c21df7e9499c6c7c64d1e546dddc4 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_pl011.c @@ -0,0 +1,38 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'pl011'. + */ + +#include "scp_mmap.h" + +#include + +#include +#include +#include + +#define MOD_PL011_ELEMENT_COUNT 2 + +static const struct fwk_element pl011_table[MOD_PL011_ELEMENT_COUNT] = { + { + .name = "scp_uart", + .data = + &(struct mod_pl011_element_cfg){ + .reg_base = SCP_UART_BASE, + .baud_rate_bps = 115200, + .clock_rate_hz = 24 * FWK_MHZ, + .clock_id = FWK_ID_NONE_INIT, + .pd_id = FWK_ID_NONE_INIT, + }, + }, + { 0 }, +}; + +const struct fwk_module_config config_pl011 = { + .elements = FWK_MODULE_STATIC_ELEMENTS_PTR(pl011_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_power_domain.c b/product/automotive-rd/rd1ae/scp_ramfw/config_power_domain.c new file mode 100644 index 0000000000000000000000000000000000000000..886eab1a800b90a664c69e2dae0e5dbb7659536c --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_power_domain.c @@ -0,0 +1,299 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'power_domain'. + */ + +#include "platform_core.h" +#include "scp_cfgd_power_domain.h" + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define PD_STATIC_ELEMENT_COUNT (PD_STATIC_DEV_IDX_SYSTOP + 1) + +/* Allowed PD state count */ +#define SYSTOP_PD_STATE_COUNT 1 +#define CLUS_PD_STATE_COUNT 2 +#define CORE_PD_STATE_COUNT 2 + +/* Mask for the cluster valid power states */ +#define CLUSTER_VALID_STATE_MASK (MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK) + +/* Mask for the core valid power states */ +#define CORE_VALID_STATE_MASK (MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK) + +/* Mask of the allowed states for the systop power domain */ +static const uint32_t systop_allowed_state_mask_table[SYSTOP_PD_STATE_COUNT] = { + [0] = MOD_PD_STATE_ON_MASK +}; + +/* + * Mask of the allowed states for the cluster power domain depending on the + * system states. + */ +static const uint32_t + cluster_pd_allowed_state_mask_table[CLUS_PD_STATE_COUNT] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = CLUSTER_VALID_STATE_MASK, + }; + +/* Mask of the allowed states for a core depending on the cluster states. */ +static const uint32_t core_pd_allowed_state_mask_table[CORE_PD_STATE_COUNT] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_SLEEP_MASK, + [MOD_PD_STATE_ON] = CORE_VALID_STATE_MASK, +}; + +/* Power module specific configuration data (none) */ +static const struct mod_power_domain_config platform_power_domain_config = { + 0 +}; + +static struct fwk_element pd_static_element_table[PD_STATIC_ELEMENT_COUNT] = { + [PD_STATIC_DEV_IDX_SYSTOP] = { + .name = "SYSTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_SYSTEM, + .parent_idx = PD_STATIC_DEV_IDX_NONE, + .driver_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SYSTEM_POWER), + .api_id = FWK_ID_API_INIT( + FWK_MODULE_IDX_SYSTEM_POWER, + MOD_SYSTEM_POWER_API_IDX_PD_DRIVER), + .allowed_state_mask_table = systop_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(systop_allowed_state_mask_table) + }), + }, +}; + +static const struct fwk_element *platform_power_domain_get_element_table( + fwk_id_t module_id) +{ + const struct fwk_element *systop_elements = NULL; + const struct fwk_element *si_clus0_elements = NULL; + const struct fwk_element *si_clus1_elements = NULL; + const struct fwk_element *si_clus2_elements = NULL; + struct fwk_element *all_elements = NULL; + struct fwk_element tmp_table[1] = { 0 }; + unsigned int element_idx; + struct mod_power_domain_element_config *pd_config; + unsigned int systop_elements_count, si_clus0_elements_count, + si_clus1_elements_count, si_clus2_elements_count; + + /* Create power doamin elements for SYSTOP */ + systop_elements = create_power_domain_element_table( + platform_get_core_count(), + platform_get_cluster_count(), + FWK_MODULE_IDX_PPU_V1, + MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER, + core_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table), + cluster_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table), + pd_static_element_table, + FWK_ARRAY_SIZE(pd_static_element_table)); + + if (systop_elements == NULL) { + return NULL; + } + + /* Create power domain elements for SYSTOP_SI. + * Now 7 core in 3 cluster is supported. + */ + si_clus0_elements = create_power_domain_element_table( + 1, + 1, + FWK_MODULE_IDX_PPU_V1, + MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER, + core_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table), + cluster_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table), + tmp_table, + 0); + + if (si_clus0_elements == NULL) { + return NULL; + } + + si_clus1_elements = create_power_domain_element_table( + 2, + 1, + FWK_MODULE_IDX_PPU_V1, + MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER, + core_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table), + cluster_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table), + tmp_table, + 0); + + if (si_clus1_elements == NULL) { + return NULL; + } + + si_clus2_elements = create_power_domain_element_table( + 4, + 1, + FWK_MODULE_IDX_PPU_V1, + MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER, + core_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table), + cluster_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table), + tmp_table, + 0); + + if (si_clus2_elements == NULL) { + return NULL; + } + + systop_elements_count = platform_get_core_count() + + platform_get_cluster_count() + FWK_ARRAY_SIZE(pd_static_element_table); + + si_clus0_elements_count = 2; + si_clus1_elements_count = 3; + si_clus2_elements_count = 5; + /* Create an array for all elements */ + all_elements = fwk_mm_calloc( + systop_elements_count + si_clus0_elements_count + + si_clus1_elements_count + si_clus2_elements_count + 1, + sizeof(struct fwk_element)); + + if (all_elements == NULL) { + return NULL; + } + + /* Copy SYSTOP elements to the new array */ + fwk_str_memcpy( + all_elements, + systop_elements, + systop_elements_count * sizeof(struct fwk_element)); + /* Copy the SI_clus0 elements to the new array. + * SI elements follow SYSTOP elements. */ + fwk_str_memcpy( + all_elements + systop_elements_count, + si_clus0_elements, + si_clus0_elements_count * sizeof(struct fwk_element)); + /* Copy the SI_clus1 elements to the new array. + * SI elements follow SYSTOP elements. */ + fwk_str_memcpy( + all_elements + systop_elements_count + si_clus0_elements_count, + si_clus1_elements, + si_clus1_elements_count * sizeof(struct fwk_element)); + /* Copy the SI_clus2 elements to the new array. + * SI elements follow SYSTOP elements. */ + fwk_str_memcpy( + all_elements + systop_elements_count + si_clus0_elements_count + + si_clus1_elements_count, + si_clus2_elements, + si_clus2_elements_count * sizeof(struct fwk_element)); + + /* The parent indices of SI elements need to be updated + * because they are in a new array, their indices are not zero based. */ + + /* Update CL0CORE0 */ + element_idx = systop_elements_count; + pd_config = + (struct mod_power_domain_element_config *)all_elements[element_idx] + .data; + pd_config->parent_idx = element_idx + 1; + pd_config->driver_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, element_idx); + + /* Update CL0 */ + element_idx = element_idx + 1; + pd_config = + (struct mod_power_domain_element_config *)all_elements[element_idx] + .data; + pd_config->parent_idx = PD_STATIC_DEV_IDX_NONE; + pd_config->driver_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, element_idx); + + /* Update CL1CORE0 */ + element_idx = systop_elements_count + 2; + pd_config = + (struct mod_power_domain_element_config *)all_elements[element_idx] + .data; + pd_config->parent_idx = systop_elements_count + 4; + pd_config->driver_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, element_idx); + + /* Update CL1CORE1 */ + element_idx = systop_elements_count + 3; + pd_config = + (struct mod_power_domain_element_config *)all_elements[element_idx] + .data; + pd_config->parent_idx = systop_elements_count + 4; + pd_config->driver_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, element_idx); + + /* Update CL1 */ + element_idx = systop_elements_count + 4; + pd_config = + (struct mod_power_domain_element_config *)all_elements[element_idx] + .data; + pd_config->parent_idx = PD_STATIC_DEV_IDX_NONE; + pd_config->driver_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, element_idx); + + /* Update CL2CORE0 */ + element_idx = systop_elements_count + 5; + pd_config = + (struct mod_power_domain_element_config *)all_elements[element_idx] + .data; + pd_config->parent_idx = systop_elements_count + 9; + pd_config->driver_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, element_idx); + + /* Update CL2CORE1 */ + element_idx = systop_elements_count + 6; + pd_config = + (struct mod_power_domain_element_config *)all_elements[element_idx] + .data; + pd_config->parent_idx = systop_elements_count + 9; + pd_config->driver_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, element_idx); + + /* Update CL2CORE2 */ + element_idx = systop_elements_count + 7; + pd_config = + (struct mod_power_domain_element_config *)all_elements[element_idx] + .data; + pd_config->parent_idx = systop_elements_count + 9; + pd_config->driver_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, element_idx); + + /* Update CL2CORE3 */ + element_idx = systop_elements_count + 8; + pd_config = + (struct mod_power_domain_element_config *)all_elements[element_idx] + .data; + pd_config->parent_idx = systop_elements_count + 9; + pd_config->driver_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, element_idx); + + /* Update CL2 */ + element_idx = systop_elements_count + 9; + pd_config = + (struct mod_power_domain_element_config *)all_elements[element_idx] + .data; + pd_config->parent_idx = PD_STATIC_DEV_IDX_NONE; + pd_config->driver_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, element_idx); + + return all_elements; +} + +const struct fwk_module_config config_power_domain = { + .data = &platform_power_domain_config, + .elements = + FWK_MODULE_DYNAMIC_ELEMENTS(platform_power_domain_get_element_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_ppu_v1.c b/product/automotive-rd/rd1ae/scp_ramfw/config_ppu_v1.c new file mode 100644 index 0000000000000000000000000000000000000000..83be56595c77d23c3d1d605081723cbdca347f2e --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_ppu_v1.c @@ -0,0 +1,276 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'ppu_v1'. + */ + +#include "platform_core.h" +#include "scp_cfgd_power_domain.h" +#include "scp_mmap.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define PPU_STATIC_ELEMENT_COUNT 1 +#define PPU_CORE_NAME_SIZE 12 +#define PPU_CLUS_NAME_SIZE 7 + +/* Safety Island CPU PPU base addresses */ +#define SCP_PPU_SI_CLUS0 (0x56010000UL) +#define SCP_PPU_SI_CLUS0CORE0 (0x56040000UL) +#define SCP_PPU_SI_CLUS1 (0x56410000UL) +#define SCP_PPU_SI_CLUS1CORE0 (0x56440000UL) +#define SCP_PPU_SI_CLUS1CORE1 (0x56540000UL) +#define SCP_PPU_SI_CLUS2 (0x56810000UL) +#define SCP_PPU_SI_CLUS2CORE0 (0x56840000UL) +#define SCP_PPU_SI_CLUS2CORE1 (0x56940000UL) +#define SCP_PPU_SI_CLUS2CORE2 (0x56A40000UL) +#define SCP_PPU_SI_CLUS2CORE3 (0x56B40000UL) + +/* Module configuration data */ +static struct mod_ppu_v1_config ppu_v1_config_data = { + .pd_notification_id = FWK_ID_NOTIFICATION_INIT( + FWK_MODULE_IDX_POWER_DOMAIN, + MOD_PD_NOTIFICATION_IDX_POWER_STATE_TRANSITION), +}; + +/* List of static PPU elements */ +static struct fwk_element ppu_element_table[PPU_STATIC_ELEMENT_COUNT] = { + { + .name = "SYS0", + .data = &((struct mod_ppu_v1_pd_config){ + .pd_type = MOD_PD_TYPE_SYSTEM, + .ppu.reg_base = SCP_PPU_SYS0_BASE, + .default_power_on = true, + .observer_id = FWK_ID_NONE_INIT, + }), + }, +}; + +static const struct fwk_element *ppu_v1_get_element_table(fwk_id_t module_id) +{ + struct fwk_element *element_table; + struct mod_ppu_v1_pd_config *pd_config_table; + unsigned int cluster_idx; + unsigned int core_count; + unsigned int cluster_count; + unsigned int core_element_count = 0; + unsigned int number_elements; + int snprintf_ret_val; + + core_count = platform_get_core_count(); + cluster_count = platform_get_cluster_count(); + + /* + * Allocate element descriptors based on: + * Number of cores + * + Number of cluster descriptors + * + Number of system power domain descriptors + * + Number of SI power domain descriptors + * (10 for now: cluster0-core0, cluster0 + * cluster1-core0,1, cluster1 + * cluster2-core0-3, cluster2) + * + 1 terminator descriptor + */ + number_elements = + core_count + cluster_count + FWK_ARRAY_SIZE(ppu_element_table) + 10 + 1; + element_table = fwk_mm_calloc(number_elements, sizeof(struct fwk_element)); + + pd_config_table = fwk_mm_calloc( + core_count + cluster_count, sizeof(struct mod_ppu_v1_pd_config)); + + for (cluster_idx = 0; cluster_idx < cluster_count; cluster_idx++) { + struct fwk_element *element; + struct mod_ppu_v1_pd_config *pd_config; + unsigned int core_idx; + + for (core_idx = 0; + core_idx < platform_get_core_per_cluster_count(cluster_idx); + core_idx++) { + element = &element_table[core_element_count]; + pd_config = &pd_config_table[core_element_count]; + + element->name = fwk_mm_alloc(PPU_CORE_NAME_SIZE, 1); + + snprintf_ret_val = snprintf( + (char *)element->name, + PPU_CORE_NAME_SIZE, + "CLUS%uCORE%u", + cluster_idx, + core_idx); + + fwk_assert( + (snprintf_ret_val >= 0) && + (snprintf_ret_val <= PPU_CORE_NAME_SIZE)); + + element->data = pd_config; + + pd_config->pd_type = MOD_PD_TYPE_CORE; + pd_config->ppu.reg_base = + SCP_CLUSTER_UTILITY_CORE_PPU_BASE(cluster_idx); + pd_config->ppu.irq = FWK_INTERRUPT_NONE; + pd_config->cluster_id = FWK_ID_ELEMENT( + FWK_MODULE_IDX_PPU_V1, (core_count + cluster_idx)); + pd_config->observer_id = FWK_ID_NONE; + core_element_count++; + } + + element = &element_table[core_count + cluster_idx]; + pd_config = &pd_config_table[core_count + cluster_idx]; + + element->name = fwk_mm_alloc(PPU_CLUS_NAME_SIZE, 1); + + snprintf_ret_val = snprintf( + (char *)element->name, PPU_CLUS_NAME_SIZE, "CLUS%u", cluster_idx); + + fwk_assert( + (snprintf_ret_val >= 0) && + (snprintf_ret_val <= PPU_CLUS_NAME_SIZE)); + + element->data = pd_config; + + pd_config->pd_type = MOD_PD_TYPE_CLUSTER; + pd_config->ppu.irq = FWK_INTERRUPT_NONE; + pd_config->observer_id = FWK_ID_NONE; + pd_config->observer_api = FWK_ID_NONE; + pd_config->ppu.reg_base = + SCP_CLUSTER_UTILITY_CLUSTER_PPU_BASE(cluster_idx); + } + + fwk_str_memcpy( + &element_table[core_count + cluster_count], + ppu_element_table, + sizeof(ppu_element_table)); + + /* Setting SI elements */ + /* Allocate pd_config for SI elements */ + pd_config_table = fwk_mm_calloc(10, sizeof(struct mod_ppu_v1_pd_config)); + + /* SI Cluster 0 Core 0 */ + pd_config_table[0].pd_type = MOD_PD_TYPE_CORE; + pd_config_table[0].ppu.reg_base = SCP_PPU_SI_CLUS0CORE0; + pd_config_table[0].ppu.irq = FWK_INTERRUPT_NONE; + /* 8 cores + 8 clusters + 1 systop + 1 si-core */ + pd_config_table[0].cluster_id = FWK_ID_ELEMENT( + FWK_MODULE_IDX_PPU_V1, (core_count + cluster_count + 1 + 1)); + pd_config_table[0].observer_id = FWK_ID_NONE; + element_table[core_count + cluster_count + 1].name = "CLUS0CORE0"; + element_table[core_count + cluster_count + 1].data = &pd_config_table[0]; + + /* SI Cluster 0 */ + pd_config_table[1].pd_type = MOD_PD_TYPE_CLUSTER; + pd_config_table[1].ppu.reg_base = SCP_PPU_SI_CLUS0; + pd_config_table[1].ppu.irq = FWK_INTERRUPT_NONE; + pd_config_table[1].observer_id = FWK_ID_NONE; + pd_config_table[1].observer_api = FWK_ID_NONE; + element_table[core_count + cluster_count + 2].name = "CLUS0"; + element_table[core_count + cluster_count + 2].data = &pd_config_table[1]; + + /* SI Cluster 1 Core 0 */ + pd_config_table[2].pd_type = MOD_PD_TYPE_CORE; + pd_config_table[2].ppu.reg_base = SCP_PPU_SI_CLUS1CORE0; + pd_config_table[2].ppu.irq = FWK_INTERRUPT_NONE; + pd_config_table[2].cluster_id = FWK_ID_ELEMENT( + FWK_MODULE_IDX_PPU_V1, (core_count + cluster_count + 1 + 2 + 2)); + pd_config_table[2].observer_id = FWK_ID_NONE; + element_table[core_count + cluster_count + 3].name = "CLUS1CORE0"; + element_table[core_count + cluster_count + 3].data = &pd_config_table[2]; + + /* SI Cluster 1 Core 1 */ + pd_config_table[3].pd_type = MOD_PD_TYPE_CORE; + pd_config_table[3].ppu.reg_base = SCP_PPU_SI_CLUS1CORE1; + pd_config_table[3].ppu.irq = FWK_INTERRUPT_NONE; + pd_config_table[3].cluster_id = FWK_ID_ELEMENT( + FWK_MODULE_IDX_PPU_V1, (core_count + cluster_count + 1 + 2 + 2)); + pd_config_table[3].observer_id = FWK_ID_NONE; + element_table[core_count + cluster_count + 4].name = "CLUS1CORE1"; + element_table[core_count + cluster_count + 4].data = &pd_config_table[3]; + + /* SI Cluster 1 */ + pd_config_table[4].pd_type = MOD_PD_TYPE_CLUSTER; + pd_config_table[4].ppu.reg_base = SCP_PPU_SI_CLUS1; + pd_config_table[4].ppu.irq = FWK_INTERRUPT_NONE; + pd_config_table[4].observer_id = FWK_ID_NONE; + pd_config_table[4].observer_api = FWK_ID_NONE; + element_table[core_count + cluster_count + 5].name = "CLUS1"; + element_table[core_count + cluster_count + 5].data = &pd_config_table[4]; + + /* SI Cluster 2 Core 0 */ + pd_config_table[5].pd_type = MOD_PD_TYPE_CORE; + pd_config_table[5].ppu.reg_base = SCP_PPU_SI_CLUS2CORE0; + pd_config_table[5].ppu.irq = FWK_INTERRUPT_NONE; + pd_config_table[5].cluster_id = FWK_ID_ELEMENT( + FWK_MODULE_IDX_PPU_V1, (core_count + cluster_count + 1 + 2 + 3 + 4)); + pd_config_table[5].observer_id = FWK_ID_NONE; + element_table[core_count + cluster_count + 6].name = "CLUS2CORE0"; + element_table[core_count + cluster_count + 6].data = &pd_config_table[5]; + + /* SI Cluster 2 Core 1 */ + pd_config_table[6].pd_type = MOD_PD_TYPE_CORE; + pd_config_table[6].ppu.reg_base = SCP_PPU_SI_CLUS2CORE1; + pd_config_table[6].ppu.irq = FWK_INTERRUPT_NONE; + pd_config_table[6].cluster_id = FWK_ID_ELEMENT( + FWK_MODULE_IDX_PPU_V1, (core_count + cluster_count + 1 + 2 + 3 + 4)); + pd_config_table[6].observer_id = FWK_ID_NONE; + element_table[core_count + cluster_count + 7].name = "CLUS2CORE1"; + element_table[core_count + cluster_count + 7].data = &pd_config_table[6]; + + /* SI Cluster 2 Core 2 */ + pd_config_table[7].pd_type = MOD_PD_TYPE_CORE; + pd_config_table[7].ppu.reg_base = SCP_PPU_SI_CLUS2CORE2; + pd_config_table[7].ppu.irq = FWK_INTERRUPT_NONE; + pd_config_table[7].cluster_id = FWK_ID_ELEMENT( + FWK_MODULE_IDX_PPU_V1, (core_count + cluster_count + 1 + 2 + 3 + 4)); + pd_config_table[7].observer_id = FWK_ID_NONE; + element_table[core_count + cluster_count + 8].name = "CLUS2CORE2"; + element_table[core_count + cluster_count + 8].data = &pd_config_table[7]; + + /* SI Cluster 2 Core 3 */ + pd_config_table[8].pd_type = MOD_PD_TYPE_CORE; + pd_config_table[8].ppu.reg_base = SCP_PPU_SI_CLUS2CORE3; + pd_config_table[8].ppu.irq = FWK_INTERRUPT_NONE; + pd_config_table[8].cluster_id = FWK_ID_ELEMENT( + FWK_MODULE_IDX_PPU_V1, (core_count + cluster_count + 1 + 2 + 3 + 4)); + pd_config_table[8].observer_id = FWK_ID_NONE; + element_table[core_count + cluster_count + 9].name = "CLUS2CORE3"; + element_table[core_count + cluster_count + 9].data = &pd_config_table[8]; + + /* SI Cluster 2 */ + pd_config_table[9].pd_type = MOD_PD_TYPE_CLUSTER; + pd_config_table[9].ppu.reg_base = SCP_PPU_SI_CLUS2; + pd_config_table[9].ppu.irq = FWK_INTERRUPT_NONE; + pd_config_table[9].observer_id = FWK_ID_NONE; + pd_config_table[9].observer_api = FWK_ID_NONE; + element_table[core_count + cluster_count + 10].name = "CLUS2"; + element_table[core_count + cluster_count + 10].data = &pd_config_table[9]; + + /* + * Configure pd_source_id with the SYSTOP identifier from the power domain + * module which is dynamically defined based on the number of cores. + */ + ppu_v1_config_data.pd_source_id = fwk_id_build_element_id( + fwk_module_id_power_domain, + core_count + cluster_count + PD_STATIC_DEV_IDX_SYSTOP); + + return element_table; +} + +const struct fwk_module_config config_ppu_v1 = { + .data = &ppu_v1_config_data, + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(ppu_v1_get_element_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_safety_island_platform.c b/product/automotive-rd/rd1ae/scp_ramfw/config_safety_island_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..7b13e0f51e0a98dabc1d28cd4b7f8027c8f34d66 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_safety_island_platform.c @@ -0,0 +1,82 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'safety_island_platform'. + */ + +#include "scp_cfgd_transport.h" + +#include + +#include +#include +#include + +/* Safety Island Cluster 0 layout */ +#define SI_CL0_ID 0U +#define SI_CL0_CORE_NUM 1U +#define SI_CL0_CORE_OFS SI_CL0_CORE_NUM + +/* Safety Island Cluster 1 layout */ +#define SI_CL1_ID SI_CL0_ID + 1U +#define SI_CL1_CORE_NUM 2U +#define SI_CL1_CORE_OFS SI_CL0_CORE_NUM + SI_CL1_CORE_NUM + +/* Safety Island Cluster 2 layout */ +#define SI_CL2_ID SI_CL1_ID + 1U +#define SI_CL2_CORE_NUM 4U +#define SI_CL2_CORE_OFS SI_CL1_CORE_NUM + SI_CL2_CORE_NUM + +enum safety_island_cluster_idx { + SI_CL0_IDX, + SI_CL1_IDX, + SI_CL2_IDX, + SI_CL_COUNT, +}; + +static const struct fwk_element + safety_island_platform_element_table[SI_CL_COUNT + 1] = { + [SI_CL0_IDX] = { + .name = "Safety Island Cluster 0", + .data = &((struct safety_island_cluster_config) { + .transport_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_TRANSPORT, + SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS0), + .cluster_layout = {SI_CL0_ID, SI_CL0_CORE_NUM, SI_CL0_CORE_OFS}, + }), + }, + [SI_CL1_IDX] = { + .name = "Safety Island Cluster 1", + .data = &((struct safety_island_cluster_config) { + .transport_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_TRANSPORT, + SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS1), + .cluster_layout = {SI_CL1_ID, SI_CL1_CORE_NUM, SI_CL1_CORE_OFS}, + }), + }, + [SI_CL2_IDX] = { + .name = "Safety Island Cluster 2", + .data = &((struct safety_island_cluster_config) { + .transport_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_TRANSPORT, + SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS2), + .cluster_layout = {SI_CL2_ID, SI_CL2_CORE_NUM, SI_CL2_CORE_OFS}, + }), + }, + [SI_CL_COUNT] = { 0 }, +}; + +static const struct fwk_element *get_safety_island_platform_element_table( + fwk_id_t module_id) +{ + return safety_island_platform_element_table; +} + +const struct fwk_module_config config_safety_island_platform = { + .elements = + FWK_MODULE_DYNAMIC_ELEMENTS(get_safety_island_platform_element_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_scmi.c b/product/automotive-rd/rd1ae/scp_ramfw/config_scmi.c new file mode 100644 index 0000000000000000000000000000000000000000..c94196659ec359365539dc96d62ef031d4117106 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_scmi.c @@ -0,0 +1,109 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'scmi'. + */ + +#include "scp_cfgd_scmi.h" +#include "scp_cfgd_transport.h" + +#include +#include + +#include +#include +#include +#include +#include + +#define MOD_SCMI_ELEMENT_COUNT (SCP_CFGD_MOD_SCMI_EIDX_COUNT + 1) + +static const struct fwk_element service_table[MOD_SCMI_ELEMENT_COUNT] = { + [SCP_CFGD_MOD_SCMI_EIDX_PSCI] = { + .name = "SERVICE0", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_TRANSPORT, + SCP_CFGD_MOD_TRANSPORT_EIDX_PSCI), + .transport_api_id = FWK_ID_API_INIT( + FWK_MODULE_IDX_TRANSPORT, + MOD_TRANSPORT_API_IDX_SCMI_TO_TRANSPORT), + .transport_notification_init_id = FWK_ID_NOTIFICATION_INIT( + FWK_MODULE_IDX_TRANSPORT, + MOD_TRANSPORT_NOTIFICATION_IDX_INITIALIZED), + .scmi_agent_id = SCP_SCMI_AGENT_IDX_PSCI, + .scmi_p2a_id = FWK_ID_NONE_INIT, + }), + }, + [SCP_CFGD_MOD_SCMI_RSE_POWER_DOWN_SEND] = { + .name = "SERVICE_RSE_POWER_DOWN_SEND", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_TRANSPORT, + SCP_CFGD_MOD_TRANSPORT_EIDX_POWER_STATE_RSE_SEND), + .transport_api_id = FWK_ID_API_INIT( + FWK_MODULE_IDX_TRANSPORT, + MOD_TRANSPORT_API_IDX_SCMI_TO_TRANSPORT), + .transport_notification_init_id = FWK_ID_NOTIFICATION_INIT( + FWK_MODULE_IDX_TRANSPORT, + MOD_TRANSPORT_NOTIFICATION_IDX_INITIALIZED), + .scmi_agent_id = SCP_SCMI_AGENT_IDX_RSE, + .scmi_p2a_id = FWK_ID_NONE_INIT, + }), + }, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + [SCP_CFGD_MOD_SCMI_RSE_POWER_DOWN_RECV] = { + .name = "SERVICE_RSE_POWER_DOWN_RECV", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_TRANSPORT, + SCP_CFGD_MOD_TRANSPORT_EIDX_POWER_STATE_RSE_RECV), + .transport_api_id = FWK_ID_API_INIT( + FWK_MODULE_IDX_TRANSPORT, + MOD_TRANSPORT_API_IDX_SCMI_TO_TRANSPORT), + .transport_notification_init_id = FWK_ID_NOTIFICATION_INIT( + FWK_MODULE_IDX_TRANSPORT, + MOD_TRANSPORT_NOTIFICATION_IDX_INITIALIZED), + .scmi_agent_id = SCP_SCMI_AGENT_IDX_RSE, + .scmi_p2a_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_SCMI, + SCP_CFGD_MOD_SCMI_RSE_POWER_DOWN_SEND), + }), + }, +#endif + [SCP_CFGD_MOD_SCMI_EIDX_COUNT] = { 0 } +}; + +static const struct fwk_element *get_service_table(fwk_id_t module_id) +{ + return service_table; +} + +static struct mod_scmi_agent agent_table[SCP_SCMI_AGENT_IDX_COUNT] = { + [SCP_SCMI_AGENT_IDX_PSCI] = { + .type = SCMI_AGENT_TYPE_PSCI, + .name = "PSCI", + }, + [SCP_SCMI_AGENT_IDX_RSE] = { + .type = SCMI_AGENT_TYPE_MANAGEMENT, + .name = "RSE", + }, +}; + +const struct fwk_module_config config_scmi = { + .data = + &(struct mod_scmi_config){ + .protocol_count_max = 4, + .protocol_requester_count_max = 1, + .agent_count = FWK_ARRAY_SIZE(agent_table) - 1, + .agent_table = agent_table, + .vendor_identifier = "arm", + .sub_vendor_identifier = "arm", + }, + + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_service_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_scmi_power_domain.c b/product/automotive-rd/rd1ae/scp_ramfw/config_scmi_power_domain.c new file mode 100644 index 0000000000000000000000000000000000000000..26d40c7f723a268a4d1b0af510d2fc4701a60be1 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_scmi_power_domain.c @@ -0,0 +1,14 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'scmi_power_domain'. + */ + +#include + +/* No elements, no module configuration data */ +struct fwk_module_config config_scmi_power_domain = { 0 }; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_scmi_system_power.c b/product/automotive-rd/rd1ae/scp_ramfw/config_scmi_system_power.c new file mode 100644 index 0000000000000000000000000000000000000000..14f5840a0a15f65357f320023fd05a82420afa2f --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_scmi_system_power.c @@ -0,0 +1,32 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'scmi_system_power'. + */ + +#include "scp_cfgd_timer.h" + +#include +#include + +#include +#include +#include + +const struct fwk_module_config config_scmi_system_power = { + .data = &((struct mod_scmi_system_power_config){ + .system_view = MOD_SCMI_SYSTEM_VIEW_FULL, + .system_suspend_state = MOD_SYSTEM_POWER_POWER_STATE_SLEEP0, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + .alarm_id = FWK_ID_SUB_ELEMENT_INIT( + FWK_MODULE_IDX_TIMER, + SCP_ALARM_ELEMENT_IDX, + SCP_CFGD_SCMI_NOTIFICATION_ALARM_IDX), + .graceful_timeout = 1000, /* ms */ +#endif + }), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_scp_platform.c b/product/automotive-rd/rd1ae/scp_ramfw/config_scp_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..b2baae48c43c30109f377eac914b9670edd3abbe --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_scp_platform.c @@ -0,0 +1,31 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'scp_platform'. + */ + +#include "scp_cfgd_transport.h" + +#include + +#include +#include +#include + +#define RSE_SYNC_WAIT_TIMEOUT_US (800 * 1000) + +static const struct mod_scp_platform_config platform_config_data = { + .timer_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_TIMER, 0), + .rse_sync_wait_us = RSE_SYNC_WAIT_TIMEOUT_US, + .transport_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_TRANSPORT, + SCP_CFGD_MOD_TRANSPORT_EIDX_SYSTEM), +}; + +struct fwk_module_config config_scp_platform = { + .data = &platform_config_data, +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_sds.c b/product/automotive-rd/rd1ae/scp_ramfw/config_sds.c new file mode 100644 index 0000000000000000000000000000000000000000..d6cde40db6b5ccc5650583799295770abfff4396 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_sds.c @@ -0,0 +1,150 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'sds'. + */ + +#include "scp_cfgd_sds.h" +#include "scp_clock.h" +#include "scp_fw_mmap.h" +#include "scp_pwrctrl.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#define MOD_SDS_ELEMENT_COUNT (SCP_CFGD_MOD_SDS_EIDX_COUNT + 1) +#define SDS_REGION_COUNT SCP_CFGD_MOD_SDS_REGION_IDX_COUNT + +static const uint32_t version_packed = FWK_BUILD_VERSION; +static const uint32_t feature_flags; + +static const struct mod_sds_region_desc sds_regions[SDS_REGION_COUNT] = { + [SCP_CFGD_MOD_SDS_REGION_IDX_SECURE] = { + .base = (void*)SCP_SDS_SECURE_BASE, + .size = SCP_SDS_SECURE_SIZE, + }, +}; + +static_assert( + FWK_ARRAY_SIZE(sds_regions) == SCP_CFGD_MOD_SDS_REGION_IDX_COUNT, + "Mismatch between number of SDS regions and number of regions " + "provided by the SDS configuration."); + +const struct mod_sds_config sds_module_config = { + .regions = sds_regions, + .region_count = SCP_CFGD_MOD_SDS_REGION_IDX_COUNT, + .clock_id = FWK_ID_NONE_INIT, + .platform_notification = { + .notification_id = FWK_ID_NOTIFICATION_INIT( + FWK_MODULE_IDX_SCP_PLATFORM, + MOD_SCP_PLATFORM_NOTIFICATION_IDX_SUBSYS_INITIALIZED), + .source_id = FWK_ID_MODULE_INIT( + FWK_MODULE_IDX_SCP_PLATFORM), + }, +}; + +static struct fwk_element sds_element_table[MOD_SDS_ELEMENT_COUNT] = { + [SCP_CFGD_MOD_SDS_EIDX_CPU_INFO] = { + .name = "CPU Info", + .data = &((struct mod_sds_structure_desc){ + .id = SDS_AP_CPU_INFO_STRUCT_ID, + .size = SCP_CFGD_MOD_SDS_CPU_INFO_SIZE, + .region_id = SCP_CFGD_MOD_SDS_REGION_IDX_SECURE, + .finalize = true, + }), + }, + [SCP_CFGD_MOD_SDS_EIDX_ROM_VERSION] = { + .name = "ROM firmware version", + .data = &((struct mod_sds_structure_desc){ + .id = SDS_ROM_VERSION_STRUCT_ID, + .size = SCP_CFGD_MOD_SDS_ROM_VERSION_SIZE, + .payload = &version_packed, + .region_id = SCP_CFGD_MOD_SDS_REGION_IDX_SECURE, + .finalize = true, + }), + }, + [SCP_CFGD_MOD_SDS_EIDX_RAM_VERSION] = { + .name = "RAM firmware version", + .data = &((struct mod_sds_structure_desc){ + .id = SDS_RAM_VERSION_STRUCT_ID, + .size = SCP_CFGD_MOD_SDS_RAM_VERSION_SIZE, + .payload = &version_packed, + .region_id = SCP_CFGD_MOD_SDS_REGION_IDX_SECURE, + .finalize = true, + }), + }, + [SCP_CFGD_MOD_SDS_EIDX_RESET_SYNDROME] = { + .name = "Reset Syndrome", + .data = &((struct mod_sds_structure_desc){ + .id = SDS_RESET_SYNDROME_STRUCT_ID, + .size = SCP_CFGD_MOD_SDS_RESET_SYNDROME_SIZE, + .region_id = SCP_CFGD_MOD_SDS_REGION_IDX_SECURE, + .finalize = true, + }), + }, + [SCP_CFGD_MOD_SDS_EIDX_FEATURE_AVAILABILITY] = { + .name = "Feature Availability", + .data = &((struct mod_sds_structure_desc){ + .id = SDS_FEATURE_AVAIL_STRUCT_ID, + .size = SCP_CFGD_MOD_SDS_FEATURE_AVAILABILITY_SIZE, + .payload = &feature_flags, + .region_id = SCP_CFGD_MOD_SDS_REGION_IDX_SECURE, + .finalize = true, + }), + }, + [SCP_CFGD_MOD_SDS_ISOLATED_CPU_MPID] = { + .name = "Isolated CPU MPID List", + .data = &((struct mod_sds_structure_desc){ + .id = SDS_ISOLATED_CPU_MPID_STRUCT_ID, + .size = SCP_CFGD_MOD_SDS_ISOLATED_CPU_MPID_SIZE, + .region_id = SCP_CFGD_MOD_SDS_REGION_IDX_SECURE, + .finalize = true, + }), + }, + [SCP_CFGD_MOD_SDS_EIDX_PCIE_MMAP] = { + .name = "PCIe Mmap", + .data = &((struct mod_sds_structure_desc){ + .id = SDS_PCIE_MMAP, + .size = SCP_CFGD_MOD_SDS_PCIE_MMAP_SIZE, + .region_id = SCP_CFGD_MOD_SDS_REGION_IDX_SECURE, + .finalize = true, + }), + }, + [SCP_CFGD_MOD_SDS_EIDX_COUNT] = { 0 }, /* Termination description. */ +}; + +static_assert( + SCP_SDS_SECURE_SIZE > SCP_CFGD_MOD_SDS_PCIE_MMAP_SIZE + + SCP_CFGD_MOD_SDS_CPU_INFO_SIZE + SCP_CFGD_MOD_SDS_ROM_VERSION_SIZE + + SCP_CFGD_MOD_SDS_RAM_VERSION_SIZE + + SCP_CFGD_MOD_SDS_RESET_SYNDROME_SIZE + + SCP_CFGD_MOD_SDS_FEATURE_AVAILABILITY_SIZE + + SCP_CFGD_MOD_SDS_ISOLATED_CPU_MPID_SIZE, + "SDS structures too large for SDS SRAM.\n"); + +static const struct fwk_element *sds_get_element_table(fwk_id_t module_id) +{ + static_assert(BUILD_VERSION_MAJOR < UINT8_MAX, "Invalid version size"); + static_assert(BUILD_VERSION_MINOR < UINT8_MAX, "Invalid version size"); + static_assert(BUILD_VERSION_PATCH < UINT16_MAX, "Invalid version size"); + + return sds_element_table; +} + +struct fwk_module_config config_sds = { + .data = &sds_module_config, + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(sds_get_element_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_sid.c b/product/automotive-rd/rd1ae/scp_ramfw/config_sid.c new file mode 100644 index 0000000000000000000000000000000000000000..54aa7d0cf877db8b8cd310f28396fbeb659e66f7 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_sid.c @@ -0,0 +1,63 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'sid'. + */ + +#include "scp_mmap.h" + +#include + +#include +#include +#include + +#define RD1AE_PART_NUMBER 0x73E + +#define MOD_SID_ELEMENT_COUNT 2 + +static const struct fwk_element subsystem_table[MOD_SID_ELEMENT_COUNT] = { + { .name = "RD1AE", + .data = + &(struct mod_sid_subsystem_config){ + .part_number = RD1AE_PART_NUMBER, + } }, + { 0 }, +}; + +static const struct fwk_element *get_subsystem_table(fwk_id_t id) +{ + return subsystem_table; +} + +const struct fwk_module_config config_sid = { + .data = &(struct mod_sid_config) { + .sid_base = SCP_SID_BASE, + .valid_pcid_registers = + MOD_PCID_REGISTER_PID0 | + MOD_PCID_REGISTER_PID1 | + MOD_PCID_REGISTER_PID2 | + MOD_PCID_REGISTER_PID3 | + MOD_PCID_REGISTER_PID4 | + MOD_PCID_REGISTER_CID0 | + MOD_PCID_REGISTER_CID1 | + MOD_PCID_REGISTER_CID2 | + MOD_PCID_REGISTER_CID3, + .pcid_expected = { + .PID0 = 0xBCU, + .PID1 = 0xB0U, + .PID2 = 0x0BU, + .PID3 = 0x00U, + .PID4 = 0x04U, + .CID0 = 0x0DU, + .CID1 = 0xF0U, + .CID2 = 0x05U, + .CID3 = 0xB1U, + }, + }, + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_subsystem_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_system_info.c b/product/automotive-rd/rd1ae/scp_ramfw/config_system_info.c new file mode 100644 index 0000000000000000000000000000000000000000..d910f4d2a6563b8f6c2f1d0d5b6230dfb9945f5a --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_system_info.c @@ -0,0 +1,25 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'system_info'. + */ + +#include +#include + +#include +#include +#include + +const struct fwk_module_config config_system_info = { + .data = &((struct mod_system_info_config){ + .system_info_driver_module_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SID), + .system_info_driver_data_api_id = FWK_ID_API_INIT( + FWK_MODULE_IDX_SID, + MOD_SID_SYSTEM_INFO_DRIVER_DATA_API_IDX), + }), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_system_pik.c b/product/automotive-rd/rd1ae/scp_ramfw/config_system_pik.c new file mode 100644 index 0000000000000000000000000000000000000000..c46f0ce8f01ba6a3e0fcc305469bfbec57458ad7 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_system_pik.c @@ -0,0 +1,24 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'system_pik'. + */ + +#include + +#include + +#include + +static const struct mod_system_pik_device_config system_pik_data = { + .system_pik_base = (uintptr_t)SYSTEM_PIK_PTR, + .l0_gpt_size = L0GPTSZ_16GIB, +}; + +struct fwk_module_config config_system_pik = { + .data = &system_pik_data, +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_system_pll.c b/product/automotive-rd/rd1ae/scp_ramfw/config_system_pll.c new file mode 100644 index 0000000000000000000000000000000000000000..7619badd54bdffd260c05907b9fe54282c444321 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_system_pll.c @@ -0,0 +1,59 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'system_pll'. + */ + +#include "scp_clock.h" +#include "scp_exp_mmap.h" + +#include + +#include +#include +#include +#include + +#define MOD_SYSTEM_PLL_ELEMENT_COUNT (CFGD_MOD_SYSTEM_PLL_EIDX_COUNT + 1) + +static const struct fwk_element sys_pll_table[MOD_SYSTEM_PLL_ELEMENT_COUNT] = { + [CFGD_MOD_SYSTEM_PLL_EIDX_SYS] = { + .name = "SYS_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = (void *)SCP_PLL_SYSPLL, + .status_reg = (void *)SCP_PLL_STATUS0, + .lock_flag_mask = PLL_STATUS_0_SYSPLL_LOCK, + .initial_rate = 2000 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + }), + }, + [CFGD_MOD_SYSTEM_PLL_EIDX_INTERCONNECT] = { + .name = "INT_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = (void *)SCP_PLL_INTERCONNECT, + .status_reg = (void *)SCP_PLL_STATUS0, + .lock_flag_mask = PLL_STATUS_0_INTPLL_LOCK, + .initial_rate = 2000 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + }), + }, + [CFGD_MOD_SYSTEM_PLL_EIDX_COUNT] = { 0 }, /* Termination description. */ +}; + +static const struct fwk_element *system_pll_get_element_table( + fwk_id_t module_id) +{ + return sys_pll_table; +} + +const struct fwk_module_config config_system_pll = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(system_pll_get_element_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_system_power.c b/product/automotive-rd/rd1ae/scp_ramfw/config_system_power.c new file mode 100644 index 0000000000000000000000000000000000000000..9457d838c45d32313cd9761bbe7380d1c9ecae55 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_system_power.c @@ -0,0 +1,93 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'system_power'. + */ + +#include "platform_core.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* Indices for system power module elements */ +enum cfgd_mod_system_power_element_idx { + CFGD_MOD_SYSTEM_POWER_EIDX_SYS_PPU, + CFGD_MOD_SYSTEM_POWER_EIDX_COUNT +}; + +/* Module 'system_power' element count */ +#define MOD_SYSTEM_POWER_ELEMENT_COUNT (CFGD_MOD_SYSTEM_POWER_EIDX_COUNT + 1) + +#define SYS_PWR_STATE_TABLE_COUNT (MOD_SYSTEM_POWER_POWER_STATE_SLEEP0 + 1) + +static const uint8_t sys_pwr_state_table[SYS_PWR_STATE_TABLE_COUNT] = { + [MOD_PD_STATE_OFF] = (uint8_t)MOD_PD_STATE_OFF, + [MOD_PD_STATE_ON] = (uint8_t)MOD_PD_STATE_ON, + [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = (uint8_t)MOD_PD_STATE_OFF, +}; + +static struct fwk_element element_table[MOD_SYSTEM_POWER_ELEMENT_COUNT] = { + [CFGD_MOD_SYSTEM_POWER_EIDX_SYS_PPU] = { + .name = "SYS-PPU-0", + .data = &((struct mod_system_power_dev_config) { + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V1, + MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER), + .sys_state_table = sys_pwr_state_table, + }), + }, + [CFGD_MOD_SYSTEM_POWER_EIDX_COUNT] = { 0 }, /* Termination description */ +}; + +static const struct fwk_element *system_power_get_element_table(fwk_id_t unused) +{ + unsigned int ppu_idx_base; + unsigned int core_count; + unsigned int cluster_count; + unsigned int i; + + core_count = platform_get_core_count(); + cluster_count = platform_get_cluster_count(); + + /* The system PPUs are placed after the core and cluster PPUs */ + ppu_idx_base = core_count + cluster_count; + + /* Configure System PPU id */ + for (i = 0; i < (FWK_ARRAY_SIZE(element_table) - 1); i++) { + struct mod_system_power_dev_config *dev_config = + (struct mod_system_power_dev_config *)element_table[i].data; + + dev_config->sys_ppu_id = + fwk_id_build_element_id(fwk_module_id_ppu_v1, ppu_idx_base + i); + } + + return element_table; +} + +static struct mod_system_power_config system_power_config = { + .soc_wakeup_irq = FWK_INTERRUPT_NONE, + .driver_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SCP_PLATFORM), + .driver_api_id = FWK_ID_API_INIT( + FWK_MODULE_IDX_SCP_PLATFORM, + MOD_SCP_PLATFORM_API_IDX_SYSTEM_POWER_DRIVER), + .initial_system_power_state = MOD_PD_STATE_ON, +}; + +const struct fwk_module_config config_system_power = { + .data = &system_power_config, + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(system_power_get_element_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_timer.c b/product/automotive-rd/rd1ae/scp_ramfw/config_timer.c new file mode 100644 index 0000000000000000000000000000000000000000..314eaa3363fcd60d1e42ab811a497b9d737cf59d --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_timer.c @@ -0,0 +1,45 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'timer'. + */ + +#include "scp_cfgd_timer.h" + +#include + +#include +#include +#include +#include + +#include + +#define MOD_TIMER_ELEMENT_COUNT 2 + +/* Timer HAL config */ +static const struct fwk_element timer_dev_table[MOD_TIMER_ELEMENT_COUNT] = { + [0] = { + .name = "REFCLK", + .data = &((struct mod_timer_dev_config) { + .id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_GTIMER, 0), + .timer_irq = REFCLK_GTIMER_IRQ, + }), + .sub_element_count = + SCP_CFGD_MOD_TIMER_ALARM_IDX_COUNT, /* Number of alarms */ + }, + [1] = { 0 }, +}; + +static const struct fwk_element *timer_get_dev_table(fwk_id_t module_id) +{ + return timer_dev_table; +} + +const struct fwk_module_config config_timer = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(timer_get_dev_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/config_transport.c b/product/automotive-rd/rd1ae/scp_ramfw/config_transport.c new file mode 100644 index 0000000000000000000000000000000000000000..93dee511683dc7b0db73c8d336da2ecd15d3f0a4 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/config_transport.c @@ -0,0 +1,217 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'transport'. + */ + +#include "platform_core.h" +#include "scp_cfgd_mhu3.h" +#include "scp_cfgd_transport.h" +#include "scp_clock.h" +#include "scp_fw_mmap.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/* Module 'transport' element count */ +#define MOD_TRANSPORT_ELEMENT_COUNT (SCP_CFGD_MOD_TRANSPORT_EIDX_COUNT + 1) + +/* Secure transport channel with mailbox initialization policy */ +#define TRANSPORT_CH_SEC_MBX_INIT \ + (MOD_TRANSPORT_POLICY_INIT_MAILBOX | MOD_TRANSPORT_POLICY_SECURE) + +/* Subsystem initialized notification id (platform notification) */ +#define PLATFORM_SCP_NOTIFICATION_ID \ + FWK_ID_NOTIFICATION_INIT( \ + FWK_MODULE_IDX_SCP_PLATFORM, \ + MOD_SCP_PLATFORM_NOTIFICATION_IDX_SUBSYS_INITIALIZED) + +/* Module 'transport' element configuration table */ +static const struct fwk_element element_table[MOD_TRANSPORT_ELEMENT_COUNT] = { + [SCP_CFGD_MOD_TRANSPORT_EIDX_PSCI] = { + .name = "PSCI", + .data = &(( + struct mod_transport_channel_config) { + .transport_type = MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND, + .policies = TRANSPORT_CH_SEC_MBX_INIT, + .channel_type = MOD_TRANSPORT_CHANNEL_TYPE_COMPLETER, + .out_band_mailbox_address = + (uintptr_t) SCP_SCMI_PAYLOAD_S_A2P_BASE, + .out_band_mailbox_size = SCP_SCMI_PAYLOAD_SIZE, + .driver_id = + FWK_ID_SUB_ELEMENT_INIT( + FWK_MODULE_IDX_MHU3, + SCP_CFGD_MOD_MHU3_EIDX_SCP_AP_S, + 0), + .driver_api_id = + FWK_ID_API_INIT( + FWK_MODULE_IDX_MHU3, + MOD_MHU3_API_IDX_TRANSPORT_DRIVER), + .platform_notification = { + .notification_id = PLATFORM_SCP_NOTIFICATION_ID, + .source_id = FWK_ID_MODULE_INIT( + FWK_MODULE_IDX_SCP_PLATFORM), + }, + }), + }, + [SCP_CFGD_MOD_TRANSPORT_EIDX_SYSTEM] = { + .name = "SCP_PLATFORM_TRANSPORT", + .data = &(( + struct mod_transport_channel_config) { + .transport_type = MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE, + .policies = MOD_TRANSPORT_POLICY_NONE, + .channel_type = MOD_TRANSPORT_CHANNEL_TYPE_COMPLETER, + .signal_api_id = + FWK_ID_API_INIT( + FWK_MODULE_IDX_SCP_PLATFORM, + MOD_SCP_PLATFORM_API_IDX_TRANSPORT_SIGNAL), + .driver_id = + FWK_ID_SUB_ELEMENT_INIT( + FWK_MODULE_IDX_MHU3, + SCP_CFGD_MOD_MHU3_EIDX_SCP_RSE_S, + 0), + .driver_api_id = + FWK_ID_API_INIT( + FWK_MODULE_IDX_MHU3, + MOD_MHU3_API_IDX_TRANSPORT_DRIVER), + }), + }, + [SCP_CFGD_MOD_TRANSPORT_EIDX_POWER_STATE_RSE_SEND] = { + .name = "SCP_PLATFORM_TRANSPORT_POWER_STATE_RSE_SEND", + .data = &(( + struct mod_transport_channel_config) { + .transport_type = MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND, + .policies = MOD_TRANSPORT_POLICY_INIT_MAILBOX | + MOD_TRANSPORT_POLICY_SECURE, + .channel_type = MOD_TRANSPORT_CHANNEL_TYPE_REQUESTER, + .out_band_mailbox_address = + (uintptr_t) SCP_RSE_TRANSPORT_PAYLOAD_BASE, + .out_band_mailbox_size = SCP_RSE_TRANSPORT_PAYLOAD_SIZE, + .signal_api_id = + FWK_ID_API_INIT( + FWK_MODULE_IDX_SCMI, + MOD_SCMI_API_IDX_TRANSPORT), + .driver_id = + FWK_ID_SUB_ELEMENT_INIT( + FWK_MODULE_IDX_MHU3, + SCP_CFGD_MOD_MHU3_EIDX_SCP_RSE_S, + 1), + .driver_api_id = + FWK_ID_API_INIT( + FWK_MODULE_IDX_MHU3, + MOD_MHU3_API_IDX_TRANSPORT_DRIVER), + }), + }, + [SCP_CFGD_MOD_TRANSPORT_EIDX_POWER_STATE_RSE_RECV] = { + .name = "SCP_PLATFORM_TRANSPORT_POWER_STATE_RSE_RECV", + .data = &(( + struct mod_transport_channel_config) { + .transport_type = MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND, + .policies = MOD_TRANSPORT_POLICY_INIT_MAILBOX | + MOD_TRANSPORT_POLICY_SECURE, + .channel_type = MOD_TRANSPORT_CHANNEL_TYPE_COMPLETER, + .out_band_mailbox_address = + (uintptr_t) SCP_RSE_TRANSPORT_PAYLOAD_BASE, + .out_band_mailbox_size = SCP_RSE_TRANSPORT_PAYLOAD_SIZE, + .driver_id = + FWK_ID_SUB_ELEMENT_INIT( + FWK_MODULE_IDX_MHU3, + SCP_CFGD_MOD_MHU3_EIDX_SCP_RSE_S, + 1), + .driver_api_id = + FWK_ID_API_INIT( + FWK_MODULE_IDX_MHU3, + MOD_MHU3_API_IDX_TRANSPORT_DRIVER), + }), + }, + [SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS0] = { + .name = "SCP_PLATFORM_BOOT_SI_CLUS0", + .data = &(( + struct mod_transport_channel_config) { + .transport_type = MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE, + .policies = MOD_TRANSPORT_POLICY_NONE, + .channel_type = MOD_TRANSPORT_CHANNEL_TYPE_COMPLETER, + .signal_api_id = + FWK_ID_API_INIT( + FWK_MODULE_IDX_SAFETY_ISLAND_PLATFORM, + MOD_SAFETY_ISLAND_PLATFORM_API_IDX_BOOT_CLUSTER), + .driver_id = + FWK_ID_SUB_ELEMENT_INIT( + FWK_MODULE_IDX_MHU3, + SCP_CFGD_MOD_MHU3_EIDX_SCP_RSE_S, + 2), + .driver_api_id = + FWK_ID_API_INIT( + FWK_MODULE_IDX_MHU3, + MOD_MHU3_API_IDX_TRANSPORT_DRIVER), + }), + }, + [SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS1] = { + .name = "SCP_PLATFORM_BOOT_SI_CLUS1", + .data = &(( + struct mod_transport_channel_config) { + .transport_type = MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE, + .policies = MOD_TRANSPORT_POLICY_NONE, + .channel_type = MOD_TRANSPORT_CHANNEL_TYPE_COMPLETER, + .signal_api_id = + FWK_ID_API_INIT( + FWK_MODULE_IDX_SAFETY_ISLAND_PLATFORM, + MOD_SAFETY_ISLAND_PLATFORM_API_IDX_BOOT_CLUSTER), + .driver_id = + FWK_ID_SUB_ELEMENT_INIT( + FWK_MODULE_IDX_MHU3, + SCP_CFGD_MOD_MHU3_EIDX_SCP_RSE_S, + 3), + .driver_api_id = + FWK_ID_API_INIT( + FWK_MODULE_IDX_MHU3, + MOD_MHU3_API_IDX_TRANSPORT_DRIVER), + }), + }, + [SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS2] = { + .name = "SCP_PLATFORM_BOOT_SI_CLUS2", + .data = &(( + struct mod_transport_channel_config) { + .transport_type = MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE, + .policies = MOD_TRANSPORT_POLICY_NONE, + .channel_type = MOD_TRANSPORT_CHANNEL_TYPE_COMPLETER, + .signal_api_id = + FWK_ID_API_INIT( + FWK_MODULE_IDX_SAFETY_ISLAND_PLATFORM, + MOD_SAFETY_ISLAND_PLATFORM_API_IDX_BOOT_CLUSTER), + .driver_id = + FWK_ID_SUB_ELEMENT_INIT( + FWK_MODULE_IDX_MHU3, + SCP_CFGD_MOD_MHU3_EIDX_SCP_RSE_S, + 4), + .driver_api_id = + FWK_ID_API_INIT( + FWK_MODULE_IDX_MHU3, + MOD_MHU3_API_IDX_TRANSPORT_DRIVER), + }), + }, + [SCP_CFGD_MOD_TRANSPORT_EIDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *transport_get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +const struct fwk_module_config config_transport = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(transport_get_element_table), +}; diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/cmn_node_id.h b/product/automotive-rd/rd1ae/scp_ramfw/include/cmn_node_id.h new file mode 100644 index 0000000000000000000000000000000000000000..34c389c680f1e253c656a945af8d474460e2971f --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/cmn_node_id.h @@ -0,0 +1,47 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * CMN node ID. + */ + +#ifndef CMN_NODE_ID +#define CMN_NODE_ID + +/* + * CMN node ids + */ +#define MEM_CNTRL0_ID 64 +#define MEM_CNTRL1_ID 128 +#define MEM_CNTRL2_ID 192 +#define MEM_CNTRL3_ID 256 +#define MEM_CNTRL4_ID 104 +#define MEM_CNTRL5_ID 168 +#define MEM_CNTRL6_ID 232 +#define MEM_CNTRL7_ID 296 + +#define NODE_ID_HND 300 + +#define NODE_ID_HNT0 4 +#define NODE_ID_HNT1 260 +#define NODE_ID_HNT2 44 + +#define NODE_ID_HNP0 324 +#define NODE_ID_HNP2 340 +#define NODE_ID_HNP4 356 + +#define NODE_ID_SBSX 172 + +#define MESH_SIZE_X 7 +#define MESH_SIZE_Y 6 + +#define IOVB_NODE_ID0 NODE_ID_HNP0 +#define IOVB_NODE_ID1 NODE_ID_HNP2 +#define IOVB_NODE_ID2 NODE_ID_HNP4 +#define IOVB_NODE_ID3 NODE_ID_HNT0 +#define IOVB_NODE_ID4 NODE_ID_HNT2 + +#endif /* CMN_NODE_ID */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/core_manager.h b/product/automotive-rd/rd1ae/scp_ramfw/include/core_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..bccfb3c34135cd1f2ba1e1080b9dfc916f09984a --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/core_manager.h @@ -0,0 +1,77 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Core Manager and clock control registers + */ + +#ifndef CORE_MANAGER_H +#define CORE_MANAGER_H + +#include "scp_mmap.h" + +#include + +#include + +// clang-format off +struct core_manager_reg { + uint8_t RESERVED0[0x10 - 0x00]; + FWK_RW uint32_t PE_STATIC_CONFIG; + uint8_t RESERVED1[0x18 - 0x14]; + FWK_RW uint32_t PE_RVBARADDR_LW; + FWK_RW uint32_t PE_RVBARADDR_UP; + uint8_t RESERVED2[0x030-0x020]; + FWK_R uint32_t PE_STATUS; + uint8_t RESERVED3[0x800-0x034]; + FWK_RW uint32_t CLUS_MGRCLK_CTRL; + FWK_RW uint32_t CLUS_MGRCLK_DIV1; + uint8_t RESERVED4[0x820 - 0x808]; + FWK_RW uint32_t CLUS_EXP1CLK_CTRL; + FWK_RW uint32_t CLUS_EXP1CLK_DIV; + uint8_t RESERVED5[0x830 - 0x828]; + FWK_RW uint32_t CLUS_EXP2CLK_CTRL; + FWK_RW uint32_t CLUS_EXP2CLK_DIV; + uint8_t RESERVED6[0x840 - 0x838]; + FWK_RW uint32_t CLUS_GICCLK_CTRL; + FWK_RW uint32_t CLUS_GICCLK_DIV1; + uint8_t RESERVED7[0x850 -0x848]; + FWK_RW uint32_t CLUS_PERIPHCLK_CTRL; + FWK_RW uint32_t CLUS_PERIPHCLK_DIV1; + uint8_t RESERVED8[0x860 - 0x858]; + FWK_RW uint32_t CORECLK_CTRL; + FWK_RW uint32_t CORECLK_DIV1; + FWK_RW uint32_t CORECLK_MOD1; + uint8_t RESERVED9[0xA00 - 0x086C]; + FWK_R uint32_t CLKFORCE_STATUS; + FWK_W uint32_t CLKFORCE_SET; + FWK_W uint32_t CLKFORCE_CLR; + uint8_t RESERVED10[0x0FB4 - 0x0A0C]; + FWK_R uint32_t CAP3; + FWK_R uint32_t CAP2; + FWK_R uint32_t CAP1; + FWK_R uint32_t PWR_CTRL_CONFIG; + uint8_t RESERVED11[0xFD0 - 0xFC4]; + FWK_R uint32_t PID4; + FWK_R uint32_t PID5; + FWK_R uint32_t PID6; + FWK_R uint32_t PID7; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t ID0; + FWK_R uint32_t ID1; + FWK_R uint32_t ID2; + FWK_R uint32_t ID3; +}; +// clang-format on + +/* Pointer to SCP Cluster utility core manager register block */ +#define SCP_CLUSTER_UTILITY_CORE_MANAGER_PTR(IDX) \ + ((struct core_manager_reg *)SCP_CLUSTER_UTILITY_CORE_MANAGER_BASE(IDX)) + +#endif /* CORE_MANAGER_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/fmw_cmsis.h b/product/automotive-rd/rd1ae/scp_ramfw/include/fmw_cmsis.h new file mode 100644 index 0000000000000000000000000000000000000000..8753b70aa430db2812c2c7e7dd858639f427772f --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/fmw_cmsis.h @@ -0,0 +1,51 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FMW_CMSIS_H +#define FMW_CMSIS_H + +#include + +#define __CHECK_DEVICE_DEFINES +#define __CM7_REV 0x0000U +#define __FPU_PRESENT 0U +#define __MPU_PRESENT 1U +#define __ICACHE_PRESENT 0U +#define __DCACHE_PRESENT 0U +#define __DTCM_PRESENT 0U +#define __NVIC_PRIO_BITS 3U +#define __Vendor_SysTickConfig 0U +#define __VTOR_PRESENT 1U + +/* System Clock Frequency (Core Clock) */ +extern uint32_t SystemCoreClock; + +typedef enum IRQn { + Reset_IRQn = -15, + NonMaskableInt_IRQn = -14, + HardFault_IRQn = -13, + MemoryManagement_IRQn = -12, + BusFault_IRQn = -11, + UsageFault_IRQn = -10, + SVCall_IRQn = -5, + DebugMonitor_IRQn = -4, + PendSV_IRQn = -2, + SysTick_IRQn = -1, + + /* SCP REFCLK Physical Timer */ + REFCLK_GTIMER_IRQ = 32, + /* MHUv3 secure IRQ between SCP and AP */ + MHU3_AP2SCP_IRQ_S = 83, + /* MHUv3 secure IRQ between SCP and RSE */ + MHU3_RSE2SCP_IRQ_S = 86, + + IRQn_MAX = INT16_MAX, +} IRQn_Type; + +#include + +#endif /* FMW_CMSIS_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/fmw_io.h b/product/automotive-rd/rd1ae/scp_ramfw/include/fmw_io.h new file mode 100644 index 0000000000000000000000000000000000000000..ec7f589082d83b408592c8dd44c6ef6ab45ba52f --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/fmw_io.h @@ -0,0 +1,17 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FMW_IO_H +#define FMW_IO_H + +#include +#include + +#define FMW_IO_STDIN_ID FWK_ID_ELEMENT(FWK_MODULE_IDX_PL011, 0) +#define FMW_IO_STDOUT_ID FWK_ID_ELEMENT(FWK_MODULE_IDX_PL011, 0) + +#endif /* FMW_IO_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/fmw_log.h b/product/automotive-rd/rd1ae/scp_ramfw/include/fmw_log.h new file mode 100644 index 0000000000000000000000000000000000000000..dc7890b3ea9b7c04d5c81f1e492f90e427312070 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/fmw_log.h @@ -0,0 +1,16 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FMW_LOG_H +#define FMW_LOG_H + +/* + * Number of columns per line the framework will limit itself to. + */ +#define FMW_LOG_COLUMNS 100 + +#endif /* FMW_LOG_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/fmw_memory.h b/product/automotive-rd/rd1ae/scp_ramfw/include/fmw_memory.h new file mode 100644 index 0000000000000000000000000000000000000000..b8c39e3a9f1ffb166d36d9d9d0aa3560327c51f8 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/fmw_memory.h @@ -0,0 +1,30 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * SCP RAM firmware memory layout for the linker script. + */ + +#ifndef FMW_MEMORY_H +#define FMW_MEMORY_H + +#include "scp_mmap.h" + +#define FMW_MEM_MODE ARCH_MEM_MODE_DUAL_REGION_RELOCATION + +/* + * RAM instruction memory + */ +#define FMW_MEM0_SIZE SCP_ITC_RAM_SIZE +#define FMW_MEM0_BASE SCP_ITC_RAM_BASE + +/* + * RAM data memory + */ +#define FMW_MEM1_SIZE SCP_DTC_RAM_SIZE +#define FMW_MEM1_BASE SCP_DTC_RAM_BASE + +#endif /* FMW_MEMORY_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/fmw_notification.h b/product/automotive-rd/rd1ae/scp_ramfw/include/fmw_notification.h new file mode 100644 index 0000000000000000000000000000000000000000..3f1717c530c32e274afe4e25900141223affbca5 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/fmw_notification.h @@ -0,0 +1,16 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * SCP RAM firmware notification configuration. + */ + +#ifndef FMW_NOTIFICATION_H +#define FMW_NOTIFICATION_H + +#define FMW_NOTIFICATION_MAX 128 + +#endif /* FMW_NOTIFICATION_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/io_macro_layout.h b/product/automotive-rd/rd1ae/scp_ramfw/include/io_macro_layout.h new file mode 100644 index 0000000000000000000000000000000000000000..b9b0cb6f845271525099fb8adc5b31c3b7c69de2 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/io_macro_layout.h @@ -0,0 +1,75 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Base address definitions for the SCP's sub-system and access extending + * into the rest of the CSS. + */ + +#ifndef IO_MACRO_LAYOUT +#define IO_MACRO_LAYOUT + +#include "scp_mmap.h" + +/* Calculate the base address of NCI GVP for IO Block using its index. */ +#define NCI_GVP_BLOCK_BASE(idx) \ + (SCP_IO_BLOCK_NCI_GVP_BASE + (idx * SCP_IO_BLOCK_REGISTER_SIZE)) +/* Calculate the base address for the TCU in IO block using IO block's index. */ +#define TCU_REG_BASE(idx) \ + (SCP_IO_BLOCK_BASE + (idx * SCP_IO_BLOCK_REGISTER_SIZE)) +#define TCU_REG_SIZE (0x4000000UL) +/* Calculate the base address of IO control register bank. */ +#define CTRL_REG_BASE(idx) \ + (SCP_IO_BLOCK_CONTROL_REG + (idx * SCP_IO_BLOCK_REGISTER_SIZE)) +#define CTRL_REG_SIZE (0x10000UL) + +enum asni_domain_id { + /*! CMN completer Node ID. */ + ASNI_CMN, + /*! PCIe X1 completer Node ID. */ + ASNI_PCIEX1_0, + /*! PCIe X2_1 completer Node ID. */ + ASNI_PCIEX2_1, + /*! Maximum number of completer Node IDs*/ + ASNI_DOMAIN_MAX_ID +}; + +enum amni_domain_id { + /*! requester Node ID. */ + AMNI_CMN, + /*! Inline IO configuration requester Node ID. */ + AMNI_INLINE_IO_CFG, + /*! Inline IO requester Node ID. */ + AMNI_INLINE_IO, + /*! PCIE x1_0 configurtion requester Node ID. */ + AMNI_PCIEX1_0_CFG, + /*! PCIe x1_0 requester Node ID. */ + AMNI_PCIEX1_0, + /*! PCIE x2_0 configurtion requester Node ID. */ + AMNI_PCIEX2_0_CFG, + /*! PCIe x2_0 requester Node ID. */ + AMNI_PCIEX2_0, + /*! PCIE x2_1 configurtion requester Node ID. */ + AMNI_PCIEX2_1_CFG, + /*! PCIe x2_1 requester Node ID. */ + AMNI_PCIEX2_1, + /*! PCIE x4 configurtion requester Node ID. */ + AMNI_PCIEX4_0_CFG, + /*! PCIe x4 requester Node ID. */ + AMNI_PCIEX4_0, + /*! PCIE x8 configurtion requester Node ID. */ + AMNI_PCIEX8_0_CFG, + /*! PCIe x8 requester Node ID. */ + AMNI_PCIEX8_0, + /*! PMNI Control requester Node ID. */ + AMNI_PMNI_CTRL_REG_APB, + /*! TCU APB requester Node ID. */ + AMNI_PMNI_TCU_APB, + /*! Maximum numbers of requester Node ID. */ + AMNI_DOMAIN_MAX_ID +}; + +#endif /* IO_MACRO_LAYOUT */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/platform_core.h b/product/automotive-rd/rd1ae/scp_ramfw/include/platform_core.h new file mode 100644 index 0000000000000000000000000000000000000000..88dba1a114672729bc2701065f982b79d7fe93b8 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/platform_core.h @@ -0,0 +1,42 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Platform generic definitions. + */ + +#ifndef PLATFORM_CORE_H +#define PLATFORM_CORE_H + +#include + +#define NUMBER_OF_ROOTPORTS 5 + +#define CORES_PER_CLUSTER 1 +#define NUMBER_OF_CLUSTERS 16 + +#define NUM_PCIE_INTEG_CTRL 4 + +static inline unsigned int platform_get_cluster_count(void) +{ + return NUMBER_OF_CLUSTERS; +} + +static inline unsigned int platform_get_core_per_cluster_count( + unsigned int cluster) +{ + fwk_assert(cluster < platform_get_cluster_count()); + + return CORES_PER_CLUSTER; +} + +static inline unsigned int platform_get_core_count(void) +{ + return platform_get_core_per_cluster_count(0) * + platform_get_cluster_count(); +} + +#endif /* PLATFORM_CORE_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_mhu3.h b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_mhu3.h new file mode 100644 index 0000000000000000000000000000000000000000..7f87224431f93b979e3701cebb6827eaa83c105d --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_mhu3.h @@ -0,0 +1,21 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Definitions for MHUv3 module configuration data in SCP firmware. + */ + +#ifndef SCP_CFGD_MHU3_H +#define SCP_CFGD_MHU3_H + +/* MHUv3 device indices */ +enum scp_cfgd_mod_mhu3_device_idx { + SCP_CFGD_MOD_MHU3_EIDX_SCP_AP_S, + SCP_CFGD_MOD_MHU3_EIDX_SCP_RSE_S, + SCP_CFGD_MOD_MHU3_EIDX_COUNT +}; + +#endif /* SCP_CFGD_MHU3_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_power_domain.h b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_power_domain.h new file mode 100644 index 0000000000000000000000000000000000000000..4c1a43de1f0ccf8902b222784d58f238ab7c40de --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_power_domain.h @@ -0,0 +1,29 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Definitions for power domain module configuration data in SCP-firmware. + */ + +#ifndef SCP_CFGD_POWER_DOMAIN_H +#define SCP_CFGD_POWER_DOMAIN_H + +#include + +/* + * Power domain indices for the statically defined domains used for: + * - Indexing the domains in the platform_power_domain_static_element_table + * - Indexing the SYSTOP children in the power domain tree + * + * When calculating a power domain element index, use the formula: + * core_count + cluster_count + pd_static_dev_idx + */ +enum pd_static_dev_idx { + PD_STATIC_DEV_IDX_SYSTOP, + PD_STATIC_DEV_IDX_NONE = UINT32_MAX +}; + +#endif /* SCP_CFGD_POWER_DOMAIN_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_scmi.h b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_scmi.h new file mode 100644 index 0000000000000000000000000000000000000000..337fe9445116535c89b71138efe4dbbd2e47a5b7 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_scmi.h @@ -0,0 +1,39 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Definitions for SCMI module configuration data in SCP firmware. + */ + +#ifndef SCP_CFGD_SCMI_H +#define SCP_CFGD_SCMI_H + +#include + +/* SCMI agent identifier indexes in the SCMI agent table */ +enum scp_scmi_agent_idx { + /* 0 is reserved for the platform */ + SCP_SCMI_AGENT_IDX_PSCI = 1, + SCP_SCMI_AGENT_IDX_RSE, + SCP_SCMI_AGENT_IDX_COUNT, +}; + +/* Module 'scmi' element indexes (SCMI services supported) */ +enum scp_cfgd_mod_scmi_element_idx { + SCP_CFGD_MOD_SCMI_EIDX_PSCI, + SCP_CFGD_MOD_SCMI_RSE_POWER_DOWN_SEND, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + SCP_CFGD_MOD_SCMI_RSE_POWER_DOWN_RECV, +#endif + SCP_CFGD_MOD_SCMI_EIDX_COUNT, +}; + +struct scp_cfgd_scmi_sys_power_state_set_payload { + uint32_t flags; + uint32_t system_state; +}; + +#endif /* SCP_CFGD_SCMI_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_sds.h b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_sds.h new file mode 100644 index 0000000000000000000000000000000000000000..d8dc77a45d255b0a7ec8cb4dcc128211acbb2b65 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_sds.h @@ -0,0 +1,71 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Definitions for SDS module configuration data in SCP firmware. + */ + +#ifndef SCP_CFGD_SDS_H +#define SCP_CFGD_SDS_H + +#include + +#include +#include + +#include + +#define SDS_STRUCT_ID(idx) (idx | 1 << MOD_SDS_ID_VERSION_MAJOR_POS) + +/* SDS structure identifiers. */ +enum scp_cfgd_mod_sds_struct_id { + SDS_AP_CPU_INFO_STRUCT_ID = SDS_STRUCT_ID(1), + SDS_ROM_VERSION_STRUCT_ID = SDS_STRUCT_ID(2), + SDS_RAM_VERSION_STRUCT_ID = SDS_STRUCT_ID(3), + SDS_RESET_SYNDROME_STRUCT_ID = SDS_STRUCT_ID(5), + SDS_FEATURE_AVAIL_STRUCT_ID = SDS_STRUCT_ID(6), + SDS_ISOLATED_CPU_MPID_STRUCT_ID = SDS_STRUCT_ID(128), + SDS_PCIE_MMAP = SDS_STRUCT_ID(129), +}; + +/* Memory region identifiers that hold the SDS structures. */ +enum scp_cfgd_mod_sds_region_idx { + SCP_CFGD_MOD_SDS_REGION_IDX_SECURE, + SCP_CFGD_MOD_SDS_REGION_IDX_COUNT, +}; + +/* Module 'sds' element indexes (SDS region descriptors) */ +enum scp_cfgd_mod_sds_element_idx { + SCP_CFGD_MOD_SDS_EIDX_CPU_INFO, + SCP_CFGD_MOD_SDS_EIDX_ROM_VERSION, + SCP_CFGD_MOD_SDS_EIDX_RAM_VERSION, + SCP_CFGD_MOD_SDS_EIDX_RESET_SYNDROME, + SCP_CFGD_MOD_SDS_EIDX_FEATURE_AVAILABILITY, + SCP_CFGD_MOD_SDS_ISOLATED_CPU_MPID, + SCP_CFGD_MOD_SDS_EIDX_PCIE_MMAP, + SCP_CFGD_MOD_SDS_EIDX_COUNT +}; + +/* SDS region descriptor structure sizes. */ +#define SCP_CFGD_MOD_SDS_CPU_INFO_SIZE 4 +#define SCP_CFGD_MOD_SDS_ROM_VERSION_SIZE 4 +#define SCP_CFGD_MOD_SDS_RAM_VERSION_SIZE 4 +#define SCP_CFGD_MOD_SDS_RESET_SYNDROME_SIZE 4 +#define SCP_CFGD_MOD_SDS_FEATURE_AVAILABILITY_SIZE 4 +#define SCP_CFGD_MOD_SDS_PCIE_MMAP_SIZE \ + (sizeof(struct mod_pcie_setup_block_mmap_list)) + \ + (NUM_PCIE_INTEG_CTRL * \ + (sizeof(struct mod_pcie_setup_block_mmap) + \ + (sizeof(struct mod_pcie_setup_mmap) * NUMBER_OF_ROOTPORTS))) + +/* + * Max size of structure listing the MPID of the isolated CPUs. + * size = (Number of CPUs * sizeof MPID register) + sizeof CPU count variable + */ +#define SCP_CFGD_MOD_SDS_ISOLATED_CPU_MPID_SIZE \ + ((NUMBER_OF_CLUSTERS * sizeof(uint64_t)) + sizeof(uint64_t)) + +#endif /* SCP_CFGD_SDS_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_timer.h b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_timer.h new file mode 100644 index 0000000000000000000000000000000000000000..3f62fe745b313f5d4e4c18da38207f0521774cc1 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_timer.h @@ -0,0 +1,24 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Definitions for timer module configuration data in SCP firmware. + */ + +#ifndef SCP_CFGD_TIMER_H +#define SCP_CFGD_TIMER_H + +#define SCP_ALARM_ELEMENT_IDX 0 + +/* Sub-element indexes (alarms) for SCP timer device */ +enum scp_cfgd_mod_timer_alarm_idx { +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + SCP_CFGD_SCMI_NOTIFICATION_ALARM_IDX, +#endif + SCP_CFGD_MOD_TIMER_ALARM_IDX_COUNT, +}; + +#endif /* SCP_CFGD_TIMER_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_transport.h b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_transport.h new file mode 100644 index 0000000000000000000000000000000000000000..ccbe061f669286ae3e77a6486dcd83ed7e023bad --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_cfgd_transport.h @@ -0,0 +1,27 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Definitions for transport module configuration data in SCP + * firmware. + */ + +#ifndef SCP_CFGD_TRANSPORT_H +#define SCP_CFGD_TRANSPORT_H + +/* Module 'transport' element indexes */ +enum scp_cfgd_mod_transport_element_idx { + SCP_CFGD_MOD_TRANSPORT_EIDX_PSCI, + SCP_CFGD_MOD_TRANSPORT_EIDX_SYSTEM, + SCP_CFGD_MOD_TRANSPORT_EIDX_POWER_STATE_RSE_SEND, + SCP_CFGD_MOD_TRANSPORT_EIDX_POWER_STATE_RSE_RECV, + SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS0, + SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS1, + SCP_CFGD_MOD_TRANSPORT_EIDX_BOOT_SI_CLUS2, + SCP_CFGD_MOD_TRANSPORT_EIDX_COUNT, +}; + +#endif /* SCP_CFGD_TRANSPORT_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/scp_clock.h b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_clock.h new file mode 100644 index 0000000000000000000000000000000000000000..7d6c6e1ba983af92dc5a25fcbd2c798484e08508 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_clock.h @@ -0,0 +1,80 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * SCP clock definitions. + */ + +#ifndef SCP_CLOCK_H +#define SCP_CLOCK_H + +#include + +#define CLOCK_RATE_SYSPLLCLK (2000UL * FWK_MHZ) + +/* + * PLL clock indices. + */ +enum clock_pll_idx { + CFGD_MOD_SYSTEM_PLL_EIDX_SYS, + CFGD_MOD_SYSTEM_PLL_EIDX_INTERCONNECT, + CFGD_MOD_SYSTEM_PLL_EIDX_COUNT +}; + +/* + * PIK clock indexes. + */ +enum clock_pik_idx { + CFGD_MOD_PIK_CLOCK_EIDX_CPU0, + CFGD_MOD_PIK_CLOCK_EIDX_CPU1, + CFGD_MOD_PIK_CLOCK_EIDX_CPU2, + CFGD_MOD_PIK_CLOCK_EIDX_CPU3, + CFGD_MOD_PIK_CLOCK_EIDX_CPU4, + CFGD_MOD_PIK_CLOCK_EIDX_CPU5, + CFGD_MOD_PIK_CLOCK_EIDX_CPU6, + CFGD_MOD_PIK_CLOCK_EIDX_CPU7, + CFGD_MOD_PIK_CLOCK_EIDX_CPU8, + CFGD_MOD_PIK_CLOCK_EIDX_CPU9, + CFGD_MOD_PIK_CLOCK_EIDX_CPU10, + CFGD_MOD_PIK_CLOCK_EIDX_CPU11, + CFGD_MOD_PIK_CLOCK_EIDX_CPU12, + CFGD_MOD_PIK_CLOCK_EIDX_CPU13, + CFGD_MOD_PIK_CLOCK_EIDX_CPU14, + CFGD_MOD_PIK_CLOCK_EIDX_CPU15, + CFGD_MOD_PIK_CLOCK_EIDX_CMN, + CFGD_MOD_PIK_CLOCK_EIDX_SCP, + CFGD_MOD_PIK_CLOCK_EIDX_GIC, + CFGD_MOD_PIK_CLOCK_EIDX_SCP_PIK, + CFGD_MOD_PIK_CLOCK_EIDX_SYSPERCLK, + CFGD_MOD_PIK_CLOCK_EIDX_UARTCLK, + CFGD_MOD_PIK_CLOCK_EIDX_COUNT +}; + +/* + * Module 'clock' element indexes + */ +enum cfgd_mod_clock_element_idx { + CFGD_MOD_CLOCK_EIDX_CPU0, + CFGD_MOD_CLOCK_EIDX_CPU1, + CFGD_MOD_CLOCK_EIDX_CPU2, + CFGD_MOD_CLOCK_EIDX_CPU3, + CFGD_MOD_CLOCK_EIDX_CPU4, + CFGD_MOD_CLOCK_EIDX_CPU5, + CFGD_MOD_CLOCK_EIDX_CPU6, + CFGD_MOD_CLOCK_EIDX_CPU7, + CFGD_MOD_CLOCK_EIDX_CPU8, + CFGD_MOD_CLOCK_EIDX_CPU9, + CFGD_MOD_CLOCK_EIDX_CPU10, + CFGD_MOD_CLOCK_EIDX_CPU11, + CFGD_MOD_CLOCK_EIDX_CPU12, + CFGD_MOD_CLOCK_EIDX_CPU13, + CFGD_MOD_CLOCK_EIDX_CPU14, + CFGD_MOD_CLOCK_EIDX_CPU15, + CFGD_MOD_CLOCK_EIDX_CMN, + CFGD_MOD_CLOCK_EIDX_COUNT +}; + +#endif /* SCP_CLOCK_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/scp_exp_mmap.h b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_exp_mmap.h new file mode 100644 index 0000000000000000000000000000000000000000..540a73bb734ca32d294407dd2238012255645aef --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_exp_mmap.h @@ -0,0 +1,27 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Base address definitions for the SCP's expansion memory regions. + */ + +#ifndef SCP_EXP_MMAP_H +#define SCP_EXP_MMAP_H + +#include "scp_mmap.h" + +/* PLLs are connected in SCP's expansion3 memory region */ +#define SCP_PLL_BASE (SCP_SOC_EXPANSION3_BASE + 0x03000000UL) + +#define SCP_PLL_SYSPLL (SCP_PLL_BASE + 0x00000000UL) +#define SCP_PLL_INTERCONNECT (SCP_PLL_BASE + 0x00000020UL) +#define SCP_PLL_STATUS0 (SCP_PLL_BASE + 0x00000180UL) + +/* PLL lock status flag mask */ +#define PLL_STATUS_0_SYSPLL_LOCK (0x00000002UL) +#define PLL_STATUS_0_INTPLL_LOCK (0x00000008UL) + +#endif /* SCP_EXP_MMAP_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/scp_fw_mmap.h b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_fw_mmap.h new file mode 100644 index 0000000000000000000000000000000000000000..a131d20553fa3958f5d6081334b17e7d03090f72 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_fw_mmap.h @@ -0,0 +1,49 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Base address and size definitions for the various SCP's firmware defined + * memory carveouts. + */ + +#ifndef SCP_FW_MMAP_H +#define SCP_FW_MMAP_H + +#include "scp_mmap.h" + +/* AP Peripheral trusted SRAM base in SCP's memory map (4KB) */ +#define SCP_AP_PERIPHERAL_SRAM_TRUSTED_BASE SCP_ATW0_AP_PERIPHERAL_SRAM_BASE + +/* Secure Shared memory between AP and SCP */ +#define SCP_AP_PERIPHERAL_SRAM_SHARED_SECURE_BASE \ + (SCP_AP_PERIPHERAL_SRAM_TRUSTED_BASE) +#define SCP_AP_PERIPHERAL_SRAM_SHARED_SECURE_SIZE (4 * FWK_KIB) + +/* + * AP Context Memory Region inside Secure AP Peripheral SRAM that is shared + * between AP and SCP. + */ +#define SCP_AP_CONTEXT_SIZE (64) +#define SCP_AP_CONTEXT_BASE \ + (SCP_AP_PERIPHERAL_SRAM_SHARED_SECURE_BASE + \ + SCP_AP_PERIPHERAL_SRAM_SHARED_SECURE_SIZE - SCP_AP_CONTEXT_SIZE) + +/* + * SDS Memory Region inside Secure AP Peripheral SRAM that is shared between + * AP and SCP. + */ +#define SCP_SDS_SECURE_BASE (SCP_AP_PERIPHERAL_SRAM_SHARED_SECURE_BASE) +#define SCP_SDS_SECURE_SIZE (3520) + +/* SCMI Secure Payload Area */ +#define SCP_SCMI_PAYLOAD_S_A2P_BASE (SCP_SDS_SECURE_BASE + SCP_SDS_SECURE_SIZE) +#define SCP_SCMI_PAYLOAD_SIZE (128) + +/* Payload Area for SCP-RSE outband message */ +#define SCP_RSE_TRANSPORT_PAYLOAD_BASE (SCP_SHARED_SRAM_RSM_BASE) +#define SCP_RSE_TRANSPORT_PAYLOAD_SIZE (128) + +#endif /* SCP_FW_MMAP_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/scp_mmap.h b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_mmap.h new file mode 100644 index 0000000000000000000000000000000000000000..505301ab236fa9248fa3efa9453764ba86efafbd --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_mmap.h @@ -0,0 +1,144 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Base address definitions for the SCP's sub-system. + */ + +#ifndef SCP_MMAP_H +#define SCP_MMAP_H + +/* Base address and size of SCP's ITCM */ +#define SCP_ITC_RAM_BASE (0x00000000) +#define SCP_ITC_RAM_SIZE (256 * 1024) + +/* Base address and size of SCP's DTCM */ +#define SCP_DTC_RAM_BASE (0x20000000) +#define SCP_DTC_RAM_SIZE (256 * 1024) + +/* SCP sub-system peripherals */ +#define SCP_AP2SCP_MHUV3_RCV_S_BASE (0x45030000UL) +#define SCP_ATU_BASE (0x50010000UL) +#define SCP_POWER_CONTROL_BASE (0x50000000UL) +#define SCP_PPU_SYS0_BASE (0x50041000UL) +#define SCP_REFCLK_CNTCONTROL_BASE (0x2A430000UL) +#define SCP_REFCLK_CNTCTL_BASE (0x44000000UL) +#define SCP_REFCLK_CNTBASE0_BASE (0x44001000UL) +#define SCP_RSE2SCP_MHUV3_RCV_S_BASE (0x46010000UL) +#define SCP_SCP2AP_MHUV3_SEND_S_BASE (0x45020000UL) +#define SCP_SCP2RSE_MHUV3_SEND_S_BASE (0x46000000UL) +#define SCP_SID_BASE (0x2A4A0000UL) +#define SCP_SYSTEM_PIK_BASE (0x50040000UL) +#define SCP_UART_BASE (0x44002000UL) + +/* Base address of SCP expansion memory regions */ +#define SCP_SOC_EXPANSION3_BASE (0x40000000UL) /* 64MB size */ + +/* SCP addresses mapped via ATU into address translation windows */ +#define SCP_ADDRESS_TRANSLATION_WINDOW0_BASE (0x60000000UL) +#define SCP_ADDRESS_TRANSLATION_WINDOW1_BASE (0xA0000000UL) + +/* + * Offsets within SCP's Address Translation Window0 + * __________________________ + * | | + * | IO Block NCI 16M | + * |__________________________| 0x78600000 + * | | + * | ATU MMIO (1M) | + * |__________________________| 0x78500000 + * | | + * | RSM_SRAM 4M | + * |__________________________| 0x78100000 + * | | + * | GPC_MMU 1M | + * |__________________________| 0x78000000 + * | | + * | SHARED SRAM 128M | + * |__________________________| 0x70000000 + * | | + * | CLUSTER UTIL 256M | + * |__________________________| 0x60000000 + */ + +#define SCP_ATW0_CLUSTER_UTILITY_SIZE (256 * FWK_MIB) +#define SCP_ATW0_AP_PERIPHERAL_SRAM_SIZE (128 * FWK_MIB) +#define SCP_ATW0_AP_PERIPHERAL_GPC_SMMU_SIZE (1 * FWK_MIB) +#define SCP_ATW0_SHARED_SRAM_RSM_SIZE (4 * FWK_MIB) +#define SCP_ATW0_ATU_MMIO_SIZE (1 * FWK_MIB) +#define SCP_ATW0_AP_IO_BLOCK_NCI_SIZE (16 * FWK_MIB) + +#define SCP_ATW0_CLUSTER_UTILITY_BASE SCP_ADDRESS_TRANSLATION_WINDOW0_BASE +#define SCP_ATW0_AP_PERIPHERAL_SRAM_BASE \ + (SCP_ATW0_CLUSTER_UTILITY_BASE + SCP_ATW0_CLUSTER_UTILITY_SIZE) +#define SCP_ATW0_AP_PERIPHERAL_GPC_SMMU_BASE \ + (SCP_ATW0_AP_PERIPHERAL_SRAM_BASE + SCP_ATW0_AP_PERIPHERAL_SRAM_SIZE) +#define SCP_ATW0_SHARED_SRAM_RSM_BASE \ + (SCP_ATW0_AP_PERIPHERAL_GPC_SMMU_BASE + \ + SCP_ATW0_AP_PERIPHERAL_GPC_SMMU_SIZE) +#define SCP_ATW0_ATU_MMIO_BASE \ + (SCP_ATW0_SHARED_SRAM_RSM_BASE + SCP_ATW0_SHARED_SRAM_RSM_SIZE) +#define SCP_ATW0_AP_IO_BLOCK_NCI_BASE \ + SCP_ATW0_ATU_MMIO_BASE + SCP_ATW0_ATU_MMIO_SIZE + +/* + * Offsets within SCP's Address Translation Window1 + * __________________________ + * | | + * | CMN 1G | + * |__________________________| 0xA0000000 + */ +#define SCP_ATW1_CMN_BASE (SCP_ADDRESS_TRANSLATION_WINDOW1_BASE) +#define SCP_ATW1_CMN_SIZE (1 * FWK_GIB) + +/* + * Size of SCP's view of per-cluster utility memory region. + */ +#define SCP_CLUSTER_UTILITY_SIZE (0x200000UL) + +/* + * Offsets of various blocks within cluster utility that is + * mapped into SCP's address translation window 0. These offsets are applicable + * to each cluster in the system. + */ +#define SCP_CLUSTER_UTILITY_CORE_MANAGER_OFFSET (0x80000UL) +#define SCP_CLUSTER_UTILITY_CLUSTER_PPU_OFFSET (0x130000UL) +#define SCP_CLUSTER_UTILITY_CORE_PPU_OFFSET (0x180000UL) + +/* Core Manager base address for a cluster 'n' */ +#define SCP_CLUSTER_UTILITY_CORE_MANAGER_BASE(n) \ + (SCP_ATW0_CLUSTER_UTILITY_BASE + (n * SCP_CLUSTER_UTILITY_SIZE) + \ + SCP_CLUSTER_UTILITY_CORE_MANAGER_OFFSET) + +/* Cluster PPU base address */ +#define SCP_CLUSTER_UTILITY_CLUSTER_PPU_BASE(n) \ + (SCP_ATW0_CLUSTER_UTILITY_BASE + (n * SCP_CLUSTER_UTILITY_SIZE) + \ + SCP_CLUSTER_UTILITY_CLUSTER_PPU_OFFSET) + +/* Application core PPU base address */ +#define SCP_CLUSTER_UTILITY_CORE_PPU_BASE(n) \ + (SCP_ATW0_CLUSTER_UTILITY_BASE + (n * SCP_CLUSTER_UTILITY_SIZE) + \ + SCP_CLUSTER_UTILITY_CORE_PPU_OFFSET) + +/* CMN config space is mapped in the SCP address translation window 1 */ +#define SCP_CMN_BASE SCP_ATW1_CMN_BASE + +/* + * Shared RSM SRAM (shared between RSE and SCP) is mapped by ATU in + * the SCP address translation window 0 at the address 0x7810_0000. + */ +#define SCP_SHARED_SRAM_RSM_BASE (SCP_ATW0_SHARED_SRAM_RSM_BASE) + +/* Base address of the IO block register bank. */ +#define SCP_IO_BLOCK_BASE (0x280000000UL) +/* Base address of the NCI in the IO block. */ +#define SCP_IO_BLOCK_NCI_GVP_BASE (SCP_IO_BLOCK_BASE + 0x4000000UL) +/* Size of the register bank of IO block. */ +#define SCP_IO_BLOCK_REGISTER_SIZE (0x8000000UL) +/* Base address of th Control register set. */ +#define SCP_IO_BLOCK_CONTROL_REG (SCP_IO_BLOCK_BASE + 0x5B00000UL) + +#endif /* SCP_MMAP_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/scp_pwrctrl.h b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_pwrctrl.h new file mode 100644 index 0000000000000000000000000000000000000000..a5899890951f076340b0401eb72c38db2bfaec83 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/scp_pwrctrl.h @@ -0,0 +1,139 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * SCP Power Control registers + */ + +#ifndef SCP_PWRCTRL_H +#define SCP_PWRCTRL_H + +#include "scp_mmap.h" + +#include + +#include + +/*! + * \brief SCP Power Control register definitions + */ + +// clang-format off +struct scp_power_control_reg { + uint8_t RESERVED0[0x10 - 0x0]; + FWK_RW uint32_t RESET_SYNDROME; + uint8_t RESERVED1[0x18 - 0x14]; + FWK_RW uint32_t LCP2SCP_INT_SOURCE_GROUP0; + FWK_RW uint32_t LCP2SCP_INT_SOURCE_GROUP1; + FWK_RW uint32_t LCP2SCP_INT_SOURCE_GROUP2; + FWK_RW uint32_t LCP2SCP_INT_SOURCE_GROUP3; + FWK_RW uint32_t LCP2SCP_INT_SOURCE_GROUP4; + FWK_RW uint32_t LCP2SCP_INT_SOURCE_GROUP5; + FWK_RW uint32_t LCP2SCP_INT_SOURCE_GROUP6; + FWK_RW uint32_t LCP2SCP_INT_SOURCE_GROUP7; + uint8_t RESERVED2[0x200 - 0x38]; + FWK_R uint32_t SCP2LCP_MHU_PBX_INT_SOURCE_GROUP; + FWK_R uint32_t SCP2LCP_MHU_PBX_INT_SOURCE_GROUP0; + FWK_R uint32_t SCP2LCP_MHU_PBX_INT_SOURCE_GROUP1; + FWK_R uint32_t SCP2LCP_MHU_PBX_INT_SOURCE_GROUP2; + FWK_R uint32_t SCP2LCP_MHU_PBX_INT_SOURCE_GROUP3; + FWK_R uint32_t SCP2LCP_MHU_PBX_INT_SOURCE_GROUP4; + FWK_R uint32_t SCP2LCP_MHU_PBX_INT_SOURCE_GROUP5; + FWK_R uint32_t SCP2LCP_MHU_PBX_INT_SOURCE_GROUP6; + FWK_R uint32_t SCP2LCP_MHU_PBX_INT_SOURCE_GROUP7; + FWK_R uint32_t LCP2SCP_MHU_MBX_INT_SOURCE_GROUP; + FWK_R uint32_t LCP2SCP_MHU_MBX_INT_SOURCE_GROUP0; + FWK_R uint32_t LCP2SCP_MHU_MBX_INT_SOURCE_GROUP1; + FWK_R uint32_t LCP2SCP_MHU_MBX_INT_SOURCE_GROUP2; + FWK_R uint32_t LCP2SCP_MHU_MBX_INT_SOURCE_GROUP3; + FWK_R uint32_t LCP2SCP_MHU_MBX_INT_SOURCE_GROUP4; + FWK_R uint32_t LCP2SCP_MHU_MBX_INT_SOURCE_GROUP5; + FWK_R uint32_t LCP2SCP_MHU_MBX_INT_SOURCE_GROUP6; + FWK_R uint32_t LCP2SCP_MHU_MBX_INT_SOURCE_GROUP7; + uint8_t RESERVED3[0x810 - 0x248]; + FWK_RW uint32_t CORECLK_CTRL; + FWK_RW uint32_t CORECLK_DIV1; + uint8_t RESERVED4[0x820 - 0x818]; + FWK_RW uint32_t ACLK_CTRL; + FWK_RW uint32_t ACLK_DIV1; + uint8_t RESERVED5[0x830 - 0x828]; + FWK_RW uint32_t GTSYNCCLK_CTRL; + FWK_RW uint32_t GTSYNCCLK_DIV1; + uint8_t RESERVED6[0x840 - 0x838]; + FWK_RW uint32_t LCPCLK_CTRL; + FWK_RW uint32_t LCPCLK_DIV1; + uint8_t RESERVED7[0xA00 - 0x848]; + FWK_R uint32_t CLKFORCE_STATUS; + FWK_W uint32_t CLKFORCE_SET; + FWK_W uint32_t CLKFORCE_CLEAR; + uint8_t RESERVED8[0xA50 - 0xA0C]; + FWK_R uint32_t CONS_MMUTCU_INT_STATUS; + FWK_W uint32_t CONS_MMUTCU_INT_CLR; + FWK_R uint32_t CONS_MMUTCU1_INT_STATUS; + FWK_W uint32_t CONS_MMUTCU1_INT_CLR; + uint8_t RESERVED9[0xA68 - 0xA60]; + FWK_R uint32_t CONS_MMUTBU_INT_STATUS0; + FWK_W uint32_t CONS_MMUTBU_INT_CLR0; + FWK_R uint32_t CONS_MMUTBU_INT_STATUS1; + FWK_W uint32_t CONS_MMUTBU_INT_CLR1; + FWK_R uint32_t CONS_MMUTBU_INT_STATUS2; + FWK_W uint32_t CONS_MMUTBU_INT_CLR2; + FWK_R uint32_t CONS_MMUTBU_INT_STATUS3; + FWK_W uint32_t CONS_MMUTBU_INT_CLR3; + FWK_R uint32_t CONS_MMUTBU_INT_STATUS4; + FWK_W uint32_t CONS_MMUTBU_INT_CLR4; + FWK_R uint32_t CONS_MMUTBU_INT_STATUS5; + FWK_W uint32_t CONS_MMUTBU_INT_CLR5; + uint8_t RESERVED10[0xB20 - 0xA98]; + FWK_R uint32_t CPU_PPU_INT_STATUS[8]; + FWK_R uint32_t CLUS_PPU_INT_STATUS[8]; + FWK_R uint32_t PROC_PEX_INT_STATUS[8]; + FWK_RW uint32_t CPU_PLL_LOCK_STATUS[8]; + uint8_t RESERVED11[0xBC0 - 0xBA0]; + FWK_RW uint32_t CPU_PLL_UNLOCK_STATUS[7]; + uint8_t RESERVED12[0xC10 - 0xBE0]; + FWK_W uint32_t SMCF_MGI_TRIGGER; + uint8_t RESERVED13[0xC20 - 0xC14]; + FWK_R uint32_t SRAMECC_ERRFR; + FWK_R uint32_t SRAMECC_ERRFR_H; + FWK_RW uint32_t SRAMECC_ERRCTRL; + FWK_RW uint32_t SRAMECC_ERRCTRL_H; + FWK_RW uint32_t SRAMECC_ERRSTATUS; + FWK_RW uint32_t SRAMECC_ERRSTATUS_H; + FWK_RW uint32_t SRAMECC_ERRADDR; + FWK_RW uint32_t SRAMECC_ERRADDR_H; + uint8_t RESERVED14[0xC48 - 0xC40]; + FWK_RW uint32_t SRAMECC_ERRMISC1; + FWK_RW uint32_t SRAMECC_ERRMISC1_H; + uint8_t RESERVED15[0xC60 - 0xC50]; + FWK_R uint32_t SYSNCI_PMU_CONS_INT_STATUS; + FWK_R uint32_t SYSNCI_CONS_INT_STATUS; + FWK_R uint32_t INTNCI_PMU_CONS_INT_STATUS; + FWK_R uint32_t INTNCI_CONS_INT_STATUS; + FWK_R uint32_t PERIPHNCI_PMU_CONS_INT_STATUS; + FWK_R uint32_t PERIPHNCI_CONS_INT_STATUS; + uint8_t RESERVED16[0xFC0 - 0xC78]; + FWK_R uint32_t PWR_CTRL_CONFIG; + uint8_t RESERVED17[0xFD0 - 0xFC4]; + FWK_R uint32_t PERIPHERAL_ID4; + FWK_R uint32_t PERIPHERAL_ID5; + FWK_R uint32_t PERIPHERAL_ID6; + FWK_R uint32_t PERIPHERAL_ID7; + FWK_R uint32_t PERIPHERAL_ID0; + FWK_R uint32_t PERIPHERAL_ID1; + FWK_R uint32_t PERIPHERAL_ID2; + FWK_R uint32_t PERIPHERAL_ID3; + FWK_R uint32_t COMPONENT_ID0; + FWK_R uint32_t COMPONENT_ID1; + FWK_R uint32_t COMPONENT_ID2; + FWK_R uint32_t COMPONENT_ID3; +}; +// clang-format on + +/* Pointer to SCP Power Control register block */ +#define SCP_PWRCTRL_PTR ((struct scp_power_control_reg *)SCP_POWER_CONTROL_BASE) + +#endif /* SCP_PWRCTRL_H */ diff --git a/product/automotive-rd/rd1ae/scp_ramfw/include/system_pik.h b/product/automotive-rd/rd1ae/scp_ramfw/include/system_pik.h new file mode 100644 index 0000000000000000000000000000000000000000..d65243af8ac36e94528502fe60be9fe1320a2da6 --- /dev/null +++ b/product/automotive-rd/rd1ae/scp_ramfw/include/system_pik.h @@ -0,0 +1,81 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * SCP System PIK registers + */ + +#ifndef SYSTEM_PIK_H +#define SYSTEM_PIK_H + +#include "scp_mmap.h" + +#include + +#include + +/*! + * \brief System PIK register definitions + */ + +// clang-format off +struct system_pik_reg { + uint8_t RESERVED0[0x820 - 0x0]; + FWK_RW uint32_t INTCLK_CTRL; + FWK_RW uint32_t INTCLK_DIV1; + uint8_t RESERVED1[0x850 - 0x828]; + FWK_RW uint32_t GICCLK_CTRL; + FWK_RW uint32_t GICCLK_DIV1; + uint8_t RESERVED2[0x860 - 0x858]; + FWK_RW uint32_t SCPPIKCLK_CTRL; + FWK_RW uint32_t SCPPIKCLK_DIV1; + uint8_t RESERVED3[0x870 - 0x868]; + FWK_RW uint32_t SYSPERCLK_CTRL; + FWK_RW uint32_t SYSPERCLK_DIV1; + uint8_t RESERVED4[0x8A0 - 0x878]; + FWK_RW uint32_t APUARTCLK_CTRL; + FWK_RW uint32_t APUARTCLK_DIV1; + uint8_t RESERVED5[0x8B0 - 0x8A8]; + FWK_RW uint32_t IONCICLK_CTRL; + FWK_RW uint32_t IONCICLK_DIV1; + uint8_t RESERVED6[0x900 - 0x8B8]; + FWK_RW uint32_t TCUCLK_CTRL; + FWK_RW uint32_t TCUCLK_DIV1; + uint8_t RESERVED7[0x940 - 0x908]; + FWK_RW uint32_t TCU_CLK_ENABLE; + FWK_RW uint32_t NCI_CLK_ENABLE; + uint8_t RESERVED8[0xA00 - 0x948]; + FWK_R uint32_t CLKFORCE_STATUS; + FWK_W uint32_t CLKFORCE_SET; + FWK_W uint32_t CLKFORCE_CLR; + uint8_t RESERVED9[0xB10 - 0xA0C]; + FWK_RW uint32_t IOMACRO_OVERRIDE; + FWK_RW uint32_t RSEPSI_STATUS; + FWK_RW uint32_t RSESAM_STATUS0; + FWK_RW uint32_t RSESAM_STATUS1; + FWK_RW uint32_t RSELCM_STATUS; + uint8_t RESERVED10[0xFC0 - 0xB24]; + FWK_R uint32_t PIK_CONFIG; + uint8_t RESERVED11[0xFD0 - 0xFC4]; + FWK_R uint32_t PID4; + FWK_R uint32_t PID5; + FWK_R uint32_t PID6; + FWK_R uint32_t PID7; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t ID0; + FWK_R uint32_t ID1; + FWK_R uint32_t ID2; + FWK_R uint32_t ID3; +}; +// clang-format on + +/* Pointer to SCP System PIK register block */ +#define SYSTEM_PIK_PTR ((struct system_pik_reg *)SCP_SYSTEM_PIK_BASE) + +#endif /* SYSTEM_PIK_H */ diff --git a/product/test/CMakeLists.txt b/product/test/CMakeLists.txt index c5558f1b33a4cfee16463c37ddd674d440036117..d0fc9fb5789ca424116f482c1afa7976ce8ebf73 100644 --- a/product/test/CMakeLists.txt +++ b/product/test/CMakeLists.txt @@ -110,6 +110,7 @@ list(APPEND SCP_UNITY_SRC ${SCP_ROOT}/unit_test/unity_mocks/scp_unity.c) #Append common unit tests under product/ below here (alphabetical order) list(APPEND UNIT_PRODUCT optee/common/module/mbx) +list(APPEND UNIT_PRODUCT automotive-rd/rd1ae/module/safety_island_platform) list(LENGTH UNIT_PRODUCT UNIT_PRODUCT_MAX) diff --git a/tools/config/check_build/default_products_build.yml b/tools/config/check_build/default_products_build.yml index 3175bd48743f4fa3bc1f81161ab92240f0e7c10b..be443eb1ac9f658937e959c3fb0096666203d837 100644 --- a/tools/config/check_build/default_products_build.yml +++ b/tools/config/check_build/default_products_build.yml @@ -56,3 +56,6 @@ - name: 0 - name: 1 product_group: totalcompute + +- product: rd1ae + product_group: automotive-rd