xref: /optee_os/core/pta/bcm/gpio.c (revision fc5d98e88a105f705ae424eb7d2b636a2f5a44ca)
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 
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 */
75*fc5d98e8SManish Tomar 		gc->ops->set_direction(NULL, gpio_num, GPIO_DIR_OUT);
76*fc5d98e8SManish Tomar 		gc->ops->set_value(NULL, gpio_num, 0);
7715542a72SSheetal Tigadoli 	} else {
78*fc5d98e8SManish Tomar 		gc->ops->set_direction(NULL, gpio_num, GPIO_DIR_IN);
7915542a72SSheetal Tigadoli 	}
8015542a72SSheetal Tigadoli 
8115542a72SSheetal Tigadoli 	return res;
8215542a72SSheetal Tigadoli }
8315542a72SSheetal Tigadoli 
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 	 */
118*fc5d98e8SManish 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 
123*fc5d98e8SManish Tomar 	gc->ops->set_value(NULL, gpio_num, val);
12415542a72SSheetal Tigadoli 
125*fc5d98e8SManish Tomar 	DMSG("GPIO(%d) value = 0x%08x", gpio_num,
126*fc5d98e8SManish Tomar 	     gc->ops->get_value(NULL, gpio_num));
12715542a72SSheetal Tigadoli 
12815542a72SSheetal Tigadoli 	return res;
12915542a72SSheetal Tigadoli }
13015542a72SSheetal Tigadoli 
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 
157*fc5d98e8SManish 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 
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:
18415542a72SSheetal Tigadoli 		EMSG("cmd: %d Not supported %s\n", 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