aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--includes/dt_util.h5
-rw-r--r--modules/devices/devicetree.c24
-rw-r--r--modules/devices/devicetree/dt_util.c68
3 files changed, 91 insertions, 6 deletions
diff --git a/includes/dt_util.h b/includes/dt_util.h
index 5f016f2f..273d227d 100644
--- a/includes/dt_util.h
+++ b/includes/dt_util.h
@@ -20,8 +20,8 @@ enum {
DTP_EMPTY, /* empty property */
DTP_STR, /* null-delimited list of strings */
DTP_HEX, /* list of 32-bit values displayed in hex */
- DTP_UINT,
- /* DTP_INT, */
+ DTP_UINT, /* unsigned int list */
+ DTP_INTRUPT, /* interrupt-specifier list */
DTP_OVR, /* all in /__overrides__ */
DTP_PH, /* phandle */
DTP_PH_REF, /* reference to phandle */
@@ -42,6 +42,7 @@ typedef struct _dtr_obj dtr_obj;
dtr *dtr_new(char *base_path); /* NULL for DTR_ROOT */
void dtr_free(dtr *);
const char *dtr_base_path(dtr *);
+char *dtr_messages(dtr *); /* returns a message log */
dtr_obj *dtr_obj_read(dtr *, const char *dtp);
void dtr_obj_free(dtr_obj *);
diff --git a/modules/devices/devicetree.c b/modules/devices/devicetree.c
index 7252323b..c6207972 100644
--- a/modules/devices/devicetree.c
+++ b/modules/devices/devicetree.c
@@ -260,20 +260,44 @@ void add_keys(char *np) {
g_dir_close(dir);
}
+char *msg_section(int dump) {
+ gchar *aslbl = NULL;
+ gchar *messages = dtr_messages(dt);
+ gchar *ret = g_strdup_printf("[%s]\n", _("Messages"));
+ gchar **lines = g_strsplit(messages, "\n", 0);
+ int i = 0;
+ while(lines[i] != NULL) {
+ aslbl = hardinfo_clean_label(lines[i], 0);
+ ret = appf(ret, "%s=\n", aslbl);
+ g_free(aslbl);
+ i++;
+ }
+ g_strfreev(lines);
+ if (dump)
+ printf(messages);
+ g_free(messages);
+ return ret;
+}
+
void __scan_dtree()
{
dt = dtr_new(NULL);
gchar *summary = get_summary();
gchar *maps = dtr_maps_info(dt);
+ gchar *messages = NULL;
dtree_info = g_strdup("[Device Tree]\n");
mi_add("Summary", summary);
mi_add("Maps", maps);
add_keys("/");
+ messages = msg_section(0);
+ mi_add("Messages", messages);
//printf("%s\n", dtree_info);
+
g_free(summary);
g_free(maps);
+ g_free(messages);
dtr_free(dt);
}
diff --git a/modules/devices/devicetree/dt_util.c b/modules/devices/devicetree/dt_util.c
index de371da2..8cc5fadb 100644
--- a/modules/devices/devicetree/dt_util.c
+++ b/modules/devices/devicetree/dt_util.c
@@ -38,8 +38,9 @@ static struct {
{ "gpios", DTP_GPIOS },
{ "cs-gpios", DTP_GPIOS },
{ "phandle", DTP_PH },
- { "interrupts", DTP_HEX },
+ { "interrupts", DTP_INTRUPT },
{ "interrupt-parent", DTP_PH_REF },
+ { "interrupt-controller", DTP_EMPTY },
{ "regulator-min-microvolt", DTP_UINT },
{ "regulator-max-microvolt", DTP_UINT },
{ "clock-frequency", DTP_UINT },
@@ -67,6 +68,7 @@ struct _dtr {
dtr_map *symbols;
dtr_map *phandles;
char *base_path;
+ char *log;
};
struct _dtr_obj {
@@ -226,6 +228,8 @@ dtr *dtr_new_x(char *base_path, int fast) {
else
dt->base_path = strdup(DTR_ROOT);
+ dt->log = strdup("");
+
/* build alias and phandle lists */
dt->aliases = NULL;
dt->symbols = NULL;
@@ -249,10 +253,31 @@ void dtr_free(dtr *s) {
dtr_map_free(s->symbols);
dtr_map_free(s->phandles);
free(s->base_path);
+ free(s->log);
free(s);
}
}
+void dtr_msg(dtr *s, char *fmt, ...) {
+ gchar *buf, *tmp;
+ va_list args;
+
+ va_start(args, fmt);
+ buf = g_strdup_vprintf(fmt, args);
+ va_end(args);
+
+ tmp = g_strdup_printf("%s%s", s->log, buf);
+ g_free(s->log);
+ s->log = tmp;
+}
+
+char *dtr_messages(dtr *s) {
+ if (s != NULL)
+ return strdup(s->log);
+ else
+ return NULL;
+}
+
const char *dtr_base_path(dtr *s) {
if (s)
return s->base_path;
@@ -630,14 +655,43 @@ char *dtr_list_phref(dtr_obj *obj, char *ext_cell_prop) {
return ret;
}
+char *dtr_list_interrupts(dtr_obj *obj) {
+ char *ext, *ret = NULL;
+ uint32_t iparent, icells;
+ int count, i = 0;
+
+ iparent = dtr_inh_find(obj, "interrupt-parent", 0);
+ if (!iparent) {
+ dtr_msg(obj->dt, "Did not find an interrupt-parent for %s", obj->path);
+ goto intr_err;
+ }
+ icells = dtr_get_phref_prop(obj->dt, iparent, "#interrupt-cells");
+ if (!icells) {
+ dtr_msg(obj->dt, "Invalid #interrupt-cells value %d for %s", icells, obj->path);
+ goto intr_err;
+ }
+
+ count = obj->length / 4;
+ while (i < count) {
+ icells = MIN(icells, count - i);
+ ext = dtr_list_hex((obj->data_int + i), icells); i+=icells;
+ ret = appf(ret, "<%s>", ext);
+ }
+ return ret;
+
+intr_err:
+ return dtr_list_hex(obj->data_int, obj->length);
+
+}
+
char *dtr_list_reg(dtr_obj *obj) {
char *tup_str, *ret = NULL;
uint32_t acells, scells, tup_len;
uint32_t tups, extra, consumed; /* extra and consumed are bytes */
uint32_t *next;
- acells = dtr_cellv_find(obj, "#address-cells", 2);
- scells = dtr_cellv_find(obj, "#size-cells", 2);
+ acells = dtr_inh_find(obj, "#address-cells", 2);
+ scells = dtr_inh_find(obj, "#size-cells", 2);
tup_len = acells + scells;
tups = obj->length / (tup_len * 4);
extra = obj->length % (tup_len * 4);
@@ -647,6 +701,8 @@ char *dtr_list_reg(dtr_obj *obj) {
if (extra) {
/* error: length is not a multiple of tuples */
+ dtr_msg(obj->dt, "Data length (%u) is not a multiple of (#address-cells:%u + #size-cells:%u) for %s\n",
+ obj->length, acells, scells, obj->path);
return dtr_list_hex(obj->data, obj->length / 4);
}
@@ -705,6 +761,9 @@ char* dtr_str(dtr_obj *obj) {
/* <#address-cells #size-cells> */
ret = dtr_list_reg(obj);
break;
+ case DTP_INTRUPT:
+ ret = dtr_list_interrupts(obj);
+ break;
case DTP_PH:
case DTP_HEX:
if (obj->length % 4)
@@ -751,7 +810,7 @@ dtr_obj *dtr_get_parent_obj(dtr_obj *obj) {
}
/* find the value of a path-inherited property by climbing the path */
-int dtr_cellv_find(dtr_obj *obj, char *qprop, int limit) {
+int dtr_inh_find(dtr_obj *obj, char *qprop, int limit) {
dtr_obj *tobj, *pobj, *qobj;
uint32_t ret = 0;
int i, found = 0;
@@ -781,6 +840,7 @@ int dtr_cellv_find(dtr_obj *obj, char *qprop, int limit) {
while(default_values[i].name != NULL) {
if (strcmp(default_values[i].name, qprop) == 0) {
ret = default_values[i].v;
+ dtr_msg(obj->dt, "Using default value %d for %s in %s\n", ret, qprop, obj->path);
break;
}
i++;