pta: bcm: Add Broadcom gpio PTA
Add Broadcom gpio PTA
The PTA supports below operations on the GPIO pin:
- Configure gpio pin to input/output
- Set value on output gpio pin
- Get value from gpio pin
Signed-off-by: Sheetal Tigadoli <sheetal.tigadoli@broadcom.com>
Acked-by: Jerome Forissier <jerome@forissier.org>
diff --git a/core/pta/bcm/gpio.c b/core/pta/bcm/gpio.c
new file mode 100644
index 0000000..d9070e9
--- /dev/null
+++ b/core/pta/bcm/gpio.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2019 Broadcom.
+ */
+
+#include <drivers/bcm_gpio.h>
+#include <io.h>
+#include <kernel/pseudo_ta.h>
+#include <trace.h>
+
+#define GPIO_SERVICE_UUID \
+ { 0x6272636D, 0x2018, 0x1101, \
+ { 0x42, 0x43, 0x4D, 0x5F, 0x47, 0x50, 0x49, 0x4F } }
+
+/*
+ * Configure GPIO Pin
+ *
+ * [in] value[0].a: gpio pin number
+ * [in] value[0].b: direction to configure
+ */
+#define PTA_BCM_GPIO_CMD_CFG 0
+
+/*
+ * Set GPIO pin
+ *
+ * [in] value[0].a: gpio pin number
+ * [in] value[0].b: value drive on pin
+ */
+#define PTA_BCM_GPIO_CMD_SET 1
+
+/*
+ * Get GPIO pin
+ *
+ * [in] value[0].a: gpio pin number
+ * [out] value[1].a: value read from gpio pin
+ */
+#define PTA_BCM_GPIO_CMD_GET 2
+
+#define GPIO_TA_NAME "pta_bcm_gpio.ta"
+
+static TEE_Result pta_gpio_config(uint32_t param_types,
+ TEE_Param params[TEE_NUM_PARAMS])
+{
+ uint32_t gpio_num = 0;
+ struct bcm_gpio_chip *bcm_gc = NULL;
+ struct gpio_chip *gc = NULL;
+ bool dir = false;
+ TEE_Result res = TEE_SUCCESS;
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ if (exp_param_types != param_types) {
+ EMSG("Invalid Param types");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ gpio_num = params[0].value.a;
+ dir = params[0].value.b;
+
+ bcm_gc = bcm_gpio_pin_to_chip(gpio_num);
+ if (!bcm_gc) {
+ EMSG("GPIO %u not supported", gpio_num);
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+
+ gc = &bcm_gc->chip;
+
+ /* Make gpio secure. */
+ iproc_gpio_set_secure(gpio_num);
+
+ if (dir) {
+ /* Set GPIO to output with default value to 0 */
+ gc->ops->set_direction(gpio_num, GPIO_DIR_OUT);
+ gc->ops->set_value(gpio_num, 0);
+ } else {
+ gc->ops->set_direction(gpio_num, GPIO_DIR_IN);
+ }
+
+ return res;
+}
+
+static TEE_Result pta_gpio_set(uint32_t param_types,
+ TEE_Param params[TEE_NUM_PARAMS])
+{
+ uint32_t gpio_num = 0;
+ uint32_t val = 0;
+ TEE_Result res = TEE_SUCCESS;
+ struct bcm_gpio_chip *bcm_gc = NULL;
+ struct gpio_chip *gc = NULL;
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ if (exp_param_types != param_types) {
+ EMSG("Invalid Param types");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ gpio_num = params[0].value.a;
+ val = !!params[0].value.b;
+
+ bcm_gc = bcm_gpio_pin_to_chip(gpio_num);
+ if (!bcm_gc) {
+ EMSG("GPIO %u not supported", gpio_num);
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+
+ gc = &bcm_gc->chip;
+
+ /*
+ * For setting a value to GPIO Pin,
+ * need to make sure the PIN is configured in
+ * output direction.
+ */
+ if (gc->ops->get_direction(gpio_num) != GPIO_DIR_OUT) {
+ EMSG("gpio pin %u is configured as INPUT", gpio_num);
+ return TEE_ERROR_ACCESS_DENIED;
+ }
+
+ gc->ops->set_value(gpio_num, val);
+
+ DMSG("GPIO(%d) value = 0x%08x", gpio_num, gc->ops->get_value(gpio_num));
+
+ return res;
+}
+
+static TEE_Result pta_gpio_get(uint32_t param_types,
+ TEE_Param params[TEE_NUM_PARAMS])
+{
+ uint32_t gpio_num = 0;
+ struct bcm_gpio_chip *bcm_gc = NULL;
+ struct gpio_chip *gc = NULL;
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_VALUE_OUTPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ if (exp_param_types != param_types) {
+ EMSG("Invalid Param types");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ gpio_num = params[0].value.a;
+
+ bcm_gc = bcm_gpio_pin_to_chip(gpio_num);
+ if (!bcm_gc) {
+ EMSG("GPIO %u not supported", gpio_num);
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+
+ gc = &bcm_gc->chip;
+
+ params[1].value.a = gc->ops->get_value(gpio_num);
+
+ DMSG("gpio(%d) value = 0x%08x", gpio_num, params[1].value.a);
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result invoke_command(void *session_context __unused,
+ uint32_t cmd_id,
+ uint32_t param_types,
+ TEE_Param params[TEE_NUM_PARAMS])
+{
+ TEE_Result res = TEE_SUCCESS;
+
+ DMSG("command entry point[%d] for \"%s\"", cmd_id, GPIO_TA_NAME);
+
+ switch (cmd_id) {
+ case PTA_BCM_GPIO_CMD_CFG:
+ res = pta_gpio_config(param_types, params);
+ break;
+ case PTA_BCM_GPIO_CMD_SET:
+ res = pta_gpio_set(param_types, params);
+ break;
+ case PTA_BCM_GPIO_CMD_GET:
+ res = pta_gpio_get(param_types, params);
+ break;
+ default:
+ EMSG("cmd: %d Not supported %s\n", cmd_id, GPIO_TA_NAME);
+ res = TEE_ERROR_NOT_SUPPORTED;
+ break;
+ }
+
+ return res;
+}
+
+pseudo_ta_register(.uuid = GPIO_SERVICE_UUID,
+ .name = GPIO_TA_NAME,
+ .flags = PTA_DEFAULT_FLAGS,
+ .invoke_command_entry_point = invoke_command);
diff --git a/core/pta/bcm/sub.mk b/core/pta/bcm/sub.mk
index 9f9ba5f..ab8c04d 100644
--- a/core/pta/bcm/sub.mk
+++ b/core/pta/bcm/sub.mk
@@ -2,3 +2,4 @@
srcs-$(CFG_SP805_WDT) += wdt.c
srcs-$(CFG_BCM_HWRNG) += hwrng.c
srcs-$(CFG_BCM_SOTP) += sotp.c
+srcs-$(CFG_BCM_GPIO) += gpio.c