aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamas Kaman <tamas.kaman@arm.com>2019-11-17 15:34:47 +0100
committerTamas Kaman <tamas.kaman@arm.com>2019-12-13 15:49:37 +0100
commitd326142f2465ea74b88fcf9ddd23a8285de62f00 (patch)
treec00ca916e764c12a6cbe83978d45522439a7dc9d
parent28d993c7c483966b7d71ac2dd4c691ee6ba29c5d (diff)
downloadtrusted-firmware-m-master.tar.gz
Platform: Add GPIO platform service for Musca-A and B1HEADmaster
Both on Musca-A and Musca-B1 GPIO is accessible only from the secure world so a secure service is added for these platforms to make it accessible from the non-secure code as well. Signed-off-by: Tamas Kaman <tamas.kaman@arm.com> Change-Id: I0d65d6f43efb31236ea75b5c18d279d7d02e3b91
-rw-r--r--platform/ext/musca_a.cmake7
-rw-r--r--platform/ext/musca_b1.cmake1
-rw-r--r--platform/ext/target/musca_a/Device/Config/device_cfg.h3
-rw-r--r--platform/ext/target/musca_a/Device/Include/device_definition.h4
-rw-r--r--platform/ext/target/musca_a/Device/Source/device_definition.c5
-rw-r--r--platform/ext/target/musca_a/Native_Driver/gpio_cmsdk_drv.c324
-rw-r--r--platform/ext/target/musca_a/Native_Driver/gpio_cmsdk_drv.h279
-rw-r--r--platform/ext/target/musca_a/services/include/tfm_ioctl_api.h171
-rw-r--r--platform/ext/target/musca_a/services/src/tfm_ioctl_ns_api.c207
-rw-r--r--platform/ext/target/musca_a/services/src/tfm_ioctl_s_api.c207
-rw-r--r--platform/ext/target/musca_a/services/src/tfm_platform_system.c124
-rw-r--r--platform/ext/target/musca_b1/Device/Config/device_cfg.h3
-rw-r--r--platform/ext/target/musca_b1/Device/Include/device_definition.h4
-rw-r--r--platform/ext/target/musca_b1/Device/Source/device_definition.c5
-rw-r--r--platform/ext/target/musca_b1/Native_Driver/gpio_cmsdk_drv.c324
-rw-r--r--platform/ext/target/musca_b1/Native_Driver/gpio_cmsdk_drv.h279
-rw-r--r--platform/ext/target/musca_b1/services/include/tfm_ioctl_api.h144
-rw-r--r--platform/ext/target/musca_b1/services/src/tfm_ioctl_ns_api.c198
-rw-r--r--platform/ext/target/musca_b1/services/src/tfm_ioctl_s_api.c198
-rw-r--r--platform/ext/target/musca_b1/services/src/tfm_platform_system.c94
20 files changed, 2550 insertions, 31 deletions
diff --git a/platform/ext/musca_a.cmake b/platform/ext/musca_a.cmake
index 69fdec895..9d76f37f2 100644
--- a/platform/ext/musca_a.cmake
+++ b/platform/ext/musca_a.cmake
@@ -42,10 +42,15 @@ embedded_include_directories(PATH "${PLATFORM_DIR}/target/musca_a/Device/Config"
embedded_include_directories(PATH "${PLATFORM_DIR}/target/musca_a/Device/Include" ABSOLUTE)
embedded_include_directories(PATH "${PLATFORM_DIR}/target/musca_a/Native_Driver" ABSOLUTE)
embedded_include_directories(PATH "${PLATFORM_DIR}/target/musca_a/partition" ABSOLUTE)
+embedded_include_directories(PATH "${PLATFORM_DIR}/target/musca_a/services/include" ABSOLUTE)
embedded_include_directories(PATH "${PLATFORM_DIR}/target/musca_a/Libraries" ABSOLUTE)
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_a/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)
@@ -78,6 +83,7 @@ elseif(BUILD_NATIVE_DRIVERS)
list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_a/Native_Driver/uart_pl011_drv.c")
list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_a/Native_Driver/musca_a1_scc_drv.c")
list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_a/Native_Driver/qspi_ip6514e_drv.c")
+ list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_a/Native_Driver/gpio_cmsdk_drv.c")
list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/musca_a/Native_Driver/mpc_sie200_drv.c"
"${PLATFORM_DIR}/target/musca_a/Native_Driver/ppc_sse200_drv.c")
@@ -120,6 +126,7 @@ elseif(BUILD_TARGET_CFG)
list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/common/tfm_platform.c")
if (TFM_PARTITION_PLATFORM)
list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/musca_a/services/src/tfm_platform_system.c")
+ list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/musca_a/services/src/tfm_ioctl_s_api.c")
endif()
embedded_include_directories(PATH "${PLATFORM_DIR}/common" ABSOLUTE)
endif()
diff --git a/platform/ext/musca_b1.cmake b/platform/ext/musca_b1.cmake
index 69ed2ae1e..a8d6e1ab3 100644
--- a/platform/ext/musca_b1.cmake
+++ b/platform/ext/musca_b1.cmake
@@ -98,6 +98,7 @@ if (NOT DEFINED BUILD_NATIVE_DRIVERS)
elseif (BUILD_NATIVE_DRIVERS)
list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_b1/Native_Driver/uart_pl011_drv.c"
"${PLATFORM_DIR}/target/musca_b1/Native_Driver/musca_b1_scc_drv.c")
+ list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_b1/Native_Driver/gpio_cmsdk_drv.c")
list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/musca_b1/Native_Driver/mpc_sie200_drv.c"
"${PLATFORM_DIR}/target/musca_b1/Native_Driver/ppc_sse200_drv.c")
diff --git a/platform/ext/target/musca_a/Device/Config/device_cfg.h b/platform/ext/target/musca_a/Device/Config/device_cfg.h
index 30aaa8f5f..9b32ca6b5 100644
--- a/platform/ext/target/musca_a/Device/Config/device_cfg.h
+++ b/platform/ext/target/musca_a/Device/Config/device_cfg.h
@@ -31,6 +31,9 @@
#define MUSCA_A1_SCC_S
#define MUSCA_A1_SCC_NS
+/* CMSDK 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_a/Device/Include/device_definition.h b/platform/ext/target/musca_a/Device/Include/device_definition.h
index bccd2fb2d..4021e0a78 100644
--- a/platform/ext/target/musca_a/Device/Include/device_definition.h
+++ b/platform/ext/target/musca_a/Device/Include/device_definition.h
@@ -49,10 +49,6 @@ extern struct musca_a1_scc_dev_t MUSCA_A1_SCC_DEV_NS;
#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_a/Device/Source/device_definition.c b/platform/ext/target/musca_a/Device/Source/device_definition.c
index 8aa430d68..43913d4c5 100644
--- a/platform/ext/target/musca_a/Device/Source/device_definition.c
+++ b/platform/ext/target/musca_a/Device/Source/device_definition.c
@@ -47,11 +47,6 @@ static const struct gpio_cmsdk_dev_cfg_t GPIO0_CMSDK_DEV_CFG_S = {
.base = MUSCA_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_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_a/Native_Driver/gpio_cmsdk_drv.c b/platform/ext/target/musca_a/Native_Driver/gpio_cmsdk_drv.c
new file mode 100644
index 000000000..70260697c
--- /dev/null
+++ b/platform/ext/target/musca_a/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_a/Native_Driver/gpio_cmsdk_drv.h b/platform/ext/target/musca_a/Native_Driver/gpio_cmsdk_drv.h
new file mode 100644
index 000000000..2671cc4ab
--- /dev/null
+++ b/platform/ext/target/musca_a/Native_Driver/gpio_cmsdk_drv.h
@@ -0,0 +1,279 @@
+/*
+ * 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.
+ */
+
+/**
+ * \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_a/services/include/tfm_ioctl_api.h b/platform/ext/target/musca_a/services/include/tfm_ioctl_api.h
new file mode 100644
index 000000000..f4bbbf3cf
--- /dev/null
+++ b/platform/ext/target/musca_a/services/include/tfm_ioctl_api.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_IOCTL_API__
+#define __TFM_IOCTL_API__
+
+#include <limits.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_a/services/src/tfm_ioctl_ns_api.c b/platform/ext/target/musca_a/services/src/tfm_ioctl_ns_api.c
new file mode 100644
index 000000000..732802a94
--- /dev/null
+++ b/platform/ext/target/musca_a/services/src/tfm_ioctl_ns_api.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.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_a/services/src/tfm_ioctl_s_api.c b/platform/ext/target/musca_a/services/src/tfm_ioctl_s_api.c
new file mode 100644
index 000000000..e734f1271
--- /dev/null
+++ b/platform/ext/target/musca_a/services/src/tfm_ioctl_s_api.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.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_a/services/src/tfm_platform_system.c b/platform/ext/target/musca_a/services/src/tfm_platform_system.c
index 78d8f38d2..4a8dc3611 100644
--- a/platform/ext/target/musca_a/services/src/tfm_platform_system.c
+++ b/platform/ext/target/musca_a/services/src/tfm_platform_system.c
@@ -5,8 +5,41 @@
*
*/
+#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 "tfm_secure_api.h"
+#include "services/include/tfm_ioctl_api.h"
+
+#ifndef TFM_PSA_API
+/*!
+ * \brief Verify access rights for memory addresses sent in io vectors
+ *
+ * \param[in] in_vec Pointer to in_vec array, which contains pointer
+ * to input arguments for the service
+ * \param[in] out_vec Pointer out_vec array, which contains pointer to
+ * output data of the pin service
+ *
+ * \return Returns true if memory is accessible by the service
+ */
+static bool memory_addr_check(const psa_invec *in_vec,
+ const psa_outvec *out_vec)
+{
+ if ((in_vec->base != NULL) &&
+ (tfm_core_memory_permission_check((void *)in_vec->base, in_vec->len,
+ TFM_MEMORY_ACCESS_RO) == TFM_SUCCESS) &&
+ (out_vec->base != NULL) &&
+ (tfm_core_memory_permission_check((void *)out_vec->base, out_vec->len,
+ TFM_MEMORY_ACCESS_RW) == TFM_SUCCESS)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+#endif /* TFM_PSA_API */
void tfm_platform_hal_system_reset(void)
{
@@ -14,15 +47,94 @@ void tfm_platform_hal_system_reset(void)
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-A, the default value is passed to the driver
+ */
+ enum gpio_cmsdk_altfunc_t altfunc = GPIO_CMSDK_MAIN_FUNC;
+
+#ifndef TFM_PSA_API
+ if (memory_addr_check(in_vec, out_vec) == false) {
+ return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+ }
+#endif /* TFM_PSA_API */
+
+ 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;
+ }
}
diff --git a/platform/ext/target/musca_b1/Device/Config/device_cfg.h b/platform/ext/target/musca_b1/Device/Config/device_cfg.h
index 506c545ea..8f15b7b6c 100644
--- a/platform/ext/target/musca_b1/Device/Config/device_cfg.h
+++ b/platform/ext/target/musca_b1/Device/Config/device_cfg.h
@@ -30,6 +30,9 @@
/* ARM SCC */
#define MUSCA_B1_SCC_S
+/* CMSDK 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_b1/Device/Include/device_definition.h b/platform/ext/target/musca_b1/Device/Include/device_definition.h
index f8dabe792..a1e8bb51a 100644
--- a/platform/ext/target/musca_b1/Device/Include/device_definition.h
+++ b/platform/ext/target/musca_b1/Device/Include/device_definition.h
@@ -135,10 +135,6 @@ extern struct mpc_sie200_dev_t MPC_EFLASH1_DEV_S;
#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
/** CMSDK Timer driver structures */
#ifdef CMSDK_TIMER0_S
diff --git a/platform/ext/target/musca_b1/Device/Source/device_definition.c b/platform/ext/target/musca_b1/Device/Source/device_definition.c
index 165d2033e..303e41f3e 100644
--- a/platform/ext/target/musca_b1/Device/Source/device_definition.c
+++ b/platform/ext/target/musca_b1/Device/Source/device_definition.c
@@ -302,11 +302,6 @@ static const struct gpio_cmsdk_dev_cfg_t GPIO0_CMSDK_DEV_CFG_S = {
.base = MUSCA_B1_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_B1_GPIO_NS_BASE};
-struct gpio_cmsdk_dev_t GPIO0_CMSDK_DEV_NS = {&(GPIO0_CMSDK_DEV_CFG_NS)};
-#endif
/** Arm UART PL011 driver structures */
#ifdef UART0_PL011_S
diff --git a/platform/ext/target/musca_b1/Native_Driver/gpio_cmsdk_drv.c b/platform/ext/target/musca_b1/Native_Driver/gpio_cmsdk_drv.c
new file mode 100644
index 000000000..70260697c
--- /dev/null
+++ b/platform/ext/target/musca_b1/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_b1/Native_Driver/gpio_cmsdk_drv.h b/platform/ext/target/musca_b1/Native_Driver/gpio_cmsdk_drv.h
new file mode 100644
index 000000000..2671cc4ab
--- /dev/null
+++ b/platform/ext/target/musca_b1/Native_Driver/gpio_cmsdk_drv.h
@@ -0,0 +1,279 @@
+/*
+ * 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.
+ */
+
+/**
+ * \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_b1/services/include/tfm_ioctl_api.h b/platform/ext/target/musca_b1/services/include/tfm_ioctl_api.h
index 6109a7ead..b391bf6ee 100644
--- a/platform/ext/target/musca_b1/services/include/tfm_ioctl_api.h
+++ b/platform/ext/target/musca_b1/services/include/tfm_ioctl_api.h
@@ -10,6 +10,7 @@
#include <limits.h>
#include <stdbool.h>
+#include <stdint.h>
#include "tfm_api.h"
#include "tfm_platform_api.h"
@@ -19,6 +20,64 @@ extern "C" {
enum tfm_platform_ioctl_reqest_types_t {
TFM_PLATFORM_IOCTL_PIN_SERVICE,
+ 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;
};
/*!
@@ -100,6 +159,91 @@ enum tfm_platform_err_t
tfm_platform_set_pin_mode(uint64_t pin_mask, uint32_t pin_mode,
uint32_t *result);
+/*!
+ * \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
diff --git a/platform/ext/target/musca_b1/services/src/tfm_ioctl_ns_api.c b/platform/ext/target/musca_b1/services/src/tfm_ioctl_ns_api.c
index 6c83aeb7e..81605a62f 100644
--- a/platform/ext/target/musca_b1/services/src/tfm_ioctl_ns_api.c
+++ b/platform/ext/target/musca_b1/services/src/tfm_ioctl_ns_api.c
@@ -5,6 +5,8 @@
*
*/
+#include <stdint.h>
+#include <stdbool.h>
#include "tfm_platform_api.h"
#include "services/include/tfm_ioctl_api.h"
@@ -99,3 +101,199 @@ tfm_platform_set_pin_mode(uint64_t pin_mask, uint32_t pin_mode,
return ret;
}
+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_b1/services/src/tfm_ioctl_s_api.c b/platform/ext/target/musca_b1/services/src/tfm_ioctl_s_api.c
index 29efe8614..4472bf59f 100644
--- a/platform/ext/target/musca_b1/services/src/tfm_ioctl_s_api.c
+++ b/platform/ext/target/musca_b1/services/src/tfm_ioctl_s_api.c
@@ -5,6 +5,8 @@
*
*/
+#include <stdint.h>
+#include <stdbool.h>
#include "tfm_platform_api.h"
#include "services/include/tfm_ioctl_api.h"
@@ -108,3 +110,199 @@ tfm_platform_set_pin_mode(uint64_t pin_mask, uint32_t pin_mode,
return TFM_PLATFORM_ERR_SUCCESS;
}
+__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_b1/services/src/tfm_platform_system.c b/platform/ext/target/musca_b1/services/src/tfm_platform_system.c
index a1d4c390d..47eedb284 100644
--- a/platform/ext/target/musca_b1/services/src/tfm_platform_system.c
+++ b/platform/ext/target/musca_b1/services/src/tfm_platform_system.c
@@ -75,7 +75,7 @@ musca_b1_pin_service(const psa_invec *in_vec,
if (in_vec->len != sizeof(struct tfm_pin_service_args_t) ||
out_vec->len != sizeof(uint32_t)) {
- return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+ return TFM_PLATFORM_ERR_INVALID_PARAM;
}
args = (struct tfm_pin_service_args_t *)in_vec->base;
@@ -106,15 +106,95 @@ musca_b1_pin_service(const psa_invec *in_vec,
return TFM_PLATFORM_ERR_SUCCESS;
}
+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-B1, the default value is passed to the driver
+ */
+ enum gpio_cmsdk_altfunc_t altfunc = GPIO_CMSDK_MAIN_FUNC;
+
+#ifndef TFM_PSA_API
+ if (memory_addr_check(in_vec, out_vec) == false) {
+ return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+ }
+#endif /* TFM_PSA_API */
+
+ 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)
{
- switch (request)
- {
- case TFM_PLATFORM_IOCTL_PIN_SERVICE:
- return musca_b1_pin_service(in_vec, out_vec);
- default:
- return TFM_PLATFORM_ERR_NOT_SUPPORTED;
+ switch (request) {
+ case TFM_PLATFORM_IOCTL_PIN_SERVICE:
+ return musca_b1_pin_service(in_vec, out_vec);
+ case TFM_PLATFORM_IOCTL_GPIO_SERVICE:
+ return tfm_platform_hal_gpio_service(in_vec, out_vec);
+ default:
+ return TFM_PLATFORM_ERR_NOT_SUPPORTED;
}
}