blob: 33b1bb32f117554f93378507c186dea8c3612d73 [file] [log] [blame]
Brad Bishopc9ed7202019-06-14 12:33:18 -04001From b6b1cda6a526bad8c7f50aa4427bedbc6e539a4d Mon Sep 17 00:00:00 2001
2From: Artem Senichev <a.senichev@yadro.com>
3Date: Fri, 23 Nov 2018 10:31:59 +0300
4Subject: [PATCH] Replace ColdFire FSI with plain FSI-over-GPIO
5
6Workaround to fix ColdFire FSI performance issue:
7https://github.com/openbmc/openbmc/issues/3433
8Current implementation based on an old version of skeleton
9(revision 517b35ed92ad2c0df5e048711c175bacb632f6d0), mostly it's
10a copy-paste of op-hostctl module.
11
12Signed-off-by: Artem Senichev <a.senichev@yadro.com>
13Signed-off-by: Alexander Filippov <a.filippov@yadro.com>
14---
15 control_host_obj.c | 259 ++++++++++++++++++++--------------
16 1 file changed, 152 insertions(+), 107 deletions(-)
17
18diff --git a/control_host_obj.c b/control_host_obj.c
19index 27f7fc7..ca45182 100644
20--- a/control_host_obj.c
21+++ b/control_host_obj.c
22@@ -5,10 +5,10 @@
23 #include <unistd.h>
24 #include <sys/stat.h>
25 #include <sys/mman.h>
26-#include <errno.h>
27-
28 #include <openbmc_intf.h>
29 #include <openbmc.h>
30+#include <gpio.h>
31+#include <gpio_configs.h>
32
33 /* ------------------------------------------------------------------------- */
34 static const gchar* dbus_object_path = "/org/openbmc/control";
35@@ -17,36 +17,31 @@ static const gchar* dbus_name = "org.openbmc.control.Host";
36
37 static GDBusObjectManagerServer *manager = NULL;
38
39-#define PPC_BIT32(bit) (0x80000000UL >> (bit))
40-
41-#define FSI_EXTERNAL_MODE_PATH "/sys/devices/platform/gpio-fsi/external_mode"
42-#define FSI_SCAN_PATH "/sys/devices/platform/gpio-fsi/fsi0/rescan"
43-
44-/* TODO: Change this over to the cfam path once the cfam chardev patches have landed */
45-#define FSI_RAW_PATH "/sys/devices/platform/gpio-fsi/fsi0/slave@00:00/raw"
46-
47-#define FSI_SCAN_DELAY_US 10000
48+static GPIO* fsi_data;
49+static GPIO* fsi_clk;
50+static GPIO* fsi_enable;
51+static GPIO* cronus_sel;
52+static size_t num_optionals;
53+static GPIO* optionals;
54+static gboolean* optional_pols;
55
56-/* Attention registers */
57-#define FSI_A_SI1S 0x081c
58-#define TRUE_MASK 0x100d
59-#define INTERRUPT_STATUS_REG 0x100b
60+/* Bit bang patterns */
61
62-/* SBE boot register and values */
63-#define SBE_VITAL 0x281c
64-#define SBE_WARMSTART PPC_BIT32(0)
65-#define SBE_HW_TRIGGER PPC_BIT32(2)
66-#define SBE_UPDATE_1ST_NIBBLE PPC_BIT32(3)
67-#define SBE_IMAGE_SELECT PPC_BIT32(8)
68-#define SBE_UPDATE_3RD_NIBBLE PPC_BIT32(11)
69+//putcfam pu 281c 30000000 -p0 (Primary Side Select)
70+static const char* primary = "000011111111110101111000111001100111111111111111111111111111101111111111";
71+//putcfam pu 281c B0000000 -p0
72+static const char* go = "000011111111110101111000111000100111111111111111111111111111101101111111";
73+//putcfam pu 0x281c 30900000 (Golden Side Select)
74+static const char* golden = "000011111111110101111000111001100111101101111111111111111111101001111111";
75
76-/* Once the side is selected and attention bits are set, this starts the SBE */
77-#define START_SBE (SBE_WARMSTART | SBE_HW_TRIGGER | SBE_UPDATE_1ST_NIBBLE)
78+/* Setup attentions */
79+//putcfam pu 0x081C 20000000
80+static const char* attnA = "000011111111111101111110001001101111111111111111111111111111110001111111";
81+//putcfam pu 0x100D 40000000
82+static const char* attnB = "000011111111111011111100101001011111111111111111111111111111110001111111";
83+//putcfam pu 0x100B FFFFFFFF
84+static const char* attnC = "000011111111111011111101001000000000000000000000000000000000001011111111";
85
86-/* Primary is first side. Golden is second side */
87-#define PRIMARY_SIDE (SBE_HW_TRIGGER | SBE_UPDATE_1ST_NIBBLE)
88-#define GOLDEN_SIDE (SBE_HW_TRIGGER | SBE_UPDATE_1ST_NIBBLE | \
89- SBE_IMAGE_SELECT | SBE_UPDATE_3RD_NIBBLE)
90
91 static gboolean
92 on_init(Control *control,
93@@ -57,126 +52,147 @@ on_init(Control *control,
94 return TRUE;
95 }
96
97-static gint
98-fsi_putcfam(int fd, uint64_t addr64, uint32_t val_host)
99+int gpio_clock_cycle(GPIO* gpio, int num_clks)
100 {
101- int rc;
102- uint32_t val = htobe32(val_host);
103- /* Map FSI to FSI_BYTE, as the 'raw' kernel interface expects this */
104- uint32_t addr = (addr64 & 0x7ffc00) | ((addr64 & 0x3ff) << 2);
105-
106- rc = lseek(fd, addr, SEEK_SET);
107- if (rc < 0) {
108- g_print("ERROR HostControl: cfam seek failed (0x%08x): %s\n", addr,
109- strerror(errno));
110- return errno;
111- };
112-
113- rc = write(fd, &val, sizeof(val));
114- if (rc < 0) {
115- g_print("ERROR HostControl: cfam write failed: %s\n",
116- strerror(errno));
117- return errno;
118- }
119-
120- return 0;
121+ g_assert(gpio != NULL);
122+ int i = 0;
123+ int r = GPIO_OK;
124+ for (i = 0; i < num_clks; i++)
125+ {
126+ if (gpio_write(gpio, 0) == -1)
127+ {
128+ r = GPIO_WRITE_ERROR;
129+ break;
130+ }
131+ if (gpio_write(gpio, 1) == -1)
132+ {
133+ r = GPIO_WRITE_ERROR;
134+ break;
135+ }
136+ }
137+
138+ return r;
139 }
140
141-static int fsi_rescan(void)
142+int
143+fsi_bitbang(const char* pattern)
144 {
145- char *one = "1";
146- int fd, rc;
147-
148- fd = open(FSI_SCAN_PATH, O_WRONLY);
149- if (fd < 0) {
150- g_print("ERROR HostControl: Failed to open path '%s': %s\n",
151- FSI_SCAN_PATH, strerror(errno));
152- return errno;
153- }
154- rc = write(fd, one, sizeof(one));
155- close(fd);
156- if (rc < 0) {
157- g_print("ERROR HostControl: Failed to perform FSI scan: %s\n",
158- strerror(errno));
159- return errno;
160+ int rc=GPIO_OK;
161+ int i;
162+ for(i=0;i<strlen(pattern);i++) {
163+ rc = gpio_write(fsi_data,pattern[i] - '0');
164+ if(rc!=GPIO_OK) { break; }
165+ rc = gpio_clock_cycle(fsi_clk,1);
166+ if(rc!=GPIO_OK) { break; }
167 }
168- g_print("HostControl: Performing FSI scan (delay %d us)\n",
169- FSI_SCAN_DELAY_US);
170- usleep(FSI_SCAN_DELAY_US);
171+ return rc;
172+}
173
174- return 0;
175+int
176+fsi_standby()
177+{
178+ int rc=GPIO_OK;
179+ rc = gpio_write(fsi_data,1);
180+ if(rc!=GPIO_OK) { return rc; }
181+ rc = gpio_clock_cycle(fsi_clk,5000);
182+ if(rc!=GPIO_OK) { return rc; }
183+ return rc;
184 }
185
186+
187 static gboolean
188 on_boot(ControlHost *host,
189 GDBusMethodInvocation *invocation,
190 gpointer user_data)
191 {
192- int rc, cfam_fd;
193+ int rc = GPIO_OK;
194 GDBusProxy *proxy;
195 GError *error = NULL;
196 GDBusConnection *connection =
197 g_dbus_object_manager_server_get_connection(manager);
198
199+ if (!(fsi_data && fsi_clk && fsi_enable && cronus_sel)) {
200+ g_print("ERROR invalid GPIO configuration, will not boot\n");
201+ return FALSE;
202+ }
203 if(control_host_get_debug_mode(host)==1) {
204- int fd;
205- char *one = "1";
206 g_print("Enabling debug mode; not booting host\n");
207- fd = open(FSI_EXTERNAL_MODE_PATH, O_RDWR);
208- if (fd < 0) {
209- g_print("ERROR HostControl: Failed to open path '%s'\n",
210- FSI_EXTERNAL_MODE_PATH);
211- return TRUE;
212+ rc |= gpio_open(fsi_enable, 1);
213+ rc |= gpio_open(cronus_sel, 0);
214+ if(rc!=GPIO_OK) {
215+ g_print("ERROR enabling debug mode: %d\n",rc);
216 }
217- rc = write(fd, one, sizeof(one));
218- if (rc < 0) {
219- g_print("ERROR HostControl: Failed to enable debug mode '%s'\n",
220- FSI_EXTERNAL_MODE_PATH);
221- }
222- close(fd);
223 return TRUE;
224 }
225 g_print("Booting host\n");
226-
227- rc = fsi_rescan();
228- if (rc < 0)
229- return FALSE;
230-
231- cfam_fd = open(FSI_RAW_PATH, O_RDWR);
232- if (cfam_fd < 0) {
233- g_print("ERROR HostControl: Failed to open '%s'\n", FSI_RAW_PATH);
234- return FALSE;
235- }
236-
237 Control* control = object_get_control((Object*)user_data);
238 control_host_complete_boot(host,invocation);
239 do {
240- rc = fsi_putcfam(cfam_fd, FSI_A_SI1S, 0x20000000);
241- rc |= fsi_putcfam(cfam_fd, TRUE_MASK, 0x40000000);
242- rc |= fsi_putcfam(cfam_fd, INTERRUPT_STATUS_REG, 0xFFFFFFFF);
243- if(rc) { break; }
244+ rc = gpio_open(fsi_clk, 1);
245+ rc |= gpio_open(fsi_data, 0);
246+ rc |= gpio_open(fsi_enable, 1);
247+ rc |= gpio_open(cronus_sel, 1);
248+ for (size_t i = 0; i < num_optionals; ++i) {
249+ rc |= gpio_open(&optionals[i], optional_pols[i]);
250+ }
251+ if(rc!=GPIO_OK) { break; }
252+
253+ //data standy state
254+ rc = fsi_standby();
255+
256+ //clear out pipes
257+ rc |= gpio_write(fsi_data,0);
258+ rc |= gpio_clock_cycle(fsi_clk,256);
259+ rc |= gpio_write(fsi_data,1);
260+ rc |= gpio_clock_cycle(fsi_clk,50);
261+ if(rc!=GPIO_OK) { break; }
262+
263+ rc = fsi_bitbang(attnA);
264+ rc |= fsi_standby();
265+
266+ rc |= fsi_bitbang(attnB);
267+ rc |= fsi_standby();
268+
269+ rc |= fsi_bitbang(attnC);
270+ rc |= fsi_standby();
271+ if(rc!=GPIO_OK) { break; }
272
273 const gchar* flash_side = control_host_get_flash_side(host);
274 g_print("Using %s side of the bios flash\n",flash_side);
275 if(strcmp(flash_side,"primary")==0) {
276- rc |= fsi_putcfam(cfam_fd, SBE_VITAL, PRIMARY_SIDE);
277+ rc |= fsi_bitbang(primary);
278 } else if(strcmp(flash_side,"golden") == 0) {
279- rc |= fsi_putcfam(cfam_fd, SBE_VITAL, GOLDEN_SIDE);
280+ rc |= fsi_bitbang(golden);
281 } else {
282 g_print("ERROR: Invalid flash side: %s\n",flash_side);
283 rc = 0xff;
284
285 }
286- if(rc) { break; }
287+ rc |= fsi_standby();
288+ if(rc!=GPIO_OK) { break; }
289+
290+ rc = fsi_bitbang(go);
291+
292+ rc |= gpio_write(fsi_data,1); /* Data standby state */
293+ rc |= gpio_clock_cycle(fsi_clk,2);
294+
295+ rc |= gpio_write(fsi_clk,0); /* hold clk low for clock mux */
296+ rc |= gpio_write(fsi_enable,0);
297+ rc |= gpio_clock_cycle(fsi_clk,16);
298+ rc |= gpio_write(fsi_clk,0); /* Data standby state */
299
300- rc = fsi_putcfam(cfam_fd, SBE_VITAL, START_SBE);
301 } while(0);
302- if(rc)
303+ if(rc != GPIO_OK)
304 {
305- g_print("ERROR HostControl: SBE sequence failed (rc=%d)\n",rc);
306+ g_print("ERROR HostControl: GPIO sequence failed (rc=%d)\n",rc);
307+ }
308+ gpio_close(fsi_clk);
309+ gpio_close(fsi_data);
310+ gpio_close(fsi_enable);
311+ gpio_close(cronus_sel);
312+ for (size_t i = 0; i < num_optionals; ++i) {
313+ gpio_close(&optionals[i]);
314 }
315- /* Close file descriptor */
316- close(cfam_fd);
317
318 control_host_emit_booted(host);
319
320@@ -222,6 +238,35 @@ on_bus_acquired(GDBusConnection *connection,
321 g_dbus_object_manager_server_set_connection(manager, connection);
322 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object));
323 g_object_unref(object);
324+
325+ // We don't free allocated memory as the service is a singleton,
326+ // this function can be called only once and these GPIO objects
327+ // have a process lifetime.
328+ fsi_data = malloc(sizeof(GPIO));
329+ fsi_data->name = g_strdup("FSI_DATA"); // GPIO struct has non-const char pointer
330+ fsi_clk = malloc(sizeof(GPIO));
331+ fsi_clk->name = g_strdup("FSI_CLK");
332+ fsi_enable = malloc(sizeof(GPIO));
333+ fsi_enable->name = g_strdup("FSI_ENABLE");
334+ cronus_sel = malloc(sizeof(GPIO));
335+ cronus_sel->name = g_strdup("CRONUS_SEL");
336+
337+ // WARNING: This portion of the hardcode is usable only with VESNIN.
338+ // For the upstream, it should be rewritten for reading this data from the
339+ // JSON file.
340+ num_optionals = 1;
341+ optionals = malloc(sizeof(GPIO));
342+ optionals->name = g_strdup("CP0_FSI0_DATA_EN");
343+ optional_pols = malloc(sizeof(gboolean));
344+ optional_pols[0] = TRUE;
345+
346+ gpio_get_params(fsi_data);
347+ gpio_get_params(fsi_clk);
348+ gpio_get_params(fsi_enable);
349+ gpio_get_params(cronus_sel);
350+ for (int i = 0; i < num_optionals; ++i) {
351+ gpio_get_params(&optionals[i]);
352+ }
353 }
354
355 static void
356--
3572.20.1
358