pwrctl: Use PowerGpio configuration for power control

Use power GPIO configuration read from Python system configuration to
control power and reset lines. This removes the need for
machine-specific patches.

Signed-off-by: Xo Wang <xow@google.com>
Change-Id: I83d55a7069558ec810bc2e0dbbff1c5495957e6d
diff --git a/op-pwrctl/power_control_obj.c b/op-pwrctl/power_control_obj.c
index dfc7fa9..cd13c68 100644
--- a/op-pwrctl/power_control_obj.c
+++ b/op-pwrctl/power_control_obj.c
@@ -10,18 +10,14 @@
 #include <openbmc_intf.h>
 #include <openbmc.h>
 #include <gpio.h>
+#include <power_gpio.h>
 
 /* ------------------------------------------------------------------------- */
 static const gchar* dbus_object_path = "/org/openbmc/control";
 static const gchar* instance_name = "power0";
 static const gchar* dbus_name = "org.openbmc.control.Power";
 
-//This object will use these GPIOs
-GPIO power_pin    = (GPIO){ "POWER_PIN" };
-GPIO pgood        = (GPIO){ "PGOOD" };
-GPIO usb_reset    = (GPIO){ "USB_RESET" };
-GPIO pcie_reset   = (GPIO){ "PCIE_RESET" };
-
+static PowerGpio g_power_gpio;
 
 static GDBusObjectManagerServer *manager = NULL;
 
@@ -38,7 +34,7 @@
 	guint poll_int = control_get_poll_interval(control);
 	if(poll_int == 0)
 	{
-		printf("ERROR PowerControl: Poll interval cannot be 0\n");
+		g_print("ERROR PowerControl: Poll interval cannot be 0\n");
 		return FALSE;
 	}
 	//handle timeout
@@ -46,56 +42,67 @@
 	if(difftime(current_time,pgood_timeout_start) > control_power_get_pgood_timeout(control_power)
 			&& pgood_timeout_start != 0)
 	{
-		printf("ERROR PowerControl: Pgood poll timeout\n");
+		g_print("ERROR PowerControl: Pgood poll timeout\n");
 		// set timeout to 0 so timeout doesn't happen again
 		control_power_set_pgood_timeout(control_power,0);
 		pgood_timeout_start = 0;
 		return TRUE;
 	}
-	uint8_t gpio;
+	uint8_t pgood_state;
 
-	int rc = gpio_open(&pgood);
-	rc = gpio_read(&pgood,&gpio);
-	gpio_close(&pgood);
+	int rc = gpio_open(&g_power_gpio.power_good_in);
+	if(rc != GPIO_OK) {
+		g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n",
+				g_power_gpio.power_good_in.name, rc);
+		return FALSE;
+	}
+	rc = gpio_read(&g_power_gpio.power_good_in, &pgood_state);
+	gpio_close(&g_power_gpio.power_good_in);
 	if(rc == GPIO_OK)
 	{
 		//if changed, set property and emit signal
-		if(gpio != control_power_get_pgood(control_power))
+		if(pgood_state != control_power_get_pgood(control_power))
 		{
-			control_power_set_pgood(control_power,gpio);
-			if(gpio==0)
+			int i;
+			uint8_t reset_state;
+			control_power_set_pgood(control_power, pgood_state);
+			if(pgood_state == 0)
 			{
 				control_power_emit_power_lost(control_power);
 				control_emit_goto_system_state(control,"HOST_POWERED_OFF");
-				rc = gpio_open(&pcie_reset);
-				rc = gpio_write(&pcie_reset,0);
-				gpio_close(&pcie_reset);
-
-				rc = gpio_open(&usb_reset);
-				rc = gpio_write(&usb_reset,0);
-				gpio_close(&usb_reset);
-
 			}
 			else
 			{
 				control_power_emit_power_good(control_power);
 				control_emit_goto_system_state(control,"HOST_POWERED_ON");
-				rc = gpio_open(&pcie_reset);
-				rc = gpio_write(&pcie_reset,1);
-				gpio_close(&pcie_reset);
+			}
 
-				rc = gpio_open(&usb_reset);
-				rc = gpio_write(&usb_reset,1);
-				gpio_close(&usb_reset);
+			for(i = 0; i < g_power_gpio.num_reset_outs; i++)
+			{
+				GPIO *reset_out = &g_power_gpio.reset_outs[i];
+				rc = gpio_open(reset_out);
+				if(rc != GPIO_OK)
+				{
+					g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n",
+							reset_out->name, rc);
+					continue;
+				}
+
+				reset_state = pgood_state ^ g_power_gpio.reset_pols[i];
+				g_print("PowerControl: setting reset %s to %d\n", reset_out->name,
+						(int)reset_state);
+				gpio_write(reset_out, reset_state);
+				gpio_close(reset_out);
 			}
 		}
 	} else {
-		printf("ERROR PowerControl: GPIO read error (gpio=%s,rc=%d)\n",pgood.name,rc);
+		g_print("ERROR PowerControl: GPIO read error (gpio=%s,rc=%d)\n",
+				g_power_gpio.power_good_in.name, rc);
 		//return false so poll won't get called anymore
 		return FALSE;
 	}
 	//pgood is not at desired state yet
-	if(gpio != control_power_get_state(control_power) &&
+	if(pgood_state != control_power_get_state(control_power) &&
 			control_power_get_pgood_timeout(control_power) > 0)
 	{
 		if(pgood_timeout_start == 0 ) {
@@ -133,21 +140,36 @@
 	{
 		int error = 0;
 		do {
+			int i;
+			uint8_t power_up_out;
 			if(state == 1) {
 				control_emit_goto_system_state(control,"HOST_POWERING_ON");
 			} else {
 				control_emit_goto_system_state(control,"HOST_POWERING_OFF");
 			}
-			error = gpio_open(&power_pin);
+			for (i = 0; i < g_power_gpio.num_power_up_outs; i++) {
+				GPIO *power_pin = &g_power_gpio.power_up_outs[i];
+				error = gpio_open(power_pin);
+				if(error != GPIO_OK) {
+					g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n",
+							g_power_gpio.power_up_outs[i].name, error);
+					continue;
+				}
+				power_up_out = state ^ g_power_gpio.power_up_pols[i];
+				g_print("PowerControl: setting power up %s to %d\n",
+						g_power_gpio.power_up_outs[i].name, (int)power_up_out);
+				error = gpio_write(power_pin, power_up_out);
+				if(error != GPIO_OK) {
+					continue;
+				}
+				gpio_close(power_pin);
+			}
 			if(error != GPIO_OK) { break;	}
-			error = gpio_write(&power_pin,!state);
-			if(error != GPIO_OK) { break;	}
-			gpio_close(&power_pin);
 			control_power_set_state(pwr,state);
 		} while(0);
 		if(error != GPIO_OK)
 		{
-			printf("ERROR PowerControl: GPIO set power state (rc=%d)\n",error);
+			g_print("ERROR PowerControl: GPIO set power state (rc=%d)\n",error);
 		}
 	}
 	return TRUE;
@@ -175,6 +197,50 @@
 	return TRUE;
 }
 
+static int
+set_up_gpio(GDBusConnection *connection,
+		PowerGpio *power_gpio,
+		ControlPower* control_power)
+{
+	int error = GPIO_OK;
+	int rc;
+	int i;
+	uint8_t pgood_state;
+
+	// get gpio device paths
+	rc = gpio_init(connection, &power_gpio->power_good_in);
+	if(rc != GPIO_OK) {
+		error = rc;
+	}
+	for(int i = 0; i < power_gpio->num_power_up_outs; i++) {
+		rc = gpio_init(connection, &power_gpio->power_up_outs[i]);
+		if(rc != GPIO_OK) {
+			error = rc;
+		}
+	}
+	for(int i = 0; i < power_gpio->num_reset_outs; i++) {
+		rc = gpio_init(connection, &power_gpio->reset_outs[i]);
+		if(rc != GPIO_OK) {
+			error = rc;
+		}
+	}
+
+	rc = gpio_open(&power_gpio->power_good_in);
+	if(rc != GPIO_OK) {
+		return rc;
+	}
+	rc = gpio_read(&power_gpio->power_good_in, &pgood_state);
+	if(rc != GPIO_OK) {
+		return rc;
+	}
+	gpio_close(&power_gpio->power_good_in);
+	control_power_set_pgood(control_power, pgood_state);
+	control_power_set_state(control_power, pgood_state);
+	g_print("Pgood state: %d\n", pgood_state);
+
+	return error;
+}
+
 static void
 on_bus_acquired(GDBusConnection *connection,
 		const gchar *name,
@@ -223,39 +289,20 @@
 	g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object));
 	g_object_unref(object);
 
-	// get gpio device paths
-	int rc = GPIO_OK;
-	do {
-		rc = gpio_init(connection,&power_pin);
-		if(rc != GPIO_OK) { break; }
-		rc = gpio_init(connection,&pgood);
-		if(rc != GPIO_OK) { break; }
-		rc = gpio_init(connection,&pcie_reset);
-		if(rc != GPIO_OK) { break; }
-		rc = gpio_init(connection,&usb_reset);
-		if(rc != GPIO_OK) { break; }
+	if(read_power_gpio(connection, &g_power_gpio) != TRUE) {
+		g_print("ERROR PowerControl: could not read power GPIO configuration\n");
+	}
 
-		uint8_t gpio;
-		rc = gpio_open(&pgood);
-		if(rc != GPIO_OK) { break; }
-		rc = gpio_read(&pgood,&gpio);
-		if(rc != GPIO_OK) { break; }
-		gpio_close(&pgood);
-		control_power_set_pgood(control_power,gpio);
-		control_power_set_state(control_power,gpio);
-		printf("Pgood state: %d\n",gpio);
-
-	} while(0);
-	if(rc != GPIO_OK)
-	{
-		printf("ERROR PowerControl: GPIO setup (rc=%d)\n",rc);
+	int rc = set_up_gpio(connection, &g_power_gpio, control_power);
+	if(rc != GPIO_OK) {
+		g_print("ERROR PowerControl: GPIO setup (rc=%d)\n",rc);
 	}
 	//start poll
 	pgood_timeout_start = 0;
 	int poll_interval = atoi(cmd->argv[1]);
 	int pgood_timeout = atoi(cmd->argv[2]);
 	if(poll_interval < 1000 || pgood_timeout <5) {
-		printf("ERROR PowerControl: poll_interval < 1000 or pgood_timeout < 5\n");
+		g_print("ERROR PowerControl: poll_interval < 1000 or pgood_timeout < 5\n");
 	} else {
 		control_set_poll_interval(control,poll_interval);
 		control_power_set_pgood_timeout(control_power,pgood_timeout);
@@ -275,6 +322,7 @@
 		const gchar *name,
 		gpointer user_data)
 {
+	free_power_gpio(&g_power_gpio);
 }
 
 /*----------------------------------------------------------------*/