summaryrefslogtreecommitdiffstats
path: root/op-pwrctl
diff options
context:
space:
mode:
authorYi Li <adamliyi@msn.com>2016-10-25 13:19:59 +0800
committerPatrick Williams <patrick@stwcx.xyz>2016-11-18 15:01:54 +0000
commit0475f65f5feb9381ef2710dca96b545546ccd944 (patch)
tree87b47b5740441be769d0e4ae0f487c4d6b259991 /op-pwrctl
parentdfda936510a56421370267ef5fc54b10b739c67c (diff)
downloadtalos-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.c114
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);
OpenPOWER on IntegriCloud