blob: 6108467afd8cd0b60ee076bea9ffb2d7448f37a5 [file] [log] [blame]
Brad Bishop77390492016-04-13 10:47:19 -04001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <fcntl.h>
5#include <unistd.h>
6#include <sys/stat.h>
7#include <sys/mman.h>
Brad Bishopf6c85682016-06-27 11:56:39 -04008#include <openbmc_intf.h>
9#include <openbmc.h>
10#include <gpio.h>
Lei YU45cb4fc2016-11-29 01:48:26 +080011#include <gpio_configs.h>
Brad Bishop77390492016-04-13 10:47:19 -040012
13/* ------------------------------------------------------------------------- */
14static const gchar* dbus_object_path = "/org/openbmc/control";
15static const gchar* instance_name = "host0";
16static const gchar* dbus_name = "org.openbmc.control.Host";
17
Lei YU75a18a22016-11-22 01:47:47 +080018static GpioConfigs g_gpio_configs;
19
Brad Bishop77390492016-04-13 10:47:19 -040020static GDBusObjectManagerServer *manager = NULL;
21
Lei YU75a18a22016-11-22 01:47:47 +080022static GPIO* fsi_data;
23static GPIO* fsi_clk;
24static GPIO* fsi_enable;
25static GPIO* cronus_sel;
26static size_t num_optionals;
27static GPIO* optionals;
28static gboolean* optional_pols;
Brad Bishop77390492016-04-13 10:47:19 -040029
30/* Bit bang patterns */
31
32//putcfam pu 281c 30000000 -p0 (Primary Side Select)
33static const char* primary = "000011111111110101111000111001100111111111111111111111111111101111111111";
34//putcfam pu 281c B0000000 -p0
35static const char* go = "000011111111110101111000111000100111111111111111111111111111101101111111";
36//putcfam pu 0x281c 30900000 (Golden Side Select)
37static const char* golden = "000011111111110101111000111001100111101101111111111111111111101001111111";
38
39/* Setup attentions */
40//putcfam pu 0x081C 20000000
41static const char* attnA = "000011111111111101111110001001101111111111111111111111111111110001111111";
42//putcfam pu 0x100D 40000000
43static const char* attnB = "000011111111111011111100101001011111111111111111111111111111110001111111";
Lei YU75a18a22016-11-22 01:47:47 +080044//putcfam pu 0x100B FFFFFFFF
Brad Bishop77390492016-04-13 10:47:19 -040045static const char* attnC = "000011111111111011111101001000000000000000000000000000000000001011111111";
46
47
48
49static gboolean
50on_init(Control *control,
51 GDBusMethodInvocation *invocation,
52 gpointer user_data)
53{
54 control_complete_init(control,invocation);
55 return TRUE;
56}
57
58int
59fsi_bitbang(const char* pattern)
60{
61 int rc=GPIO_OK;
62 int i;
63 for(i=0;i<strlen(pattern);i++) {
Lei YU75a18a22016-11-22 01:47:47 +080064 rc = gpio_writec(fsi_data,pattern[i]);
Brad Bishop77390492016-04-13 10:47:19 -040065 if(rc!=GPIO_OK) { break; }
Lei YU75a18a22016-11-22 01:47:47 +080066 rc = gpio_clock_cycle(fsi_clk,1);
Brad Bishop77390492016-04-13 10:47:19 -040067 if(rc!=GPIO_OK) { break; }
68 }
69 return rc;
70}
71
72int
73fsi_standby()
74{
75 int rc=GPIO_OK;
Lei YU75a18a22016-11-22 01:47:47 +080076 rc = gpio_write(fsi_data,1);
Brad Bishop77390492016-04-13 10:47:19 -040077 if(rc!=GPIO_OK) { return rc; }
Lei YU75a18a22016-11-22 01:47:47 +080078 rc = gpio_clock_cycle(fsi_clk,5000);
Brad Bishop77390492016-04-13 10:47:19 -040079 if(rc!=GPIO_OK) { return rc; }
80 return rc;
81}
82
83
84static gboolean
85on_boot(ControlHost *host,
86 GDBusMethodInvocation *invocation,
87 gpointer user_data)
88{
89 int rc = GPIO_OK;
Adriana Kobylak37846da2016-08-19 10:57:18 -050090 GDBusProxy *proxy;
91 GError *error = NULL;
92 GVariant *result = NULL;
93 GDBusConnection *connection =
94 g_dbus_object_manager_server_get_connection(manager);
Brad Bishop77390492016-04-13 10:47:19 -040095
Lei YU75a18a22016-11-22 01:47:47 +080096 if (!(fsi_data && fsi_clk && fsi_enable && cronus_sel)) {
97 g_print("ERROR invalid GPIO configuration, will not boot\n");
98 return FALSE;
99 }
100 if(control_host_get_debug_mode(host)==1) {
Brad Bishop77390492016-04-13 10:47:19 -0400101 g_print("Enabling debug mode; not booting host\n");
Lei YU75a18a22016-11-22 01:47:47 +0800102 rc |= gpio_open(fsi_enable);
103 rc |= gpio_open(cronus_sel);
104 rc |= gpio_write(fsi_enable,1);
105 rc |= gpio_write(cronus_sel,0);
Brad Bishop77390492016-04-13 10:47:19 -0400106 if(rc!=GPIO_OK) {
107 g_print("ERROR enabling debug mode: %d\n",rc);
108 }
109 return TRUE;
110 }
111 g_print("Booting host\n");
112 Control* control = object_get_control((Object*)user_data);
113 control_host_complete_boot(host,invocation);
114 do {
Lei YU75a18a22016-11-22 01:47:47 +0800115 rc = gpio_open(fsi_clk);
116 rc |= gpio_open(fsi_data);
117 rc |= gpio_open(fsi_enable);
118 rc |= gpio_open(cronus_sel);
119 for (size_t i = 0; i < num_optionals; ++i) {
120 rc |= gpio_open(&optionals[i]);
121 }
Brad Bishop77390492016-04-13 10:47:19 -0400122 if(rc!=GPIO_OK) { break; }
123
124 //setup dc pins
Lei YU75a18a22016-11-22 01:47:47 +0800125 rc = gpio_write(cronus_sel,1);
126 rc |= gpio_write(fsi_enable,1);
127 rc |= gpio_write(fsi_clk,1);
128 for (size_t i = 0; i < num_optionals; ++i) {
129 rc |= gpio_write(&optionals[i], optional_pols[i]);
130 }
Brad Bishop77390492016-04-13 10:47:19 -0400131 if(rc!=GPIO_OK) { break; }
132
133 //data standy state
134 rc = fsi_standby();
135
136 //clear out pipes
Lei YU75a18a22016-11-22 01:47:47 +0800137 rc |= gpio_write(fsi_data,0);
138 rc |= gpio_clock_cycle(fsi_clk,256);
139 rc |= gpio_write(fsi_data,1);
140 rc |= gpio_clock_cycle(fsi_clk,50);
Brad Bishop77390492016-04-13 10:47:19 -0400141 if(rc!=GPIO_OK) { break; }
142
143 rc = fsi_bitbang(attnA);
144 rc |= fsi_standby();
145
146 rc |= fsi_bitbang(attnB);
147 rc |= fsi_standby();
148
149 rc |= fsi_bitbang(attnC);
150 rc |= fsi_standby();
151 if(rc!=GPIO_OK) { break; }
152
153 const gchar* flash_side = control_host_get_flash_side(host);
154 g_print("Using %s side of the bios flash\n",flash_side);
155 if(strcmp(flash_side,"primary")==0) {
156 rc |= fsi_bitbang(primary);
157 } else if(strcmp(flash_side,"golden") == 0) {
158 rc |= fsi_bitbang(golden);
159 } else {
160 g_print("ERROR: Invalid flash side: %s\n",flash_side);
161 rc = 0xff;
162
163 }
164 rc |= fsi_standby();
165 if(rc!=GPIO_OK) { break; }
166
167 rc = fsi_bitbang(go);
168
Lei YU75a18a22016-11-22 01:47:47 +0800169 rc |= gpio_write(fsi_data,1); /* Data standby state */
170 rc |= gpio_clock_cycle(fsi_clk,2);
Brad Bishop77390492016-04-13 10:47:19 -0400171
Lei YU75a18a22016-11-22 01:47:47 +0800172 rc |= gpio_write(fsi_clk,0); /* hold clk low for clock mux */
173 rc |= gpio_write(fsi_enable,0);
174 rc |= gpio_clock_cycle(fsi_clk,16);
175 rc |= gpio_write(fsi_clk,0); /* Data standby state */
Brad Bishop77390492016-04-13 10:47:19 -0400176
177 } while(0);
178 if(rc != GPIO_OK)
179 {
180 g_print("ERROR HostControl: GPIO sequence failed (rc=%d)\n",rc);
181 } else {
182 control_emit_goto_system_state(control,"HOST_BOOTING");
183 }
Lei YU75a18a22016-11-22 01:47:47 +0800184 gpio_close(fsi_clk);
185 gpio_close(fsi_data);
186 gpio_close(fsi_enable);
187 gpio_close(cronus_sel);
188 for (size_t i = 0; i < num_optionals; ++i) {
189 gpio_close(&optionals[i]);
190 }
Brad Bishop77390492016-04-13 10:47:19 -0400191
Adriana Kobylak37846da2016-08-19 10:57:18 -0500192 // Start watchdog with 30s timeout per the OpenPower Host IPMI Spec.
193 // Once the host starts booting, it'll reset and refresh the timer.
194 error = NULL;
195 // TODO Use the object mapper to lookup the bus name when this is
196 // refactored to use sdbus.
197 proxy = g_dbus_proxy_new_sync(connection,
198 G_DBUS_PROXY_FLAGS_NONE,
199 NULL, /* GDBusInterfaceInfo* */
200 "org.openbmc.watchdog.Host", /* name */
201 "/org/openbmc/watchdog/host0", /* object path */
202 "org.openbmc.Watchdog", /* interface name */
203 NULL, /* GCancellable */
204 &error);
205 g_assert_no_error(error);
206 if(error)
207 goto exit;
208
209 // Set watchdog timer to 30s
210 error = NULL;
211 result = g_dbus_proxy_call_sync(proxy,
212 "set",
213 g_variant_new("(i)", 30000),
214 G_DBUS_CALL_FLAGS_NONE,
215 -1,
216 NULL,
217 &error);
218 g_assert_no_error(error);
219 if (error)
220 goto exit;
221 if (result)
222 g_variant_unref(result);
223
224 // Start watchdog timer
225 error = NULL;
226 result = g_dbus_proxy_call_sync(proxy,
227 "start",
228 NULL,
229 G_DBUS_CALL_FLAGS_NONE,
230 -1,
231 NULL,
232 &error);
233 g_assert_no_error(error);
234 if (error)
235 goto exit;
236
Brad Bishop77390492016-04-13 10:47:19 -0400237 control_host_emit_booted(host);
Adriana Kobylak37846da2016-08-19 10:57:18 -0500238
239exit:
240 if (result)
241 g_variant_unref(result);
242
Brad Bishop77390492016-04-13 10:47:19 -0400243 return TRUE;
244}
245
246static void
247on_bus_acquired(GDBusConnection *connection,
248 const gchar *name,
249 gpointer user_data)
250{
251 ObjectSkeleton *object;
252 //g_print ("Acquired a message bus connection: %s\n",name);
Brad Bishop77390492016-04-13 10:47:19 -0400253 manager = g_dbus_object_manager_server_new(dbus_object_path);
254
255 gchar *s;
256 s = g_strdup_printf("%s/%s",dbus_object_path,instance_name);
257 object = object_skeleton_new(s);
258 g_free(s);
259
260 ControlHost* control_host = control_host_skeleton_new();
261 object_skeleton_set_control_host(object, control_host);
262 g_object_unref(control_host);
263
264 Control* control = control_skeleton_new();
265 object_skeleton_set_control(object, control);
266 g_object_unref(control);
267
Brad Bishop77390492016-04-13 10:47:19 -0400268 //define method callbacks here
269 g_signal_connect(control_host,
270 "handle-boot",
271 G_CALLBACK(on_boot),
272 object); /* user_data */
273 g_signal_connect(control,
274 "handle-init",
275 G_CALLBACK(on_init),
276 NULL); /* user_data */
277
278 control_host_set_debug_mode(control_host,0);
279 control_host_set_flash_side(control_host,"primary");
280
281 /* Export the object (@manager takes its own reference to @object) */
Brad Bishop58e694d2016-04-13 16:04:32 -0400282 g_dbus_object_manager_server_set_connection(manager, connection);
Brad Bishop77390492016-04-13 10:47:19 -0400283 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object));
284 g_object_unref(object);
285
Lei YU75a18a22016-11-22 01:47:47 +0800286 if(read_gpios(connection, &g_gpio_configs) != TRUE) {
287 g_print("ERROR Hostctl: could not read GPIO configuration\n");
288 return;
289 }
290
291 fsi_data = &g_gpio_configs.hostctl_gpio.fsi_data;
292 fsi_clk = &g_gpio_configs.hostctl_gpio.fsi_clk;
293 fsi_enable = &g_gpio_configs.hostctl_gpio.fsi_enable;
294 cronus_sel = &g_gpio_configs.hostctl_gpio.cronus_sel;
295 num_optionals = g_gpio_configs.hostctl_gpio.num_optionals;
296 optionals = g_gpio_configs.hostctl_gpio.optionals;
297 optional_pols = g_gpio_configs.hostctl_gpio.optional_pols;
298
299 gpio_init(connection, fsi_data);
300 gpio_init(connection, fsi_clk);
301 gpio_init(connection, fsi_enable);
302 gpio_init(connection, cronus_sel);
303 for (int i = 0; i < num_optionals; ++i) {
304 gpio_init(connection, &optionals[i]);
305 }
Brad Bishop77390492016-04-13 10:47:19 -0400306}
307
308static void
309on_name_acquired(GDBusConnection *connection,
310 const gchar *name,
311 gpointer user_data)
312{
Lei YU75a18a22016-11-22 01:47:47 +0800313 // g_print ("Acquired the name %s\n", name);
Brad Bishop77390492016-04-13 10:47:19 -0400314}
315
316static void
317on_name_lost(GDBusConnection *connection,
318 const gchar *name,
319 gpointer user_data)
320{
Lei YU75a18a22016-11-22 01:47:47 +0800321 // g_print ("Lost the name %s\n", name);
322 free_gpios(&g_gpio_configs);
Brad Bishop77390492016-04-13 10:47:19 -0400323}
324
325gint
326main(gint argc, gchar *argv[])
327{
328 GMainLoop *loop;
329 cmdline cmd;
330 cmd.argc = argc;
331 cmd.argv = argv;
332
333 guint id;
334 loop = g_main_loop_new(NULL, FALSE);
335
336 id = g_bus_own_name(DBUS_TYPE,
337 dbus_name,
338 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
339 G_BUS_NAME_OWNER_FLAGS_REPLACE,
340 on_bus_acquired,
341 on_name_acquired,
342 on_name_lost,
343 &cmd,
344 NULL);
345
346 g_main_loop_run(loop);
347
348 g_bus_unown_name(id);
349 g_main_loop_unref(loop);
350 return 0;
351}