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 #include <gpio_configs.h> 12 13 /* ------------------------------------------------------------------------- */ 14 static const gchar* dbus_object_path = "/org/openbmc/control"; 15 static const gchar* instance_name = "host0"; 16 static const gchar* dbus_name = "org.openbmc.control.Host"; 17 18 static GpioConfigs g_gpio_configs; 19 20 static GDBusObjectManagerServer *manager = NULL; 21 22 static GPIO* fsi_data; 23 static GPIO* fsi_clk; 24 static GPIO* fsi_enable; 25 static GPIO* cronus_sel; 26 static size_t num_optionals; 27 static GPIO* optionals; 28 static gboolean* optional_pols; 29 30 /* Bit bang patterns */ 31 32 //putcfam pu 281c 30000000 -p0 (Primary Side Select) 33 static const char* primary = "000011111111110101111000111001100111111111111111111111111111101111111111"; 34 //putcfam pu 281c B0000000 -p0 35 static const char* go = "000011111111110101111000111000100111111111111111111111111111101101111111"; 36 //putcfam pu 0x281c 30900000 (Golden Side Select) 37 static const char* golden = "000011111111110101111000111001100111101101111111111111111111101001111111"; 38 39 /* Setup attentions */ 40 //putcfam pu 0x081C 20000000 41 static const char* attnA = "000011111111111101111110001001101111111111111111111111111111110001111111"; 42 //putcfam pu 0x100D 40000000 43 static const char* attnB = "000011111111111011111100101001011111111111111111111111111111110001111111"; 44 //putcfam pu 0x100B FFFFFFFF 45 static const char* attnC = "000011111111111011111101001000000000000000000000000000000000001011111111"; 46 47 48 49 static gboolean 50 on_init(Control *control, 51 GDBusMethodInvocation *invocation, 52 gpointer user_data) 53 { 54 control_complete_init(control,invocation); 55 return TRUE; 56 } 57 58 int 59 fsi_bitbang(const char* pattern) 60 { 61 int rc=GPIO_OK; 62 int i; 63 for(i=0;i<strlen(pattern);i++) { 64 rc = gpio_writec(fsi_data,pattern[i]); 65 if(rc!=GPIO_OK) { break; } 66 rc = gpio_clock_cycle(fsi_clk,1); 67 if(rc!=GPIO_OK) { break; } 68 } 69 return rc; 70 } 71 72 int 73 fsi_standby() 74 { 75 int rc=GPIO_OK; 76 rc = gpio_write(fsi_data,1); 77 if(rc!=GPIO_OK) { return rc; } 78 rc = gpio_clock_cycle(fsi_clk,5000); 79 if(rc!=GPIO_OK) { return rc; } 80 return rc; 81 } 82 83 84 static gboolean 85 on_boot(ControlHost *host, 86 GDBusMethodInvocation *invocation, 87 gpointer user_data) 88 { 89 int rc = GPIO_OK; 90 GDBusProxy *proxy; 91 GError *error = NULL; 92 GVariant *result = NULL; 93 GDBusConnection *connection = 94 g_dbus_object_manager_server_get_connection(manager); 95 96 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) { 101 g_print("Enabling debug mode; not booting host\n"); 102 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); 106 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 { 115 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 } 122 if(rc!=GPIO_OK) { break; } 123 124 //setup dc pins 125 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 } 131 if(rc!=GPIO_OK) { break; } 132 133 //data standy state 134 rc = fsi_standby(); 135 136 //clear out pipes 137 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); 141 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 169 rc |= gpio_write(fsi_data,1); /* Data standby state */ 170 rc |= gpio_clock_cycle(fsi_clk,2); 171 172 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 */ 176 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 } 184 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 } 191 192 // 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 237 control_host_emit_booted(host); 238 239 exit: 240 if (result) 241 g_variant_unref(result); 242 243 return TRUE; 244 } 245 246 static void 247 on_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); 253 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 268 //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) */ 282 g_dbus_object_manager_server_set_connection(manager, connection); 283 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object)); 284 g_object_unref(object); 285 286 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 } 306 } 307 308 static void 309 on_name_acquired(GDBusConnection *connection, 310 const gchar *name, 311 gpointer user_data) 312 { 313 // g_print ("Acquired the name %s\n", name); 314 } 315 316 static void 317 on_name_lost(GDBusConnection *connection, 318 const gchar *name, 319 gpointer user_data) 320 { 321 // g_print ("Lost the name %s\n", name); 322 free_gpios(&g_gpio_configs); 323 } 324 325 gint 326 main(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 } 352