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 } 181 gpio_close(fsi_clk); 182 gpio_close(fsi_data); 183 gpio_close(fsi_enable); 184 gpio_close(cronus_sel); 185 for (size_t i = 0; i < num_optionals; ++i) { 186 gpio_close(&optionals[i]); 187 } 188 189 control_host_emit_booted(host); 190 191 return TRUE; 192 } 193 194 static void 195 on_bus_acquired(GDBusConnection *connection, 196 const gchar *name, 197 gpointer user_data) 198 { 199 ObjectSkeleton *object; 200 //g_print ("Acquired a message bus connection: %s\n",name); 201 manager = g_dbus_object_manager_server_new(dbus_object_path); 202 203 gchar *s; 204 s = g_strdup_printf("%s/%s",dbus_object_path,instance_name); 205 object = object_skeleton_new(s); 206 g_free(s); 207 208 ControlHost* control_host = control_host_skeleton_new(); 209 object_skeleton_set_control_host(object, control_host); 210 g_object_unref(control_host); 211 212 Control* control = control_skeleton_new(); 213 object_skeleton_set_control(object, control); 214 g_object_unref(control); 215 216 //define method callbacks here 217 g_signal_connect(control_host, 218 "handle-boot", 219 G_CALLBACK(on_boot), 220 object); /* user_data */ 221 g_signal_connect(control, 222 "handle-init", 223 G_CALLBACK(on_init), 224 NULL); /* user_data */ 225 226 control_host_set_debug_mode(control_host,0); 227 control_host_set_flash_side(control_host,"primary"); 228 229 /* Export the object (@manager takes its own reference to @object) */ 230 g_dbus_object_manager_server_set_connection(manager, connection); 231 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object)); 232 g_object_unref(object); 233 234 if(read_gpios(connection, &g_gpio_configs) != TRUE) { 235 g_print("ERROR Hostctl: could not read GPIO configuration\n"); 236 return; 237 } 238 239 fsi_data = &g_gpio_configs.hostctl_gpio.fsi_data; 240 fsi_clk = &g_gpio_configs.hostctl_gpio.fsi_clk; 241 fsi_enable = &g_gpio_configs.hostctl_gpio.fsi_enable; 242 cronus_sel = &g_gpio_configs.hostctl_gpio.cronus_sel; 243 num_optionals = g_gpio_configs.hostctl_gpio.num_optionals; 244 optionals = g_gpio_configs.hostctl_gpio.optionals; 245 optional_pols = g_gpio_configs.hostctl_gpio.optional_pols; 246 247 gpio_init(connection, fsi_data); 248 gpio_init(connection, fsi_clk); 249 gpio_init(connection, fsi_enable); 250 gpio_init(connection, cronus_sel); 251 for (int i = 0; i < num_optionals; ++i) { 252 gpio_init(connection, &optionals[i]); 253 } 254 } 255 256 static void 257 on_name_acquired(GDBusConnection *connection, 258 const gchar *name, 259 gpointer user_data) 260 { 261 // g_print ("Acquired the name %s\n", name); 262 } 263 264 static void 265 on_name_lost(GDBusConnection *connection, 266 const gchar *name, 267 gpointer user_data) 268 { 269 // g_print ("Lost the name %s\n", name); 270 free_gpios(&g_gpio_configs); 271 } 272 273 gint 274 main(gint argc, gchar *argv[]) 275 { 276 GMainLoop *loop; 277 cmdline cmd; 278 cmd.argc = argc; 279 cmd.argv = argv; 280 281 guint id; 282 loop = g_main_loop_new(NULL, FALSE); 283 284 id = g_bus_own_name(DBUS_TYPE, 285 dbus_name, 286 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | 287 G_BUS_NAME_OWNER_FLAGS_REPLACE, 288 on_bus_acquired, 289 on_name_acquired, 290 on_name_lost, 291 &cmd, 292 NULL); 293 294 g_main_loop_run(loop); 295 296 g_bus_unown_name(id); 297 g_main_loop_unref(loop); 298 return 0; 299 } 300