1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-11-26 GuEe-GUI first version
9 */
10
11 #include <dt-bindings/pin/pin.h>
12
13 #include "dev_pin_dm.h"
14
15 static const char * const gpio_suffixes[] =
16 {
17 "gpios", "gpio"
18 };
19
rt_ofw_get_named_pin(struct rt_ofw_node * np,const char * propname,int index,rt_uint8_t * out_mode,rt_uint8_t * out_value)20 rt_ssize_t rt_ofw_get_named_pin(struct rt_ofw_node *np, const char *propname, int index,
21 rt_uint8_t *out_mode, rt_uint8_t *out_value)
22 {
23 rt_ssize_t pin = -1;
24 rt_uint8_t mode;
25 rt_uint8_t value;
26 rt_uint32_t flags;
27 char gpios_name[64];
28 struct rt_device_pin *pin_dev = 0;
29 struct rt_ofw_node *pin_dev_np = 0;
30 struct rt_ofw_cell_args pin_args = {0};
31
32 if (!np && index < 0)
33 {
34 return -RT_EINVAL;
35 }
36
37 for (int i = 0; i < RT_ARRAY_SIZE(gpio_suffixes); ++i)
38 {
39 if (propname)
40 {
41 rt_snprintf(gpios_name, sizeof(gpios_name), "%s-%s", propname, gpio_suffixes[i]);
42 }
43 else
44 {
45 rt_snprintf(gpios_name, sizeof(gpios_name), "%s", gpio_suffixes[i]);
46 }
47
48 pin = rt_ofw_parse_phandle_cells(np, gpios_name, "#gpio-cells", index, &pin_args);
49
50 if (pin >= 0)
51 {
52 break;
53 }
54 }
55
56 if (pin < 0)
57 {
58 return pin;
59 }
60
61 pin_dev_np = pin_args.data;
62
63 if (!rt_ofw_data(pin_dev_np))
64 {
65 rt_platform_ofw_request(pin_dev_np);
66 }
67
68 pin_dev = rt_ofw_data(pin_dev_np);
69
70 if (!pin_dev)
71 {
72 pin = -RT_ERROR;
73
74 goto _out_converts;
75 }
76
77 value = PIN_LOW;
78 mode = PIN_MODE_OUTPUT;
79
80 if (pin_dev->ops->pin_parse)
81 {
82 pin = pin_dev->ops->pin_parse(&pin_dev->parent, &pin_args, &flags);
83 }
84 else
85 {
86 /*
87 * We always assume that the args[0] is the pin number if driver not
88 * implemented `pin_parse`.
89 */
90 pin = pin_args.args[0];
91
92 goto _out_converts;
93 }
94
95 if (out_mode)
96 {
97 if (flags & PIN_OPEN_DRAIN)
98 {
99 mode = PIN_MODE_OUTPUT_OD;
100 }
101
102 switch (flags & RT_GENMASK(6, 4))
103 {
104 case PIN_PULL_UP:
105 mode = PIN_MODE_INPUT_PULLUP;
106 break;
107
108 case PIN_PULL_DOWN:
109 mode = PIN_MODE_INPUT_PULLDOWN;
110 break;
111
112 case PIN_PULL_DISABLE:
113 mode = PIN_MODE_INPUT;
114 break;
115 }
116 }
117
118 if (out_value)
119 {
120 if ((flags & 1) == PIN_ACTIVE_HIGH)
121 {
122 value = PIN_HIGH;
123 }
124 else if ((flags & 1) == PIN_ACTIVE_LOW)
125 {
126 value = PIN_LOW;
127 }
128 }
129
130 _out_converts:
131 rt_ofw_node_put(pin_dev_np);
132
133 if (pin >= 0)
134 {
135 /* Get virtual pin */
136 pin += pin_dev->pin_start;
137
138 if (out_mode)
139 {
140 *out_mode = mode;
141 }
142
143 if (out_value)
144 {
145 *out_value = value;
146 }
147 }
148
149 return pin;
150 }
151
rt_ofw_get_named_pin_count(struct rt_ofw_node * np,const char * propname)152 rt_ssize_t rt_ofw_get_named_pin_count(struct rt_ofw_node *np, const char *propname)
153 {
154 char gpios_name[64];
155 rt_ssize_t count = 0;
156
157 if (!np)
158 {
159 return -RT_EINVAL;
160 }
161
162 for (int i = 0; i < RT_ARRAY_SIZE(gpio_suffixes); ++i)
163 {
164 if (propname)
165 {
166 rt_snprintf(gpios_name, sizeof(gpios_name), "%s-%s", propname, gpio_suffixes[i]);
167 }
168 else
169 {
170 rt_snprintf(gpios_name, sizeof(gpios_name), "%s", gpio_suffixes[i]);
171 }
172
173 count = rt_ofw_count_phandle_cells(np, propname, "#gpio-cells");
174
175 if (count > 0)
176 {
177 break;
178 }
179 }
180
181 return count;
182 }
183