140a360c2SBrad Bishop #include <stdint.h>
240a360c2SBrad Bishop #include <stdio.h>
340a360c2SBrad Bishop #include <stdlib.h>
440a360c2SBrad Bishop #include <string.h>
540a360c2SBrad Bishop #include <fcntl.h>
640a360c2SBrad Bishop #include <unistd.h>
740a360c2SBrad Bishop #include <sys/stat.h>
840a360c2SBrad Bishop #include <sys/mman.h>
940a360c2SBrad Bishop #include <syslog.h>
10f6c85685SBrad Bishop #include <openbmc_intf.h>
11f6c85685SBrad Bishop #include <openbmc.h>
12f6c85685SBrad Bishop #include <gpio.h>
1345cb4fccSLei YU #include <gpio_configs.h>
1440a360c2SBrad Bishop
1540a360c2SBrad Bishop /* ------------------------------------------------------------------------- */
1640a360c2SBrad Bishop static const gchar* dbus_object_path = "/org/openbmc/control";
1740a360c2SBrad Bishop static const gchar* instance_name = "power0";
1840a360c2SBrad Bishop static const gchar* dbus_name = "org.openbmc.control.Power";
1940a360c2SBrad Bishop
200475f65fSYi Li static int g_pci_reset_held = 1;
210475f65fSYi Li
2275a18a23SLei YU static GpioConfigs g_gpio_configs;
2340a360c2SBrad Bishop
2440a360c2SBrad Bishop static GDBusObjectManagerServer *manager = NULL;
2540a360c2SBrad Bishop
2640a360c2SBrad Bishop time_t pgood_timeout_start = 0;
2740a360c2SBrad Bishop
2840a360c2SBrad Bishop // TODO: Change to interrupt driven instead of polling
2940a360c2SBrad Bishop static gboolean
poll_pgood(gpointer user_data)3040a360c2SBrad Bishop poll_pgood(gpointer user_data)
3140a360c2SBrad Bishop {
3240a360c2SBrad Bishop ControlPower *control_power = object_get_control_power((Object*)user_data);
3340a360c2SBrad Bishop Control* control = object_get_control((Object*)user_data);
3440a360c2SBrad Bishop
3540a360c2SBrad Bishop //send the heartbeat
3640a360c2SBrad Bishop guint poll_int = control_get_poll_interval(control);
3740a360c2SBrad Bishop if(poll_int == 0)
3840a360c2SBrad Bishop {
3920a19416SXo Wang g_print("ERROR PowerControl: Poll interval cannot be 0\n");
4040a360c2SBrad Bishop return FALSE;
4140a360c2SBrad Bishop }
4240a360c2SBrad Bishop //handle timeout
4340a360c2SBrad Bishop time_t current_time = time(NULL);
4440a360c2SBrad Bishop if(difftime(current_time,pgood_timeout_start) > control_power_get_pgood_timeout(control_power)
4540a360c2SBrad Bishop && pgood_timeout_start != 0)
4640a360c2SBrad Bishop {
4720a19416SXo Wang g_print("ERROR PowerControl: Pgood poll timeout\n");
4840a360c2SBrad Bishop // set timeout to 0 so timeout doesn't happen again
4940a360c2SBrad Bishop control_power_set_pgood_timeout(control_power,0);
5040a360c2SBrad Bishop pgood_timeout_start = 0;
5127eaf901SPatrick Williams return TRUE;
5240a360c2SBrad Bishop }
5320a19416SXo Wang uint8_t pgood_state;
5440a360c2SBrad Bishop
55c0c74e7cSAnthony Wilson int rc = gpio_open(&g_gpio_configs.power_gpio.power_good_in, 0);
5620a19416SXo Wang if(rc != GPIO_OK) {
57c0c74e7cSAnthony Wilson gpio_close(&g_gpio_configs.power_gpio.power_good_in);
5820a19416SXo Wang g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n",
5975a18a23SLei YU g_gpio_configs.power_gpio.power_good_in.name, rc);
6020a19416SXo Wang return FALSE;
6120a19416SXo Wang }
6275a18a23SLei YU rc = gpio_read(&g_gpio_configs.power_gpio.power_good_in, &pgood_state);
6375a18a23SLei YU gpio_close(&g_gpio_configs.power_gpio.power_good_in);
6440a360c2SBrad Bishop if(rc == GPIO_OK)
6540a360c2SBrad Bishop {
6640a360c2SBrad Bishop //if changed, set property and emit signal
6720a19416SXo Wang if(pgood_state != control_power_get_pgood(control_power))
6840a360c2SBrad Bishop {
69*600ff330SPatrick Williams size_t i;
7020a19416SXo Wang uint8_t reset_state;
7120a19416SXo Wang control_power_set_pgood(control_power, pgood_state);
7220a19416SXo Wang if(pgood_state == 0)
7340a360c2SBrad Bishop {
7440a360c2SBrad Bishop control_power_emit_power_lost(control_power);
750475f65fSYi Li g_pci_reset_held = 1;
7640a360c2SBrad Bishop }
7740a360c2SBrad Bishop else
7840a360c2SBrad Bishop {
7940a360c2SBrad Bishop control_power_emit_power_good(control_power);
8020a19416SXo Wang }
8140a360c2SBrad Bishop
8275a18a23SLei YU for(i = 0; i < g_gpio_configs.power_gpio.num_reset_outs; i++)
8320a19416SXo Wang {
8475a18a23SLei YU GPIO *reset_out = &g_gpio_configs.power_gpio.reset_outs[i];
85c0c74e7cSAnthony Wilson reset_state = pgood_state ^ g_gpio_configs.power_gpio.reset_pols[i];
86c0c74e7cSAnthony Wilson rc = gpio_open(reset_out, reset_state);
8720a19416SXo Wang if(rc != GPIO_OK)
8820a19416SXo Wang {
89c0c74e7cSAnthony Wilson gpio_close(reset_out);
9020a19416SXo Wang g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n",
9120a19416SXo Wang reset_out->name, rc);
9220a19416SXo Wang continue;
9320a19416SXo Wang }
9420a19416SXo Wang
9539df4035SYi Li g_print("PowerControl: pgood: %d, setting reset %s to %d\n",
9639df4035SYi Li (int)pgood_state, reset_out->name, (int)reset_state);
9720a19416SXo Wang gpio_write(reset_out, reset_state);
9820a19416SXo Wang gpio_close(reset_out);
9940a360c2SBrad Bishop }
1000475f65fSYi Li
10175a18a23SLei YU for(i = 0; i < g_gpio_configs.power_gpio.num_pci_reset_outs; i++)
1020475f65fSYi Li {
10375a18a23SLei YU GPIO *pci_reset_out = &g_gpio_configs.power_gpio.pci_reset_outs[i];
1040475f65fSYi Li if(pgood_state == 1)
1050475f65fSYi Li {
1060475f65fSYi Li /*
1070475f65fSYi Li * When powering on, hold PCI reset until
1080475f65fSYi Li * the processor can forward clocks and control reset.
1090475f65fSYi Li */
11075a18a23SLei YU if(g_gpio_configs.power_gpio.pci_reset_holds[i])
1110475f65fSYi Li {
1120475f65fSYi Li g_print("Holding pci reset: %s\n", pci_reset_out->name);
1130475f65fSYi Li continue;
1140475f65fSYi Li }
1150475f65fSYi Li }
116c0c74e7cSAnthony Wilson reset_state = pgood_state ^ g_gpio_configs.power_gpio.pci_reset_pols[i];
117c0c74e7cSAnthony Wilson rc = gpio_open(pci_reset_out, reset_state);
1180475f65fSYi Li if(rc != GPIO_OK)
1190475f65fSYi Li {
120c0c74e7cSAnthony Wilson gpio_close(pci_reset_out);
1210475f65fSYi Li g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n",
1220475f65fSYi Li pci_reset_out->name, rc);
1230475f65fSYi Li continue;
1240475f65fSYi Li }
1250475f65fSYi Li
12639df4035SYi Li g_print("PowerControl: pgood: %d, setting pci reset %s to %d\n",
12739df4035SYi Li (int)pgood_state, pci_reset_out->name, (int)reset_state);
1280475f65fSYi Li gpio_write(pci_reset_out, reset_state);
1290475f65fSYi Li gpio_close(pci_reset_out);
1300475f65fSYi Li }
13140a360c2SBrad Bishop }
13240a360c2SBrad Bishop } else {
13320a19416SXo Wang g_print("ERROR PowerControl: GPIO read error (gpio=%s,rc=%d)\n",
13475a18a23SLei YU g_gpio_configs.power_gpio.power_good_in.name, rc);
13540a360c2SBrad Bishop //return false so poll won't get called anymore
13640a360c2SBrad Bishop return FALSE;
13740a360c2SBrad Bishop }
13840a360c2SBrad Bishop //pgood is not at desired state yet
13920a19416SXo Wang if(pgood_state != control_power_get_state(control_power) &&
14040a360c2SBrad Bishop control_power_get_pgood_timeout(control_power) > 0)
14140a360c2SBrad Bishop {
14240a360c2SBrad Bishop if(pgood_timeout_start == 0 ) {
14340a360c2SBrad Bishop pgood_timeout_start = current_time;
14440a360c2SBrad Bishop }
14540a360c2SBrad Bishop }
14640a360c2SBrad Bishop else
14740a360c2SBrad Bishop {
14840a360c2SBrad Bishop pgood_timeout_start = 0;
14940a360c2SBrad Bishop }
15040a360c2SBrad Bishop return TRUE;
15140a360c2SBrad Bishop }
15240a360c2SBrad Bishop
1530475f65fSYi Li /* Handler for BootProgress signal from BootProgress sensor */
1540475f65fSYi Li 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)1550475f65fSYi Li on_boot_progress(GDBusConnection *connection,
1560475f65fSYi Li const gchar *sender_name,
1570475f65fSYi Li const gchar *object_path,
1580475f65fSYi Li const gchar *interface_name,
1590475f65fSYi Li const gchar *signal_name,
1600475f65fSYi Li GVariant *parameters,
1610475f65fSYi Li gpointer user_data)
1620475f65fSYi Li {
163*600ff330SPatrick Williams (void) connection;
164*600ff330SPatrick Williams (void) sender_name;
165*600ff330SPatrick Williams (void) object_path;
166*600ff330SPatrick Williams (void) interface_name;
167*600ff330SPatrick Williams (void) signal_name;
168*600ff330SPatrick Williams (void) user_data;
169*600ff330SPatrick Williams
17093b84e42SLei YU gchar *interface;
17193b84e42SLei YU GVariantIter *properties;
17293b84e42SLei YU GVariantIter *dummy;
17393b84e42SLei YU gchar *boot_progress = NULL;
17493b84e42SLei YU gchar *property;
17593b84e42SLei YU GVariant *value;
1760475f65fSYi Li uint8_t pgood_state;
1770475f65fSYi Li uint8_t reset_state;
1780475f65fSYi Li int rc;
179*600ff330SPatrick Williams size_t i;
18093b84e42SLei YU int ignore;
1810475f65fSYi Li
1820475f65fSYi Li if(!parameters)
1830475f65fSYi Li return;
1840475f65fSYi Li
1850475f65fSYi Li /* prevent release again */
1860475f65fSYi Li if(!g_pci_reset_held)
1870475f65fSYi Li return;
1880475f65fSYi Li
18993b84e42SLei YU g_variant_get(parameters, "(&sa{sv}as)", &interface, &properties, &dummy);
19093b84e42SLei YU for(i = 0; g_variant_iter_next(properties, "{&sv}", &property, &value); i++)
19193b84e42SLei YU {
19293b84e42SLei YU if (strcmp(property, "BootProgress") == 0)
19393b84e42SLei YU {
19493b84e42SLei YU gchar* tmp;
19593b84e42SLei YU g_variant_get(value, "&s", &tmp);
19693b84e42SLei YU boot_progress = g_strdup(tmp);
19793b84e42SLei YU g_print("BootProgress: %s\n", boot_progress);
19893b84e42SLei YU g_variant_unref(value);
19993b84e42SLei YU }
20093b84e42SLei YU }
20193b84e42SLei YU
20293b84e42SLei YU g_variant_iter_free(properties);
20393b84e42SLei YU g_variant_iter_free(dummy);
20493b84e42SLei YU if (boot_progress == NULL)
20593b84e42SLei YU return;
20693b84e42SLei YU
2070475f65fSYi Li /* Release PCI reset when FW boot progress goes beyond 'Baseboard Init' */
20893b84e42SLei YU ignore = strcmp(boot_progress,
20993b84e42SLei YU "xyz.openbmc_project.State.Boot.Progress.ProgressStages.MotherboardInit") == 0;
21093b84e42SLei YU g_free(boot_progress);
21193b84e42SLei YU
21293b84e42SLei YU if (ignore)
2130475f65fSYi Li return;
2140475f65fSYi Li
215c0c74e7cSAnthony Wilson rc = gpio_open(&g_gpio_configs.power_gpio.power_good_in, 0);
2160475f65fSYi Li if(rc != GPIO_OK)
2170475f65fSYi Li {
218c0c74e7cSAnthony Wilson gpio_close(&g_gpio_configs.power_gpio.power_good_in);
2190475f65fSYi Li g_print("ERROR PowerControl: on_boot_progress(): GPIO open error (gpio=%s,rc=%d)\n",
22075a18a23SLei YU g_gpio_configs.power_gpio.power_good_in.name, rc);
2210475f65fSYi Li return;
2220475f65fSYi Li }
22375a18a23SLei YU rc = gpio_read(&g_gpio_configs.power_gpio.power_good_in, &pgood_state);
22475a18a23SLei YU gpio_close(&g_gpio_configs.power_gpio.power_good_in);
2250475f65fSYi Li if(rc != GPIO_OK || pgood_state != 1)
2260475f65fSYi Li return;
2270475f65fSYi Li
22875a18a23SLei YU for(i = 0; i < g_gpio_configs.power_gpio.num_pci_reset_outs; i++)
2290475f65fSYi Li {
23075a18a23SLei YU GPIO *pci_reset_out = &g_gpio_configs.power_gpio.pci_reset_outs[i];
2310475f65fSYi Li
23275a18a23SLei YU if(!g_gpio_configs.power_gpio.pci_reset_holds[i])
2330475f65fSYi Li continue;
234c0c74e7cSAnthony Wilson reset_state = pgood_state ^ g_gpio_configs.power_gpio.pci_reset_pols[i];
235c0c74e7cSAnthony Wilson rc = gpio_open(pci_reset_out, reset_state);
2360475f65fSYi Li if(rc != GPIO_OK)
2370475f65fSYi Li {
238c0c74e7cSAnthony Wilson gpio_close(pci_reset_out);
2390475f65fSYi Li g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n",
2400475f65fSYi Li pci_reset_out->name, rc);
2410475f65fSYi Li continue;
2420475f65fSYi Li }
2430475f65fSYi Li
24439df4035SYi Li g_print("PowerControl: pgood: %d, setting pci reset %s to %d\n",
24539df4035SYi Li (int)pgood_state, pci_reset_out->name, (int)reset_state);
2460475f65fSYi Li gpio_write(pci_reset_out, reset_state);
2470475f65fSYi Li gpio_close(pci_reset_out);
24893b84e42SLei YU g_print("Released pci reset: %s\n", pci_reset_out->name);
2490475f65fSYi Li }
2500475f65fSYi Li g_pci_reset_held = 0;
2510475f65fSYi Li }
2520475f65fSYi Li
25340a360c2SBrad Bishop static gboolean
on_set_power_state(ControlPower * pwr,GDBusMethodInvocation * invocation,guint state,gpointer user_data)25440a360c2SBrad Bishop on_set_power_state(ControlPower *pwr,
25540a360c2SBrad Bishop GDBusMethodInvocation *invocation,
25640a360c2SBrad Bishop guint state,
25740a360c2SBrad Bishop gpointer user_data)
25840a360c2SBrad Bishop {
259*600ff330SPatrick Williams (void) user_data;
260aa6c76fcSXo Wang PowerGpio *power_gpio = &g_gpio_configs.power_gpio;
26140a360c2SBrad Bishop if(state > 1)
26240a360c2SBrad Bishop {
26340a360c2SBrad Bishop g_dbus_method_invocation_return_dbus_error(invocation,
26440a360c2SBrad Bishop "org.openbmc.ControlPower.Error.Failed",
26540a360c2SBrad Bishop "Invalid power state");
26640a360c2SBrad Bishop return TRUE;
26740a360c2SBrad Bishop }
26840a360c2SBrad Bishop // return from method call
26940a360c2SBrad Bishop control_power_complete_set_power_state(pwr,invocation);
270*600ff330SPatrick Williams if(state == (guint) control_power_get_state(pwr))
27140a360c2SBrad Bishop {
27240a360c2SBrad Bishop g_print("Power already at requested state: %d\n",state);
27340a360c2SBrad Bishop }
27440a360c2SBrad Bishop else
27540a360c2SBrad Bishop {
27640a360c2SBrad Bishop int error = 0;
27740a360c2SBrad Bishop do {
278*600ff330SPatrick Williams size_t i;
27920a19416SXo Wang uint8_t power_up_out;
280aa6c76fcSXo Wang for (i = 0; i < power_gpio->num_power_up_outs; i++) {
281aa6c76fcSXo Wang GPIO *power_pin = &power_gpio->power_up_outs[i];
282c0c74e7cSAnthony Wilson power_up_out = state ^ !power_gpio->power_up_pols[i];
283c0c74e7cSAnthony Wilson error = gpio_open(power_pin, power_up_out);
28420a19416SXo Wang if(error != GPIO_OK) {
285c0c74e7cSAnthony Wilson gpio_close(power_pin);
28620a19416SXo Wang g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n",
287aa6c76fcSXo Wang power_gpio->power_up_outs[i].name, error);
28820a19416SXo Wang continue;
28920a19416SXo Wang }
29020a19416SXo Wang g_print("PowerControl: setting power up %s to %d\n",
291aa6c76fcSXo Wang power_gpio->power_up_outs[i].name, (int)power_up_out);
29220a19416SXo Wang error = gpio_write(power_pin, power_up_out);
29320a19416SXo Wang if(error != GPIO_OK) {
294c0c74e7cSAnthony Wilson gpio_close(power_pin);
29520a19416SXo Wang continue;
29620a19416SXo Wang }
29720a19416SXo Wang gpio_close(power_pin);
29820a19416SXo Wang }
29940a360c2SBrad Bishop if(error != GPIO_OK) { break; }
30040a360c2SBrad Bishop control_power_set_state(pwr,state);
30140a360c2SBrad Bishop } while(0);
30240a360c2SBrad Bishop if(error != GPIO_OK)
30340a360c2SBrad Bishop {
30420a19416SXo Wang g_print("ERROR PowerControl: GPIO set power state (rc=%d)\n",error);
30540a360c2SBrad Bishop }
306aa6c76fcSXo Wang
307aa6c76fcSXo Wang /* If there's a latch, it should be enabled following changes to the
308aa6c76fcSXo Wang * power pins' states. This commits the changes to the latch states. */
309aa6c76fcSXo Wang if (power_gpio->latch_out.name != NULL) {
310aa6c76fcSXo Wang int rc;
311c0c74e7cSAnthony Wilson uint8_t latch_value = 1;
312c0c74e7cSAnthony Wilson rc = gpio_open(&power_gpio->latch_out, latch_value);
313aa6c76fcSXo Wang if (rc != GPIO_OK) {
314aa6c76fcSXo Wang /* Failures are non-fatal. */
315c0c74e7cSAnthony Wilson gpio_close(&power_gpio->latch_out);
316aa6c76fcSXo Wang g_print("PowerControl ERROR failed to open latch %s rc=%d\n",
317aa6c76fcSXo Wang power_gpio->latch_out.name, rc);
318aa6c76fcSXo Wang return TRUE;
31940a360c2SBrad Bishop }
320aa6c76fcSXo Wang /* Make the latch transparent for as brief of a time as possible. */
321c0c74e7cSAnthony Wilson rc = gpio_write(&power_gpio->latch_out, latch_value--);
322aa6c76fcSXo Wang if (rc != GPIO_OK) {
323aa6c76fcSXo Wang g_print("PowerControl ERROR failed to assert latch %s rc=%d\n",
324aa6c76fcSXo Wang power_gpio->latch_out.name, rc);
325aa6c76fcSXo Wang } else {
326aa6c76fcSXo Wang g_print("PowerControl asserted latch %s\n",
327aa6c76fcSXo Wang power_gpio->latch_out.name);
328aa6c76fcSXo Wang }
329c0c74e7cSAnthony Wilson rc = gpio_write(&power_gpio->latch_out, latch_value);
330aa6c76fcSXo Wang if (rc != GPIO_OK) {
331aa6c76fcSXo Wang g_print("PowerControl ERROR failed to clear latch %s rc=%d\n",
332aa6c76fcSXo Wang power_gpio->latch_out.name, rc);
333aa6c76fcSXo Wang }
334aa6c76fcSXo Wang gpio_close(&power_gpio->latch_out);
335aa6c76fcSXo Wang }
336aa6c76fcSXo Wang }
337aa6c76fcSXo Wang
33840a360c2SBrad Bishop return TRUE;
33940a360c2SBrad Bishop }
34040a360c2SBrad Bishop
34140a360c2SBrad Bishop static gboolean
on_init(Control * control,GDBusMethodInvocation * invocation,gpointer user_data)34240a360c2SBrad Bishop on_init(Control *control,
34340a360c2SBrad Bishop GDBusMethodInvocation *invocation,
34440a360c2SBrad Bishop gpointer user_data)
34540a360c2SBrad Bishop {
346*600ff330SPatrick Williams (void) user_data;
34740a360c2SBrad Bishop pgood_timeout_start = 0;
34840a360c2SBrad Bishop //guint poll_interval = control_get_poll_interval(control);
34940a360c2SBrad Bishop //g_timeout_add(poll_interval, poll_pgood, user_data);
35040a360c2SBrad Bishop control_complete_init(control,invocation);
35140a360c2SBrad Bishop return TRUE;
35240a360c2SBrad Bishop }
35340a360c2SBrad Bishop
35440a360c2SBrad Bishop static gboolean
on_get_power_state(ControlPower * pwr,GDBusMethodInvocation * invocation,gpointer user_data)35540a360c2SBrad Bishop on_get_power_state(ControlPower *pwr,
35640a360c2SBrad Bishop GDBusMethodInvocation *invocation,
35740a360c2SBrad Bishop gpointer user_data)
35840a360c2SBrad Bishop {
359*600ff330SPatrick Williams (void) user_data;
36040a360c2SBrad Bishop guint pgood = control_power_get_pgood(pwr);
36140a360c2SBrad Bishop control_power_complete_get_power_state(pwr,invocation,pgood);
36240a360c2SBrad Bishop return TRUE;
36340a360c2SBrad Bishop }
36440a360c2SBrad Bishop
36520a19416SXo Wang static int
set_up_gpio(PowerGpio * power_gpio,ControlPower * control_power)3660f3fd5aaSMatt Spinler set_up_gpio(PowerGpio *power_gpio, ControlPower* control_power)
36720a19416SXo Wang {
36820a19416SXo Wang int error = GPIO_OK;
36920a19416SXo Wang int rc;
370*600ff330SPatrick Williams size_t i;
37120a19416SXo Wang uint8_t pgood_state;
37220a19416SXo Wang
37320a19416SXo Wang // get gpio device paths
374c1ce68b3SXo Wang if(power_gpio->latch_out.name != NULL) { /* latch is optional */
375c0c74e7cSAnthony Wilson rc = gpio_get_params(&power_gpio->latch_out);
376c1ce68b3SXo Wang if(rc != GPIO_OK) {
377c1ce68b3SXo Wang error = rc;
378c1ce68b3SXo Wang }
379c1ce68b3SXo Wang }
380c0c74e7cSAnthony Wilson rc = gpio_get_params(&power_gpio->power_good_in);
38120a19416SXo Wang if(rc != GPIO_OK) {
38220a19416SXo Wang error = rc;
38320a19416SXo Wang }
384*600ff330SPatrick Williams for(i = 0; i < power_gpio->num_power_up_outs; i++) {
385c0c74e7cSAnthony Wilson rc = gpio_get_params(&power_gpio->power_up_outs[i]);
38620a19416SXo Wang if(rc != GPIO_OK) {
38720a19416SXo Wang error = rc;
38820a19416SXo Wang }
38920a19416SXo Wang }
390*600ff330SPatrick Williams for(i = 0; i < power_gpio->num_reset_outs; i++) {
391c0c74e7cSAnthony Wilson rc = gpio_get_params(&power_gpio->reset_outs[i]);
39220a19416SXo Wang if(rc != GPIO_OK) {
39320a19416SXo Wang error = rc;
39420a19416SXo Wang }
39520a19416SXo Wang }
396*600ff330SPatrick Williams for(i = 0; i < power_gpio->num_pci_reset_outs; i++) {
397c0c74e7cSAnthony Wilson rc = gpio_get_params(&power_gpio->pci_reset_outs[i]);
3980475f65fSYi Li if(rc != GPIO_OK) {
3990475f65fSYi Li error = rc;
4000475f65fSYi Li }
4010475f65fSYi Li }
40220a19416SXo Wang
4030f0946beSMatt Spinler gpio_inits_done();
4040f0946beSMatt Spinler
405c0c74e7cSAnthony Wilson rc = gpio_open(&power_gpio->power_good_in, 0);
40620a19416SXo Wang if(rc != GPIO_OK) {
407c0c74e7cSAnthony Wilson gpio_close(&power_gpio->power_good_in);
40820a19416SXo Wang return rc;
40920a19416SXo Wang }
41020a19416SXo Wang rc = gpio_read(&power_gpio->power_good_in, &pgood_state);
41120a19416SXo Wang if(rc != GPIO_OK) {
412c0c74e7cSAnthony Wilson gpio_close(&power_gpio->power_good_in);
41320a19416SXo Wang return rc;
41420a19416SXo Wang }
41520a19416SXo Wang gpio_close(&power_gpio->power_good_in);
41620a19416SXo Wang control_power_set_pgood(control_power, pgood_state);
41720a19416SXo Wang control_power_set_state(control_power, pgood_state);
41820a19416SXo Wang g_print("Pgood state: %d\n", pgood_state);
41920a19416SXo Wang
42020a19416SXo Wang return error;
42120a19416SXo Wang }
42220a19416SXo Wang
42340a360c2SBrad Bishop static void
on_bus_acquired(GDBusConnection * connection,const gchar * name,gpointer user_data)42440a360c2SBrad Bishop on_bus_acquired(GDBusConnection *connection,
42540a360c2SBrad Bishop const gchar *name,
42640a360c2SBrad Bishop gpointer user_data)
42740a360c2SBrad Bishop {
428*600ff330SPatrick Williams (void) name;
42940a360c2SBrad Bishop ObjectSkeleton *object;
43040a360c2SBrad Bishop cmdline *cmd = user_data;
43140a360c2SBrad Bishop if(cmd->argc < 3)
43240a360c2SBrad Bishop {
43340a360c2SBrad Bishop g_print("Usage: power_control.exe [poll interval] [timeout]\n");
43440a360c2SBrad Bishop return;
43540a360c2SBrad Bishop }
43640a360c2SBrad Bishop manager = g_dbus_object_manager_server_new(dbus_object_path);
43740a360c2SBrad Bishop gchar *s;
43840a360c2SBrad Bishop s = g_strdup_printf("%s/%s",dbus_object_path,instance_name);
43940a360c2SBrad Bishop object = object_skeleton_new(s);
44040a360c2SBrad Bishop g_free(s);
44140a360c2SBrad Bishop
44240a360c2SBrad Bishop ControlPower* control_power = control_power_skeleton_new();
44340a360c2SBrad Bishop object_skeleton_set_control_power(object, control_power);
44440a360c2SBrad Bishop g_object_unref(control_power);
44540a360c2SBrad Bishop
44640a360c2SBrad Bishop Control* control = control_skeleton_new();
44740a360c2SBrad Bishop object_skeleton_set_control(object, control);
44840a360c2SBrad Bishop g_object_unref(control);
44940a360c2SBrad Bishop
45040a360c2SBrad Bishop //define method callbacks here
45140a360c2SBrad Bishop g_signal_connect(control_power,
45240a360c2SBrad Bishop "handle-set-power-state",
45340a360c2SBrad Bishop G_CALLBACK(on_set_power_state),
45440a360c2SBrad Bishop object); /* user_data */
45540a360c2SBrad Bishop
45640a360c2SBrad Bishop g_signal_connect(control_power,
45740a360c2SBrad Bishop "handle-get-power-state",
45840a360c2SBrad Bishop G_CALLBACK(on_get_power_state),
45940a360c2SBrad Bishop NULL); /* user_data */
46040a360c2SBrad Bishop
46140a360c2SBrad Bishop g_signal_connect(control,
46240a360c2SBrad Bishop "handle-init",
46340a360c2SBrad Bishop G_CALLBACK(on_init),
46440a360c2SBrad Bishop object); /* user_data */
46540a360c2SBrad Bishop
4660475f65fSYi Li /* Listen for BootProgress signal from BootProgress sensor */
4670475f65fSYi Li g_dbus_connection_signal_subscribe(connection,
4680475f65fSYi Li NULL, /* service */
46993b84e42SLei YU "org.freedesktop.DBus.Properties", /* interface_name */
47093b84e42SLei YU "PropertiesChanged", /* member: name of the signal */
47193b84e42SLei YU "/xyz/openbmc_project/state/host0", /* obj path */
4720475f65fSYi Li NULL, /* arg0 */
4730475f65fSYi Li G_DBUS_SIGNAL_FLAGS_NONE,
4740475f65fSYi Li (GDBusSignalCallback) on_boot_progress,
4750475f65fSYi Li object, /* user data */
4760475f65fSYi Li NULL );
47740a360c2SBrad Bishop
47840a360c2SBrad Bishop /* Export the object (@manager takes its own reference to @object) */
47940a360c2SBrad Bishop g_dbus_object_manager_server_set_connection(manager, connection);
48040a360c2SBrad Bishop g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object));
48140a360c2SBrad Bishop g_object_unref(object);
48240a360c2SBrad Bishop
4830f3fd5aaSMatt Spinler if(read_gpios(&g_gpio_configs) != TRUE) {
48420a19416SXo Wang g_print("ERROR PowerControl: could not read power GPIO configuration\n");
4851acfd753SYong Li exit(-1);
48620a19416SXo Wang }
48740a360c2SBrad Bishop
4880f3fd5aaSMatt Spinler int rc = set_up_gpio(&g_gpio_configs.power_gpio, control_power);
48920a19416SXo Wang if(rc != GPIO_OK) {
49020a19416SXo Wang g_print("ERROR PowerControl: GPIO setup (rc=%d)\n",rc);
4911acfd753SYong Li exit(-1);
49240a360c2SBrad Bishop }
49340a360c2SBrad Bishop //start poll
49440a360c2SBrad Bishop pgood_timeout_start = 0;
49540a360c2SBrad Bishop int poll_interval = atoi(cmd->argv[1]);
49640a360c2SBrad Bishop int pgood_timeout = atoi(cmd->argv[2]);
49789e6c918SMatt Spinler if(poll_interval < 500 || pgood_timeout <5) {
49889e6c918SMatt Spinler g_print("ERROR PowerControl: poll_interval < 500 or pgood_timeout < 5\n");
4991acfd753SYong Li exit(-1);
50040a360c2SBrad Bishop } else {
50140a360c2SBrad Bishop control_set_poll_interval(control,poll_interval);
50240a360c2SBrad Bishop control_power_set_pgood_timeout(control_power,pgood_timeout);
50340a360c2SBrad Bishop g_timeout_add(poll_interval, poll_pgood, object);
50440a360c2SBrad Bishop }
50540a360c2SBrad Bishop }
50640a360c2SBrad Bishop
50740a360c2SBrad Bishop static void
on_name_acquired(GDBusConnection * connection,const gchar * name,gpointer user_data)50840a360c2SBrad Bishop on_name_acquired(GDBusConnection *connection,
50940a360c2SBrad Bishop const gchar *name,
51040a360c2SBrad Bishop gpointer user_data)
51140a360c2SBrad Bishop {
512*600ff330SPatrick Williams (void) connection;
513*600ff330SPatrick Williams (void) name;
514*600ff330SPatrick Williams (void) user_data;
51540a360c2SBrad Bishop }
51640a360c2SBrad Bishop
51740a360c2SBrad Bishop static void
on_name_lost(GDBusConnection * connection,const gchar * name,gpointer user_data)51840a360c2SBrad Bishop on_name_lost(GDBusConnection *connection,
51940a360c2SBrad Bishop const gchar *name,
52040a360c2SBrad Bishop gpointer user_data)
52140a360c2SBrad Bishop {
522*600ff330SPatrick Williams (void) connection;
523*600ff330SPatrick Williams (void) name;
524*600ff330SPatrick Williams (void) user_data;
52575a18a23SLei YU free_gpios(&g_gpio_configs);
52640a360c2SBrad Bishop }
52740a360c2SBrad Bishop
52840a360c2SBrad Bishop /*----------------------------------------------------------------*/
52940a360c2SBrad Bishop /* Main Event Loop */
53040a360c2SBrad Bishop
53140a360c2SBrad Bishop gint
main(gint argc,gchar * argv[])53240a360c2SBrad Bishop main(gint argc, gchar *argv[])
53340a360c2SBrad Bishop {
53440a360c2SBrad Bishop GMainLoop *loop;
53540a360c2SBrad Bishop cmdline cmd;
53640a360c2SBrad Bishop cmd.argc = argc;
53740a360c2SBrad Bishop cmd.argv = argv;
53840a360c2SBrad Bishop
53940a360c2SBrad Bishop guint id;
54040a360c2SBrad Bishop loop = g_main_loop_new(NULL, FALSE);
54140a360c2SBrad Bishop
54240a360c2SBrad Bishop id = g_bus_own_name(DBUS_TYPE,
54340a360c2SBrad Bishop dbus_name,
54440a360c2SBrad Bishop G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
54540a360c2SBrad Bishop G_BUS_NAME_OWNER_FLAGS_REPLACE,
54640a360c2SBrad Bishop on_bus_acquired,
54740a360c2SBrad Bishop on_name_acquired,
54840a360c2SBrad Bishop on_name_lost,
54940a360c2SBrad Bishop &cmd,
55040a360c2SBrad Bishop NULL);
55140a360c2SBrad Bishop
55240a360c2SBrad Bishop g_main_loop_run(loop);
55340a360c2SBrad Bishop
55440a360c2SBrad Bishop g_bus_unown_name(id);
55540a360c2SBrad Bishop g_main_loop_unref(loop);
55640a360c2SBrad Bishop return 0;
55740a360c2SBrad Bishop }
558