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