1 #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 <openbmc_intf.h> 11 #include <openbmc.h> 12 #include <gpio.h> 13 #include <gpio_configs.h> 14 15 /* ------------------------------------------------------------------------- */ 16 static const gchar* dbus_object_path = "/org/openbmc/control"; 17 static const gchar* instance_name = "power0"; 18 static const gchar* dbus_name = "org.openbmc.control.Power"; 19 20 static int g_pci_reset_held = 1; 21 22 static GpioConfigs g_gpio_configs; 23 24 static GDBusObjectManagerServer *manager = NULL; 25 26 time_t pgood_timeout_start = 0; 27 28 // TODO: Change to interrupt driven instead of polling 29 static gboolean 30 poll_pgood(gpointer user_data) 31 { 32 ControlPower *control_power = object_get_control_power((Object*)user_data); 33 Control* control = object_get_control((Object*)user_data); 34 35 //send the heartbeat 36 guint poll_int = control_get_poll_interval(control); 37 if(poll_int == 0) 38 { 39 g_print("ERROR PowerControl: Poll interval cannot be 0\n"); 40 return FALSE; 41 } 42 //handle timeout 43 time_t current_time = time(NULL); 44 if(difftime(current_time,pgood_timeout_start) > control_power_get_pgood_timeout(control_power) 45 && pgood_timeout_start != 0) 46 { 47 g_print("ERROR PowerControl: Pgood poll timeout\n"); 48 // set timeout to 0 so timeout doesn't happen again 49 control_power_set_pgood_timeout(control_power,0); 50 pgood_timeout_start = 0; 51 return TRUE; 52 } 53 uint8_t pgood_state; 54 55 int rc = gpio_open(&g_gpio_configs.power_gpio.power_good_in); 56 if(rc != GPIO_OK) { 57 g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n", 58 g_gpio_configs.power_gpio.power_good_in.name, rc); 59 return FALSE; 60 } 61 rc = gpio_read(&g_gpio_configs.power_gpio.power_good_in, &pgood_state); 62 gpio_close(&g_gpio_configs.power_gpio.power_good_in); 63 if(rc == GPIO_OK) 64 { 65 //if changed, set property and emit signal 66 if(pgood_state != control_power_get_pgood(control_power)) 67 { 68 int i; 69 uint8_t reset_state; 70 control_power_set_pgood(control_power, pgood_state); 71 if(pgood_state == 0) 72 { 73 control_power_emit_power_lost(control_power); 74 control_emit_goto_system_state(control,"HOST_POWERED_OFF"); 75 g_pci_reset_held = 1; 76 } 77 else 78 { 79 control_power_emit_power_good(control_power); 80 control_emit_goto_system_state(control,"HOST_POWERED_ON"); 81 } 82 83 for(i = 0; i < g_gpio_configs.power_gpio.num_reset_outs; i++) 84 { 85 GPIO *reset_out = &g_gpio_configs.power_gpio.reset_outs[i]; 86 rc = gpio_open(reset_out); 87 if(rc != GPIO_OK) 88 { 89 g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n", 90 reset_out->name, rc); 91 continue; 92 } 93 94 reset_state = pgood_state ^ g_gpio_configs.power_gpio.reset_pols[i]; 95 g_print("PowerControl: pgood: %d, setting reset %s to %d\n", 96 (int)pgood_state, reset_out->name, (int)reset_state); 97 gpio_write(reset_out, reset_state); 98 gpio_close(reset_out); 99 } 100 101 for(i = 0; i < g_gpio_configs.power_gpio.num_pci_reset_outs; i++) 102 { 103 GPIO *pci_reset_out = &g_gpio_configs.power_gpio.pci_reset_outs[i]; 104 if(pgood_state == 1) 105 { 106 /* 107 * When powering on, hold PCI reset until 108 * the processor can forward clocks and control reset. 109 */ 110 if(g_gpio_configs.power_gpio.pci_reset_holds[i]) 111 { 112 g_print("Holding pci reset: %s\n", pci_reset_out->name); 113 continue; 114 } 115 } 116 rc = gpio_open(pci_reset_out); 117 if(rc != GPIO_OK) 118 { 119 g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n", 120 pci_reset_out->name, rc); 121 continue; 122 } 123 124 reset_state = pgood_state ^ g_gpio_configs.power_gpio.pci_reset_pols[i]; 125 g_print("PowerControl: pgood: %d, setting pci reset %s to %d\n", 126 (int)pgood_state, pci_reset_out->name, (int)reset_state); 127 gpio_write(pci_reset_out, reset_state); 128 gpio_close(pci_reset_out); 129 } 130 } 131 } else { 132 g_print("ERROR PowerControl: GPIO read error (gpio=%s,rc=%d)\n", 133 g_gpio_configs.power_gpio.power_good_in.name, rc); 134 //return false so poll won't get called anymore 135 return FALSE; 136 } 137 //pgood is not at desired state yet 138 if(pgood_state != control_power_get_state(control_power) && 139 control_power_get_pgood_timeout(control_power) > 0) 140 { 141 if(pgood_timeout_start == 0 ) { 142 pgood_timeout_start = current_time; 143 } 144 } 145 else 146 { 147 pgood_timeout_start = 0; 148 } 149 return TRUE; 150 } 151 152 /* Handler for BootProgress signal from BootProgress sensor */ 153 static void 154 on_boot_progress(GDBusConnection *connection, 155 const gchar *sender_name, 156 const gchar *object_path, 157 const gchar *interface_name, 158 const gchar *signal_name, 159 GVariant *parameters, 160 gpointer user_data) 161 { 162 gchar *boot_progress; 163 uint8_t pgood_state; 164 uint8_t reset_state; 165 int rc; 166 int i; 167 168 if(!parameters) 169 return; 170 171 /* prevent release again */ 172 if(!g_pci_reset_held) 173 return; 174 175 g_variant_get(parameters, "(s)", &boot_progress); 176 /* Release PCI reset when FW boot progress goes beyond 'Baseboard Init' */ 177 if(strcmp(boot_progress, "FW Progress, Baseboard Init") == 0) 178 return; 179 180 rc = gpio_open(&g_gpio_configs.power_gpio.power_good_in); 181 if(rc != GPIO_OK) 182 { 183 g_print("ERROR PowerControl: on_boot_progress(): GPIO open error (gpio=%s,rc=%d)\n", 184 g_gpio_configs.power_gpio.power_good_in.name, rc); 185 return; 186 } 187 rc = gpio_read(&g_gpio_configs.power_gpio.power_good_in, &pgood_state); 188 gpio_close(&g_gpio_configs.power_gpio.power_good_in); 189 if(rc != GPIO_OK || pgood_state != 1) 190 return; 191 192 for(i = 0; i < g_gpio_configs.power_gpio.num_pci_reset_outs; i++) 193 { 194 GPIO *pci_reset_out = &g_gpio_configs.power_gpio.pci_reset_outs[i]; 195 196 if(!g_gpio_configs.power_gpio.pci_reset_holds[i]) 197 continue; 198 rc = gpio_open(pci_reset_out); 199 if(rc != GPIO_OK) 200 { 201 g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n", 202 pci_reset_out->name, rc); 203 continue; 204 } 205 206 reset_state = pgood_state ^ g_gpio_configs.power_gpio.pci_reset_pols[i]; 207 g_print("PowerControl: pgood: %d, setting pci reset %s to %d\n", 208 (int)pgood_state, pci_reset_out->name, (int)reset_state); 209 gpio_write(pci_reset_out, reset_state); 210 gpio_close(pci_reset_out); 211 g_print("Released pci reset: %s - %s\n", pci_reset_out->name, boot_progress); 212 } 213 g_pci_reset_held = 0; 214 } 215 216 static gboolean 217 on_set_power_state(ControlPower *pwr, 218 GDBusMethodInvocation *invocation, 219 guint state, 220 gpointer user_data) 221 { 222 Control* control = object_get_control((Object*)user_data); 223 PowerGpio *power_gpio = &g_gpio_configs.power_gpio; 224 if(state > 1) 225 { 226 g_dbus_method_invocation_return_dbus_error(invocation, 227 "org.openbmc.ControlPower.Error.Failed", 228 "Invalid power state"); 229 return TRUE; 230 } 231 // return from method call 232 control_power_complete_set_power_state(pwr,invocation); 233 if(state == control_power_get_state(pwr)) 234 { 235 g_print("Power already at requested state: %d\n",state); 236 } 237 else 238 { 239 int error = 0; 240 do { 241 int i; 242 uint8_t power_up_out; 243 if(state == 1) { 244 control_emit_goto_system_state(control,"HOST_POWERING_ON"); 245 } else { 246 control_emit_goto_system_state(control,"HOST_POWERING_OFF"); 247 } 248 for (i = 0; i < power_gpio->num_power_up_outs; i++) { 249 GPIO *power_pin = &power_gpio->power_up_outs[i]; 250 error = gpio_open(power_pin); 251 if(error != GPIO_OK) { 252 g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n", 253 power_gpio->power_up_outs[i].name, error); 254 continue; 255 } 256 power_up_out = state ^ !power_gpio->power_up_pols[i]; 257 g_print("PowerControl: setting power up %s to %d\n", 258 power_gpio->power_up_outs[i].name, (int)power_up_out); 259 error = gpio_write(power_pin, power_up_out); 260 if(error != GPIO_OK) { 261 continue; 262 } 263 gpio_close(power_pin); 264 } 265 if(error != GPIO_OK) { break; } 266 control_power_set_state(pwr,state); 267 } while(0); 268 if(error != GPIO_OK) 269 { 270 g_print("ERROR PowerControl: GPIO set power state (rc=%d)\n",error); 271 } 272 273 /* If there's a latch, it should be enabled following changes to the 274 * power pins' states. This commits the changes to the latch states. */ 275 if (power_gpio->latch_out.name != NULL) { 276 int rc; 277 uint8_t latch_value = 0; 278 rc = gpio_open(&power_gpio->latch_out); 279 if (rc != GPIO_OK) { 280 /* Failures are non-fatal. */ 281 g_print("PowerControl ERROR failed to open latch %s rc=%d\n", 282 power_gpio->latch_out.name, rc); 283 return TRUE; 284 } 285 /* Make the latch transparent for as brief of a time as possible. */ 286 rc = gpio_write(&power_gpio->latch_out, 1); 287 if (rc != GPIO_OK) { 288 g_print("PowerControl ERROR failed to assert latch %s rc=%d\n", 289 power_gpio->latch_out.name, rc); 290 } else { 291 g_print("PowerControl asserted latch %s\n", 292 power_gpio->latch_out.name); 293 } 294 rc = gpio_write(&power_gpio->latch_out, 0); 295 if (rc != GPIO_OK) { 296 g_print("PowerControl ERROR failed to clear latch %s rc=%d\n", 297 power_gpio->latch_out.name, rc); 298 } 299 gpio_close(&power_gpio->latch_out); 300 } 301 } 302 303 return TRUE; 304 } 305 306 static gboolean 307 on_init(Control *control, 308 GDBusMethodInvocation *invocation, 309 gpointer user_data) 310 { 311 pgood_timeout_start = 0; 312 //guint poll_interval = control_get_poll_interval(control); 313 //g_timeout_add(poll_interval, poll_pgood, user_data); 314 control_complete_init(control,invocation); 315 return TRUE; 316 } 317 318 static gboolean 319 on_get_power_state(ControlPower *pwr, 320 GDBusMethodInvocation *invocation, 321 gpointer user_data) 322 { 323 guint pgood = control_power_get_pgood(pwr); 324 control_power_complete_get_power_state(pwr,invocation,pgood); 325 return TRUE; 326 } 327 328 static int 329 set_up_gpio(GDBusConnection *connection, 330 PowerGpio *power_gpio, 331 ControlPower* control_power) 332 { 333 int error = GPIO_OK; 334 int rc; 335 int i; 336 uint8_t pgood_state; 337 338 // get gpio device paths 339 if(power_gpio->latch_out.name != NULL) { /* latch is optional */ 340 rc = gpio_init(connection, &power_gpio->latch_out); 341 if(rc != GPIO_OK) { 342 error = rc; 343 } 344 } 345 rc = gpio_init(connection, &power_gpio->power_good_in); 346 if(rc != GPIO_OK) { 347 error = rc; 348 } 349 for(int i = 0; i < power_gpio->num_power_up_outs; i++) { 350 rc = gpio_init(connection, &power_gpio->power_up_outs[i]); 351 if(rc != GPIO_OK) { 352 error = rc; 353 } 354 } 355 for(int i = 0; i < power_gpio->num_reset_outs; i++) { 356 rc = gpio_init(connection, &power_gpio->reset_outs[i]); 357 if(rc != GPIO_OK) { 358 error = rc; 359 } 360 } 361 for(int i = 0; i < power_gpio->num_pci_reset_outs; i++) { 362 rc = gpio_init(connection, &power_gpio->pci_reset_outs[i]); 363 if(rc != GPIO_OK) { 364 error = rc; 365 } 366 } 367 368 rc = gpio_open(&power_gpio->power_good_in); 369 if(rc != GPIO_OK) { 370 return rc; 371 } 372 rc = gpio_read(&power_gpio->power_good_in, &pgood_state); 373 if(rc != GPIO_OK) { 374 return rc; 375 } 376 gpio_close(&power_gpio->power_good_in); 377 control_power_set_pgood(control_power, pgood_state); 378 control_power_set_state(control_power, pgood_state); 379 g_print("Pgood state: %d\n", pgood_state); 380 381 return error; 382 } 383 384 static void 385 on_bus_acquired(GDBusConnection *connection, 386 const gchar *name, 387 gpointer user_data) 388 { 389 ObjectSkeleton *object; 390 cmdline *cmd = user_data; 391 if(cmd->argc < 3) 392 { 393 g_print("Usage: power_control.exe [poll interval] [timeout]\n"); 394 return; 395 } 396 manager = g_dbus_object_manager_server_new(dbus_object_path); 397 gchar *s; 398 s = g_strdup_printf("%s/%s",dbus_object_path,instance_name); 399 object = object_skeleton_new(s); 400 g_free(s); 401 402 ControlPower* control_power = control_power_skeleton_new(); 403 object_skeleton_set_control_power(object, control_power); 404 g_object_unref(control_power); 405 406 Control* control = control_skeleton_new(); 407 object_skeleton_set_control(object, control); 408 g_object_unref(control); 409 410 //define method callbacks here 411 g_signal_connect(control_power, 412 "handle-set-power-state", 413 G_CALLBACK(on_set_power_state), 414 object); /* user_data */ 415 416 g_signal_connect(control_power, 417 "handle-get-power-state", 418 G_CALLBACK(on_get_power_state), 419 NULL); /* user_data */ 420 421 g_signal_connect(control, 422 "handle-init", 423 G_CALLBACK(on_init), 424 object); /* user_data */ 425 426 /* Listen for BootProgress signal from BootProgress sensor */ 427 g_dbus_connection_signal_subscribe(connection, 428 NULL, /* service */ 429 NULL, /* interface_name */ 430 "BootProgress", /* member: name of the signal */ 431 "/org/openbmc/sensors/host/BootProgress", /* obj path */ 432 NULL, /* arg0 */ 433 G_DBUS_SIGNAL_FLAGS_NONE, 434 (GDBusSignalCallback) on_boot_progress, 435 object, /* user data */ 436 NULL ); 437 438 /* Export the object (@manager takes its own reference to @object) */ 439 g_dbus_object_manager_server_set_connection(manager, connection); 440 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object)); 441 g_object_unref(object); 442 443 if(read_gpios(connection, &g_gpio_configs) != TRUE) { 444 g_print("ERROR PowerControl: could not read power GPIO configuration\n"); 445 } 446 447 int rc = set_up_gpio(connection, &g_gpio_configs.power_gpio, control_power); 448 if(rc != GPIO_OK) { 449 g_print("ERROR PowerControl: GPIO setup (rc=%d)\n",rc); 450 } 451 //start poll 452 pgood_timeout_start = 0; 453 int poll_interval = atoi(cmd->argv[1]); 454 int pgood_timeout = atoi(cmd->argv[2]); 455 if(poll_interval < 1000 || pgood_timeout <5) { 456 g_print("ERROR PowerControl: poll_interval < 1000 or pgood_timeout < 5\n"); 457 } else { 458 control_set_poll_interval(control,poll_interval); 459 control_power_set_pgood_timeout(control_power,pgood_timeout); 460 g_timeout_add(poll_interval, poll_pgood, object); 461 } 462 } 463 464 static void 465 on_name_acquired(GDBusConnection *connection, 466 const gchar *name, 467 gpointer user_data) 468 { 469 } 470 471 static void 472 on_name_lost(GDBusConnection *connection, 473 const gchar *name, 474 gpointer user_data) 475 { 476 free_gpios(&g_gpio_configs); 477 } 478 479 /*----------------------------------------------------------------*/ 480 /* Main Event Loop */ 481 482 gint 483 main(gint argc, gchar *argv[]) 484 { 485 GMainLoop *loop; 486 cmdline cmd; 487 cmd.argc = argc; 488 cmd.argv = argv; 489 490 guint id; 491 loop = g_main_loop_new(NULL, FALSE); 492 493 id = g_bus_own_name(DBUS_TYPE, 494 dbus_name, 495 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | 496 G_BUS_NAME_OWNER_FLAGS_REPLACE, 497 on_bus_acquired, 498 on_name_acquired, 499 on_name_lost, 500 &cmd, 501 NULL); 502 503 g_main_loop_run(loop); 504 505 g_bus_unown_name(id); 506 g_main_loop_unref(loop); 507 return 0; 508 } 509