diff options
20 files changed, 2550 insertions, 31 deletions
diff --git a/platform/ext/musca_a.cmake b/platform/ext/musca_a.cmake index 69fdec8958..9d76f37f24 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 69ed2ae1e6..a8d6e1ab39 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 30aaa8f5fa..9b32ca6b5f 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 bccd2fb2d2..4021e0a78b 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 8aa430d688..43913d4c59 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 0000000000..70260697c1 --- /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 0000000000..2671cc4abe --- /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 0000000000..f4bbbf3cf0 --- /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 0000000000..732802a942 --- /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 0000000000..e734f1271a --- /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 78d8f38d20..4a8dc36115 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 506c545ea9..8f15b7b6c8 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 f8dabe792c..a1e8bb51a0 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 165d2033ec..303e41f3e1 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 0000000000..70260697c1 --- /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 0000000000..2671cc4abe --- /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 6109a7ead1..b391bf6eed 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 6c83aeb7e6..81605a62f4 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 29efe8614e..4472bf59fa 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 a1d4c390de..47eedb284d 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; } } |