xref: /optee_os/core/pta/bcm/gpio.c (revision 15542a729763fbe326f0479e0263d9f57e6a3364)
1*15542a72SSheetal Tigadoli // SPDX-License-Identifier: BSD-2-Clause
2*15542a72SSheetal Tigadoli /*
3*15542a72SSheetal Tigadoli  * Copyright 2019 Broadcom.
4*15542a72SSheetal Tigadoli  */
5*15542a72SSheetal Tigadoli 
6*15542a72SSheetal Tigadoli #include <drivers/bcm_gpio.h>
7*15542a72SSheetal Tigadoli #include <io.h>
8*15542a72SSheetal Tigadoli #include <kernel/pseudo_ta.h>
9*15542a72SSheetal Tigadoli #include <trace.h>
10*15542a72SSheetal Tigadoli 
11*15542a72SSheetal Tigadoli #define GPIO_SERVICE_UUID \
12*15542a72SSheetal Tigadoli 		{ 0x6272636D, 0x2018, 0x1101,  \
13*15542a72SSheetal Tigadoli 		{ 0x42, 0x43, 0x4D, 0x5F, 0x47, 0x50, 0x49, 0x4F } }
14*15542a72SSheetal Tigadoli 
15*15542a72SSheetal Tigadoli /*
16*15542a72SSheetal Tigadoli  * Configure GPIO Pin
17*15542a72SSheetal Tigadoli  *
18*15542a72SSheetal Tigadoli  * [in]    value[0].a:    gpio pin number
19*15542a72SSheetal Tigadoli  * [in]    value[0].b:    direction to configure
20*15542a72SSheetal Tigadoli  */
21*15542a72SSheetal Tigadoli #define PTA_BCM_GPIO_CMD_CFG	0
22*15542a72SSheetal Tigadoli 
23*15542a72SSheetal Tigadoli /*
24*15542a72SSheetal Tigadoli  * Set GPIO pin
25*15542a72SSheetal Tigadoli  *
26*15542a72SSheetal Tigadoli  * [in]    value[0].a:    gpio pin number
27*15542a72SSheetal Tigadoli  * [in]    value[0].b:    value drive on pin
28*15542a72SSheetal Tigadoli  */
29*15542a72SSheetal Tigadoli #define PTA_BCM_GPIO_CMD_SET	1
30*15542a72SSheetal Tigadoli 
31*15542a72SSheetal Tigadoli /*
32*15542a72SSheetal Tigadoli  * Get GPIO pin
33*15542a72SSheetal Tigadoli  *
34*15542a72SSheetal Tigadoli  * [in]    value[0].a:    gpio pin number
35*15542a72SSheetal Tigadoli  * [out]   value[1].a:    value read from gpio pin
36*15542a72SSheetal Tigadoli  */
37*15542a72SSheetal Tigadoli #define PTA_BCM_GPIO_CMD_GET	2
38*15542a72SSheetal Tigadoli 
39*15542a72SSheetal Tigadoli #define GPIO_TA_NAME		"pta_bcm_gpio.ta"
40*15542a72SSheetal Tigadoli 
41*15542a72SSheetal Tigadoli static TEE_Result pta_gpio_config(uint32_t param_types,
42*15542a72SSheetal Tigadoli 				  TEE_Param params[TEE_NUM_PARAMS])
43*15542a72SSheetal Tigadoli {
44*15542a72SSheetal Tigadoli 	uint32_t gpio_num = 0;
45*15542a72SSheetal Tigadoli 	struct bcm_gpio_chip *bcm_gc = NULL;
46*15542a72SSheetal Tigadoli 	struct gpio_chip *gc = NULL;
47*15542a72SSheetal Tigadoli 	bool dir = false;
48*15542a72SSheetal Tigadoli 	TEE_Result res = TEE_SUCCESS;
49*15542a72SSheetal Tigadoli 	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
50*15542a72SSheetal Tigadoli 						   TEE_PARAM_TYPE_NONE,
51*15542a72SSheetal Tigadoli 						   TEE_PARAM_TYPE_NONE,
52*15542a72SSheetal Tigadoli 						   TEE_PARAM_TYPE_NONE);
53*15542a72SSheetal Tigadoli 
54*15542a72SSheetal Tigadoli 	if (exp_param_types != param_types) {
55*15542a72SSheetal Tigadoli 		EMSG("Invalid Param types");
56*15542a72SSheetal Tigadoli 		return TEE_ERROR_BAD_PARAMETERS;
57*15542a72SSheetal Tigadoli 	}
58*15542a72SSheetal Tigadoli 
59*15542a72SSheetal Tigadoli 	gpio_num = params[0].value.a;
60*15542a72SSheetal Tigadoli 	dir = params[0].value.b;
61*15542a72SSheetal Tigadoli 
62*15542a72SSheetal Tigadoli 	bcm_gc = bcm_gpio_pin_to_chip(gpio_num);
63*15542a72SSheetal Tigadoli 	if (!bcm_gc) {
64*15542a72SSheetal Tigadoli 		EMSG("GPIO %u not supported", gpio_num);
65*15542a72SSheetal Tigadoli 		return TEE_ERROR_NOT_SUPPORTED;
66*15542a72SSheetal Tigadoli 	}
67*15542a72SSheetal Tigadoli 
68*15542a72SSheetal Tigadoli 	gc = &bcm_gc->chip;
69*15542a72SSheetal Tigadoli 
70*15542a72SSheetal Tigadoli 	/* Make gpio secure. */
71*15542a72SSheetal Tigadoli 	iproc_gpio_set_secure(gpio_num);
72*15542a72SSheetal Tigadoli 
73*15542a72SSheetal Tigadoli 	if (dir) {
74*15542a72SSheetal Tigadoli 		/* Set GPIO to output with default value to 0 */
75*15542a72SSheetal Tigadoli 		gc->ops->set_direction(gpio_num, GPIO_DIR_OUT);
76*15542a72SSheetal Tigadoli 		gc->ops->set_value(gpio_num, 0);
77*15542a72SSheetal Tigadoli 	} else {
78*15542a72SSheetal Tigadoli 		gc->ops->set_direction(gpio_num, GPIO_DIR_IN);
79*15542a72SSheetal Tigadoli 	}
80*15542a72SSheetal Tigadoli 
81*15542a72SSheetal Tigadoli 	return res;
82*15542a72SSheetal Tigadoli }
83*15542a72SSheetal Tigadoli 
84*15542a72SSheetal Tigadoli static TEE_Result pta_gpio_set(uint32_t param_types,
85*15542a72SSheetal Tigadoli 			       TEE_Param params[TEE_NUM_PARAMS])
86*15542a72SSheetal Tigadoli {
87*15542a72SSheetal Tigadoli 	uint32_t gpio_num = 0;
88*15542a72SSheetal Tigadoli 	uint32_t val = 0;
89*15542a72SSheetal Tigadoli 	TEE_Result res = TEE_SUCCESS;
90*15542a72SSheetal Tigadoli 	struct bcm_gpio_chip *bcm_gc = NULL;
91*15542a72SSheetal Tigadoli 	struct gpio_chip *gc = NULL;
92*15542a72SSheetal Tigadoli 	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
93*15542a72SSheetal Tigadoli 						   TEE_PARAM_TYPE_NONE,
94*15542a72SSheetal Tigadoli 						   TEE_PARAM_TYPE_NONE,
95*15542a72SSheetal Tigadoli 						   TEE_PARAM_TYPE_NONE);
96*15542a72SSheetal Tigadoli 
97*15542a72SSheetal Tigadoli 	if (exp_param_types != param_types) {
98*15542a72SSheetal Tigadoli 		EMSG("Invalid Param types");
99*15542a72SSheetal Tigadoli 		return TEE_ERROR_BAD_PARAMETERS;
100*15542a72SSheetal Tigadoli 	}
101*15542a72SSheetal Tigadoli 
102*15542a72SSheetal Tigadoli 	gpio_num = params[0].value.a;
103*15542a72SSheetal Tigadoli 	val = !!params[0].value.b;
104*15542a72SSheetal Tigadoli 
105*15542a72SSheetal Tigadoli 	bcm_gc = bcm_gpio_pin_to_chip(gpio_num);
106*15542a72SSheetal Tigadoli 	if (!bcm_gc) {
107*15542a72SSheetal Tigadoli 		EMSG("GPIO %u not supported", gpio_num);
108*15542a72SSheetal Tigadoli 		return TEE_ERROR_NOT_SUPPORTED;
109*15542a72SSheetal Tigadoli 	}
110*15542a72SSheetal Tigadoli 
111*15542a72SSheetal Tigadoli 	gc = &bcm_gc->chip;
112*15542a72SSheetal Tigadoli 
113*15542a72SSheetal Tigadoli 	/*
114*15542a72SSheetal Tigadoli 	 * For setting a value to GPIO Pin,
115*15542a72SSheetal Tigadoli 	 * need to make sure the PIN is configured in
116*15542a72SSheetal Tigadoli 	 * output direction.
117*15542a72SSheetal Tigadoli 	 */
118*15542a72SSheetal Tigadoli 	if (gc->ops->get_direction(gpio_num) != GPIO_DIR_OUT) {
119*15542a72SSheetal Tigadoli 		EMSG("gpio pin %u is configured as INPUT", gpio_num);
120*15542a72SSheetal Tigadoli 		return TEE_ERROR_ACCESS_DENIED;
121*15542a72SSheetal Tigadoli 	}
122*15542a72SSheetal Tigadoli 
123*15542a72SSheetal Tigadoli 	gc->ops->set_value(gpio_num, val);
124*15542a72SSheetal Tigadoli 
125*15542a72SSheetal Tigadoli 	DMSG("GPIO(%d) value = 0x%08x", gpio_num, gc->ops->get_value(gpio_num));
126*15542a72SSheetal Tigadoli 
127*15542a72SSheetal Tigadoli 	return res;
128*15542a72SSheetal Tigadoli }
129*15542a72SSheetal Tigadoli 
130*15542a72SSheetal Tigadoli static TEE_Result pta_gpio_get(uint32_t param_types,
131*15542a72SSheetal Tigadoli 			       TEE_Param params[TEE_NUM_PARAMS])
132*15542a72SSheetal Tigadoli {
133*15542a72SSheetal Tigadoli 	uint32_t gpio_num = 0;
134*15542a72SSheetal Tigadoli 	struct bcm_gpio_chip *bcm_gc = NULL;
135*15542a72SSheetal Tigadoli 	struct gpio_chip *gc = NULL;
136*15542a72SSheetal Tigadoli 	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
137*15542a72SSheetal Tigadoli 						   TEE_PARAM_TYPE_VALUE_OUTPUT,
138*15542a72SSheetal Tigadoli 						   TEE_PARAM_TYPE_NONE,
139*15542a72SSheetal Tigadoli 						   TEE_PARAM_TYPE_NONE);
140*15542a72SSheetal Tigadoli 
141*15542a72SSheetal Tigadoli 	if (exp_param_types != param_types) {
142*15542a72SSheetal Tigadoli 		EMSG("Invalid Param types");
143*15542a72SSheetal Tigadoli 		return TEE_ERROR_BAD_PARAMETERS;
144*15542a72SSheetal Tigadoli 	}
145*15542a72SSheetal Tigadoli 
146*15542a72SSheetal Tigadoli 	gpio_num = params[0].value.a;
147*15542a72SSheetal Tigadoli 
148*15542a72SSheetal Tigadoli 	bcm_gc = bcm_gpio_pin_to_chip(gpio_num);
149*15542a72SSheetal Tigadoli 	if (!bcm_gc) {
150*15542a72SSheetal Tigadoli 		EMSG("GPIO %u not supported", gpio_num);
151*15542a72SSheetal Tigadoli 		return TEE_ERROR_NOT_SUPPORTED;
152*15542a72SSheetal Tigadoli 	}
153*15542a72SSheetal Tigadoli 
154*15542a72SSheetal Tigadoli 	gc = &bcm_gc->chip;
155*15542a72SSheetal Tigadoli 
156*15542a72SSheetal Tigadoli 	params[1].value.a = gc->ops->get_value(gpio_num);
157*15542a72SSheetal Tigadoli 
158*15542a72SSheetal Tigadoli 	DMSG("gpio(%d) value = 0x%08x", gpio_num, params[1].value.a);
159*15542a72SSheetal Tigadoli 
160*15542a72SSheetal Tigadoli 	return TEE_SUCCESS;
161*15542a72SSheetal Tigadoli }
162*15542a72SSheetal Tigadoli 
163*15542a72SSheetal Tigadoli static TEE_Result invoke_command(void *session_context __unused,
164*15542a72SSheetal Tigadoli 				 uint32_t cmd_id,
165*15542a72SSheetal Tigadoli 				 uint32_t param_types,
166*15542a72SSheetal Tigadoli 				 TEE_Param params[TEE_NUM_PARAMS])
167*15542a72SSheetal Tigadoli {
168*15542a72SSheetal Tigadoli 	TEE_Result res = TEE_SUCCESS;
169*15542a72SSheetal Tigadoli 
170*15542a72SSheetal Tigadoli 	DMSG("command entry point[%d] for \"%s\"", cmd_id, GPIO_TA_NAME);
171*15542a72SSheetal Tigadoli 
172*15542a72SSheetal Tigadoli 	switch (cmd_id) {
173*15542a72SSheetal Tigadoli 	case PTA_BCM_GPIO_CMD_CFG:
174*15542a72SSheetal Tigadoli 		res = pta_gpio_config(param_types, params);
175*15542a72SSheetal Tigadoli 		break;
176*15542a72SSheetal Tigadoli 	case PTA_BCM_GPIO_CMD_SET:
177*15542a72SSheetal Tigadoli 		res = pta_gpio_set(param_types, params);
178*15542a72SSheetal Tigadoli 		break;
179*15542a72SSheetal Tigadoli 	case PTA_BCM_GPIO_CMD_GET:
180*15542a72SSheetal Tigadoli 		res = pta_gpio_get(param_types, params);
181*15542a72SSheetal Tigadoli 		break;
182*15542a72SSheetal Tigadoli 	default:
183*15542a72SSheetal Tigadoli 		EMSG("cmd: %d Not supported %s\n", cmd_id, GPIO_TA_NAME);
184*15542a72SSheetal Tigadoli 		res = TEE_ERROR_NOT_SUPPORTED;
185*15542a72SSheetal Tigadoli 		break;
186*15542a72SSheetal Tigadoli 	}
187*15542a72SSheetal Tigadoli 
188*15542a72SSheetal Tigadoli 	return res;
189*15542a72SSheetal Tigadoli }
190*15542a72SSheetal Tigadoli 
191*15542a72SSheetal Tigadoli pseudo_ta_register(.uuid = GPIO_SERVICE_UUID,
192*15542a72SSheetal Tigadoli 		   .name = GPIO_TA_NAME,
193*15542a72SSheetal Tigadoli 		   .flags = PTA_DEFAULT_FLAGS,
194*15542a72SSheetal Tigadoli 		   .invoke_command_entry_point = invoke_command);
195