1 /**
2  * Copyright © 2016 Google Inc.
3  * Copyright © 2016 IBM Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include "gpio_configs.h"
19 #include "gpio_json.h"
20 #include <cjson/cJSON.h>
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <glib.h>
26 
27 
28 /**
29  * Loads the GPIO information into the gpios->power_gpio structure
30  * from the JSON.
31  *
32  * @param gpios - the structure where GpioConfigs.power_gpio will
33  *                be filled in.
34  * @param gpio_configs - cJSON pointer to the GPIO JSON
35  */
36 void read_power_gpios(GpioConfigs* gpios, const cJSON* gpio_configs)
37 {
38 	size_t i = 0;
39 
40 	const cJSON* power_config = cJSON_GetObjectItem(
41 			gpio_configs, "power_config");
42 	g_assert(power_config != NULL);
43 
44 	/* PGOOD - required */
45 
46 	const cJSON* pgood = cJSON_GetObjectItem(power_config, "power_good_in");
47 	g_assert(pgood != NULL);
48 
49 	gpios->power_gpio.power_good_in.name = g_strdup(pgood->valuestring);
50 
51 	g_print("Power GPIO power good input: %s\n",
52 			gpios->power_gpio.power_good_in.name);
53 
54 	/* Latch out - optional */
55 
56 	const cJSON* latch = cJSON_GetObjectItem(power_config, "latch_out");
57 	if (latch != NULL)
58 	{
59 		gpios->power_gpio.latch_out.name = g_strdup(latch->valuestring);
60 		g_print("Power GPIO latch output: %s\n",
61 				gpios->power_gpio.latch_out.name);
62 	}
63 	else
64 	{
65 		//Must be NULL if not there
66 		gpios->power_gpio.latch_out.name = NULL;
67 	}
68 
69 	/* Power Up Outs - required */
70 
71 	const cJSON* power_up_outs = cJSON_GetObjectItem(
72 			power_config, "power_up_outs");
73 	g_assert(power_up_outs != NULL);
74 
75 	gpios->power_gpio.num_power_up_outs = cJSON_GetArraySize(power_up_outs);
76 	g_print("Power GPIO %zu power_up outputs\n",
77 			gpios->power_gpio.num_power_up_outs);
78 
79 	if (gpios->power_gpio.num_power_up_outs != 0)
80 	{
81 		gpios->power_gpio.power_up_outs =
82 			g_malloc0_n(gpios->power_gpio.num_power_up_outs, sizeof(GPIO));
83 		gpios->power_gpio.power_up_pols =
84 			g_malloc0_n(gpios->power_gpio.num_power_up_outs, sizeof(gboolean));
85 
86 		const cJSON* power_out;
87 		cJSON_ArrayForEach(power_out, power_up_outs)
88 		{
89 			cJSON* name = cJSON_GetObjectItem(power_out, "name");
90 			g_assert(name != NULL);
91 			gpios->power_gpio.power_up_outs[i].name =
92 				g_strdup(name->valuestring);
93 
94 			const cJSON* polarity = cJSON_GetObjectItem(power_out, "polarity");
95 			g_assert(polarity != NULL);
96 			gpios->power_gpio.power_up_pols[i] = polarity->valueint;
97 
98 			g_print("Power GPIO power_up[%d] = %s active %s\n",
99 					i, gpios->power_gpio.power_up_outs[i].name,
100 					gpios->power_gpio.power_up_pols[i] ? "HIGH" : "LOW");
101 			i++;
102 		}
103 	}
104 
105 	/* Resets - optional */
106 
107 	const cJSON* reset_outs = cJSON_GetObjectItem(power_config, "reset_outs");
108 	gpios->power_gpio.num_reset_outs = cJSON_GetArraySize(reset_outs);
109 
110 	g_print("Power GPIO %zu reset outputs\n",
111 			gpios->power_gpio.num_reset_outs);
112 
113 	if (gpios->power_gpio.num_reset_outs != 0)
114 	{
115 		gpios->power_gpio.reset_outs =
116 			g_malloc0_n(gpios->power_gpio.num_reset_outs, sizeof(GPIO));
117 		gpios->power_gpio.reset_pols =
118 			g_malloc0_n(gpios->power_gpio.num_reset_outs, sizeof(gboolean));
119 
120 		i = 0;
121 		const cJSON* reset_out;
122 		cJSON_ArrayForEach(reset_out, reset_outs)
123 		{
124 			cJSON* name = cJSON_GetObjectItem(reset_out, "name");
125 			g_assert(name != NULL);
126 			gpios->power_gpio.reset_outs[i].name = g_strdup(name->valuestring);
127 
128 			const cJSON* polarity = cJSON_GetObjectItem(reset_out, "polarity");
129 			g_assert(polarity != NULL);
130 			gpios->power_gpio.reset_pols[i] = polarity->valueint;
131 
132 			g_print("Power GPIO reset[%d] = %s active %s\n", i,
133 					gpios->power_gpio.reset_outs[i].name,
134 					gpios->power_gpio.reset_pols[i] ? "HIGH" : "LOW");
135 			i++;
136 		}
137 	}
138 
139 	/* PCI Resets - optional */
140 
141 	const cJSON* pci_reset_outs = cJSON_GetObjectItem(
142 			power_config, "pci_reset_outs");
143 
144 	gpios->power_gpio.num_pci_reset_outs =
145 		cJSON_GetArraySize(pci_reset_outs);
146 
147 	g_print("Power GPIO %zd pci reset outputs\n",
148 			gpios->power_gpio.num_pci_reset_outs);
149 
150 	if (gpios->power_gpio.num_pci_reset_outs != 0)
151 	{
152 		gpios->power_gpio.pci_reset_outs =
153 			g_malloc0_n(gpios->power_gpio.num_pci_reset_outs, sizeof(GPIO));
154 		gpios->power_gpio.pci_reset_pols =
155 			g_malloc0_n(gpios->power_gpio.num_pci_reset_outs, sizeof(gboolean));
156 		gpios->power_gpio.pci_reset_holds =
157 			g_malloc0_n(gpios->power_gpio.num_pci_reset_outs, sizeof(gboolean));
158 
159 		i = 0;
160 		const cJSON* pci_reset_out;
161 		cJSON_ArrayForEach(pci_reset_out, pci_reset_outs)
162 		{
163 			cJSON* name = cJSON_GetObjectItem(pci_reset_out, "name");
164 			g_assert(name != NULL);
165             gpios->power_gpio.pci_reset_outs[i].name =
166                 g_strdup(name->valuestring);
167 
168 			const cJSON* polarity = cJSON_GetObjectItem(
169                     pci_reset_out, "polarity");
170 			g_assert(polarity != NULL);
171 			gpios->power_gpio.pci_reset_pols[i] = polarity->valueint;
172 
173 			const cJSON* hold = cJSON_GetObjectItem(pci_reset_out, "hold");
174 			g_assert(hold != NULL);
175 			gpios->power_gpio.pci_reset_holds[i] = polarity->valueint;
176 
177 			g_print("Power GPIO pci reset[%d] = %s active %s, hold %s\n", i,
178 					gpios->power_gpio.pci_reset_outs[i].name,
179 					gpios->power_gpio.pci_reset_pols[i] ? "HIGH" : "LOW",
180 					gpios->power_gpio.pci_reset_holds[i] ? "Yes" : "No");
181 			i++;
182 		}
183 	}
184 }
185 
186 gboolean read_gpios(GDBusConnection *connection, GpioConfigs *gpios)
187 {
188 	cJSON* json = load_json();
189 	if (json == NULL)
190 	{
191 		return FALSE;
192 	}
193 
194 	const cJSON* configs = cJSON_GetObjectItem(json, "gpio_configs");
195 	g_assert(configs != NULL);
196 
197 	read_power_gpios(gpios, configs);
198 
199 	cJSON_Delete(json);
200 	return TRUE;
201 }
202 
203 void free_gpios(GpioConfigs *gpios) {
204 	int i;
205 	g_free(gpios->power_gpio.latch_out.name);
206 	g_free(gpios->power_gpio.power_good_in.name);
207 	for(i = 0; i < gpios->power_gpio.num_power_up_outs; i++) {
208 		g_free(gpios->power_gpio.power_up_outs[i].name);
209 	}
210 	g_free(gpios->power_gpio.power_up_outs);
211 	g_free(gpios->power_gpio.power_up_pols);
212 	for(i = 0; i < gpios->power_gpio.num_reset_outs; i++) {
213 		g_free(gpios->power_gpio.reset_outs[i].name);
214 	}
215 	g_free(gpios->power_gpio.reset_outs);
216 	g_free(gpios->power_gpio.reset_pols);
217 	for(i = 0; i < gpios->power_gpio.num_pci_reset_outs; i++) {
218 		g_free(gpios->power_gpio.pci_reset_outs[i].name);
219 	}
220 	g_free(gpios->power_gpio.pci_reset_outs);
221 	g_free(gpios->power_gpio.pci_reset_pols);
222 	g_free(gpios->power_gpio.pci_reset_holds);
223 
224 	g_free(gpios->hostctl_gpio.fsi_data.name);
225 	g_free(gpios->hostctl_gpio.fsi_clk.name);
226 	g_free(gpios->hostctl_gpio.fsi_enable.name);
227 	g_free(gpios->hostctl_gpio.cronus_sel.name);
228 	for (i = 0; i < gpios->hostctl_gpio.num_optionals; ++i) {
229 		g_free(gpios->hostctl_gpio.optionals[i].name);
230 	}
231 }
232