summaryrefslogtreecommitdiff
path: root/common/bootstage.c
diff options
context:
space:
mode:
authorDa Zheng <zhengda@google.com>2011-08-08 15:05:44 -0700
committerSimon Glass <sjg@chromium.org>2011-08-29 10:59:32 -0700
commit2be0791847a37a3203b760443a1514a0ead82fbf (patch)
tree9986d1181c79a887c2d521139708f2692316457b /common/bootstage.c
parentb5330c3bc3e2d2240a1d79c6b084d3de0e199d95 (diff)
save boot timing in the device tree.
BUG=chromium-os:18126 TEST=run "cat /sys/kernel/debug/bootstage/report" in chromeos to see the boot timing of u-boot. Change-Id: Ie7b2677f2df58ae80305989ebe79cbe9f5c142fe Reviewed-on: http://gerrit.chromium.org/gerrit/5504 Tested-by: Da Zheng <zhengda@chromium.org> Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'common/bootstage.c')
-rw-r--r--common/bootstage.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/common/bootstage.c b/common/bootstage.c
index 6c0805d4ec..a6f17ee237 100644
--- a/common/bootstage.c
+++ b/common/bootstage.c
@@ -28,6 +28,7 @@
*/
#include <common.h>
+#include <libfdt.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -84,6 +85,87 @@ static int h_compare_record(const void *r1, const void *r2)
return rec1->time_us - rec2->time_us;
}
+#define BOOTSTAGE_NODE "bootstage"
+
+/**
+ * This function add a new node to the device tree.
+ *
+ * @param pathp the path where the new node is added.
+ * @param nodep the name of the new node
+ * @return 0 on success, != 0 on failure.
+ */
+static int add_new_node(struct fdt_header *fdt,
+ const char *pathp, const char *nodep)
+{
+ int nodeoffset;
+ int err;
+
+ nodeoffset = fdt_path_offset(fdt, pathp);
+ if (nodeoffset < 0)
+ return nodeoffset;
+ err = fdt_add_subnode(working_fdt, nodeoffset, nodep);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+/**
+ * this function add all bootstage timings to the device tree.
+ *
+ * @param fdt the point to the device tree.
+ * @return 0 on success, != 0 on failure.
+ */
+static int add_bootstages_devicetree(struct fdt_header *fdt)
+{
+ int id;
+ int i;
+ int ret = 0;
+
+ if (fdt == NULL)
+ return 0;
+
+ /*
+ * Create the node for bootstage.
+ * The address of flat device tree is set up by the command bootm.
+ */
+ ret = add_new_node(fdt, "/", BOOTSTAGE_NODE);
+
+ /*
+ * insert the timings to the device tree in the reverse order,
+ * so that they can be printed in the Linux kernel in the right order.
+ */
+ for (id = BOOTSTAGE_COUNT - 1, i = 0; id >= 0 && ret == 0; id--) {
+ struct bootstage_record *rec = &record[id];
+ static char path[32];
+ static char node[8];
+ int nodeoffset;
+
+ sprintf(path, "/%s/", BOOTSTAGE_NODE);
+ if (id != BOOTSTAGE_AWAKE && rec->time_us == 0)
+ continue;
+
+ sprintf(node, "%d", i);
+ if ((ret = add_new_node(fdt, path, node)))
+ break;
+
+ /* add properties to the node. */
+ strncat(path, node, sizeof(path) - strlen(path));
+ nodeoffset = fdt_path_offset(fdt, path);
+ if (nodeoffset < 0)
+ ret = nodeoffset;
+ if (!ret)
+ ret = fdt_setprop_string(fdt, nodeoffset, "name", rec->name);
+ if (!ret)
+ ret = fdt_setprop_cell(fdt, nodeoffset, "time", rec->time_us);
+
+ i++;
+ }
+ if (ret)
+ printf("add_bootstages: failed to add to device tree\n");
+ return ret;
+}
+
void bootstage_report(void)
{
struct bootstage_record *rec = record;
@@ -108,6 +190,9 @@ void bootstage_report(void)
if (rec->time_us != 0)
prev = print_time_record(id, rec, prev);
}
+
+ add_bootstages_devicetree(working_fdt);
+
if (flags & GD_FLG_SILENT)
gd->flags |= GD_FLG_SILENT;
}