1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2022, Microchip 4 */ 5 6 #include <drivers/gpio.h> 7 #include <libfdt.h> 8 #include <stdio.h> 9 #include <tee_api_defines.h> 10 #include <tee_api_types.h> 11 #include <util.h> 12 13 /* gpio suffixes used for device tree lookup */ 14 static const char * const gpio_suffixes[] = { "gpios", "gpio" }; 15 16 TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs, struct gpio **out_gpio) 17 { 18 struct gpio *gpio = NULL; 19 20 if (pargs->args_count != 2) 21 return TEE_ERROR_BAD_PARAMETERS; 22 23 gpio = calloc(1, sizeof(struct gpio)); 24 if (!gpio) 25 return TEE_ERROR_OUT_OF_MEMORY; 26 27 gpio->pin = pargs->args[0]; 28 gpio->dt_flags = pargs->args[1]; 29 30 *out_gpio = gpio; 31 32 return TEE_SUCCESS; 33 } 34 35 TEE_Result gpio_dt_get_by_index(const void *fdt, int nodeoffset, 36 unsigned int index, const char *gpio_name, 37 struct gpio **gpio) 38 { 39 TEE_Result res = TEE_ERROR_GENERIC; 40 char prop_name[32]; /* 32 is max size of property name in DT */ 41 void *out_gpio = NULL; 42 unsigned int i = 0; 43 44 /* Try GPIO properties "foo-gpios" and "foo-gpio" */ 45 for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { 46 if (gpio_name) 47 snprintf(prop_name, sizeof(prop_name), "%s-%s", 48 gpio_name, gpio_suffixes[i]); 49 else 50 snprintf(prop_name, sizeof(prop_name), "%s", 51 gpio_suffixes[i]); 52 53 res = dt_driver_device_from_node_idx_prop(prop_name, fdt, 54 nodeoffset, 55 index, DT_DRIVER_GPIO, 56 &out_gpio); 57 58 if (res != TEE_ERROR_ITEM_NOT_FOUND) 59 break; 60 } 61 62 if (!res) 63 *gpio = out_gpio; 64 65 return res; 66 } 67 68 TEE_Result gpio_configure(struct gpio *gpio, enum gpio_flags flags) 69 { 70 enum gpio_level value = GPIO_LEVEL_LOW; 71 TEE_Result res = TEE_ERROR_GENERIC; 72 73 assert(gpio && gpio->chip && gpio->chip->ops); 74 75 /* Configure GPIO with DT flags */ 76 if (gpio && gpio->chip->ops->configure) { 77 res = gpio->chip->ops->configure(gpio->chip, gpio); 78 if (res) 79 return res; 80 } 81 82 /* Process requester flags */ 83 if (flags & GPIO_FLAGS_BIT_DIR_SET) { 84 if (flags & GPIO_FLAGS_BIT_DIR_OUT) { 85 if (flags & GPIO_FLAGS_BIT_DIR_VAL) 86 value = GPIO_LEVEL_HIGH; 87 gpio_set_value(gpio, value); 88 gpio_set_direction(gpio, GPIO_DIR_OUT); 89 } else { 90 gpio_set_direction(gpio, GPIO_DIR_IN); 91 } 92 } 93 94 return TEE_SUCCESS; 95 } 96 97 TEE_Result gpio_dt_cfg_by_index(const void *fdt, int nodeoffset, 98 unsigned int index, const char *gpio_name, 99 enum gpio_flags flags, struct gpio **gpio) 100 { 101 TEE_Result res = TEE_ERROR_GENERIC; 102 103 res = gpio_dt_get_by_index(fdt, nodeoffset, index, gpio_name, gpio); 104 if (!res) 105 return gpio_configure(*gpio, flags); 106 107 return res; 108 } 109