115542a72SSheetal Tigadoli // SPDX-License-Identifier: BSD-2-Clause
215542a72SSheetal Tigadoli /*
315542a72SSheetal Tigadoli * Copyright 2019 Broadcom.
415542a72SSheetal Tigadoli */
515542a72SSheetal Tigadoli
615542a72SSheetal Tigadoli #include <drivers/bcm_gpio.h>
715542a72SSheetal Tigadoli #include <io.h>
815542a72SSheetal Tigadoli #include <kernel/pseudo_ta.h>
915542a72SSheetal Tigadoli #include <trace.h>
1015542a72SSheetal Tigadoli
1115542a72SSheetal Tigadoli #define GPIO_SERVICE_UUID \
1215542a72SSheetal Tigadoli { 0x6272636D, 0x2018, 0x1101, \
1315542a72SSheetal Tigadoli { 0x42, 0x43, 0x4D, 0x5F, 0x47, 0x50, 0x49, 0x4F } }
1415542a72SSheetal Tigadoli
1515542a72SSheetal Tigadoli /*
1615542a72SSheetal Tigadoli * Configure GPIO Pin
1715542a72SSheetal Tigadoli *
1815542a72SSheetal Tigadoli * [in] value[0].a: gpio pin number
1915542a72SSheetal Tigadoli * [in] value[0].b: direction to configure
2015542a72SSheetal Tigadoli */
2115542a72SSheetal Tigadoli #define PTA_BCM_GPIO_CMD_CFG 0
2215542a72SSheetal Tigadoli
2315542a72SSheetal Tigadoli /*
2415542a72SSheetal Tigadoli * Set GPIO pin
2515542a72SSheetal Tigadoli *
2615542a72SSheetal Tigadoli * [in] value[0].a: gpio pin number
2715542a72SSheetal Tigadoli * [in] value[0].b: value drive on pin
2815542a72SSheetal Tigadoli */
2915542a72SSheetal Tigadoli #define PTA_BCM_GPIO_CMD_SET 1
3015542a72SSheetal Tigadoli
3115542a72SSheetal Tigadoli /*
3215542a72SSheetal Tigadoli * Get GPIO pin
3315542a72SSheetal Tigadoli *
3415542a72SSheetal Tigadoli * [in] value[0].a: gpio pin number
3515542a72SSheetal Tigadoli * [out] value[1].a: value read from gpio pin
3615542a72SSheetal Tigadoli */
3715542a72SSheetal Tigadoli #define PTA_BCM_GPIO_CMD_GET 2
3815542a72SSheetal Tigadoli
3915542a72SSheetal Tigadoli #define GPIO_TA_NAME "pta_bcm_gpio.ta"
4015542a72SSheetal Tigadoli
pta_gpio_config(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])4115542a72SSheetal Tigadoli static TEE_Result pta_gpio_config(uint32_t param_types,
4215542a72SSheetal Tigadoli TEE_Param params[TEE_NUM_PARAMS])
4315542a72SSheetal Tigadoli {
4415542a72SSheetal Tigadoli uint32_t gpio_num = 0;
4515542a72SSheetal Tigadoli struct bcm_gpio_chip *bcm_gc = NULL;
4615542a72SSheetal Tigadoli struct gpio_chip *gc = NULL;
4715542a72SSheetal Tigadoli bool dir = false;
4815542a72SSheetal Tigadoli TEE_Result res = TEE_SUCCESS;
4915542a72SSheetal Tigadoli uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
5015542a72SSheetal Tigadoli TEE_PARAM_TYPE_NONE,
5115542a72SSheetal Tigadoli TEE_PARAM_TYPE_NONE,
5215542a72SSheetal Tigadoli TEE_PARAM_TYPE_NONE);
5315542a72SSheetal Tigadoli
5415542a72SSheetal Tigadoli if (exp_param_types != param_types) {
5515542a72SSheetal Tigadoli EMSG("Invalid Param types");
5615542a72SSheetal Tigadoli return TEE_ERROR_BAD_PARAMETERS;
5715542a72SSheetal Tigadoli }
5815542a72SSheetal Tigadoli
5915542a72SSheetal Tigadoli gpio_num = params[0].value.a;
6015542a72SSheetal Tigadoli dir = params[0].value.b;
6115542a72SSheetal Tigadoli
6215542a72SSheetal Tigadoli bcm_gc = bcm_gpio_pin_to_chip(gpio_num);
6315542a72SSheetal Tigadoli if (!bcm_gc) {
6415542a72SSheetal Tigadoli EMSG("GPIO %u not supported", gpio_num);
6515542a72SSheetal Tigadoli return TEE_ERROR_NOT_SUPPORTED;
6615542a72SSheetal Tigadoli }
6715542a72SSheetal Tigadoli
6815542a72SSheetal Tigadoli gc = &bcm_gc->chip;
6915542a72SSheetal Tigadoli
7015542a72SSheetal Tigadoli /* Make gpio secure. */
7115542a72SSheetal Tigadoli iproc_gpio_set_secure(gpio_num);
7215542a72SSheetal Tigadoli
7315542a72SSheetal Tigadoli if (dir) {
7415542a72SSheetal Tigadoli /* Set GPIO to output with default value to 0 */
75fc5d98e8SManish Tomar gc->ops->set_direction(NULL, gpio_num, GPIO_DIR_OUT);
76fc5d98e8SManish Tomar gc->ops->set_value(NULL, gpio_num, 0);
7715542a72SSheetal Tigadoli } else {
78fc5d98e8SManish Tomar gc->ops->set_direction(NULL, gpio_num, GPIO_DIR_IN);
7915542a72SSheetal Tigadoli }
8015542a72SSheetal Tigadoli
8115542a72SSheetal Tigadoli return res;
8215542a72SSheetal Tigadoli }
8315542a72SSheetal Tigadoli
pta_gpio_set(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])8415542a72SSheetal Tigadoli static TEE_Result pta_gpio_set(uint32_t param_types,
8515542a72SSheetal Tigadoli TEE_Param params[TEE_NUM_PARAMS])
8615542a72SSheetal Tigadoli {
8715542a72SSheetal Tigadoli uint32_t gpio_num = 0;
8815542a72SSheetal Tigadoli uint32_t val = 0;
8915542a72SSheetal Tigadoli TEE_Result res = TEE_SUCCESS;
9015542a72SSheetal Tigadoli struct bcm_gpio_chip *bcm_gc = NULL;
9115542a72SSheetal Tigadoli struct gpio_chip *gc = NULL;
9215542a72SSheetal Tigadoli uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
9315542a72SSheetal Tigadoli TEE_PARAM_TYPE_NONE,
9415542a72SSheetal Tigadoli TEE_PARAM_TYPE_NONE,
9515542a72SSheetal Tigadoli TEE_PARAM_TYPE_NONE);
9615542a72SSheetal Tigadoli
9715542a72SSheetal Tigadoli if (exp_param_types != param_types) {
9815542a72SSheetal Tigadoli EMSG("Invalid Param types");
9915542a72SSheetal Tigadoli return TEE_ERROR_BAD_PARAMETERS;
10015542a72SSheetal Tigadoli }
10115542a72SSheetal Tigadoli
10215542a72SSheetal Tigadoli gpio_num = params[0].value.a;
10315542a72SSheetal Tigadoli val = !!params[0].value.b;
10415542a72SSheetal Tigadoli
10515542a72SSheetal Tigadoli bcm_gc = bcm_gpio_pin_to_chip(gpio_num);
10615542a72SSheetal Tigadoli if (!bcm_gc) {
10715542a72SSheetal Tigadoli EMSG("GPIO %u not supported", gpio_num);
10815542a72SSheetal Tigadoli return TEE_ERROR_NOT_SUPPORTED;
10915542a72SSheetal Tigadoli }
11015542a72SSheetal Tigadoli
11115542a72SSheetal Tigadoli gc = &bcm_gc->chip;
11215542a72SSheetal Tigadoli
11315542a72SSheetal Tigadoli /*
11415542a72SSheetal Tigadoli * For setting a value to GPIO Pin,
11515542a72SSheetal Tigadoli * need to make sure the PIN is configured in
11615542a72SSheetal Tigadoli * output direction.
11715542a72SSheetal Tigadoli */
118fc5d98e8SManish Tomar if (gc->ops->get_direction(NULL, gpio_num) != GPIO_DIR_OUT) {
11915542a72SSheetal Tigadoli EMSG("gpio pin %u is configured as INPUT", gpio_num);
12015542a72SSheetal Tigadoli return TEE_ERROR_ACCESS_DENIED;
12115542a72SSheetal Tigadoli }
12215542a72SSheetal Tigadoli
123fc5d98e8SManish Tomar gc->ops->set_value(NULL, gpio_num, val);
12415542a72SSheetal Tigadoli
125fc5d98e8SManish Tomar DMSG("GPIO(%d) value = 0x%08x", gpio_num,
126fc5d98e8SManish Tomar gc->ops->get_value(NULL, gpio_num));
12715542a72SSheetal Tigadoli
12815542a72SSheetal Tigadoli return res;
12915542a72SSheetal Tigadoli }
13015542a72SSheetal Tigadoli
pta_gpio_get(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])13115542a72SSheetal Tigadoli static TEE_Result pta_gpio_get(uint32_t param_types,
13215542a72SSheetal Tigadoli TEE_Param params[TEE_NUM_PARAMS])
13315542a72SSheetal Tigadoli {
13415542a72SSheetal Tigadoli uint32_t gpio_num = 0;
13515542a72SSheetal Tigadoli struct bcm_gpio_chip *bcm_gc = NULL;
13615542a72SSheetal Tigadoli struct gpio_chip *gc = NULL;
13715542a72SSheetal Tigadoli uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
13815542a72SSheetal Tigadoli TEE_PARAM_TYPE_VALUE_OUTPUT,
13915542a72SSheetal Tigadoli TEE_PARAM_TYPE_NONE,
14015542a72SSheetal Tigadoli TEE_PARAM_TYPE_NONE);
14115542a72SSheetal Tigadoli
14215542a72SSheetal Tigadoli if (exp_param_types != param_types) {
14315542a72SSheetal Tigadoli EMSG("Invalid Param types");
14415542a72SSheetal Tigadoli return TEE_ERROR_BAD_PARAMETERS;
14515542a72SSheetal Tigadoli }
14615542a72SSheetal Tigadoli
14715542a72SSheetal Tigadoli gpio_num = params[0].value.a;
14815542a72SSheetal Tigadoli
14915542a72SSheetal Tigadoli bcm_gc = bcm_gpio_pin_to_chip(gpio_num);
15015542a72SSheetal Tigadoli if (!bcm_gc) {
15115542a72SSheetal Tigadoli EMSG("GPIO %u not supported", gpio_num);
15215542a72SSheetal Tigadoli return TEE_ERROR_NOT_SUPPORTED;
15315542a72SSheetal Tigadoli }
15415542a72SSheetal Tigadoli
15515542a72SSheetal Tigadoli gc = &bcm_gc->chip;
15615542a72SSheetal Tigadoli
157fc5d98e8SManish Tomar params[1].value.a = gc->ops->get_value(NULL, gpio_num);
15815542a72SSheetal Tigadoli
15915542a72SSheetal Tigadoli DMSG("gpio(%d) value = 0x%08x", gpio_num, params[1].value.a);
16015542a72SSheetal Tigadoli
16115542a72SSheetal Tigadoli return TEE_SUCCESS;
16215542a72SSheetal Tigadoli }
16315542a72SSheetal Tigadoli
invoke_command(void * session_context __unused,uint32_t cmd_id,uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])16415542a72SSheetal Tigadoli static TEE_Result invoke_command(void *session_context __unused,
16515542a72SSheetal Tigadoli uint32_t cmd_id,
16615542a72SSheetal Tigadoli uint32_t param_types,
16715542a72SSheetal Tigadoli TEE_Param params[TEE_NUM_PARAMS])
16815542a72SSheetal Tigadoli {
16915542a72SSheetal Tigadoli TEE_Result res = TEE_SUCCESS;
17015542a72SSheetal Tigadoli
17115542a72SSheetal Tigadoli DMSG("command entry point[%d] for \"%s\"", cmd_id, GPIO_TA_NAME);
17215542a72SSheetal Tigadoli
17315542a72SSheetal Tigadoli switch (cmd_id) {
17415542a72SSheetal Tigadoli case PTA_BCM_GPIO_CMD_CFG:
17515542a72SSheetal Tigadoli res = pta_gpio_config(param_types, params);
17615542a72SSheetal Tigadoli break;
17715542a72SSheetal Tigadoli case PTA_BCM_GPIO_CMD_SET:
17815542a72SSheetal Tigadoli res = pta_gpio_set(param_types, params);
17915542a72SSheetal Tigadoli break;
18015542a72SSheetal Tigadoli case PTA_BCM_GPIO_CMD_GET:
18115542a72SSheetal Tigadoli res = pta_gpio_get(param_types, params);
18215542a72SSheetal Tigadoli break;
18315542a72SSheetal Tigadoli default:
184*bce2f88aSVincent Mailhol EMSG("cmd: %d Not supported %s", cmd_id, GPIO_TA_NAME);
18515542a72SSheetal Tigadoli res = TEE_ERROR_NOT_SUPPORTED;
18615542a72SSheetal Tigadoli break;
18715542a72SSheetal Tigadoli }
18815542a72SSheetal Tigadoli
18915542a72SSheetal Tigadoli return res;
19015542a72SSheetal Tigadoli }
19115542a72SSheetal Tigadoli
19215542a72SSheetal Tigadoli pseudo_ta_register(.uuid = GPIO_SERVICE_UUID,
19315542a72SSheetal Tigadoli .name = GPIO_TA_NAME,
19415542a72SSheetal Tigadoli .flags = PTA_DEFAULT_FLAGS,
19515542a72SSheetal Tigadoli .invoke_command_entry_point = invoke_command);
196