14fc179b6SThomas Perrot // SPDX-License-Identifier: BSD-2-Clause 24fc179b6SThomas Perrot /* 34fc179b6SThomas Perrot * Copyright (c) 2022, Microchip 44fc179b6SThomas Perrot */ 54fc179b6SThomas Perrot 64fc179b6SThomas Perrot #include <drivers/gpio.h> 74fc179b6SThomas Perrot #include <libfdt.h> 84fc179b6SThomas Perrot #include <stdio.h> 94fc179b6SThomas Perrot #include <tee_api_defines.h> 104fc179b6SThomas Perrot #include <tee_api_types.h> 114fc179b6SThomas Perrot #include <util.h> 124fc179b6SThomas Perrot 13a37f67edSPatrick Delaunay /* gpio suffixes used for device tree lookup */ 14a37f67edSPatrick Delaunay static const char * const gpio_suffixes[] = { "gpios", "gpio" }; 15a37f67edSPatrick Delaunay 16b357d34fSEtienne Carriere TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs, struct gpio **out_gpio) 174fc179b6SThomas Perrot { 184fc179b6SThomas Perrot struct gpio *gpio = NULL; 194fc179b6SThomas Perrot 20b357d34fSEtienne Carriere if (pargs->args_count != 2) 21b357d34fSEtienne Carriere return TEE_ERROR_BAD_PARAMETERS; 224fc179b6SThomas Perrot 234fc179b6SThomas Perrot gpio = calloc(1, sizeof(struct gpio)); 24b357d34fSEtienne Carriere if (!gpio) 25b357d34fSEtienne Carriere return TEE_ERROR_OUT_OF_MEMORY; 264fc179b6SThomas Perrot 278fd620f7SEtienne Carriere gpio->pin = pargs->args[0]; 288fd620f7SEtienne Carriere gpio->dt_flags = pargs->args[1]; 294fc179b6SThomas Perrot 30b357d34fSEtienne Carriere *out_gpio = gpio; 31b357d34fSEtienne Carriere 32b357d34fSEtienne Carriere return TEE_SUCCESS; 334fc179b6SThomas Perrot } 344fc179b6SThomas Perrot 354fc179b6SThomas Perrot TEE_Result gpio_dt_get_by_index(const void *fdt, int nodeoffset, 364fc179b6SThomas Perrot unsigned int index, const char *gpio_name, 374fc179b6SThomas Perrot struct gpio **gpio) 384fc179b6SThomas Perrot { 394fc179b6SThomas Perrot TEE_Result res = TEE_ERROR_GENERIC; 40a37f67edSPatrick Delaunay char prop_name[32]; /* 32 is max size of property name in DT */ 41b357d34fSEtienne Carriere void *out_gpio = NULL; 42a37f67edSPatrick Delaunay unsigned int i = 0; 434fc179b6SThomas Perrot 44a37f67edSPatrick Delaunay /* Try GPIO properties "foo-gpios" and "foo-gpio" */ 45a37f67edSPatrick Delaunay for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { 46a37f67edSPatrick Delaunay if (gpio_name) 47a37f67edSPatrick Delaunay snprintf(prop_name, sizeof(prop_name), "%s-%s", 48a37f67edSPatrick Delaunay gpio_name, gpio_suffixes[i]); 49a37f67edSPatrick Delaunay else 50a37f67edSPatrick Delaunay snprintf(prop_name, sizeof(prop_name), "%s", 51a37f67edSPatrick Delaunay gpio_suffixes[i]); 524fc179b6SThomas Perrot 53a37f67edSPatrick Delaunay res = dt_driver_device_from_node_idx_prop(prop_name, fdt, 54a37f67edSPatrick Delaunay nodeoffset, 554fc179b6SThomas Perrot index, DT_DRIVER_GPIO, 56b357d34fSEtienne Carriere &out_gpio); 57a37f67edSPatrick Delaunay 58a37f67edSPatrick Delaunay if (res != TEE_ERROR_ITEM_NOT_FOUND) 59a37f67edSPatrick Delaunay break; 60a37f67edSPatrick Delaunay } 61a37f67edSPatrick Delaunay 62b357d34fSEtienne Carriere if (!res) 63b357d34fSEtienne Carriere *gpio = out_gpio; 644fc179b6SThomas Perrot 654fc179b6SThomas Perrot return res; 664fc179b6SThomas Perrot } 67*39d1e320SPatrick Delaunay 68*39d1e320SPatrick Delaunay TEE_Result gpio_configure(struct gpio *gpio, enum gpio_flags flags) 69*39d1e320SPatrick Delaunay { 70*39d1e320SPatrick Delaunay enum gpio_level value = GPIO_LEVEL_LOW; 71*39d1e320SPatrick Delaunay 72*39d1e320SPatrick Delaunay /* Process requester flags */ 73*39d1e320SPatrick Delaunay if (flags & GPIO_FLAGS_BIT_DIR_SET) { 74*39d1e320SPatrick Delaunay if (flags & GPIO_FLAGS_BIT_DIR_OUT) { 75*39d1e320SPatrick Delaunay if (flags & GPIO_FLAGS_BIT_DIR_VAL) 76*39d1e320SPatrick Delaunay value = GPIO_LEVEL_HIGH; 77*39d1e320SPatrick Delaunay gpio_set_value(gpio, value); 78*39d1e320SPatrick Delaunay gpio_set_direction(gpio, GPIO_DIR_OUT); 79*39d1e320SPatrick Delaunay } else { 80*39d1e320SPatrick Delaunay gpio_set_direction(gpio, GPIO_DIR_IN); 81*39d1e320SPatrick Delaunay } 82*39d1e320SPatrick Delaunay } 83*39d1e320SPatrick Delaunay 84*39d1e320SPatrick Delaunay return TEE_SUCCESS; 85*39d1e320SPatrick Delaunay } 86*39d1e320SPatrick Delaunay 87*39d1e320SPatrick Delaunay TEE_Result gpio_dt_cfg_by_index(const void *fdt, int nodeoffset, 88*39d1e320SPatrick Delaunay unsigned int index, const char *gpio_name, 89*39d1e320SPatrick Delaunay enum gpio_flags flags, struct gpio **gpio) 90*39d1e320SPatrick Delaunay { 91*39d1e320SPatrick Delaunay TEE_Result res = TEE_ERROR_GENERIC; 92*39d1e320SPatrick Delaunay 93*39d1e320SPatrick Delaunay res = gpio_dt_get_by_index(fdt, nodeoffset, index, gpio_name, gpio); 94*39d1e320SPatrick Delaunay if (!res) 95*39d1e320SPatrick Delaunay return gpio_configure(*gpio, flags); 96*39d1e320SPatrick Delaunay 97*39d1e320SPatrick Delaunay return res; 98*39d1e320SPatrick Delaunay } 99