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
gpio_dt_alloc_pin(struct dt_pargs * pargs,struct gpio ** out_gpio)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
gpio_dt_get_by_index(const void * fdt,int nodeoffset,unsigned int index,const char * gpio_name,struct gpio ** gpio)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
gpio_configure(struct gpio * gpio,enum gpio_flags flags)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
gpio_dt_cfg_by_index(const void * fdt,int nodeoffset,unsigned int index,const char * gpio_name,enum gpio_flags flags,struct gpio ** gpio)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