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