diff options
author | Yi Li <adamliyi@msn.com> | 2016-10-25 13:19:59 +0800 |
---|---|---|
committer | Patrick Williams <patrick@stwcx.xyz> | 2016-11-18 15:01:54 +0000 |
commit | 0475f65f5feb9381ef2710dca96b545546ccd944 (patch) | |
tree | 87b47b5740441be769d0e4ae0f487c4d6b259991 /op-pwrctl | |
parent | dfda936510a56421370267ef5fc54b10b739c67c (diff) | |
download | talos-skeleton-0475f65f5feb9381ef2710dca96b545546ccd944.tar.gz talos-skeleton-0475f65f5feb9381ef2710dca96b545546ccd944.zip |
op-pwrctl: Hold PCI resets until BootProgress passes BASE_INITIALIZATION state
When powering on host, hold PCI resets until hostboot passes stage
"BASE_INITIALIZATION"(0x14).
This fix applies to Firestone and Garrison.
Partially resolves openbmc/openbmc#315
Change-Id: Ic71c81406ac188b34df89569e2264ea0b94406f3
Signed-off-by: Yi Li <adamliyi@msn.com>
Diffstat (limited to 'op-pwrctl')
-rw-r--r-- | op-pwrctl/power_control_obj.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/op-pwrctl/power_control_obj.c b/op-pwrctl/power_control_obj.c index eb6be21..f6cfdbc 100644 --- a/op-pwrctl/power_control_obj.c +++ b/op-pwrctl/power_control_obj.c @@ -17,6 +17,8 @@ static const gchar* dbus_object_path = "/org/openbmc/control"; static const gchar* instance_name = "power0"; static const gchar* dbus_name = "org.openbmc.control.Power"; +static int g_pci_reset_held = 1; + static PowerGpio g_power_gpio; static GDBusObjectManagerServer *manager = NULL; @@ -70,6 +72,7 @@ poll_pgood(gpointer user_data) { control_power_emit_power_lost(control_power); control_emit_goto_system_state(control,"HOST_POWERED_OFF"); + g_pci_reset_held = 1; } else { @@ -94,6 +97,36 @@ poll_pgood(gpointer user_data) gpio_write(reset_out, reset_state); gpio_close(reset_out); } + + for(i = 0; i < g_power_gpio.num_pci_reset_outs; i++) + { + GPIO *pci_reset_out = &g_power_gpio.pci_reset_outs[i]; + if(pgood_state == 1) + { + /* + * When powering on, hold PCI reset until + * the processor can forward clocks and control reset. + */ + if(g_power_gpio.pci_reset_holds[i]) + { + g_print("Holding pci reset: %s\n", pci_reset_out->name); + continue; + } + } + rc = gpio_open(pci_reset_out); + if(rc != GPIO_OK) + { + g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n", + pci_reset_out->name, rc); + continue; + } + + reset_state = pgood_state ^ !g_power_gpio.pci_reset_pols[i]; + g_print("PowerControl: setting pci reset %s to %d\n", pci_reset_out->name, + (int)reset_state); + gpio_write(pci_reset_out, reset_state); + gpio_close(pci_reset_out); + } } } else { g_print("ERROR PowerControl: GPIO read error (gpio=%s,rc=%d)\n", @@ -116,6 +149,70 @@ poll_pgood(gpointer user_data) return TRUE; } +/* Handler for BootProgress signal from BootProgress sensor */ +static void +on_boot_progress(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + gchar *boot_progress; + uint8_t pgood_state; + uint8_t reset_state; + int rc; + int i; + + if(!parameters) + return; + + /* prevent release again */ + if(!g_pci_reset_held) + return; + + g_variant_get(parameters, "(s)", &boot_progress); + /* Release PCI reset when FW boot progress goes beyond 'Baseboard Init' */ + if(strcmp(boot_progress, "FW Progress, Baseboard Init") == 0) + return; + + rc = gpio_open(&g_power_gpio.power_good_in); + if(rc != GPIO_OK) + { + g_print("ERROR PowerControl: on_boot_progress(): GPIO open error (gpio=%s,rc=%d)\n", + g_power_gpio.power_good_in.name, rc); + return; + } + rc = gpio_read(&g_power_gpio.power_good_in, &pgood_state); + gpio_close(&g_power_gpio.power_good_in); + if(rc != GPIO_OK || pgood_state != 1) + return; + + for(i = 0; i < g_power_gpio.num_pci_reset_outs; i++) + { + GPIO *pci_reset_out = &g_power_gpio.pci_reset_outs[i]; + + if(!g_power_gpio.pci_reset_holds[i]) + continue; + rc = gpio_open(pci_reset_out); + if(rc != GPIO_OK) + { + g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n", + pci_reset_out->name, rc); + continue; + } + + reset_state = pgood_state ^ !g_power_gpio.pci_reset_pols[i]; + g_print("PowerControl: setting pci reset %s to %d\n", pci_reset_out->name, + (int)reset_state); + gpio_write(pci_reset_out, reset_state); + gpio_close(pci_reset_out); + g_print("Released pci reset: %s - %s\n", pci_reset_out->name, boot_progress); + } + g_pci_reset_held = 0; +} + static gboolean on_set_power_state(ControlPower *pwr, GDBusMethodInvocation *invocation, @@ -230,6 +327,12 @@ set_up_gpio(GDBusConnection *connection, error = rc; } } + for(int i = 0; i < power_gpio->num_pci_reset_outs; i++) { + rc = gpio_init(connection, &power_gpio->pci_reset_outs[i]); + if(rc != GPIO_OK) { + error = rc; + } + } /* If there's a latch, it only needs to be set once. */ if(power_gpio->latch_out.name != NULL) { @@ -309,6 +412,17 @@ on_bus_acquired(GDBusConnection *connection, G_CALLBACK(on_init), object); /* user_data */ + /* Listen for BootProgress signal from BootProgress sensor */ + g_dbus_connection_signal_subscribe(connection, + NULL, /* service */ + NULL, /* interface_name */ + "BootProgress", /* member: name of the signal */ + "/org/openbmc/sensors/host/BootProgress", /* obj path */ + NULL, /* arg0 */ + G_DBUS_SIGNAL_FLAGS_NONE, + (GDBusSignalCallback) on_boot_progress, + object, /* user data */ + NULL ); /* Export the object (@manager takes its own reference to @object) */ g_dbus_object_manager_server_set_connection(manager, connection); |