blob: 9253007c6681f3ab68dee8144184e53cd9627631 [file] [log] [blame]
Brad Bishop77390492016-04-13 10:47:19 -04001#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 "interfaces/openbmc_intf.h"
9#include "openbmc.h"
10#include "gpio.h"
Brad Bishop77390492016-04-13 10:47:19 -040011
12/* ------------------------------------------------------------------------- */
13static const gchar* dbus_object_path = "/org/openbmc/control";
14static const gchar* instance_name = "host0";
15static const gchar* dbus_name = "org.openbmc.control.Host";
16
17static GDBusObjectManagerServer *manager = NULL;
18
19GPIO fsi_data = (GPIO){ "FSI_DATA" };
20GPIO fsi_clk = (GPIO){ "FSI_CLK" };
21GPIO fsi_enable = (GPIO){ "FSI_ENABLE" };
22GPIO cronus_sel = (GPIO){ "CRONUS_SEL" };
23GPIO Throttle = (GPIO){ "BMC_THROTTLE" };
24
25/* Bit bang patterns */
26
27//putcfam pu 281c 30000000 -p0 (Primary Side Select)
28static const char* primary = "000011111111110101111000111001100111111111111111111111111111101111111111";
29//putcfam pu 281c B0000000 -p0
30static const char* go = "000011111111110101111000111000100111111111111111111111111111101101111111";
31//putcfam pu 0x281c 30900000 (Golden Side Select)
32static const char* golden = "000011111111110101111000111001100111101101111111111111111111101001111111";
33
34/* Setup attentions */
35//putcfam pu 0x081C 20000000
36static const char* attnA = "000011111111111101111110001001101111111111111111111111111111110001111111";
37//putcfam pu 0x100D 40000000
38static const char* attnB = "000011111111111011111100101001011111111111111111111111111111110001111111";
39//putcfam pu 0x100B FFFFFFFF
40static const char* attnC = "000011111111111011111101001000000000000000000000000000000000001011111111";
41
42
43
44static gboolean
45on_init(Control *control,
46 GDBusMethodInvocation *invocation,
47 gpointer user_data)
48{
49 control_complete_init(control,invocation);
50 return TRUE;
51}
52
53int
54fsi_bitbang(const char* pattern)
55{
56 int rc=GPIO_OK;
57 int i;
58 for(i=0;i<strlen(pattern);i++) {
59 rc = gpio_writec(&fsi_data,pattern[i]);
60 if(rc!=GPIO_OK) { break; }
61 rc = gpio_clock_cycle(&fsi_clk,1);
62 if(rc!=GPIO_OK) { break; }
63 }
64 return rc;
65}
66
67int
68fsi_standby()
69{
70 int rc=GPIO_OK;
71 rc = gpio_write(&fsi_data,1);
72 if(rc!=GPIO_OK) { return rc; }
73 rc = gpio_clock_cycle(&fsi_clk,5000);
74 if(rc!=GPIO_OK) { return rc; }
75 return rc;
76}
77
78
79static gboolean
80on_boot(ControlHost *host,
81 GDBusMethodInvocation *invocation,
82 gpointer user_data)
83{
84 int rc = GPIO_OK;
85
86 if(control_host_get_debug_mode(host)==1)
87 {
88 g_print("Enabling debug mode; not booting host\n");
89 rc |= gpio_open(&fsi_enable);
90 rc |= gpio_open(&cronus_sel);
91 rc |= gpio_write(&fsi_enable,1);
92 rc |= gpio_write(&cronus_sel,0);
93 if(rc!=GPIO_OK) {
94 g_print("ERROR enabling debug mode: %d\n",rc);
95 }
96 return TRUE;
97 }
98 g_print("Booting host\n");
99 Control* control = object_get_control((Object*)user_data);
100 control_host_complete_boot(host,invocation);
101 do {
102 rc = gpio_open(&fsi_clk);
103 rc |= gpio_open(&fsi_data);
104 rc |= gpio_open(&fsi_enable);
105 rc |= gpio_open(&cronus_sel);
106 rc |= gpio_open(&Throttle);
107 if(rc!=GPIO_OK) { break; }
108
109 //setup dc pins
110 rc = gpio_write(&cronus_sel,1);
111 rc |= gpio_write(&fsi_enable,1);
112 rc |= gpio_write(&fsi_clk,1);
113 rc |= gpio_write(&Throttle,1);
114 if(rc!=GPIO_OK) { break; }
115
116 //data standy state
117 rc = fsi_standby();
118
119 //clear out pipes
120 rc |= gpio_write(&fsi_data,0);
121 rc |= gpio_clock_cycle(&fsi_clk,256);
122 rc |= gpio_write(&fsi_data,1);
123 rc |= gpio_clock_cycle(&fsi_clk,50);
124 if(rc!=GPIO_OK) { break; }
125
126 rc = fsi_bitbang(attnA);
127 rc |= fsi_standby();
128
129 rc |= fsi_bitbang(attnB);
130 rc |= fsi_standby();
131
132 rc |= fsi_bitbang(attnC);
133 rc |= fsi_standby();
134 if(rc!=GPIO_OK) { break; }
135
136 const gchar* flash_side = control_host_get_flash_side(host);
137 g_print("Using %s side of the bios flash\n",flash_side);
138 if(strcmp(flash_side,"primary")==0) {
139 rc |= fsi_bitbang(primary);
140 } else if(strcmp(flash_side,"golden") == 0) {
141 rc |= fsi_bitbang(golden);
142 } else {
143 g_print("ERROR: Invalid flash side: %s\n",flash_side);
144 rc = 0xff;
145
146 }
147 rc |= fsi_standby();
148 if(rc!=GPIO_OK) { break; }
149
150 rc = fsi_bitbang(go);
151
152 rc |= gpio_write(&fsi_data,1); /* Data standby state */
153 rc |= gpio_clock_cycle(&fsi_clk,2);
154
155 rc |= gpio_write(&fsi_clk,0); /* hold clk low for clock mux */
156 rc |= gpio_write(&fsi_enable,0);
157 rc |= gpio_clock_cycle(&fsi_clk,16);
158 rc |= gpio_write(&fsi_clk,0); /* Data standby state */
159
160 } while(0);
161 if(rc != GPIO_OK)
162 {
163 g_print("ERROR HostControl: GPIO sequence failed (rc=%d)\n",rc);
164 } else {
165 control_emit_goto_system_state(control,"HOST_BOOTING");
166 }
167 gpio_close(&fsi_clk);
168 gpio_close(&fsi_data);
169 gpio_close(&fsi_enable);
170 gpio_close(&cronus_sel);
171 gpio_close(&Throttle);
172
173 control_host_emit_booted(host);
174 return TRUE;
175}
176
177static void
178on_bus_acquired(GDBusConnection *connection,
179 const gchar *name,
180 gpointer user_data)
181{
182 ObjectSkeleton *object;
183 //g_print ("Acquired a message bus connection: %s\n",name);
Brad Bishop77390492016-04-13 10:47:19 -0400184 manager = g_dbus_object_manager_server_new(dbus_object_path);
185
186 gchar *s;
187 s = g_strdup_printf("%s/%s",dbus_object_path,instance_name);
188 object = object_skeleton_new(s);
189 g_free(s);
190
191 ControlHost* control_host = control_host_skeleton_new();
192 object_skeleton_set_control_host(object, control_host);
193 g_object_unref(control_host);
194
195 Control* control = control_skeleton_new();
196 object_skeleton_set_control(object, control);
197 g_object_unref(control);
198
Brad Bishop77390492016-04-13 10:47:19 -0400199 //define method callbacks here
200 g_signal_connect(control_host,
201 "handle-boot",
202 G_CALLBACK(on_boot),
203 object); /* user_data */
204 g_signal_connect(control,
205 "handle-init",
206 G_CALLBACK(on_init),
207 NULL); /* user_data */
208
209 control_host_set_debug_mode(control_host,0);
210 control_host_set_flash_side(control_host,"primary");
211
212 /* Export the object (@manager takes its own reference to @object) */
Brad Bishop58e694d2016-04-13 16:04:32 -0400213 g_dbus_object_manager_server_set_connection(manager, connection);
Brad Bishop77390492016-04-13 10:47:19 -0400214 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object));
215 g_object_unref(object);
216
Brad Bishop77390492016-04-13 10:47:19 -0400217 gpio_init(connection,&fsi_data);
218 gpio_init(connection,&fsi_clk);
219 gpio_init(connection,&fsi_enable);
220 gpio_init(connection,&cronus_sel);
221 gpio_init(connection,&Throttle);
Brad Bishop77390492016-04-13 10:47:19 -0400222}
223
224static void
225on_name_acquired(GDBusConnection *connection,
226 const gchar *name,
227 gpointer user_data)
228{
229 // g_print ("Acquired the name %s\n", name);
230}
231
232static void
233on_name_lost(GDBusConnection *connection,
234 const gchar *name,
235 gpointer user_data)
236{
237 // g_print ("Lost the name %s\n", name);
238}
239
240gint
241main(gint argc, gchar *argv[])
242{
243 GMainLoop *loop;
244 cmdline cmd;
245 cmd.argc = argc;
246 cmd.argv = argv;
247
248 guint id;
249 loop = g_main_loop_new(NULL, FALSE);
250
251 id = g_bus_own_name(DBUS_TYPE,
252 dbus_name,
253 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
254 G_BUS_NAME_OWNER_FLAGS_REPLACE,
255 on_bus_acquired,
256 on_name_acquired,
257 on_name_lost,
258 &cmd,
259 NULL);
260
261 g_main_loop_run(loop);
262
263 g_bus_unown_name(id);
264 g_main_loop_unref(loop);
265 return 0;
266}