Platform: Add GPIO platform service for Musca-S1
On Musca-S1 GPIO is accessible only from the secure world
so a secure service is added for this platform to make it
accessible from the non-secure code as well.
Change-Id: I122c8fda72461bb9c7b20abc640183f552249766
Signed-off-by: Gabor Abonyi <gabor.abonyi@arm.com>
diff --git a/platform/ext/musca_s1.cmake b/platform/ext/musca_s1.cmake
index c5c476d..f2c8b90 100644
--- a/platform/ext/musca_s1.cmake
+++ b/platform/ext/musca_s1.cmake
@@ -59,6 +59,10 @@
embedded_include_directories(PATH "${PLATFORM_DIR}/../include" ABSOLUTE)
# Gather all source files we need.
+if (TFM_PARTITION_PLATFORM)
+ list(APPEND ALL_SRC_C_NS "${PLATFORM_DIR}/target/musca_s1/services/src/tfm_ioctl_ns_api.c")
+endif()
+
if (NOT DEFINED BUILD_CMSIS_CORE)
message(FATAL_ERROR "Configuration variable BUILD_CMSIS_CORE (true|false) is undefined!")
elseif (BUILD_CMSIS_CORE)
@@ -89,8 +93,9 @@
message(FATAL_ERROR "Configuration variable BUILD_NATIVE_DRIVERS (true|false) is undefined!")
elseif (BUILD_NATIVE_DRIVERS)
list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_s1/Native_Driver/uart_pl011_drv.c")
- list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/musca_s1/Native_Driver/mpc_sie200_drv.c")
list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_s1/Native_Driver/ppc_sse200_drv.c")
+ list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/musca_s1/Native_Driver/gpio_cmsdk_drv.c")
+ list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/musca_s1/Native_Driver/mpc_sie200_drv.c")
endif()
if (NOT DEFINED BUILD_TIME)
@@ -127,6 +132,7 @@
list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/musca_s1/Native_Driver/mpu_armv8m_drv.c")
if (TFM_PARTITION_PLATFORM)
list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/musca_s1/services/src/tfm_platform_system.c")
+ list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/musca_s1/services/src/tfm_ioctl_s_api.c")
endif()
list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/common/tfm_platform.c")
embedded_include_directories(PATH "${PLATFORM_DIR}/common" ABSOLUTE)
diff --git a/platform/ext/target/musca_s1/Device/Config/device_cfg.h b/platform/ext/target/musca_s1/Device/Config/device_cfg.h
index 94cefc0..8e296f9 100644
--- a/platform/ext/target/musca_s1/Device/Config/device_cfg.h
+++ b/platform/ext/target/musca_s1/Device/Config/device_cfg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Arm Limited. All rights reserved.
+ * Copyright (c) 2017-2020 Arm Limited. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +27,9 @@
* This is a default device configuration file with all peripherals enabled.
*/
+/* ARM GPIO */
+#define GPIO0_CMSDK_S
+
/* ARM Memory Protection Controller (MPC) SIE 200 */
#define MPC_ISRAM0_S
#define MPC_ISRAM1_S
diff --git a/platform/ext/target/musca_s1/Device/Include/device_definition.h b/platform/ext/target/musca_s1/Device/Include/device_definition.h
index 30b624d..5484672 100644
--- a/platform/ext/target/musca_s1/Device/Include/device_definition.h
+++ b/platform/ext/target/musca_s1/Device/Include/device_definition.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Arm Limited. All rights reserved.
+ * Copyright (c) 2017-2020 Arm Limited. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,10 +39,6 @@
#include "gpio_cmsdk_drv.h"
extern struct gpio_cmsdk_dev_t GPIO0_CMSDK_DEV_S;
#endif
-#ifdef GPIO0_CMSDK_NS
-#include "gpio_cmsdk_drv.h"
-extern struct gpio_cmsdk_dev_t GPIO0_CMSDK_DEV_NS;
-#endif
/* ARM MPC SIE 200 driver structures */
#ifdef MPC_ISRAM0_S
diff --git a/platform/ext/target/musca_s1/Device/Source/device_definition.c b/platform/ext/target/musca_s1/Device/Source/device_definition.c
index d6031d8..8a47e2f 100644
--- a/platform/ext/target/musca_s1/Device/Source/device_definition.c
+++ b/platform/ext/target/musca_s1/Device/Source/device_definition.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Arm Limited. All rights reserved.
+ * Copyright (c) 2017-2020 Arm Limited. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,11 +35,6 @@
.base = MUSCA_S1_GPIO_S_BASE};
struct gpio_cmsdk_dev_t GPIO0_CMSDK_DEV_S = {&(GPIO0_CMSDK_DEV_CFG_S)};
#endif
-#ifdef GPIO0_CMSDK_NS
-static const struct gpio_cmsdk_dev_cfg_t GPIO0_CMSDK_DEV_CFG_NS = {
- .base = MUSCA_S1_GPIO_NS_BASE};
-struct gpio_cmsdk_dev_t GPIO0_CMSDK_DEV_NS = {&(GPIO0_CMSDK_DEV_CFG_NS)};
-#endif
/* ARM PPC SSE 200 driver structures */
#ifdef AHB_PPC0_S
diff --git a/platform/ext/target/musca_s1/Native_Driver/gpio_cmsdk_drv.c b/platform/ext/target/musca_s1/Native_Driver/gpio_cmsdk_drv.c
new file mode 100644
index 0000000..7026069
--- /dev/null
+++ b/platform/ext/target/musca_s1/Native_Driver/gpio_cmsdk_drv.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2016-2018 Arm Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include "gpio_cmsdk_drv.h"
+
+/* GPIO register map structure */
+struct gpio_cmsdk_reg_map_t {
+ volatile uint32_t data; /* Offset: 0x000 (R/W) Data register */
+ volatile uint32_t dataout; /* Offset: 0x004 (R/W) Data output
+ * latch register */
+ volatile uint32_t reserved0[2];
+ volatile uint32_t outenableset; /* Offset: 0x010 (R/W) Output enable
+ * set register */
+ volatile uint32_t outenableclr; /* Offset: 0x014 (R/W) Output enable
+ * clear register */
+ volatile uint32_t altfuncset; /* Offset: 0x018 (R/W) Alternate function
+ * set register */
+ volatile uint32_t altfuncclr; /* Offset: 0x01C (R/W) Alternate function
+ * clear register */
+ volatile uint32_t intenset; /* Offset: 0x020 (R/W) Interrupt enable
+ * set register */
+ volatile uint32_t intenclr; /* Offset: 0x024 (R/W) Interrupt enable
+ * clear register */
+ volatile uint32_t inttypeset; /* Offset: 0x028 (R/W) Interrupt type
+ * set register */
+ volatile uint32_t inttypeclr; /* Offset: 0x02C (R/W) Interrupt type
+ * clear register */
+ volatile uint32_t intpolset; /* Offset: 0x030 (R/W) Interrupt polarity
+ * set register */
+ volatile uint32_t intpolclr; /* Offset: 0x034 (R/W) Interrupt polarity
+ * clear register */
+ union {
+ volatile uint32_t intstatus; /* Offset: 0x038 (R/ ) Interrupt status
+ * register */
+ volatile uint32_t intclear; /* Offset: 0x038 ( /W) Interrupt clear
+ * register */
+ }intreg;
+ volatile uint32_t reserved1[997];
+ volatile uint32_t pid4; /* Peripheral ID Register 4 */
+ volatile uint32_t pid0; /* Peripheral ID Register 0 */
+ volatile uint32_t pid1; /* Peripheral ID Register 1 */
+ volatile uint32_t pid2; /* Peripheral ID Register 2 */
+ volatile uint32_t pid3; /* Peripheral ID Register 3 */
+ volatile uint32_t cid0; /* Component ID Register 0 */
+ volatile uint32_t cid1; /* Component ID Register 1 */
+ volatile uint32_t cid2; /* Component ID Register 2 */
+ volatile uint32_t cid4; /* Component ID Register 3 */
+};
+
+void gpio_cmsdk_init(struct gpio_cmsdk_dev_t* dev)
+{
+ /* Nothing to init on the GPIO device */
+}
+
+/**
+ * \brief Configures port.
+ *
+ * \param[in] dev GPIO device to initalize \ref gpio_cmsdk_dev_t
+ * \param[in] pin_mask Pin mask for port access
+ * \param[in] direction Input or output \ref gpio_cmsdk_direction_t
+ * \param[in] altfunc_flags Alternate function \ref gpio_cmsdk_altfunc_t
+ *
+ */
+static void set_port_config(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
+ enum gpio_cmsdk_direction_t direction,
+ enum gpio_cmsdk_altfunc_t altfunc_flags)
+{
+ struct gpio_cmsdk_reg_map_t* p_gpio_port =
+ (struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
+
+ if(direction == GPIO_CMSDK_INPUT) {
+ p_gpio_port->outenableclr = pin_mask;
+ } else {
+ p_gpio_port->outenableset = pin_mask;
+ }
+
+ if (altfunc_flags == GPIO_CMSDK_MAIN_FUNC) {
+ p_gpio_port->altfuncclr = pin_mask;
+ } else {
+ p_gpio_port->altfuncset = pin_mask;
+ }
+
+ return;
+}
+
+enum gpio_cmsdk_error_t
+gpio_cmsdk_pin_config(struct gpio_cmsdk_dev_t* dev, uint32_t pin_num,
+ enum gpio_cmsdk_direction_t direction,
+ enum gpio_cmsdk_altfunc_t altfunc_flags)
+{
+ uint32_t pin_mask = (1UL << pin_num);
+
+ if(pin_num >= GPIO_CMSDK_MAX_PIN_NUM) {
+ return GPIO_CMSDK_ERR_INVALID_ARG;
+ }
+
+ set_port_config(dev, pin_mask, direction, altfunc_flags);
+
+ return GPIO_CMSDK_ERR_NONE;
+}
+
+enum gpio_cmsdk_error_t
+gpio_cmsdk_port_config(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
+ enum gpio_cmsdk_direction_t direction,
+ enum gpio_cmsdk_altfunc_t altfunc_flags)
+{
+ if(pin_mask > GPIO_CMSDK_MAX_PORT_MASK) {
+ return GPIO_CMSDK_ERR_INVALID_ARG;
+ }
+
+ set_port_config(dev, pin_mask, direction, altfunc_flags);
+
+ return GPIO_CMSDK_ERR_NONE;
+}
+
+void gpio_cmsdk_config_irq(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
+ enum gpio_cmsdk_irq_type_t irq_type,
+ enum gpio_cmsdk_irq_polarity_t irq_pol)
+{
+ struct gpio_cmsdk_reg_map_t* p_gpio_port =
+ (struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
+
+ /* Interrupt type: EDGE = 1 - LEVEL = 0 */
+ if(irq_type == GPIO_CMSDK_IRQ_EDGE) {
+ p_gpio_port->inttypeset = pin_mask;
+ } else if(irq_type == GPIO_CMSDK_IRQ_LEVEL) {
+ p_gpio_port->inttypeclr = pin_mask;
+ }
+
+ /* Interrupt polarity */
+ if(irq_pol == GPIO_CMSDK_IRQ_LOW_OR_FALLING_EDGE) {
+ p_gpio_port->intpolclr = pin_mask;
+ } else if(irq_pol == GPIO_CMSDK_IRQ_HIGH_OR_RISING_EDGE) {
+ p_gpio_port->intpolset = pin_mask;
+ }
+}
+
+enum gpio_cmsdk_error_t gpio_cmsdk_pin_write(struct gpio_cmsdk_dev_t* dev,
+ uint32_t pin_num,
+ uint32_t value)
+{
+ struct gpio_cmsdk_reg_map_t* p_gpio_port =
+ (struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
+
+ /* GPIO data output register is a read-modify-write register,
+ * so before writing a value on a GPIO pin it is required to disable
+ * the interrupts to prevent concurrency problems.
+ */
+ if(pin_num >= GPIO_CMSDK_MAX_PIN_NUM) {
+ return GPIO_CMSDK_ERR_INVALID_ARG;
+ }
+ if(value) {
+ /* Sets the pin */
+ p_gpio_port->dataout |= (1UL << pin_num);
+ } else {
+ /* Clears the pin */
+ p_gpio_port->dataout &= ~(1UL << pin_num);
+ }
+
+ return GPIO_CMSDK_ERR_NONE;
+}
+
+enum gpio_cmsdk_error_t gpio_cmsdk_port_write(struct gpio_cmsdk_dev_t* dev,
+ uint32_t pin_mask,
+ uint32_t value)
+{
+ struct gpio_cmsdk_reg_map_t* p_gpio_port =
+ (struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
+
+ /* GPIO data output register is a read-modify-write register,
+ * so before writing a value on a GPIO pin it is required to disable
+ * the interrupts to prevent concurrency problems.
+ */
+ if(pin_mask > GPIO_CMSDK_MAX_PORT_MASK) {
+ return GPIO_CMSDK_ERR_INVALID_ARG;
+ }
+
+ /* Clear all bits defined in the mask,
+ * and set selected bits from value parameter.
+ */
+ p_gpio_port->dataout =
+ ((~pin_mask & p_gpio_port->dataout) | (pin_mask & value));
+
+ return GPIO_CMSDK_ERR_NONE;
+}
+
+enum gpio_cmsdk_error_t
+gpio_cmsdk_pin_read(struct gpio_cmsdk_dev_t* dev,
+ uint32_t pin_num,
+ uint32_t *data)
+{
+ uint32_t value;
+ struct gpio_cmsdk_reg_map_t* p_gpio_port =
+ (struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
+
+ if(pin_num >= GPIO_CMSDK_MAX_PIN_NUM) {
+ return GPIO_CMSDK_ERR_INVALID_ARG;
+ }
+
+ value = p_gpio_port->data;
+
+ *data = (value >> pin_num) & 1UL;
+
+ return GPIO_CMSDK_ERR_NONE;
+}
+
+enum gpio_cmsdk_error_t
+gpio_cmsdk_port_read(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
+ uint32_t *data)
+{
+ struct gpio_cmsdk_reg_map_t* p_gpio_port =
+ (struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
+
+ if(pin_mask > GPIO_CMSDK_MAX_PORT_MASK) {
+ return GPIO_CMSDK_ERR_INVALID_ARG;
+ }
+
+ *data = p_gpio_port->data & pin_mask;
+
+ return GPIO_CMSDK_ERR_NONE;
+}
+
+enum gpio_cmsdk_error_t
+gpio_cmsdk_set_pin_irq_cfg(struct gpio_cmsdk_dev_t* dev, uint32_t pin_num,
+ enum gpio_cmsdk_irq_status_t status)
+{
+ struct gpio_cmsdk_reg_map_t* p_gpio_port =
+ (struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
+
+ if(pin_num >= GPIO_CMSDK_MAX_PIN_NUM) {
+ return GPIO_CMSDK_ERR_INVALID_ARG;
+ }
+
+ if(status == GPIO_CMSDK_IRQ_ENABLE) {
+ p_gpio_port->intenset = (1UL << pin_num);
+ } else {
+ p_gpio_port->intenclr = (1UL << pin_num);
+ }
+
+ return GPIO_CMSDK_ERR_NONE;
+}
+
+enum gpio_cmsdk_error_t
+gpio_cmsdk_set_port_irq_cfg(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
+ enum gpio_cmsdk_irq_status_t status)
+{
+ struct gpio_cmsdk_reg_map_t* p_gpio_port =
+ (struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
+
+ if(pin_mask > GPIO_CMSDK_MAX_PORT_MASK) {
+ return GPIO_CMSDK_ERR_INVALID_ARG;
+ }
+
+ if(status == GPIO_CMSDK_IRQ_ENABLE) {
+ p_gpio_port->intenset = pin_mask;
+ } else {
+ p_gpio_port->intenclr = pin_mask;
+ }
+
+ return GPIO_CMSDK_ERR_NONE;
+}
+
+enum gpio_cmsdk_error_t
+gpio_cmsdk_get_pin_irq_status(struct gpio_cmsdk_dev_t* dev,
+ uint32_t pin_num, uint32_t* status)
+{
+ struct gpio_cmsdk_reg_map_t* p_gpio_port =
+ (struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
+
+ if(pin_num >= GPIO_CMSDK_MAX_PIN_NUM) {
+ return GPIO_CMSDK_ERR_INVALID_ARG;
+ }
+
+ *status = ((p_gpio_port->intreg.intstatus >> pin_num) & 1UL);
+
+ return GPIO_CMSDK_ERR_NONE;
+}
+
+enum gpio_cmsdk_error_t
+gpio_cmsdk_get_port_irq_status(struct gpio_cmsdk_dev_t* dev,
+ uint32_t pin_mask, uint32_t* status)
+{
+ struct gpio_cmsdk_reg_map_t* p_gpio_port =
+ (struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
+
+ if(pin_mask > GPIO_CMSDK_MAX_PORT_MASK) {
+ return GPIO_CMSDK_ERR_INVALID_ARG;
+ }
+
+ *status = (p_gpio_port->intreg.intstatus & pin_mask);
+
+ return GPIO_CMSDK_ERR_NONE;
+}
+
+
+enum gpio_cmsdk_error_t gpio_cmsdk_clear_irq(struct gpio_cmsdk_dev_t* dev,
+ uint8_t pin_num)
+{
+ struct gpio_cmsdk_reg_map_t* p_gpio_port =
+ (struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
+
+ if(pin_num >= GPIO_CMSDK_MAX_PIN_NUM) {
+ return GPIO_CMSDK_ERR_INVALID_ARG;
+ }
+
+ p_gpio_port->intreg.intclear = (1UL << pin_num);
+
+ return GPIO_CMSDK_ERR_NONE;
+}
diff --git a/platform/ext/target/musca_s1/Native_Driver/gpio_cmsdk_drv.h b/platform/ext/target/musca_s1/Native_Driver/gpio_cmsdk_drv.h
new file mode 100644
index 0000000..1df0f5f
--- /dev/null
+++ b/platform/ext/target/musca_s1/Native_Driver/gpio_cmsdk_drv.h
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2016-2020 Arm Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file gpio_cmsdk_drv.h
+ * \brief Generic driver for ARM GPIO.
+ */
+
+#ifndef __GPIO_CMSDK_DRV_H__
+#define __GPIO_CMSDK_DRV_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GPIO_CMSDK_MAX_PIN_NUM 16U
+#define GPIO_CMSDK_MAX_PORT_MASK ((1U << GPIO_CMSDK_MAX_PIN_NUM) - 1U)
+
+/* GPIO enumeration types */
+enum gpio_cmsdk_direction_t {
+ GPIO_CMSDK_INPUT = 0, /*!< GPIO is input */
+ GPIO_CMSDK_OUTPUT /*!< GPIO is output */
+};
+
+enum gpio_cmsdk_altfunc_t {
+ GPIO_CMSDK_MAIN_FUNC = 0, /*!< Alternate function is not enabled */
+ GPIO_CMSDK_ALT_FUNC /*!< Alternate function is enabled */
+};
+
+enum gpio_cmsdk_irq_status_t {
+ GPIO_CMSDK_IRQ_DISABLE = 0, /*!< Disable interruptions */
+ GPIO_CMSDK_IRQ_ENABLE /*!< Enable interruptions */
+};
+
+enum gpio_cmsdk_irq_type_t {
+ GPIO_CMSDK_IRQ_LEVEL = 0, /*!< Level Interrupt */
+ GPIO_CMSDK_IRQ_EDGE /*!< Edge Interrupt */
+};
+
+enum gpio_cmsdk_irq_polarity_t {
+ GPIO_CMSDK_IRQ_LOW_OR_FALLING_EDGE = 0, /*!< Interrupt active low or
+ falling edge */
+ GPIO_CMSDK_IRQ_HIGH_OR_RISING_EDGE /*!< Interrupt active high or
+ rising edge */
+};
+
+enum gpio_cmsdk_error_t {
+ GPIO_CMSDK_ERR_NONE = 0, /*!< No error */
+ GPIO_CMSDK_ERR_INVALID_ARG, /*!< Error invalid input argument */
+ GPIO_CMSDK_ALTFUNC_EERROR, /*!< Alternate function returned error */
+};
+
+/* CMSDK GPIO device configuration structure */
+struct gpio_cmsdk_dev_cfg_t {
+ const uint32_t base; /*!< GPIO base address */
+};
+
+/* CMSDK GPIO device structure */
+struct gpio_cmsdk_dev_t {
+ const struct gpio_cmsdk_dev_cfg_t* const cfg; /*!< GPIO configuration */
+};
+
+/**
+ * \brief Initializes GPIO port.
+ *
+ * \param[in] dev GPIO device to initalize \ref gpio_cmsdk_dev_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+void gpio_cmsdk_init(struct gpio_cmsdk_dev_t* dev);
+
+/**
+ * \brief Configures pin.
+ *
+ * \param[in] dev GPIO device to configure \ref gpio_cmsdk_dev_t
+ * \param[in] pin_num Pin number for pin access
+ * \param[in] direction Input or output \ref gpio_cmsdk_direction_t
+ * \param[in] altfunc_flags Alternate function \ref gpio_cmsdk_altfunc_t
+ *
+ * \return Returns error code as specified in \ref gpio_cmsdk_flags_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum gpio_cmsdk_error_t
+gpio_cmsdk_pin_config(struct gpio_cmsdk_dev_t* dev, uint32_t pin_num,
+ enum gpio_cmsdk_direction_t direction,
+ enum gpio_cmsdk_altfunc_t altfunc_flags);
+
+/**
+ * \brief Configures port.
+ *
+ * \param[in] dev GPIO device to configure \ref gpio_cmsdk_dev_t
+ * \param[in] pin_mask Bitmask of the selected pins
+ * \param[in] direction Input or output \ref gpio_cmsdk_direction_t
+ * \param[in] altfunc_flags Alternate function \ref gpio_cmsdk_altfunc_t
+ *
+ * \return Returns error code as specified in \ref gpio_cmsdk_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum gpio_cmsdk_error_t
+gpio_cmsdk_port_config(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
+ enum gpio_cmsdk_direction_t direction,
+ enum gpio_cmsdk_altfunc_t altfunc_flags);
+
+
+/**
+ * \brief Configures interrupt type
+ *
+ * \param[in] dev GPIO device to initalize \ref gpio_cmsdk_dev_t
+ * \param[in] pin_mask Bitmask of the selected pins
+ * \param[in] irq_type Interrupt type \ref gpio_cmsdk_irq_type_t
+ * \param[in] irq_pol Interrupt polarity \ref gpio_cmsdk_irq_polarity_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+void gpio_cmsdk_config_irq(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
+ enum gpio_cmsdk_irq_type_t irq_type,
+ enum gpio_cmsdk_irq_polarity_t irq_pol);
+
+/**
+ * \brief Sets state of the output pin.
+ *
+ * \param[in] dev GPIO device to use for the pin \ref gpio_cmsdk_dev_t
+ * \param[in] pin_num Pin number for pin access
+ * \param[in] value Value(s) to set.
+ *
+ * \return Returns error code as specified in \ref gpio_cmsdk_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ * \note GPIO data output register is a read-modify-write register,
+ * so before writing a value on a GPIO pin it is required to disable
+ * the interrupts to prevent concurrency problems.
+ */
+enum gpio_cmsdk_error_t gpio_cmsdk_pin_write(struct gpio_cmsdk_dev_t* dev,
+ uint32_t pin_num,
+ uint32_t value);
+
+/**
+ * \brief Sets state of the output port.
+ *
+ * \param[in] dev GPIO device to use for the pins \ref gpio_cmsdk_dev_t
+ * \param[in] pin_mask Bitmask of the selected pins
+ * \param[in] value Bitmask of pins states to set
+ *
+ * \return Returns error code as specified in \ref gpio_cmsdk_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ * \note GPIO data output register is a read-modify-write register,
+ * so before writing a value on a GPIO pin it is required to disable
+ * the interrupts to prevent concurrency problems.
+ */
+enum gpio_cmsdk_error_t gpio_cmsdk_port_write(struct gpio_cmsdk_dev_t* dev,
+ uint32_t pin_mask,
+ uint32_t value);
+
+/**
+ * \brief Reads the pin status.
+ *
+ * \param[in] dev GPIO device to use for the pin \ref gpio_cmsdk_dev_t
+ * \param[in] pin_num Pin number for pin access
+ * \param[out] data Bit value read from the IO pin
+ *
+ * \return Returns error code as specified in \ref gpio_cmsdk_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum gpio_cmsdk_error_t
+gpio_cmsdk_pin_read(struct gpio_cmsdk_dev_t* dev, uint32_t pin_num,
+ uint32_t *data);
+
+/**
+ * \brief Reads the port status.
+ *
+ * \param[in] dev GPIO device to use for the pins \ref gpio_cmsdk_dev_t
+ * \param[in] pin_mask Bitmask of the selected pins
+ * \param[out] data Bit values for the mask read from the IO pin
+ *
+ * \return Returns error code as specified in \ref gpio_cmsdk_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum gpio_cmsdk_error_t
+gpio_cmsdk_port_read(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
+ uint32_t *data);
+
+/**
+ * \brief Enables/disables interrupt for the given pin.
+ *
+ * \param[in] dev GPIO device to initalize \ref gpio_cmsdk_dev_t
+ * \param[in] pin_num Pin number to configure
+ * \param[in] status Interrupt status \ref gpio_cmsdk_irq_status
+ *
+ * \return Returns error code as specified in \ref gpio_cmsdk_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum gpio_cmsdk_error_t
+gpio_cmsdk_set_pin_irq_cfg(struct gpio_cmsdk_dev_t* dev, uint32_t pin_num,
+ enum gpio_cmsdk_irq_status_t status);
+
+/**
+ * \brief Enables/disables interrupt for the given pins.
+ *
+ * \param[in] dev GPIO device to use for the pins \ref gpio_cmsdk_dev_t
+ * \param[in] pin_mask Bitmask of the pins to configure
+ * \param[in] status Interrupt status \ref gpio_cmsdk_irq_status
+ *
+ * \return Returns error code as specified in \ref gpio_cmsdk_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum gpio_cmsdk_error_t
+gpio_cmsdk_set_port_irq_cfg(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
+ enum gpio_cmsdk_irq_status_t status);
+
+/**
+ * \brief Get interrupt status for the given pin.
+ *
+ * \param[in] dev GPIO device to use for the pin \ref gpio_cmsdk_dev_t
+ * \param[in] pin_num Pin number for the access
+ * \param[out] status Interrupt status values. If the access is by pin, then
+ * the status will be 0 or 1.
+ *
+ * \return Returns error code as specified in \ref gpio_cmsdk_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum gpio_cmsdk_error_t
+gpio_cmsdk_get_pin_irq_status(struct gpio_cmsdk_dev_t* dev,
+ uint32_t pin_num, uint32_t* status);
+
+/**
+ * \brief Get interrupt status for the given port.
+ *
+ * \param[in] dev GPIO device to use for the pins \ref gpio_cmsdk_dev_t
+ * \param[in] pin_mask Bitmask of the pins to configure
+ * \param[out] status Interrupt status values. If the access is by pin,
+ * then the status will be 0 or 1.
+ *
+ * \return Returns error code as specified in \ref gpio_cmsdk_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum gpio_cmsdk_error_t
+gpio_cmsdk_get_port_irq_status(struct gpio_cmsdk_dev_t* dev,
+ uint32_t pin_mask, uint32_t* status);
+
+/**
+ * \brief Clears gpio interrupt.
+ *
+ * \param[in] dev GPIO device to initalize \ref gpio_cmsdk_dev_t
+ * \param[in] pin_num Pin number.
+ *
+ * \return Returns error code as specified in \ref gpio_cmsdk_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum gpio_cmsdk_error_t gpio_cmsdk_clear_irq(struct gpio_cmsdk_dev_t* dev,
+ uint8_t pin_num);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __GPIO_CMSDK_DRV_H__ */
diff --git a/platform/ext/target/musca_s1/services/include/tfm_ioctl_api.h b/platform/ext/target/musca_s1/services/include/tfm_ioctl_api.h
new file mode 100644
index 0000000..eedeca5
--- /dev/null
+++ b/platform/ext/target/musca_s1/services/include/tfm_ioctl_api.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_IOCTL_API__
+#define __TFM_IOCTL_API__
+
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include "tfm_api.h"
+#include "tfm_platform_api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum tfm_platform_ioctl_reqest_types_t {
+ TFM_PLATFORM_IOCTL_GPIO_SERVICE,
+};
+
+/*!
+ * \enum tfm_gpio_service_type_t
+ *
+ * \brief GPIO service types (supported types may vary based on the platform)
+ */
+enum tfm_gpio_service_type_t {
+ TFM_GPIO_SERVICE_TYPE_INIT = 0, /*!< Init */
+ TFM_GPIO_SERVICE_TYPE_PIN_CONFIG, /*!< Pin config */
+ TFM_GPIO_SERVICE_TYPE_PIN_WRITE, /*!< Pin write */
+ TFM_GPIO_SERVICE_TYPE_PIN_READ, /*!< Pin read */
+ TFM_GPIO_SERVICE_TYPE_PORT_CONFIG, /*!< Port config */
+ TFM_GPIO_SERVICE_TYPE_PORT_WRITE, /*!< Port write */
+ TFM_GPIO_SERVICE_TYPE_PORT_READ, /*!< Port read */
+ TFM_GPIO_SERVICE_TYPE_MAX = INT_MAX /*!< Max to force enum max size */
+};
+
+/*!
+ * \struct tfm_gpio_service_args_t
+ *
+ * \brief Argument list for each platform GPIO service
+ */
+struct tfm_gpio_service_args_t {
+ enum tfm_gpio_service_type_t type;
+ union {
+ struct gpio_config_args { /*!< TFM_GPIO_SERVICE_TYPE_PIN_CONFIG ||
+ TFM_GPIO_SERVICE_TYPE_PORT_CONFIG */
+ uint32_t pin_num_or_mask;
+ uint32_t direction;
+ } gpio_config;
+ struct gpio_write_args { /*!< TFM_GPIO_SERVICE_TYPE_PIN_WRITE ||
+ TFM_GPIO_SERVICE_TYPE_PORT_WRITE */
+ uint32_t pin_num_or_mask;
+ uint32_t value;
+ } gpio_write;
+ struct gpio_read_args { /*!< TFM_GPIO_SERVICE_TYPE_PIN_READ ||
+ TFM_GPIO_SERVICE_TYPE_PORT_READ */
+ uint32_t pin_num_or_mask;
+ } gpio_read;
+ } u;
+};
+
+/*!
+ * \struct tfm_gpio_service_out_t
+ *
+ * \brief Output list for each GPIO platform service
+ */
+struct tfm_gpio_service_out_t {
+ union {
+ uint32_t result; /*!< Generic result */
+ struct gpio_read_result { /*!< TFM_GPIO_SERVICE_TYPE_PIN_READ ||
+ TFM_GPIO_SERVICE_TYPE_PORT_READ */
+ uint32_t result;
+ uint32_t data;
+ } gpio_read_result;
+ } u;
+};
+
+/*!
+ * \brief Initializes GPIO module
+ *
+ * \param[out] result Return error value
+ *
+ * \return Returns values as specified by the \ref tfm_platform_err_t
+ */
+enum tfm_platform_err_t tfm_platform_gpio_init(uint32_t *result);
+
+/*!
+ * \brief Configures a GPIO pin as input or output
+ *
+ * \param[in] pin_num Pin number of the selected pin
+ * \param[in] direction Direction of the pin: 0 for input, 1 for output
+ * \param[out] result Return error value
+ *
+ * \return Returns values as specified by the \ref tfm_platform_err_t
+ */
+enum tfm_platform_err_t
+tfm_platform_gpio_pin_config(uint32_t pin_num, uint32_t direction,
+ uint32_t *result);
+
+/*!
+ * \brief Sets state of a selected GPIO pin
+ *
+ * \param[in] pin_num Pin number of the selected pin
+ * \param[in] value Value to set for the pin
+ * \param[out] result Return error value
+ *
+ * \return Returns values as specified by the \ref tfm_platform_err_t
+ */
+enum tfm_platform_err_t
+tfm_platform_gpio_pin_write(uint32_t pin_num, uint32_t value, uint32_t *result);
+
+/*!
+ * \brief Reads state of a selected GPIO pin
+ *
+ * \param[in] pin_num Pin number of the selected pin
+ * \param[in,out] data Bit value read from the IO pin
+ * \param[out] result Return error value
+ *
+ * \return Returns values as specified by the \ref tfm_platform_err_t
+ */
+enum tfm_platform_err_t
+tfm_platform_gpio_pin_read(uint32_t pin_num, uint32_t *data, uint32_t *result);
+
+/*!
+ * \brief Configures GPIO pins as input or output
+ *
+ * \param[in] pin_mask Pin mask of the selected pins
+ * \param[in] direction Direction of the pin: 0 for input, 1 for output
+ * \param[out] result Return error value
+ *
+ * \return Returns values as specified by the \ref tfm_platform_err_t
+ */
+enum tfm_platform_err_t
+tfm_platform_gpio_port_config(uint32_t pin_mask, uint32_t direction,
+ uint32_t *result);
+
+/*!
+ * \brief Sets state of a selected GPIO pins
+ *
+ * \param[in] pin_mask Pin mask of the selected pins
+ * \param[in] value Value mask to set for the pins
+ * \param[out] result Return error value
+ *
+ * \return Returns values as specified by the \ref tfm_platform_err_t
+ */
+enum tfm_platform_err_t
+tfm_platform_gpio_port_write(uint32_t pin_mask, uint32_t value,
+ uint32_t *result);
+
+/*!
+ * \brief Reads state of a selected GPIO pins
+ *
+ * \param[in] pin_mask Pin mask of the selected pins
+ * \param[in,out] data Bit value mask read from the IO pins
+ * \param[out] result Return error value
+ *
+ * \return Returns values as specified by the \ref tfm_platform_err_t
+ */
+enum tfm_platform_err_t
+tfm_platform_gpio_port_read(uint32_t pin_mask, uint32_t *data,
+ uint32_t *result);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_IOCTL_API__ */
diff --git a/platform/ext/target/musca_s1/services/src/tfm_ioctl_ns_api.c b/platform/ext/target/musca_s1/services/src/tfm_ioctl_ns_api.c
new file mode 100644
index 0000000..432dc33
--- /dev/null
+++ b/platform/ext/target/musca_s1/services/src/tfm_ioctl_ns_api.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "tfm_platform_api.h"
+#include "services/include/tfm_ioctl_api.h"
+
+enum tfm_platform_err_t tfm_platform_gpio_init(uint32_t *result)
+{
+ enum tfm_platform_err_t ret;
+ psa_invec in_vec;
+ psa_outvec out_vec;
+ struct tfm_gpio_service_args_t args;
+ struct tfm_gpio_service_out_t out;
+
+ args.type = TFM_GPIO_SERVICE_TYPE_INIT;
+
+ in_vec.base = (const void *)&args;
+ in_vec.len = sizeof(args);
+
+ out_vec.base = (void *)&out;
+ out_vec.len = sizeof(out);
+
+ ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
+ &in_vec,
+ &out_vec);
+
+ *result = out.u.result;
+
+ return ret;
+}
+
+enum tfm_platform_err_t
+tfm_platform_gpio_pin_config(uint32_t pin_num, uint32_t direction,
+ uint32_t *result)
+{
+ enum tfm_platform_err_t ret;
+ psa_invec in_vec;
+ psa_outvec out_vec;
+ struct tfm_gpio_service_args_t args;
+ struct tfm_gpio_service_out_t out;
+
+ args.type = TFM_GPIO_SERVICE_TYPE_PIN_CONFIG;
+ args.u.gpio_config.pin_num_or_mask = pin_num;
+ args.u.gpio_config.direction = direction;
+
+ in_vec.base = (const void *)&args;
+ in_vec.len = sizeof(args);
+
+ out_vec.base = (void *)&out;
+ out_vec.len = sizeof(out);
+
+ ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
+ &in_vec,
+ &out_vec);
+
+ *result = out.u.result;
+
+ return ret;
+}
+
+enum tfm_platform_err_t
+tfm_platform_gpio_pin_write(uint32_t pin_num, uint32_t value, uint32_t *result)
+{
+ enum tfm_platform_err_t ret;
+ psa_invec in_vec;
+ psa_outvec out_vec;
+ struct tfm_gpio_service_args_t args;
+ struct tfm_gpio_service_out_t out;
+
+ args.type = TFM_GPIO_SERVICE_TYPE_PIN_WRITE;
+ args.u.gpio_write.pin_num_or_mask = pin_num;
+ args.u.gpio_write.value = value;
+
+ in_vec.base = (const void *)&args;
+ in_vec.len = sizeof(args);
+
+ out_vec.base = (void *)&out;
+ out_vec.len = sizeof(out);
+
+ ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
+ &in_vec,
+ &out_vec);
+
+ *result = out.u.result;
+
+ return ret;
+}
+
+enum tfm_platform_err_t
+tfm_platform_gpio_pin_read(uint32_t pin_num, uint32_t *data, uint32_t *result)
+{
+ enum tfm_platform_err_t ret;
+ psa_invec in_vec;
+ psa_outvec out_vec;
+ struct tfm_gpio_service_args_t args;
+ struct tfm_gpio_service_out_t out;
+
+ args.type = TFM_GPIO_SERVICE_TYPE_PIN_READ;
+ args.u.gpio_read.pin_num_or_mask = pin_num;
+
+ in_vec.base = (const void *)&args;
+ in_vec.len = sizeof(args);
+
+ out_vec.base = (void *)&out;
+ out_vec.len = sizeof(out);
+
+ ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
+ &in_vec,
+ &out_vec);
+
+ *result = out.u.gpio_read_result.result;
+ *data = out.u.gpio_read_result.data;
+
+ return ret;
+}
+
+enum tfm_platform_err_t
+tfm_platform_gpio_port_config(uint32_t pin_mask, uint32_t direction,
+ uint32_t *result)
+{
+ enum tfm_platform_err_t ret;
+ psa_invec in_vec;
+ psa_outvec out_vec;
+ struct tfm_gpio_service_args_t args;
+ struct tfm_gpio_service_out_t out;
+
+ args.type = TFM_GPIO_SERVICE_TYPE_PORT_CONFIG;
+ args.u.gpio_config.pin_num_or_mask = pin_mask;
+ args.u.gpio_config.direction = direction;
+
+ in_vec.base = (const void *)&args;
+ in_vec.len = sizeof(args);
+
+ out_vec.base = (void *)&out;
+ out_vec.len = sizeof(out);
+
+ ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
+ &in_vec,
+ &out_vec);
+
+ *result = out.u.result;
+
+ return ret;
+}
+
+enum tfm_platform_err_t
+tfm_platform_gpio_port_write(uint32_t pin_mask, uint32_t value,
+ uint32_t *result)
+{
+ enum tfm_platform_err_t ret;
+ psa_invec in_vec;
+ psa_outvec out_vec;
+ struct tfm_gpio_service_args_t args;
+ struct tfm_gpio_service_out_t out;
+
+ args.type = TFM_GPIO_SERVICE_TYPE_PORT_WRITE;
+ args.u.gpio_write.pin_num_or_mask = pin_mask;
+ args.u.gpio_write.value = value;
+
+ in_vec.base = (const void *)&args;
+ in_vec.len = sizeof(args);
+
+ out_vec.base = (void *)&out;
+ out_vec.len = sizeof(out);
+
+ ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
+ &in_vec,
+ &out_vec);
+
+ *result = out.u.result;
+
+ return ret;
+
+}
+
+enum tfm_platform_err_t
+tfm_platform_gpio_port_read(uint32_t pin_mask, uint32_t *data, uint32_t *result)
+{
+ enum tfm_platform_err_t ret;
+ psa_invec in_vec;
+ psa_outvec out_vec;
+ struct tfm_gpio_service_args_t args;
+ struct tfm_gpio_service_out_t out;
+
+ args.type = TFM_GPIO_SERVICE_TYPE_PORT_READ;
+ args.u.gpio_read.pin_num_or_mask = pin_mask;
+
+ in_vec.base = (const void *)&args;
+ in_vec.len = sizeof(args);
+
+ out_vec.base = (void *)&out;
+ out_vec.len = sizeof(out);
+
+ ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
+ &in_vec,
+ &out_vec);
+
+ *result = out.u.gpio_read_result.result;
+ *data = out.u.gpio_read_result.data;
+
+ return ret;
+}
diff --git a/platform/ext/target/musca_s1/services/src/tfm_ioctl_s_api.c b/platform/ext/target/musca_s1/services/src/tfm_ioctl_s_api.c
new file mode 100644
index 0000000..a53fc16
--- /dev/null
+++ b/platform/ext/target/musca_s1/services/src/tfm_ioctl_s_api.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "tfm_platform_api.h"
+#include "services/include/tfm_ioctl_api.h"
+
+__attribute__((section("SFN")))
+enum tfm_platform_err_t tfm_platform_gpio_init(uint32_t *result)
+{
+ psa_status_t ret;
+ psa_invec in_vec;
+ psa_outvec out_vec;
+ struct tfm_gpio_service_args_t args;
+ struct tfm_gpio_service_out_t out;
+
+ args.type = TFM_GPIO_SERVICE_TYPE_INIT;
+
+ in_vec.base = (const void *)&args;
+ in_vec.len = sizeof(args);
+
+ out_vec.base = (void *)&out;
+ out_vec.len = sizeof(out);
+
+ ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
+ &in_vec,
+ &out_vec);
+
+ *result = out.u.result;
+
+ return ret;
+}
+
+__attribute__((section("SFN")))
+enum tfm_platform_err_t
+tfm_platform_gpio_pin_config(uint32_t pin_num, uint32_t direction,
+ uint32_t *result)
+{
+ psa_status_t ret;
+ psa_invec in_vec;
+ psa_outvec out_vec;
+ struct tfm_gpio_service_args_t args;
+ struct tfm_gpio_service_out_t out;
+
+ args.type = TFM_GPIO_SERVICE_TYPE_PIN_CONFIG;
+ args.u.gpio_config.pin_num_or_mask = pin_num;
+ args.u.gpio_config.direction = direction;
+
+ in_vec.base = (const void *)&args;
+ in_vec.len = sizeof(args);
+
+ out_vec.base = (void *)&out;
+ out_vec.len = sizeof(out);
+
+ ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
+ &in_vec,
+ &out_vec);
+
+ *result = out.u.result;
+
+ return ret;
+}
+
+__attribute__((section("SFN")))
+enum tfm_platform_err_t
+tfm_platform_gpio_pin_write(uint32_t pin_num, uint32_t value, uint32_t *result)
+{
+ psa_status_t ret;
+ psa_invec in_vec;
+ psa_outvec out_vec;
+ struct tfm_gpio_service_args_t args;
+ struct tfm_gpio_service_out_t out;
+
+ args.type = TFM_GPIO_SERVICE_TYPE_PIN_WRITE;
+ args.u.gpio_write.pin_num_or_mask = pin_num;
+ args.u.gpio_write.value = value;
+
+ in_vec.base = (const void *)&args;
+ in_vec.len = sizeof(args);
+
+ out_vec.base = (void *)&out;
+ out_vec.len = sizeof(out);
+
+ ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
+ &in_vec,
+ &out_vec);
+
+ *result = out.u.result;
+
+ return ret;
+}
+
+__attribute__((section("SFN")))
+enum tfm_platform_err_t
+tfm_platform_gpio_pin_read(uint32_t pin_num, uint32_t *data, uint32_t *result)
+{
+ psa_status_t ret;
+ psa_invec in_vec;
+ psa_outvec out_vec;
+ struct tfm_gpio_service_args_t args;
+ struct tfm_gpio_service_out_t out;
+
+ args.type = TFM_GPIO_SERVICE_TYPE_PIN_READ;
+ args.u.gpio_read.pin_num_or_mask = pin_num;
+
+ in_vec.base = (const void *)&args;
+ in_vec.len = sizeof(args);
+
+ out_vec.base = (void *)&out;
+ out_vec.len = sizeof(out);
+
+ ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
+ &in_vec,
+ &out_vec);
+
+ *result = out.u.gpio_read_result.result;
+ *data = out.u.gpio_read_result.data;
+
+ return ret;
+}
+
+__attribute__((section("SFN")))
+enum tfm_platform_err_t
+tfm_platform_gpio_port_config(uint32_t pin_mask, uint32_t direction,
+ uint32_t *result)
+{
+ psa_status_t ret;
+ psa_invec in_vec;
+ psa_outvec out_vec;
+ struct tfm_gpio_service_args_t args;
+ struct tfm_gpio_service_out_t out;
+
+ args.type = TFM_GPIO_SERVICE_TYPE_PORT_CONFIG;
+ args.u.gpio_config.pin_num_or_mask = pin_mask;
+ args.u.gpio_config.direction = direction;
+
+ in_vec.base = (const void *)&args;
+ in_vec.len = sizeof(args);
+
+ out_vec.base = (void *)&out;
+ out_vec.len = sizeof(out);
+
+ ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
+ &in_vec,
+ &out_vec);
+
+ *result = out.u.result;
+
+ return ret;
+}
+
+__attribute__((section("SFN")))
+enum tfm_platform_err_t
+tfm_platform_gpio_port_write(uint32_t pin_mask, uint32_t value,
+ uint32_t *result)
+{
+ psa_status_t ret;
+ psa_invec in_vec;
+ psa_outvec out_vec;
+ struct tfm_gpio_service_args_t args;
+ struct tfm_gpio_service_out_t out;
+
+ args.type = TFM_GPIO_SERVICE_TYPE_PORT_WRITE;
+ args.u.gpio_write.pin_num_or_mask = pin_mask;
+ args.u.gpio_write.value = value;
+
+ in_vec.base = (const void *)&args;
+ in_vec.len = sizeof(args);
+
+ out_vec.base = (void *)&out;
+ out_vec.len = sizeof(out);
+
+ ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
+ &in_vec,
+ &out_vec);
+
+ *result = out.u.result;
+
+ return ret;
+}
+
+__attribute__((section("SFN")))
+enum tfm_platform_err_t
+tfm_platform_gpio_port_read(uint32_t pin_mask, uint32_t *data, uint32_t *result)
+{
+ psa_status_t ret;
+ psa_invec in_vec;
+ psa_outvec out_vec;
+ struct tfm_gpio_service_args_t args;
+ struct tfm_gpio_service_out_t out;
+
+ args.type = TFM_GPIO_SERVICE_TYPE_PORT_READ;
+ args.u.gpio_read.pin_num_or_mask = pin_mask;
+
+ in_vec.base = (const void *)&args;
+ in_vec.len = sizeof(args);
+
+ out_vec.base = (void *)&out;
+ out_vec.len = sizeof(out);
+
+ ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
+ &in_vec,
+ &out_vec);
+
+ *result = out.u.gpio_read_result.result;
+ *data = out.u.gpio_read_result.data;
+
+ return ret;
+}
diff --git a/platform/ext/target/musca_s1/services/src/tfm_platform_system.c b/platform/ext/target/musca_s1/services/src/tfm_platform_system.c
index 78d8f38..333fc1e 100644
--- a/platform/ext/target/musca_s1/services/src/tfm_platform_system.c
+++ b/platform/ext/target/musca_s1/services/src/tfm_platform_system.c
@@ -1,12 +1,17 @@
/*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
+#include <stdbool.h>
#include "platform/include/tfm_platform_system.h"
#include "platform_description.h"
+#include "target_cfg.h"
+#include "device_definition.h"
+#include "psa/client.h"
+#include "services/include/tfm_ioctl_api.h"
void tfm_platform_hal_system_reset(void)
{
@@ -14,15 +19,87 @@
NVIC_SystemReset();
}
+enum tfm_platform_err_t
+tfm_platform_hal_gpio_service(const psa_invec *in_vec,
+ const psa_outvec *out_vec)
+{
+ struct tfm_gpio_service_args_t *args;
+ struct tfm_gpio_service_out_t *out;
+ enum gpio_cmsdk_direction_t dir;
+ /* Alternate function is configured through the SCC, this is not used
+ * on Musca-S1, the default value is passed to the driver
+ */
+ enum gpio_cmsdk_altfunc_t altfunc = GPIO_CMSDK_MAIN_FUNC;
+
+ if (in_vec->len != sizeof(struct tfm_gpio_service_args_t) ||
+ out_vec->len != sizeof(struct tfm_gpio_service_out_t)) {
+ return TFM_PLATFORM_ERR_INVALID_PARAM;
+ }
+
+ args = (struct tfm_gpio_service_args_t *)in_vec->base;
+ out = (struct tfm_gpio_service_out_t *)out_vec->base;
+ switch (args->type) {
+ case TFM_GPIO_SERVICE_TYPE_INIT:
+ gpio_cmsdk_init(&GPIO0_CMSDK_DEV_S);
+ out->u.result = GPIO_CMSDK_ERR_NONE;
+ break;
+ case TFM_GPIO_SERVICE_TYPE_PIN_CONFIG:
+ dir = (enum gpio_cmsdk_direction_t)args->u.gpio_config.direction;
+ out->u.result = gpio_cmsdk_pin_config(
+ &GPIO0_CMSDK_DEV_S,
+ args->u.gpio_config.pin_num_or_mask,
+ dir, altfunc);
+ break;
+ case TFM_GPIO_SERVICE_TYPE_PIN_WRITE:
+ out->u.result = gpio_cmsdk_pin_write(
+ &GPIO0_CMSDK_DEV_S,
+ args->u.gpio_write.pin_num_or_mask,
+ args->u.gpio_write.value);
+ break;
+ case TFM_GPIO_SERVICE_TYPE_PIN_READ:
+ out->u.gpio_read_result.result =
+ gpio_cmsdk_pin_read(&GPIO0_CMSDK_DEV_S,
+ args->u.gpio_read.pin_num_or_mask,
+ &out->u.gpio_read_result.data);
+ break;
+ case TFM_GPIO_SERVICE_TYPE_PORT_CONFIG:
+ dir = (enum gpio_cmsdk_direction_t)args->u.gpio_config.direction;
+ out->u.result = gpio_cmsdk_port_config(
+ &GPIO0_CMSDK_DEV_S,
+ args->u.gpio_config.pin_num_or_mask,
+ dir, altfunc);
+ break;
+ case TFM_GPIO_SERVICE_TYPE_PORT_WRITE:
+ out->u.result = gpio_cmsdk_port_write(
+ &GPIO0_CMSDK_DEV_S,
+ args->u.gpio_write.pin_num_or_mask,
+ args->u.gpio_write.value);
+ break;
+ case TFM_GPIO_SERVICE_TYPE_PORT_READ:
+ out->u.gpio_read_result.result =
+ gpio_cmsdk_port_read(&GPIO0_CMSDK_DEV_S,
+ args->u.gpio_read.pin_num_or_mask,
+ &out->u.gpio_read_result.data);
+ break;
+ default:
+ out->u.result = GPIO_CMSDK_ERR_INVALID_ARG;
+ break;
+ }
+
+ in_vec++;
+ out_vec++;
+
+ return TFM_PLATFORM_ERR_SUCCESS;
+}
+
enum tfm_platform_err_t tfm_platform_hal_ioctl(tfm_platform_ioctl_req_t request,
psa_invec *in_vec,
psa_outvec *out_vec)
{
- (void)request;
- (void)in_vec;
- (void)out_vec;
-
- /* Not needed for this platform */
- return TFM_PLATFORM_ERR_NOT_SUPPORTED;
+ switch (request) {
+ case TFM_PLATFORM_IOCTL_GPIO_SERVICE:
+ return tfm_platform_hal_gpio_service(in_vec, out_vec);
+ default:
+ return TFM_PLATFORM_ERR_NOT_SUPPORTED;
+ }
}
-