1 #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> 8 #include <openbmc_intf.h> 9 #include <openbmc.h> 10 #include <gpio.h> 11 12 /* ------------------------------------------------------------------------- */ 13 static const gchar* dbus_object_path = "/org/openbmc/control"; 14 static const gchar* instance_name = "host0"; 15 static const gchar* dbus_name = "org.openbmc.control.Host"; 16 17 static GDBusObjectManagerServer *manager = NULL; 18 19 GPIO fsi_data = (GPIO){ "FSI_DATA" }; 20 GPIO fsi_clk = (GPIO){ "FSI_CLK" }; 21 GPIO fsi_enable = (GPIO){ "FSI_ENABLE" }; 22 GPIO cronus_sel = (GPIO){ "CRONUS_SEL" }; 23 GPIO Throttle = (GPIO){ "BMC_THROTTLE" }; 24 GPIO idbtn = (GPIO){ "IDBTN" }; 25 26 /* Bit bang patterns */ 27 28 //putcfam pu 281c 30000000 -p0 (Primary Side Select) 29 static const char* primary = "000011111111110101111000111001100111111111111111111111111111101111111111"; 30 //putcfam pu 281c B0000000 -p0 31 static const char* go = "000011111111110101111000111000100111111111111111111111111111101101111111"; 32 //putcfam pu 0x281c 30900000 (Golden Side Select) 33 static const char* golden = "000011111111110101111000111001100111101101111111111111111111101001111111"; 34 35 /* Setup attentions */ 36 //putcfam pu 0x081C 20000000 37 static const char* attnA = "000011111111111101111110001001101111111111111111111111111111110001111111"; 38 //putcfam pu 0x100D 40000000 39 static const char* attnB = "000011111111111011111100101001011111111111111111111111111111110001111111"; 40 //putcfam pu 0x100B FFFFFFFF 41 static const char* attnC = "000011111111111011111101001000000000000000000000000000000000001011111111"; 42 43 44 45 static gboolean 46 on_init(Control *control, 47 GDBusMethodInvocation *invocation, 48 gpointer user_data) 49 { 50 control_complete_init(control,invocation); 51 return TRUE; 52 } 53 54 int 55 fsi_bitbang(const char* pattern) 56 { 57 int rc=GPIO_OK; 58 int i; 59 for(i=0;i<strlen(pattern);i++) { 60 rc = gpio_writec(&fsi_data,pattern[i]); 61 if(rc!=GPIO_OK) { break; } 62 rc = gpio_clock_cycle(&fsi_clk,1); 63 if(rc!=GPIO_OK) { break; } 64 } 65 return rc; 66 } 67 68 int 69 fsi_standby() 70 { 71 int rc=GPIO_OK; 72 rc = gpio_write(&fsi_data,1); 73 if(rc!=GPIO_OK) { return rc; } 74 rc = gpio_clock_cycle(&fsi_clk,5000); 75 if(rc!=GPIO_OK) { return rc; } 76 return rc; 77 } 78 79 80 static gboolean 81 on_boot(ControlHost *host, 82 GDBusMethodInvocation *invocation, 83 gpointer user_data) 84 { 85 int rc = GPIO_OK; 86 GDBusProxy *proxy; 87 GError *error = NULL; 88 GVariant *result = NULL; 89 GDBusConnection *connection = 90 g_dbus_object_manager_server_get_connection(manager); 91 92 if(control_host_get_debug_mode(host)==1) 93 { 94 g_print("Enabling debug mode; not booting host\n"); 95 rc |= gpio_open(&fsi_enable); 96 rc |= gpio_open(&cronus_sel); 97 rc |= gpio_write(&fsi_enable,1); 98 rc |= gpio_write(&cronus_sel,0); 99 if(rc!=GPIO_OK) { 100 g_print("ERROR enabling debug mode: %d\n",rc); 101 } 102 return TRUE; 103 } 104 g_print("Booting host\n"); 105 Control* control = object_get_control((Object*)user_data); 106 control_host_complete_boot(host,invocation); 107 do { 108 rc = gpio_open(&fsi_clk); 109 rc |= gpio_open(&fsi_data); 110 rc |= gpio_open(&fsi_enable); 111 rc |= gpio_open(&cronus_sel); 112 rc |= gpio_open(&Throttle); 113 rc |= gpio_open(&idbtn); 114 if(rc!=GPIO_OK) { break; } 115 116 //setup dc pins 117 rc = gpio_write(&cronus_sel,1); 118 rc |= gpio_write(&fsi_enable,1); 119 rc |= gpio_write(&fsi_clk,1); 120 rc |= gpio_write(&Throttle,1); 121 rc |= gpio_write(&idbtn,0); 122 if(rc!=GPIO_OK) { break; } 123 124 //data standy state 125 rc = fsi_standby(); 126 127 //clear out pipes 128 rc |= gpio_write(&fsi_data,0); 129 rc |= gpio_clock_cycle(&fsi_clk,256); 130 rc |= gpio_write(&fsi_data,1); 131 rc |= gpio_clock_cycle(&fsi_clk,50); 132 if(rc!=GPIO_OK) { break; } 133 134 rc = fsi_bitbang(attnA); 135 rc |= fsi_standby(); 136 137 rc |= fsi_bitbang(attnB); 138 rc |= fsi_standby(); 139 140 rc |= fsi_bitbang(attnC); 141 rc |= fsi_standby(); 142 if(rc!=GPIO_OK) { break; } 143 144 const gchar* flash_side = control_host_get_flash_side(host); 145 g_print("Using %s side of the bios flash\n",flash_side); 146 if(strcmp(flash_side,"primary")==0) { 147 rc |= fsi_bitbang(primary); 148 } else if(strcmp(flash_side,"golden") == 0) { 149 rc |= fsi_bitbang(golden); 150 } else { 151 g_print("ERROR: Invalid flash side: %s\n",flash_side); 152 rc = 0xff; 153 154 } 155 rc |= fsi_standby(); 156 if(rc!=GPIO_OK) { break; } 157 158 rc = fsi_bitbang(go); 159 160 rc |= gpio_write(&fsi_data,1); /* Data standby state */ 161 rc |= gpio_clock_cycle(&fsi_clk,2); 162 163 rc |= gpio_write(&fsi_clk,0); /* hold clk low for clock mux */ 164 rc |= gpio_write(&fsi_enable,0); 165 rc |= gpio_clock_cycle(&fsi_clk,16); 166 rc |= gpio_write(&fsi_clk,0); /* Data standby state */ 167 168 } while(0); 169 if(rc != GPIO_OK) 170 { 171 g_print("ERROR HostControl: GPIO sequence failed (rc=%d)\n",rc); 172 } else { 173 control_emit_goto_system_state(control,"HOST_BOOTING"); 174 } 175 gpio_close(&fsi_clk); 176 gpio_close(&fsi_data); 177 gpio_close(&fsi_enable); 178 gpio_close(&cronus_sel); 179 gpio_close(&Throttle); 180 gpio_close(&idbtn); 181 182 // Start watchdog with 30s timeout per the OpenPower Host IPMI Spec. 183 // Once the host starts booting, it'll reset and refresh the timer. 184 error = NULL; 185 // TODO Use the object mapper to lookup the bus name when this is 186 // refactored to use sdbus. 187 proxy = g_dbus_proxy_new_sync(connection, 188 G_DBUS_PROXY_FLAGS_NONE, 189 NULL, /* GDBusInterfaceInfo* */ 190 "org.openbmc.watchdog.Host", /* name */ 191 "/org/openbmc/watchdog/host0", /* object path */ 192 "org.openbmc.Watchdog", /* interface name */ 193 NULL, /* GCancellable */ 194 &error); 195 g_assert_no_error(error); 196 if(error) 197 goto exit; 198 199 // Set watchdog timer to 30s 200 error = NULL; 201 result = g_dbus_proxy_call_sync(proxy, 202 "set", 203 g_variant_new("(i)", 30000), 204 G_DBUS_CALL_FLAGS_NONE, 205 -1, 206 NULL, 207 &error); 208 g_assert_no_error(error); 209 if (error) 210 goto exit; 211 if (result) 212 g_variant_unref(result); 213 214 // Start watchdog timer 215 error = NULL; 216 result = g_dbus_proxy_call_sync(proxy, 217 "start", 218 NULL, 219 G_DBUS_CALL_FLAGS_NONE, 220 -1, 221 NULL, 222 &error); 223 g_assert_no_error(error); 224 if (error) 225 goto exit; 226 227 control_host_emit_booted(host); 228 229 exit: 230 if (result) 231 g_variant_unref(result); 232 233 return TRUE; 234 } 235 236 static void 237 on_bus_acquired(GDBusConnection *connection, 238 const gchar *name, 239 gpointer user_data) 240 { 241 ObjectSkeleton *object; 242 //g_print ("Acquired a message bus connection: %s\n",name); 243 manager = g_dbus_object_manager_server_new(dbus_object_path); 244 245 gchar *s; 246 s = g_strdup_printf("%s/%s",dbus_object_path,instance_name); 247 object = object_skeleton_new(s); 248 g_free(s); 249 250 ControlHost* control_host = control_host_skeleton_new(); 251 object_skeleton_set_control_host(object, control_host); 252 g_object_unref(control_host); 253 254 Control* control = control_skeleton_new(); 255 object_skeleton_set_control(object, control); 256 g_object_unref(control); 257 258 //define method callbacks here 259 g_signal_connect(control_host, 260 "handle-boot", 261 G_CALLBACK(on_boot), 262 object); /* user_data */ 263 g_signal_connect(control, 264 "handle-init", 265 G_CALLBACK(on_init), 266 NULL); /* user_data */ 267 268 control_host_set_debug_mode(control_host,0); 269 control_host_set_flash_side(control_host,"primary"); 270 271 /* Export the object (@manager takes its own reference to @object) */ 272 g_dbus_object_manager_server_set_connection(manager, connection); 273 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object)); 274 g_object_unref(object); 275 276 gpio_init(connection,&fsi_data); 277 gpio_init(connection,&fsi_clk); 278 gpio_init(connection,&fsi_enable); 279 gpio_init(connection,&cronus_sel); 280 gpio_init(connection,&Throttle); 281 gpio_init(connection,&idbtn); 282 } 283 284 static void 285 on_name_acquired(GDBusConnection *connection, 286 const gchar *name, 287 gpointer user_data) 288 { 289 // g_print ("Acquired the name %s\n", name); 290 } 291 292 static void 293 on_name_lost(GDBusConnection *connection, 294 const gchar *name, 295 gpointer user_data) 296 { 297 // g_print ("Lost the name %s\n", name); 298 } 299 300 gint 301 main(gint argc, gchar *argv[]) 302 { 303 GMainLoop *loop; 304 cmdline cmd; 305 cmd.argc = argc; 306 cmd.argv = argv; 307 308 guint id; 309 loop = g_main_loop_new(NULL, FALSE); 310 311 id = g_bus_own_name(DBUS_TYPE, 312 dbus_name, 313 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | 314 G_BUS_NAME_OWNER_FLAGS_REPLACE, 315 on_bus_acquired, 316 on_name_acquired, 317 on_name_lost, 318 &cmd, 319 NULL); 320 321 g_main_loop_run(loop); 322 323 g_bus_unown_name(id); 324 g_main_loop_unref(loop); 325 return 0; 326 } 327