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