blob: da69413559a954ba525d52b47aeb6df409f10468 [file] [log] [blame]
Brad Bishop77390492016-04-13 10:47:19 -04001#include <stdint.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <fcntl.h>
6#include <unistd.h>
7#include <sys/stat.h>
8#include <sys/mman.h>
9#include <syslog.h>
10#include "interfaces/openbmc_intf.h"
11#include "openbmc.h"
12#include "gpio.h"
13#include "object_mapper.h"
14
15/* ------------------------------------------------------------------------- */
16static const gchar* dbus_object_path = "/org/openbmc/control";
17static const gchar* instance_name = "power0";
18static const gchar* dbus_name = "org.openbmc.control.Power";
19
20//This object will use these GPIOs
21GPIO power_pin = (GPIO){ "POWER_PIN" };
22GPIO pgood = (GPIO){ "PGOOD" };
23GPIO usb_reset = (GPIO){ "USB_RESET" };
24GPIO pcie_reset = (GPIO){ "PCIE_RESET" };
25
26
27static GDBusObjectManagerServer *manager = NULL;
28
29time_t pgood_timeout_start = 0;
30
31// TODO: Change to interrupt driven instead of polling
32static gboolean
33poll_pgood(gpointer user_data)
34{
35 ControlPower *control_power = object_get_control_power((Object*)user_data);
36 Control* control = object_get_control((Object*)user_data);
37
38 //send the heartbeat
Brad Bishop77390492016-04-13 10:47:19 -040039 guint poll_int = control_get_poll_interval(control);
40 if(poll_int == 0)
41 {
42 printf("ERROR PowerControl: Poll interval cannot be 0\n");
43 return FALSE;
44 }
45 //handle timeout
46 time_t current_time = time(NULL);
47 if(difftime(current_time,pgood_timeout_start) > control_power_get_pgood_timeout(control_power)
48 && pgood_timeout_start != 0)
49 {
50 printf("ERROR PowerControl: Pgood poll timeout\n");
51 // set timeout to 0 so timeout doesn't happen again
52 control_power_set_pgood_timeout(control_power,0);
53 pgood_timeout_start = 0;
54 return TRUE;
55 }
56 uint8_t gpio;
57
58 int rc = gpio_open(&pgood);
59 rc = gpio_read(&pgood,&gpio);
60 gpio_close(&pgood);
61 if(rc == GPIO_OK)
62 {
63 //if changed, set property and emit signal
64 if(gpio != control_power_get_pgood(control_power))
65 {
66 control_power_set_pgood(control_power,gpio);
67 if(gpio==0)
68 {
69 control_power_emit_power_lost(control_power);
70 control_emit_goto_system_state(control,"HOST_POWERED_OFF");
71 rc = gpio_open(&pcie_reset);
72 rc = gpio_write(&pcie_reset,0);
73 gpio_close(&pcie_reset);
74
75 rc = gpio_open(&usb_reset);
76 rc = gpio_write(&usb_reset,0);
77 gpio_close(&usb_reset);
78
79 }
80 else
81 {
82 control_power_emit_power_good(control_power);
83 control_emit_goto_system_state(control,"HOST_POWERED_ON");
84 rc = gpio_open(&pcie_reset);
85 rc = gpio_write(&pcie_reset,1);
86 gpio_close(&pcie_reset);
87
88 rc = gpio_open(&usb_reset);
89 rc = gpio_write(&usb_reset,1);
90 gpio_close(&usb_reset);
91 }
92 }
93 } else {
94 printf("ERROR PowerControl: GPIO read error (gpio=%s,rc=%d)\n",pgood.name,rc);
95 //return false so poll won't get called anymore
96 return FALSE;
97 }
98 //pgood is not at desired state yet
99 if(gpio != control_power_get_state(control_power) &&
100 control_power_get_pgood_timeout(control_power) > 0)
101 {
102 if(pgood_timeout_start == 0 ) {
103 pgood_timeout_start = current_time;
104 }
105 }
106 else
107 {
108 pgood_timeout_start = 0;
109 }
110 return TRUE;
111}
112
113static gboolean
114on_set_power_state(ControlPower *pwr,
115 GDBusMethodInvocation *invocation,
116 guint state,
117 gpointer user_data)
118{
119 Control* control = object_get_control((Object*)user_data);
Brad Bishop77390492016-04-13 10:47:19 -0400120 if(state > 1)
121 {
122 g_dbus_method_invocation_return_dbus_error(invocation,
123 "org.openbmc.ControlPower.Error.Failed",
124 "Invalid power state");
125 return TRUE;
126 }
127 // return from method call
128 control_power_complete_set_power_state(pwr,invocation);
129 if(state == control_power_get_state(pwr))
130 {
131 g_print("Power already at requested state: %d\n",state);
132 }
133 else
134 {
135 int error = 0;
136 do {
137 if(state == 1) {
138 control_emit_goto_system_state(control,"HOST_POWERING_ON");
139 } else {
140 control_emit_goto_system_state(control,"HOST_POWERING_OFF");
141 }
142 error = gpio_open(&power_pin);
143 if(error != GPIO_OK) { break; }
144 error = gpio_write(&power_pin,!state);
145 if(error != GPIO_OK) { break; }
146 gpio_close(&power_pin);
147 control_power_set_state(pwr,state);
148 } while(0);
149 if(error != GPIO_OK)
150 {
151 printf("ERROR PowerControl: GPIO set power state (rc=%d)\n",error);
152 }
153 }
154 return TRUE;
155}
156
157static gboolean
158on_init(Control *control,
159 GDBusMethodInvocation *invocation,
160 gpointer user_data)
161{
162 pgood_timeout_start = 0;
163 //guint poll_interval = control_get_poll_interval(control);
164 //g_timeout_add(poll_interval, poll_pgood, user_data);
165 control_complete_init(control,invocation);
166 return TRUE;
167}
168
169static gboolean
170on_get_power_state(ControlPower *pwr,
171 GDBusMethodInvocation *invocation,
172 gpointer user_data)
173{
174 guint pgood = control_power_get_pgood(pwr);
175 control_power_complete_get_power_state(pwr,invocation,pgood);
176 return TRUE;
177}
178
179static void
180on_bus_acquired(GDBusConnection *connection,
181 const gchar *name,
182 gpointer user_data)
183{
184 ObjectSkeleton *object;
185 cmdline *cmd = user_data;
186 if(cmd->argc < 3)
187 {
188 g_print("Usage: power_control.exe [poll interval] [timeout]\n");
189 return;
190 }
191 manager = g_dbus_object_manager_server_new(dbus_object_path);
192 gchar *s;
193 s = g_strdup_printf("%s/%s",dbus_object_path,instance_name);
194 object = object_skeleton_new(s);
195 g_free(s);
196
197 ControlPower* control_power = control_power_skeleton_new();
198 object_skeleton_set_control_power(object, control_power);
199 g_object_unref(control_power);
200
201 Control* control = control_skeleton_new();
202 object_skeleton_set_control(object, control);
203 g_object_unref(control);
204
205 ObjectMapper* mapper = object_mapper_skeleton_new();
206 object_skeleton_set_object_mapper(object, mapper);
207 g_object_unref(mapper);
208
209 //define method callbacks here
210 g_signal_connect(control_power,
211 "handle-set-power-state",
212 G_CALLBACK(on_set_power_state),
213 object); /* user_data */
214
215 g_signal_connect(control_power,
216 "handle-get-power-state",
217 G_CALLBACK(on_get_power_state),
218 NULL); /* user_data */
219
220 g_signal_connect(control,
221 "handle-init",
222 G_CALLBACK(on_init),
223 object); /* user_data */
224
225
226 /* Export the object (@manager takes its own reference to @object) */
227 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object));
228 g_object_unref(object);
229
230 /* Export all objects */
231 g_dbus_object_manager_server_set_connection(manager, connection);
232
233 // get gpio device paths
234 int rc = GPIO_OK;
235 do {
236 rc = gpio_init(connection,&power_pin);
237 if(rc != GPIO_OK) { break; }
238 rc = gpio_init(connection,&pgood);
239 if(rc != GPIO_OK) { break; }
240 rc = gpio_init(connection,&pcie_reset);
241 if(rc != GPIO_OK) { break; }
242 rc = gpio_init(connection,&usb_reset);
243 if(rc != GPIO_OK) { break; }
244
245 uint8_t gpio;
246 rc = gpio_open(&pgood);
247 if(rc != GPIO_OK) { break; }
248 rc = gpio_read(&pgood,&gpio);
249 if(rc != GPIO_OK) { break; }
250 gpio_close(&pgood);
251 control_power_set_pgood(control_power,gpio);
252 control_power_set_state(control_power,gpio);
253 printf("Pgood state: %d\n",gpio);
254
255 } while(0);
256 if(rc != GPIO_OK)
257 {
258 printf("ERROR PowerControl: GPIO setup (rc=%d)\n",rc);
259 }
260 //start poll
261 pgood_timeout_start = 0;
262 int poll_interval = atoi(cmd->argv[1]);
263 int pgood_timeout = atoi(cmd->argv[2]);
264 if(poll_interval < 1000 || pgood_timeout <5) {
265 printf("ERROR PowerControl: poll_interval < 1000 or pgood_timeout < 5\n");
266 } else {
267 control_set_poll_interval(control,poll_interval);
268 control_power_set_pgood_timeout(control_power,pgood_timeout);
269 g_timeout_add(poll_interval, poll_pgood, object);
270 }
271 emit_object_added((GDBusObjectManager*)manager);
272}
273
274static void
275on_name_acquired(GDBusConnection *connection,
276 const gchar *name,
277 gpointer user_data)
278{
279}
280
281static void
282on_name_lost(GDBusConnection *connection,
283 const gchar *name,
284 gpointer user_data)
285{
286}
287
288/*----------------------------------------------------------------*/
289/* Main Event Loop */
290
291gint
292main(gint argc, gchar *argv[])
293{
294 GMainLoop *loop;
295 cmdline cmd;
296 cmd.argc = argc;
297 cmd.argv = argv;
298
299 guint id;
300 loop = g_main_loop_new(NULL, FALSE);
301
302 id = g_bus_own_name(DBUS_TYPE,
303 dbus_name,
304 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
305 G_BUS_NAME_OWNER_FLAGS_REPLACE,
306 on_bus_acquired,
307 on_name_acquired,
308 on_name_lost,
309 &cmd,
310 NULL);
311
312 g_main_loop_run(loop);
313
314 g_bus_unown_name(id);
315 g_main_loop_unref(loop);
316 return 0;
317}