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 GDBusConnection *connection = 93 g_dbus_object_manager_server_get_connection(manager); 94 95 if (!(fsi_data && fsi_clk && fsi_enable && cronus_sel)) { 96 g_print("ERROR invalid GPIO configuration, will not boot\n"); 97 return FALSE; 98 } 99 if(control_host_get_debug_mode(host)==1) { 100 g_print("Enabling debug mode; not booting host\n"); 101 rc |= gpio_open(fsi_enable); 102 rc |= gpio_open(cronus_sel); 103 rc |= gpio_write(fsi_enable,1); 104 rc |= gpio_write(cronus_sel,0); 105 if(rc!=GPIO_OK) { 106 g_print("ERROR enabling debug mode: %d\n",rc); 107 } 108 return TRUE; 109 } 110 g_print("Booting host\n"); 111 Control* control = object_get_control((Object*)user_data); 112 control_host_complete_boot(host,invocation); 113 do { 114 rc = gpio_open(fsi_clk); 115 rc |= gpio_open(fsi_data); 116 rc |= gpio_open(fsi_enable); 117 rc |= gpio_open(cronus_sel); 118 for (size_t i = 0; i < num_optionals; ++i) { 119 rc |= gpio_open(&optionals[i]); 120 } 121 if(rc!=GPIO_OK) { break; } 122 123 //setup dc pins 124 rc = gpio_write(cronus_sel,1); 125 rc |= gpio_write(fsi_enable,1); 126 rc |= gpio_write(fsi_clk,1); 127 for (size_t i = 0; i < num_optionals; ++i) { 128 rc |= gpio_write(&optionals[i], optional_pols[i]); 129 } 130 if(rc!=GPIO_OK) { break; } 131 132 //data standy state 133 rc = fsi_standby(); 134 135 //clear out pipes 136 rc |= gpio_write(fsi_data,0); 137 rc |= gpio_clock_cycle(fsi_clk,256); 138 rc |= gpio_write(fsi_data,1); 139 rc |= gpio_clock_cycle(fsi_clk,50); 140 if(rc!=GPIO_OK) { break; } 141 142 rc = fsi_bitbang(attnA); 143 rc |= fsi_standby(); 144 145 rc |= fsi_bitbang(attnB); 146 rc |= fsi_standby(); 147 148 rc |= fsi_bitbang(attnC); 149 rc |= fsi_standby(); 150 if(rc!=GPIO_OK) { break; } 151 152 const gchar* flash_side = control_host_get_flash_side(host); 153 g_print("Using %s side of the bios flash\n",flash_side); 154 if(strcmp(flash_side,"primary")==0) { 155 rc |= fsi_bitbang(primary); 156 } else if(strcmp(flash_side,"golden") == 0) { 157 rc |= fsi_bitbang(golden); 158 } else { 159 g_print("ERROR: Invalid flash side: %s\n",flash_side); 160 rc = 0xff; 161 162 } 163 rc |= fsi_standby(); 164 if(rc!=GPIO_OK) { break; } 165 166 rc = fsi_bitbang(go); 167 168 rc |= gpio_write(fsi_data,1); /* Data standby state */ 169 rc |= gpio_clock_cycle(fsi_clk,2); 170 171 rc |= gpio_write(fsi_clk,0); /* hold clk low for clock mux */ 172 rc |= gpio_write(fsi_enable,0); 173 rc |= gpio_clock_cycle(fsi_clk,16); 174 rc |= gpio_write(fsi_clk,0); /* Data standby state */ 175 176 } while(0); 177 if(rc != GPIO_OK) 178 { 179 g_print("ERROR HostControl: GPIO sequence failed (rc=%d)\n",rc); 180 } else { 181 control_emit_goto_system_state(control,"HOST_BOOTING"); 182 } 183 gpio_close(fsi_clk); 184 gpio_close(fsi_data); 185 gpio_close(fsi_enable); 186 gpio_close(cronus_sel); 187 for (size_t i = 0; i < num_optionals; ++i) { 188 gpio_close(&optionals[i]); 189 } 190 191 control_host_emit_booted(host); 192 193 return TRUE; 194 } 195 196 static void 197 on_bus_acquired(GDBusConnection *connection, 198 const gchar *name, 199 gpointer user_data) 200 { 201 ObjectSkeleton *object; 202 //g_print ("Acquired a message bus connection: %s\n",name); 203 manager = g_dbus_object_manager_server_new(dbus_object_path); 204 205 gchar *s; 206 s = g_strdup_printf("%s/%s",dbus_object_path,instance_name); 207 object = object_skeleton_new(s); 208 g_free(s); 209 210 ControlHost* control_host = control_host_skeleton_new(); 211 object_skeleton_set_control_host(object, control_host); 212 g_object_unref(control_host); 213 214 Control* control = control_skeleton_new(); 215 object_skeleton_set_control(object, control); 216 g_object_unref(control); 217 218 //define method callbacks here 219 g_signal_connect(control_host, 220 "handle-boot", 221 G_CALLBACK(on_boot), 222 object); /* user_data */ 223 g_signal_connect(control, 224 "handle-init", 225 G_CALLBACK(on_init), 226 NULL); /* user_data */ 227 228 control_host_set_debug_mode(control_host,0); 229 control_host_set_flash_side(control_host,"primary"); 230 231 /* Export the object (@manager takes its own reference to @object) */ 232 g_dbus_object_manager_server_set_connection(manager, connection); 233 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object)); 234 g_object_unref(object); 235 236 if(read_gpios(connection, &g_gpio_configs) != TRUE) { 237 g_print("ERROR Hostctl: could not read GPIO configuration\n"); 238 return; 239 } 240 241 fsi_data = &g_gpio_configs.hostctl_gpio.fsi_data; 242 fsi_clk = &g_gpio_configs.hostctl_gpio.fsi_clk; 243 fsi_enable = &g_gpio_configs.hostctl_gpio.fsi_enable; 244 cronus_sel = &g_gpio_configs.hostctl_gpio.cronus_sel; 245 num_optionals = g_gpio_configs.hostctl_gpio.num_optionals; 246 optionals = g_gpio_configs.hostctl_gpio.optionals; 247 optional_pols = g_gpio_configs.hostctl_gpio.optional_pols; 248 249 gpio_init(connection, fsi_data); 250 gpio_init(connection, fsi_clk); 251 gpio_init(connection, fsi_enable); 252 gpio_init(connection, cronus_sel); 253 for (int i = 0; i < num_optionals; ++i) { 254 gpio_init(connection, &optionals[i]); 255 } 256 } 257 258 static void 259 on_name_acquired(GDBusConnection *connection, 260 const gchar *name, 261 gpointer user_data) 262 { 263 // g_print ("Acquired the name %s\n", name); 264 } 265 266 static void 267 on_name_lost(GDBusConnection *connection, 268 const gchar *name, 269 gpointer user_data) 270 { 271 // g_print ("Lost the name %s\n", name); 272 free_gpios(&g_gpio_configs); 273 } 274 275 gint 276 main(gint argc, gchar *argv[]) 277 { 278 GMainLoop *loop; 279 cmdline cmd; 280 cmd.argc = argc; 281 cmd.argv = argv; 282 283 guint id; 284 loop = g_main_loop_new(NULL, FALSE); 285 286 id = g_bus_own_name(DBUS_TYPE, 287 dbus_name, 288 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | 289 G_BUS_NAME_OWNER_FLAGS_REPLACE, 290 on_bus_acquired, 291 on_name_acquired, 292 on_name_lost, 293 &cmd, 294 NULL); 295 296 g_main_loop_run(loop); 297 298 g_bus_unown_name(id); 299 g_main_loop_unref(loop); 300 return 0; 301 } 302