From: Eric van Tassell <evt@evtM17x.(none)>

---
 Android.mk   |    4 +-
 Makefile     |    4 +-
 dirtree.c    |  149 ++++++++++++++++++++++++++++++++++++++++++++
 dirtree.h    |   22 +++++++
 display.c    |   12 ++++
 display.h    |    4 +-
 powerdebug.c |    1 +
 tree.c       |   28 +++++++++
 tree.h       |   11 +++-
 tree_mgr.c   |  197 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tree_mgr.h   |   25 ++++++++
 utils.c      |   58 +++++++++++++++++
 utils.h      |    3 +
 13 files changed, 511 insertions(+), 7 deletions(-)
 create mode 100644 dirtree.c
 create mode 100644 dirtree.h
 create mode 100644 tree_mgr.c
 create mode 100644 tree_mgr.h

diff --git a/Android.mk b/Android.mk
index 7bf67dc..d67317f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -28,7 +28,7 @@ LOCAL_C_INCLUDES += external/stlport/stlport/ \
                                        external/ncurses/include/ncurses
 
 LOCAL_SRC_FILES += \
-       powerdebug.c sensor.c clocks.c regulator.c gpio.c regfield.c\
-       display.c tree.c utils.c mainloop.c delimi.c mmioreg.c
+       powerdebug.c sensor.c clocks.c regulator.c gpio.c regfield.c dirtree.c \
+       display.c tree.c utils.c mainloop.c delimi.c mmioreg.c tree_mgr.c
 
 include $(BUILD_EXECUTABLE)
diff --git a/Makefile b/Makefile
index e7e3f20..b04749e 100644
--- a/Makefile
+++ b/Makefile
@@ -4,8 +4,8 @@ MANDIR=/usr/share/man/man8
 CFLAGS?=-O1 -g -Wall -Wshadow
 CC?=gcc
 
-OBJS = powerdebug.o sensor.o clocks.o regulator.o gpio.o regfield.o\
-       display.o tree.o utils.o mainloop.o delimi.o mmioreg.o
+OBJS = powerdebug.o sensor.o clocks.o regulator.o gpio.o regfield.o dirtree.o \
+       display.o tree.o utils.o mainloop.o delimi.o mmioreg.o tree_mgr.o
 
 default: powerdebug
 
diff --git a/dirtree.c b/dirtree.c
new file mode 100644
index 0000000..a630f14
--- /dev/null
+++ b/dirtree.c
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright (C) 2012, Linaro Limited.
+ *
+ * This file is part of PowerDebug.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Eric van Tassell
+ *       - initial API and implementation
+ 
******************************************************************************/
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#undef _GNU_SOURCE
+#include <sys/types.h>
+#include <stdbool.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include "display.h"
+#include "tree.h"
+#include "utils.h"
+#include "delimi.h"
+#include "dirtree.h"
+#include "regfield.h"
+
+/*
+ * This function takes the path to a config file that defines the heirarchy
+ * of memory mapped registers. ex: root -> power-domain -> register -> field
+ *
+ * This approach is taken to avoid creating tons of architecture specific
+ * debugfs files
+ *
+ * @tree : a path to the topmost directory path
+ * Returns a tree structure corresponding to the root node of the
+ * directory tree representation on success, NULL otherwise
+ */
+struct tree *tree_load_file(const char *cfg_file_path)
+{
+       struct tree *tree;
+       struct tree *node_stack[MAX_TREE_DEPTH];
+       struct tree *node;
+       int sp = 0;
+       FILE *fp;
+       char buf[MAX_LINE_LENGTH];
+       char *cfg_field;
+       char new_path[MAX_LINE_LENGTH];
+       struct tree *(*alloc)(const char *path, int depth);
+       void (*add_child)(struct tree *parent, struct tree *child);
+       struct delim_iterator *delimi;
+       struct parser_ctl *parser_ctl = &regfield_parsers;
+
+       get_tree_cbs(&alloc, &add_child);
+       if ((alloc == NULL) || (add_child == NULL))
+               BAIL_OUT(("cannnot determine alloc or add_child callbacks"));
+
+       memset(node_stack, 0, sizeof(node_stack));
+
+       tree = alloc("/", sp);
+       if (!tree)
+               return NULL;
+
+       node_stack[sp] = tree;
+
+       fp = fopen(cfg_file_path, "r");
+       if (!fp)
+               BAIL_OUT(("Cannot open config file: %s\n", cfg_file_path));
+
+       memset(buf, 0, sizeof(buf));
+
+       while (fgets(buf, sizeof(buf), fp)) {
+               if (*buf == '#')
+                       continue;
+               delimi = delimi_new(buf, ',');
+               if (delimi == NULL)
+                       BAIL_OUT(("NULL delim_iterator_t *"));
+
+               if (!strncmp(buf, "push", strlen("push"))) {
+                       char path[MAX_LINE_LENGTH];
+
+                       if (sp == MAX_TREE_DEPTH - 1) {
+                               printf("push - max tree depth reached\n");
+                               exit(0);
+                       }
+
+                       memset(path, 0, sizeof(path));
+                       sscanf(buf, "push, %s\n", path);
+                       if (sp == 0)
+                               sprintf(new_path, "%s%s",
+                                       node_stack[sp]->path,
+                                       path);
+                       else
+                               sprintf(new_path,
+                                       "%s/%s",
+                                       node_stack[sp]->path,
+                                       path);
+
+                       sp++;
+                       node_stack[sp] = alloc(new_path, sp);
+                       add_child(node_stack[sp - 1], node_stack[sp]);
+               } else if (!strncmp(buf, "pop", strlen("pop"))) {
+                       if (sp == 0) {
+                               printf("illegal - cant pop the root node\n");
+                               exit(0);
+                       }
+                       sp--;
+               } else {
+                       int i;
+                       int parser_found = 0;
+
+                       for (i = 0; i < parser_ctl->num_parsers; i++) {
+                               struct parser_descriptor *pd;
+
+                               pd = &(parser_ctl->descriptors[i]);
+                               if (!strncmp(buf, pd->verb, strlen(pd->verb))) {
+                                       void *pvdata;
+                                       char *name;
+
+                                       parser_found = 1;
+                                       pvdata = (pd->parser)(delimi, &name);
+                                       if (pvdata) {
+                                               sprintf(new_path, "%s/%s",
+                                                       node_stack[sp]->path,
+                                                       name);
+                                               node = alloc(new_path, sp + 1);
+                                               if (!node)
+                                                       BAIL_OUT(("NULL node"));
+
+                                               node->private = pvdata;
+                                               add_child(node_stack[sp], node);
+                                       }
+                                       break;
+                               }
+                       }
+                       if (!parser_found)
+                               BAIL_OUT(("illegal config line:%s\n", buf));
+               }
+               delimi_free(delimi);
+               memset(buf, 0, sizeof(buf));
+       }
+       return tree;
+}
diff --git a/dirtree.h b/dirtree.h
new file mode 100644
index 0000000..57abb98
--- /dev/null
+++ b/dirtree.h
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (C) 2012, Linaro Limited.
+ *
+ * This file is part of PowerDebug.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Eric van Tassell
+ *       - initial API and implementation
+ 
******************************************************************************/
+
+#define MAX_TREE_DEPTH 8
+#define MAX_LINE_LENGTH 255
+
+typedef void (*p_parser)(struct delim_iterator *, char **);
+
+/* prototypes */
+struct tree *tree_load_file(const char *cfg_file_path);
diff --git a/display.c b/display.c
index f06387c..fcb4ec1 100644
--- a/display.c
+++ b/display.c
@@ -24,6 +24,7 @@
 #include "mainloop.h"
 #include "regulator.h"
 #include "display.h"
+#include "utils.h"
 
 enum { PT_COLOR_DEFAULT = 1,
        PT_COLOR_HEADER_BAR,
@@ -52,6 +53,7 @@ struct windata {
        WINDOW *pad;
        struct display_ops *ops;
        struct rowdata *rowdata;
+       void *pvdata;
        char *name;
        int nrdata;
        int scrolling;
@@ -600,3 +602,13 @@ int display_register(int win, struct display_ops *ops)
 
        return 0;
 }
+
+int display_register_ex(int win, struct display_ops *ops, void *v)
+{
+       if (display_register(win, ops))
+               return -1;
+
+       windata[win].pvdata = v;
+       printf("%s: win = %d, v = %p\n", __func__, win, v);
+       return 0;
+}
diff --git a/display.h b/display.h
index 6362a48..d469a66 100644
--- a/display.h
+++ b/display.h
@@ -13,10 +13,9 @@
  *       - initial API and implementation
  
*******************************************************************************/
 
-enum { CLOCK, REGULATOR, SENSOR, GPIO };
-
 struct display_ops {
        int (*display)(bool refresh);
+       int (*display_ex)(bool refresh, void *v);
        int (*select)(void);
        int (*find)(const char *);
        int (*selectf)(void);
@@ -31,6 +30,7 @@ extern void *display_get_row_data(int window);
 
 extern int display_init(int wdefault);
 extern int display_register(int win, struct display_ops *ops);
+extern int display_register_ex(int win, struct display_ops *ops, void *v);
 extern int display_column_name(const char *line);
 
 #define NAME_MAX 255
diff --git a/powerdebug.c b/powerdebug.c
index cc9e871..0f15b38 100644
--- a/powerdebug.c
+++ b/powerdebug.c
@@ -27,6 +27,7 @@
 #include "gpio.h"
 #include "mainloop.h"
 #include "powerdebug.h"
+#include "utils.h"
 
 void usage(void)
 {
diff --git a/tree.c b/tree.c
index d331c60..d4ada79 100644
--- a/tree.c
+++ b/tree.c
@@ -229,6 +229,34 @@ int tree_for_each(struct tree *tree, tree_cb_t cb, void 
*data)
 }
 
 /*
+ * provide callbacks to allow external tree composers to be built without
+ * polluting this file with application specific code
+ */
+void get_tree_cbs(struct tree *(**alloc)(const char *path, int depth),
+                 void (**add_child)(struct tree *parent, struct tree *child))
+{
+       if ((alloc == NULL) || (add_child == NULL))
+               return;
+       *alloc     = tree_alloc;
+       *add_child = tree_add_child;
+}
+
+/* same as above but pass an integer to each cb */
+int tree_for_each_ex(struct tree *tree, tree_cb_ex_t cb, void *data, int ix)
+{
+       if (!tree)
+               return 0;
+
+       if (cb(tree, data, ix))
+               return -1;
+
+       if (tree_for_each_ex(tree->child, cb, data, ix))
+               return -1;
+
+       return tree_for_each_ex(tree->next, cb, data, ix);
+}
+
+/*
  * This function will go over the tree passed as parameter at the reverse
  * order and will call the callback passed as parameter for each.
  * @tree : the lower node where we begin to browse the tree at the reverse
diff --git a/tree.h b/tree.h
index 5c1c697..9a6649c 100644
--- a/tree.h
+++ b/tree.h
@@ -11,7 +11,7 @@
  * Author:
  *     Daniel Lezcano <daniel.lezc...@linaro.org>
  *
- 
*******************************************************************************/
+ 
******************************************************************************/
 
 /*
  * Structure describing a node of the clock tree
@@ -40,6 +40,7 @@ struct tree {
 typedef int (*tree_cb_t)(struct tree *t, void *data);
 
 typedef int (*tree_filter_t)(const char *name);
+typedef int (*tree_cb_ex_t)(struct tree *t, void *data, int ix);
 
 extern struct tree *tree_load(const char *path, tree_filter_t filter, bool 
follow);
 
@@ -47,8 +48,16 @@ extern struct tree *tree_find(struct tree *tree, const char 
*name);
 
 extern int tree_for_each(struct tree *tree, tree_cb_t cb, void *data);
 
+extern int tree_for_each_ex(struct tree *tree,
+                           tree_cb_ex_t cb,
+                           void *data,
+                           int ix);
+
 extern int tree_for_each_reverse(struct tree *tree, tree_cb_t cb, void *data);
 
 extern int tree_for_each_parent(struct tree *tree, tree_cb_t cb, void *data);
 
 extern int tree_finds(struct tree *tree, const char *name, struct tree ***ptr);
+
+void get_tree_cbs(struct tree *(**alloc)(const char *path, int depth),
+                 void (**add_child)(struct tree *parent, struct tree *child));
diff --git a/tree_mgr.c b/tree_mgr.c
new file mode 100644
index 0000000..9588a2a
--- /dev/null
+++ b/tree_mgr.c
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ * Copyright (C) 2012, Linaro Limited.
+ *
+ * This file is part of PowerDebug.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Eric van Tassell
+ *       - initial API and implementation
+ 
******************************************************************************/
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#undef _GNU_SOURCE
+#include <sys/types.h>
+#include <stdbool.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include "display.h"
+#include "tree_mgr.h"
+#include "tree.h"
+#include "utils.h"
+#include "delimi.h"
+#include "dirtree.h"
+#include "regfield.h"
+
+static int tree_mgr_dump_cb(struct tree *t, void *data)
+{
+       int i;
+       if (t->depth == 0)
+               return 0;
+
+       for (i = 1; i < t->depth; i++)
+               printf("\t");
+       printf("%s\n", t->name);
+       if (t->private) {
+               struct field_def *f = (struct field_def *) t->private;
+
+               for (i = 1; i < t->depth; i++)
+                       printf("\t");
+               if (f->decoder)
+                       printf("\t0x%x(%s)\n", f->value, field_decode(f));
+               else
+                       printf("\t0x%x\n", f->value);
+       }
+       return 0;
+}
+
+int tree_mgr_dump(struct tree_mgr *t)
+{
+       printf("%s", t->dump_header);
+
+       return tree_for_each(t->tree, tree_mgr_dump_cb, NULL);
+}
+
+static int tree_mgr_read_cb(struct tree *t, void *data)
+{
+       if (!t)
+               BAIL_OUT(("bad tree"));
+
+       field_read((struct field_def *) t->private);
+       return 0;
+}
+
+static int tree_mgr_fill_cb(struct tree *t, void *data)
+{
+       if (t->private)
+               return tree_mgr_read_cb(t, data);
+       else
+               return 0;
+}
+
+#ifdef DEBUG_PARSE
+static int tree_mgr_dump_debug_cb(struct tree *t, void *data)
+{
+       printf("%s: name = %s, depth = %d, private = %p, path = %s\n",
+              __func__,
+              t->name,
+              t->depth,
+              t->private,
+              t->path);
+       return 0;
+}
+#endif /* DEBUG_PARSE */
+
+static int tree_mgr_fill_tree(struct tree_mgr *t)
+{
+       return tree_for_each(t->tree, tree_mgr_fill_cb, NULL);
+}
+
+#ifdef DEBUG_PARSE
+static int tree_mgr_debug_dump_tree(struct tree *t)
+{
+       return tree_for_each(t, tree_mgr_dump_debug_cb, NULL);
+}
+#endif /* DEBUG_PARSE */
+
+static int tree_mgr_display_cb(struct tree *t, void *data, int ix)
+{
+       int *line = data;
+       char *buf;
+       int i;
+       struct field_def *f = (struct field_def *) t->private;
+
+       if (t == NULL)
+               BAIL_OUT(("bad tree"));
+       if (t->private == NULL)
+               return 0; /* only display register fields */
+
+       if (f->decoder)
+               asprintf(&buf, "%25s %-8x(%s)",
+                        t->path, f->value, field_decode(f));
+       else
+               asprintf(&buf, "%25s %-8x", t->path, f->value);
+       display_print_line(ix, *line, buf, 1, t);
+
+       (*line)++;
+
+       return 0;
+}
+
+static int tree_mgr_print_header(void)
+{
+       char *buf;
+       int ret;
+
+       if (asprintf(&buf, "%-36s%s", "Name", "Value") < 0)
+               return -1;
+
+       ret = display_column_name(buf);
+
+       free(buf);
+
+       return ret;
+}
+
+static int tree_mgr_display(bool refresh, void *v)
+{
+       int ret, line = 0;
+       struct tree_mgr *tm = (struct tree_mgr *) v;
+       struct tree *t;
+
+       if (!tm)
+               BAIL_OUT(("bad tree_mgr"));
+       t = tm->tree;
+       if (!t)
+               BAIL_OUT(("bad tree"));
+
+       display_reset_cursor(tm->ix);
+
+       tree_mgr_print_header();
+
+       ret = tree_for_each_ex(t, tree_mgr_display_cb, &line, tm->ix);
+
+       display_refresh_pad(tm->ix);
+
+       return ret;
+}
+
+static struct display_ops tree_mgr_ops = {
+       .display_ex = tree_mgr_display,
+};
+
+struct tree_mgr *tree_mgr_new(int ix, char *hdr_str)
+{
+       struct tree_mgr *t = calloc(1, sizeof(struct tree_mgr));
+
+       if (!t)
+               BAIL_OUT(("failed to allocated struct tree_mgr"));
+
+       t->tree = tree_load_file(get_cfg_file(ix));
+       t->dump_header = hdr_str;
+       t->ix = ix;
+
+#ifdef DEBUG_PARSE
+       tree_mgr_debug_dump_tree(t->tree);
+#endif /* DEBUG_PARSE */
+
+       if (!t->tree)
+               BAIL_OUT(("failed to allocate tree"));
+
+       if (tree_mgr_fill_tree(t))
+               return NULL;
+
+       if (display_register_ex(ix, &tree_mgr_ops, (void *)t))
+               BAIL_OUT(("display_register_ex failed"));
+       return t;
+}
+
diff --git a/tree_mgr.h b/tree_mgr.h
new file mode 100644
index 0000000..d692e1f
--- /dev/null
+++ b/tree_mgr.h
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (C) 2012, Linaro Limited.
+ *
+ * This file is part of PowerDebug.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Eric van Tassell
+ *       - initial API and implementation
+ 
******************************************************************************/
+
+
+struct tree_mgr {
+       int ix;
+       struct tree *tree;
+       char *dump_header;
+};
+
+/* prototypes */
+struct tree_mgr *tree_mgr_new(int ix, char *hdr_str);
+extern int tree_mgr_dump(struct tree_mgr *t);
diff --git a/utils.c b/utils.c
index 0e95f05..35a61a5 100644
--- a/utils.c
+++ b/utils.c
@@ -11,12 +11,17 @@
  * Contributors:
  *     Daniel Lezcano <daniel.lezc...@linaro.org> (IBM Corporation)
  *       - initial API and implementation
+ *     Eric van Tassell
+ *       - minor additions
  
*******************************************************************************/
 
 #define _GNU_SOURCE
 #include <stdio.h>
 #undef _GNU_SOURCE
 #include <stdlib.h>
+#include "utils.h"
+#include "delimi.h"
+#include "regfield.h"
 
 /*
  * This functions is a helper to read a specific file content and store
@@ -65,3 +70,56 @@ char *strchrnul(char *str, char delim)
                tmp = str + strlen(str) - 1;
        return tmp;
 }
+
+static char *get_omap4_config_file(int ix)
+{
+       switch (ix) {
+       case PWRDM:
+               return"pwrdm.regdefs.omap4";
+       case VDD:
+               return"vdd.regdefs.omap4";
+       default:
+               return NULL;
+       }
+}
+
+static int is_omap4(void)
+{
+       uint32_t omap4_ids[] = {
+               0x0B85202F, /* OMAP4430 ES1.0 */
+               0x1B85202F, /* OMAP4430 ES2.0 */
+               0x3B95C02F, /* OMAP4430 ES2.1 */
+               0x4B95C02F, /* OMAP4430 ES2.2 */
+               0x6B95C02F  /* OMAP4430 ES2.3 */
+       };
+
+       struct field_def omap4_id_code = {
+               .name = "ID_CODE",
+               .address = 0x4A002204,
+               .shift = 0,
+               .mask = 0xffffffff
+       };
+
+       uint32_t i;
+
+       field_read(&omap4_id_code);
+
+       for (i = 0; i < sizeof(omap4_ids) / sizeof(uint32_t); i++) {
+               if (omap4_ids[i] == omap4_id_code.value)
+                       return 1;
+       }
+       return 0;
+}
+
+char *get_cfg_file(int ix)
+{
+       char *ret = NULL;
+
+       if (is_omap4())
+               ret = get_omap4_config_file(ix);
+       else
+               BAIL_OUT(("unknown SOC, cannot determine config file"));
+
+       printf("%s: ret = %s\n", __func__, ret);
+       return ret;
+}
diff --git a/utils.h b/utils.h
index 581e20d..d4b7ece 100644
--- a/utils.h
+++ b/utils.h
@@ -15,6 +15,8 @@
 #ifndef __UTILS_H
 #define __UTILS_H
 
+enum { CLOCK, REGULATOR, SENSOR, PWRDM, VDD, GPIO};
+
 #define BAIL_OUT(x) \
        {                                                               \
        printf x;                                                       \
@@ -29,4 +31,5 @@ extern int file_read_value(const char *path, const char *name,
                            const char *format, void *value);
 
 char *strchrnul(char *str, char delim);
+char *get_cfg_file(int ix);
 #endif
-- 
1.7.9.5


_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to