@@ -135,7 +135,6 @@ libpdbg_la_SOURCES = \
libpdbg/bitutils.h \
libpdbg/compiler.h \
libpdbg/debug.h \
- libpdbg/device.h \
libpdbg/operations.h \
libpdbg/libpdbg.h \
libpdbg/target.h
@@ -27,7 +27,6 @@
#include "bitutils.h"
#include "operations.h"
-#include "device.h"
#include "target.h"
#include "debug.h"
@@ -42,7 +41,7 @@
* address offset */
struct gpio_pin {
uint32_t offset;
- int bit;
+ uint32_t bit;
};
enum gpio {
@@ -71,7 +70,7 @@ enum fsi_result {
FSI_ERR_C = 0x3,
};
-static int clock_delay = 0;
+static uint32_t clock_delay = 0;
#define FSI_DATA0_REG 0x1000
#define FSI_DATA1_REG 0x1001
@@ -459,17 +458,28 @@ int bmcfsi_probe(struct pdbg_target *target)
}
if (!gpio_reg) {
- gpio_pins[GPIO_FSI_CLK].offset = dt_prop_get_u32_index(target, "fsi_clk", 0);
- gpio_pins[GPIO_FSI_CLK].bit = dt_prop_get_u32_index(target, "fsi_clk", 1);
- gpio_pins[GPIO_FSI_DAT].offset = dt_prop_get_u32_index(target, "fsi_dat", 0);
- gpio_pins[GPIO_FSI_DAT].bit = dt_prop_get_u32_index(target, "fsi_dat", 1);
- gpio_pins[GPIO_FSI_DAT_EN].offset = dt_prop_get_u32_index(target, "fsi_dat_en", 0);
- gpio_pins[GPIO_FSI_DAT_EN].bit = dt_prop_get_u32_index(target, "fsi_dat_en", 1);
- gpio_pins[GPIO_FSI_ENABLE].offset = dt_prop_get_u32_index(target, "fsi_enable", 0);
- gpio_pins[GPIO_FSI_ENABLE].bit = dt_prop_get_u32_index(target, "fsi_enable", 1);
- gpio_pins[GPIO_CRONUS_SEL].offset = dt_prop_get_u32_index(target, "cronus_sel", 0);
- gpio_pins[GPIO_CRONUS_SEL].bit = dt_prop_get_u32_index(target, "cronus_sel", 1);
- clock_delay = dt_prop_get_u32(target, "clock_delay");
+ assert(!(pdbg_get_target_u32_index(target, "fsi_clk", 0,
+ &gpio_pins[GPIO_FSI_CLK].offset)));
+ assert(!(pdbg_get_target_u32_index(target, "fsi_clk", 1,
+ &gpio_pins[GPIO_FSI_CLK].bit)));
+ assert(!(pdbg_get_target_u32_index(target, "fsi_dat", 0,
+ &gpio_pins[GPIO_FSI_DAT].offset)));
+ assert(!(pdbg_get_target_u32_index(target, "fsi_dat", 1,
+ &gpio_pins[GPIO_FSI_DAT].bit)));
+ assert(!(pdbg_get_target_u32_index(target, "fsi_dat_en", 0,
+ &gpio_pins[GPIO_FSI_DAT_EN].offset)));
+ assert(!(pdbg_get_target_u32_index(target, "fsi_dat_en", 1,
+ &gpio_pins[GPIO_FSI_DAT_EN].bit)));
+ assert(!(pdbg_get_target_u32_index(target, "fsi_enable", 0,
+ &gpio_pins[GPIO_FSI_ENABLE].offset)));
+ assert(!(pdbg_get_target_u32_index(target, "fsi_enable", 1,
+ &gpio_pins[GPIO_FSI_ENABLE].bit)));
+ assert(!(pdbg_get_target_u32_index(target, "cronus_sel", 0,
+ &gpio_pins[GPIO_CRONUS_SEL].offset)));
+ assert(!(pdbg_get_target_u32_index(target, "cronus_sel", 1,
+ &gpio_pins[GPIO_CRONUS_SEL].bit)));
+ assert(!(pdbg_get_target_u32_property(target, "clock_delay",
+ &clock_delay)));
/* We only have to do this init once per backend */
gpio_reg = mmap(NULL, getpagesize(),
@@ -295,7 +295,7 @@ static int cfam_hmfsi_read(struct fsi *fsi, uint32_t addr, uint32_t *data)
{
struct pdbg_target *parent_fsi = pdbg_target_require_parent("fsi", &fsi->target);
- addr += dt_get_address(&fsi->target, 0, NULL);
+ addr += pdbg_target_address(&fsi->target, NULL);
return fsi_read(parent_fsi, addr, data);
}
@@ -304,7 +304,7 @@ static int cfam_hmfsi_write(struct fsi *fsi, uint32_t addr, uint32_t data)
{
struct pdbg_target *parent_fsi = pdbg_target_require_parent("fsi", &fsi->target);
- addr += dt_get_address(&fsi->target, 0, NULL);
+ addr += pdbg_target_address(&fsi->target, NULL);
return fsi_write(parent_fsi, addr, data);
}
@@ -317,7 +317,7 @@ static int cfam_hmfsi_probe(struct pdbg_target *target)
int rc;
/* Enable the port in the upstream control register */
- port = dt_prop_get_u32(target, "port");
+ assert(!(pdbg_get_target_u32_property(target, "port", &port)));
fsi_read(fsi_parent, 0x3404, &value);
value |= 1 << (31 - port);
if ((rc = fsi_write(fsi_parent, 0x3404, value))) {
@@ -1,4 +1,4 @@
-/* Copyright 2013-2014 IBM Corp.
+/* Copyright 2018 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,32 +14,96 @@
* limitations under the License.
*/
-#include "device.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
-#include "target.h"
+#include <stdint.h>
+#include <inttypes.h>
+#include <assert.h>
+#include <endian.h>
+
#include <libfdt/libfdt.h>
#include <libfdt/libfdt_internal.h>
#include <ccan/str/str.h>
-#include <endian.h>
+#include <ccan/list/list.h>
+#include "bitutils.h"
+#include "target.h"
+#include "operations.h"
#include "debug.h"
-#define zalloc(size) calloc(1, size)
-#define prerror printf
#define is_rodata(p) false
+struct list_head empty_list = LIST_HEAD_INIT(empty_list);
+struct list_head target_classes = LIST_HEAD_INIT(target_classes);
+
+/*
+ * An in-memory representation of a node in the device tree.
+ *
+ * This is trivially flattened into an fdt.
+ */
+struct pdt_property {
+ struct list_node list;
+ const char *name;
+ size_t len;
+ char prop[/* len */];
+};
+
/* Used to give unique handles. */
-u32 last_phandle = 0;
+static uint32_t last_phandle = 0;
+
+struct pdbg_target *pdbg_dt_root;
+
+/* Iterate nodes */
+#define pdt_for_each_node(root, node) \
+ for (node = pdt_first(root); node; node = pdt_next(root, node))
+
+#define pdt_for_each_child(parent, node) \
+ list_for_each(&parent->children, node, list)
+
+/* First child of this node. */
+static struct pdbg_target *pdt_first(const struct pdbg_target *root)
+{
+ return list_top(&root->children, struct pdbg_target, list);
+}
-struct pdbg_target *dt_root;
-struct pdbg_target *dt_chosen;
+/* Return next node, or NULL. */
+static struct pdbg_target *pdt_next(const struct pdbg_target *root,
+ const struct pdbg_target *prev)
+{
+ /* Children? */
+ if (!list_empty(&prev->children))
+ return pdt_first(prev);
+
+ do {
+ /* More siblings? */
+ if (prev->list.next != &prev->parent->children.n)
+ return list_entry(prev->list.next, struct pdbg_target,list);
+
+ /* No more siblings, move up to parent. */
+ prev = prev->parent;
+ } while (prev != root);
+
+ return NULL;
+}
+
+struct pdbg_target *__pdbg_find_compatible_node(struct pdbg_target *root,
+ struct pdbg_target *prev,
+ const char *compat)
+{
+ struct pdbg_target *target;
+
+ target = prev ? pdt_next(root, prev) : root;
+ for (; target; target = pdt_next(root, target))
+ if (pdbg_target_compatible(target, compat))
+ return target;
+ return NULL;
+}
static const char *take_name(const char *name)
{
if (!is_rodata(name) && !(name = strdup(name))) {
- prerror("Failed to allocate copy of name");
+ PR_ERROR("Failed to allocate copy of name");
abort();
}
return name;
@@ -51,7 +115,7 @@ static void free_name(const char *name)
free((char *)name);
}
-struct pdbg_target *dt_new_node(const char *name, const void *fdt, int node_offset)
+static struct pdbg_target *pdt_new_node(const char *name, const void *fdt, int node_offset)
{
struct hw_unit_info *hw_info = NULL;
const struct fdt_property *prop;
@@ -83,7 +147,7 @@ struct pdbg_target *dt_new_node(const char *name, const void *fdt, int node_offs
node = calloc(1, size);
if (!node) {
- prerror("Failed to allocate node\n");
+ PR_ERROR("Failed to allocate node\n");
abort();
}
@@ -118,7 +182,7 @@ static const char *get_unitname(const struct pdbg_target *node)
return c + 1;
}
-int dt_cmp_subnodes(const struct pdbg_target *a, const struct pdbg_target *b)
+static int pdt_cmp_subnodes(const struct pdbg_target *a, const struct pdbg_target *b)
{
const char *a_unit = get_unitname(a);
const char *b_unit = get_unitname(b);
@@ -141,7 +205,7 @@ int dt_cmp_subnodes(const struct pdbg_target *a, const struct pdbg_target *b)
return strcmp(a->dn_name, b->dn_name);
}
-bool dt_attach_root(struct pdbg_target *parent, struct pdbg_target *root)
+static bool pdt_attach_root(struct pdbg_target *parent, struct pdbg_target *root)
{
struct pdbg_target *node;
@@ -154,12 +218,12 @@ bool dt_attach_root(struct pdbg_target *parent, struct pdbg_target *root)
return true;
}
- dt_for_each_child(parent, node) {
- int cmp = dt_cmp_subnodes(node, root);
+ pdt_for_each_child(parent, node) {
+ int cmp = pdt_cmp_subnodes(node, root);
/* Look for duplicates */
if (cmp == 0) {
- prerror("DT: %s failed, duplicate %s\n",
+ PR_ERROR("DT: %s failed, duplicate %s\n",
__func__, root->dn_name);
return false;
}
@@ -176,7 +240,7 @@ bool dt_attach_root(struct pdbg_target *parent, struct pdbg_target *root)
return true;
}
-static inline void dt_destroy(struct pdbg_target *dn)
+static inline void pdt_destroy(struct pdbg_target *dn)
{
if (!dn)
return;
@@ -185,136 +249,22 @@ static inline void dt_destroy(struct pdbg_target *dn)
free(dn);
}
-char *dt_get_path(const struct pdbg_target *node)
-{
- unsigned int len = 0;
- const struct pdbg_target *n;
- char *path, *p;
-
- /* Dealing with NULL is for test/debug purposes */
- if (!node)
- return strdup("<NULL>");
-
- for (n = node; n; n = n->parent) {
- len += strlen(n->dn_name);
- if (n->parent || n == node)
- len++;
- }
- path = zalloc(len + 1);
- assert(path);
- p = path + len;
- for (n = node; n; n = n->parent) {
- len = strlen(n->dn_name);
- p -= len;
- memcpy(p, n->dn_name, len);
- if (n->parent || n == node)
- *(--p) = '/';
- }
- assert(p == path);
-
- return p;
-}
-
-static const char *__dt_path_split(const char *p,
- const char **namep, unsigned int *namel,
- const char **addrp, unsigned int *addrl)
-{
- const char *at, *sl;
-
- *namel = *addrl = 0;
-
- /* Skip initial '/' */
- while (*p == '/')
- p++;
-
- /* Check empty path */
- if (*p == 0)
- return p;
-
- at = strchr(p, '@');
- sl = strchr(p, '/');
- if (sl == NULL)
- sl = p + strlen(p);
- if (sl < at)
- at = NULL;
- if (at) {
- *addrp = at + 1;
- *addrl = sl - at - 1;
- }
- *namep = p;
- *namel = at ? (at - p) : (sl - p);
-
- return sl;
-}
-
-struct pdbg_target *dt_find_by_path(struct pdbg_target *root, const char *path)
-{
- struct pdbg_target *n;
- const char *pn, *pa = NULL, *p = path, *nn = NULL, *na = NULL;
- unsigned int pnl, pal, nnl, nal;
- bool match;
-
- /* Walk path components */
- while (*p) {
- /* Extract next path component */
- p = __dt_path_split(p, &pn, &pnl, &pa, &pal);
- if (pnl == 0 && pal == 0)
- break;
-
- /* Compare with each child node */
- match = false;
- list_for_each(&root->children, n, list) {
- match = true;
- __dt_path_split(n->dn_name, &nn, &nnl, &na, &nal);
- if (pnl && (pnl != nnl || strncmp(pn, nn, pnl)))
- match = false;
- if (pal && (pal != nal || strncmp(pa, na, pal)))
- match = false;
- if (match) {
- root = n;
- break;
- }
- }
-
- /* No child match */
- if (!match)
- return NULL;
- }
- return root;
-}
-
-struct pdbg_target *dt_find_by_name(struct pdbg_target *root, const char *name)
-{
- struct pdbg_target *child, *match;
-
- list_for_each(&root->children, child, list) {
- if (!strcmp(child->dn_name, name))
- return child;
-
- match = dt_find_by_name(child, name);
- if (match)
- return match;
- }
-
- return NULL;
-}
-
-static struct dt_property *new_property(struct pdbg_target *node,
+static struct pdt_property *pdt_new_property(struct pdbg_target *node,
const char *name, size_t size)
{
- struct dt_property *p = malloc(sizeof(*p) + size);
+ struct pdt_property *p = malloc(sizeof(*p) + size);
char *path;
if (!p) {
- path = dt_get_path(node);
- prerror("Failed to allocate property \"%s\" for %s of %zu bytes\n",
+ path = pdbg_target_path(node);
+ PR_ERROR("Failed to allocate property \"%s\" for %s of %zu bytes\n",
name, path, size);
free(path);
abort();
}
- if (dt_find_property(node, name)) {
- path = dt_get_path(node);
- prerror("Duplicate property \"%s\" in node %s\n",
+ if (pdbg_get_target_property(node, name, NULL)) {
+ path = pdbg_target_path(node);
+ PR_ERROR("Duplicate property \"%s\" in node %s\n",
name, path);
free(path);
abort();
@@ -327,11 +277,11 @@ static struct dt_property *new_property(struct pdbg_target *node,
return p;
}
-struct dt_property *dt_add_property(struct pdbg_target *node,
- const char *name,
- const void *val, size_t size)
+static struct pdt_property *pdt_add_property(struct pdbg_target *node,
+ const char *name,
+ const void *val, size_t size)
{
- struct dt_property *p;
+ struct pdt_property *p;
/*
* Filter out phandle properties, we re-generate them
@@ -346,366 +296,12 @@ struct dt_property *dt_add_property(struct pdbg_target *node,
return NULL;
}
- p = new_property(node, name, size);
+ p = pdt_new_property(node, name, size);
if (size)
memcpy(p->prop, val, size);
return p;
}
-void dt_resize_property(struct dt_property **prop, size_t len)
-{
- size_t new_len = sizeof(**prop) + len;
-
- *prop = realloc(*prop, new_len);
-
- /* Fix up linked lists in case we moved. (note: not an empty list). */
- (*prop)->list.next->prev = &(*prop)->list;
- (*prop)->list.prev->next = &(*prop)->list;
-}
-
-struct dt_property *dt_add_property_string(struct pdbg_target *node,
- const char *name,
- const char *value)
-{
- return dt_add_property(node, name, value, strlen(value)+1);
-}
-
-struct dt_property *dt_add_property_nstr(struct pdbg_target *node,
- const char *name,
- const char *value, unsigned int vlen)
-{
- struct dt_property *p;
- char *tmp = zalloc(vlen + 1);
-
- if (!tmp)
- return NULL;
-
- strncpy(tmp, value, vlen);
- p = dt_add_property(node, name, tmp, strlen(tmp)+1);
- free(tmp);
-
- return p;
-}
-
-struct dt_property *__dt_add_property_cells(struct pdbg_target *node,
- const char *name,
- int count, ...)
-{
- struct dt_property *p;
- u32 *val;
- unsigned int i;
- va_list args;
-
- p = new_property(node, name, count * sizeof(u32));
- val = (u32 *)p->prop;
- va_start(args, count);
- for (i = 0; i < count; i++)
- val[i] = cpu_to_fdt32(va_arg(args, u32));
- va_end(args);
- return p;
-}
-
-struct dt_property *__dt_add_property_u64s(struct pdbg_target *node,
- const char *name,
- int count, ...)
-{
- struct dt_property *p;
- u64 *val;
- unsigned int i;
- va_list args;
-
- p = new_property(node, name, count * sizeof(u64));
- val = (u64 *)p->prop;
- va_start(args, count);
- for (i = 0; i < count; i++)
- val[i] = cpu_to_fdt64(va_arg(args, u64));
- va_end(args);
- return p;
-}
-
-struct dt_property *__dt_add_property_strings(struct pdbg_target *node,
- const char *name,
- int count, ...)
-{
- struct dt_property *p;
- unsigned int i, size;
- va_list args;
- const char *sstr;
- char *s;
-
- va_start(args, count);
- for (i = size = 0; i < count; i++) {
- sstr = va_arg(args, const char *);
- if (sstr)
- size += strlen(sstr) + 1;
- }
- va_end(args);
- if (!size)
- size = 1;
- p = new_property(node, name, size);
- s = (char *)p->prop;
- *s = 0;
- va_start(args, count);
- for (i = 0; i < count; i++) {
- sstr = va_arg(args, const char *);
- if (sstr) {
- strcpy(s, sstr);
- s = s + strlen(sstr) + 1;
- }
- }
- va_end(args);
- return p;
-}
-
-void dt_del_property(struct pdbg_target *node, struct dt_property *prop)
-{
- list_del_from(&node->properties, &prop->list);
- free_name(prop->name);
- free(prop);
-}
-
-u32 dt_property_get_cell(const struct dt_property *prop, u32 index)
-{
- assert(prop->len >= (index+1)*sizeof(u32));
- /* Always aligned, so this works. */
- return fdt32_to_cpu(((const u32 *)prop->prop)[index]);
-}
-
-/* First child of this node. */
-struct pdbg_target *dt_first(const struct pdbg_target *root)
-{
- return list_top(&root->children, struct pdbg_target, list);
-}
-
-/* Return next node, or NULL. */
-struct pdbg_target *dt_next(const struct pdbg_target *root,
- const struct pdbg_target *prev)
-{
- /* Children? */
- if (!list_empty(&prev->children))
- return dt_first(prev);
-
- do {
- /* More siblings? */
- if (prev->list.next != &prev->parent->children.n)
- return list_entry(prev->list.next, struct pdbg_target,list);
-
- /* No more siblings, move up to parent. */
- prev = prev->parent;
- } while (prev != root);
-
- return NULL;
-}
-
-struct dt_property *__dt_find_property(struct pdbg_target *node, const char *name)
-{
- struct dt_property *i;
-
- list_for_each(&node->properties, i, list)
- if (strcmp(i->name, name) == 0)
- return i;
- return NULL;
-}
-
-struct dt_property *dt_find_property(const struct pdbg_target *node,
- const char *name)
-{
- struct dt_property *i;
-
- list_for_each(&node->properties, i, list)
- if (strcmp(i->name, name) == 0)
- return i;
- return NULL;
-}
-
-void dt_check_del_prop(struct pdbg_target *node, const char *name)
-{
- struct dt_property *p;
-
- p = __dt_find_property(node, name);
- if (p)
- dt_del_property(node, p);
-}
-const struct dt_property *dt_require_property(const struct pdbg_target *node,
- const char *name, int wanted_len)
-{
- const struct dt_property *p = dt_find_property(node, name);
-
- if (!p) {
- const char *path = dt_get_path(node);
-
- prerror("DT: Missing required property %s/%s\n",
- path, name);
- assert(false);
- }
- if (wanted_len >= 0 && p->len != wanted_len) {
- const char *path = dt_get_path(node);
-
- prerror("DT: Unexpected property length %s/%s\n",
- path, name);
- prerror("DT: Expected len: %d got len: %zu\n",
- wanted_len, p->len);
- assert(false);
- }
-
- return p;
-}
-
-bool dt_has_node_property(const struct pdbg_target *node,
- const char *name, const char *val)
-{
- const struct dt_property *p = dt_find_property(node, name);
-
- if (!p)
- return false;
- if (!val)
- return true;
-
- return p->len == strlen(val) + 1 && memcmp(p->prop, val, p->len) == 0;
-}
-
-bool dt_prop_find_string(const struct dt_property *p, const char *s)
-{
- const char *c, *end;
-
- if (!p)
- return false;
- c = p->prop;
- end = c + p->len;
-
- while(c < end) {
- if (!strcasecmp(s, c))
- return true;
- c += strlen(c) + 1;
- }
- return false;
-}
-
-bool dt_node_is_compatible(const struct pdbg_target *node, const char *compat)
-{
- const struct dt_property *p = dt_find_property(node, "compatible");
-
- return dt_prop_find_string(p, compat);
-}
-
-struct pdbg_target *dt_find_compatible_node(struct pdbg_target *root,
- struct pdbg_target *prev,
- const char *compat)
-{
- struct pdbg_target *node;
-
- node = prev ? dt_next(root, prev) : root;
- for (; node; node = dt_next(root, node))
- if (dt_node_is_compatible(node, compat))
- return node;
- return NULL;
-}
-
-u64 dt_prop_get_u64(const struct pdbg_target *node, const char *prop)
-{
- const struct dt_property *p = dt_require_property(node, prop, 8);
-
- return ((u64)dt_property_get_cell(p, 0) << 32)
- | dt_property_get_cell(p, 1);
-}
-
-u64 dt_prop_get_u64_def(const struct pdbg_target *node, const char *prop, u64 def)
-{
- const struct dt_property *p = dt_find_property(node, prop);
-
- if (!p)
- return def;
-
- return ((u64)dt_property_get_cell(p, 0) << 32)
- | dt_property_get_cell(p, 1);
-}
-
-u32 dt_prop_get_u32(const struct pdbg_target *node, const char *prop)
-{
- const struct dt_property *p = dt_require_property(node, prop, 4);
-
- return dt_property_get_cell(p, 0);
-}
-
-u32 dt_prop_get_u32_def(const struct pdbg_target *node, const char *prop, u32 def)
-{
- const struct dt_property *p = dt_find_property(node, prop);
-
- if (!p)
- return def;
-
- return dt_property_get_cell(p, 0);
-}
-
-u32 dt_prop_get_u32_index(const struct pdbg_target *node, const char *prop, u32 index)
-{
- const struct dt_property *p = dt_require_property(node, prop, -1);
-
- return dt_property_get_cell(p, index);
-}
-
-const void *dt_prop_get(const struct pdbg_target *node, const char *prop)
-{
- const struct dt_property *p = dt_require_property(node, prop, -1);
-
- return p->prop;
-}
-
-const void *dt_prop_get_def(const struct pdbg_target *node, const char *prop,
- void *def)
-{
- const struct dt_property *p = dt_find_property(node, prop);
-
- return p ? p->prop : def;
-}
-
-const void *dt_prop_get_def_size(const struct pdbg_target *node, const char *prop,
- void *def, size_t *len)
-{
- const struct dt_property *p = dt_find_property(node, prop);
- *len = 0;
- if (p)
- *len = p->len;
-
- return p ? p->prop : def;
-}
-
-u32 dt_prop_get_cell(const struct pdbg_target *node, const char *prop, u32 cell)
-{
- const struct dt_property *p = dt_require_property(node, prop, -1);
-
- return dt_property_get_cell(p, cell);
-}
-
-u32 dt_prop_get_cell_def(const struct pdbg_target *node, const char *prop,
- u32 cell, u32 def)
-{
- const struct dt_property *p = dt_find_property(node, prop);
-
- if (!p)
- return def;
-
- return dt_property_get_cell(p, cell);
-}
-
-void dt_free(struct pdbg_target *node)
-{
- struct pdbg_target *child;
- struct dt_property *p;
-
- while ((child = list_top(&node->children, struct pdbg_target, list)))
- dt_free(child);
-
- while ((p = list_pop(&node->properties, struct dt_property, list))) {
- free_name(p->name);
- free(p);
- }
-
- if (node->parent)
- list_del_from(&node->parent->children, &node->list);
- dt_destroy(node);
-}
-
enum pdbg_target_status str_to_status(const char *status)
{
if (!strcmp(status, "enabled")) {
@@ -728,7 +324,7 @@ enum pdbg_target_status str_to_status(const char *status)
assert(0);
}
-int dt_expand_node(struct pdbg_target *node, const void *fdt, int fdt_node)
+static int pdt_expand_node(struct pdbg_target *node, const void *fdt, int fdt_node)
{
const struct fdt_property *prop;
int offset, nextoffset, err;
@@ -740,7 +336,7 @@ int dt_expand_node(struct pdbg_target *node, const void *fdt, int fdt_node)
if (((err = fdt_check_header(fdt)) != 0)
|| (fdt_node < 0) || (fdt_node % FDT_TAGSIZE)
|| (fdt_next_tag(fdt, fdt_node, &fdt_node) != FDT_BEGIN_NODE)) {
- prerror("FDT: Error %d parsing node 0x%x\n", err, fdt_node);
+ PR_ERROR("FDT: Error %d parsing node 0x%x\n", err, fdt_node);
return -1;
}
@@ -761,21 +357,21 @@ int dt_expand_node(struct pdbg_target *node, const void *fdt, int fdt_node)
if (strcmp("status", name) == 0)
node->status = str_to_status(prop->data);
- dt_add_property(node, name, prop->data,
- fdt32_to_cpu(prop->len));
+ pdt_add_property(node, name, prop->data,
+ fdt32_to_cpu(prop->len));
break;
case FDT_BEGIN_NODE:
name = fdt_get_name(fdt, offset, NULL);
- child = dt_new_node(name, fdt, offset);
+ child = pdt_new_node(name, fdt, offset);
assert(child);
- nextoffset = dt_expand_node(child, fdt, offset);
+ nextoffset = pdt_expand_node(child, fdt, offset);
/*
* This may fail in case of duplicate, keep it
* going for now, we may ultimately want to
* assert
*/
- (void)dt_attach_root(node, child);
+ (void)pdt_attach_root(node, child);
break;
case FDT_END:
return -1;
@@ -785,120 +381,107 @@ int dt_expand_node(struct pdbg_target *node, const void *fdt, int fdt_node)
return nextoffset;
}
-void dt_expand(const void *fdt)
+static void pdt_expand(const void *fdt)
{
PR_DEBUG("FDT: Parsing fdt @%p\n", fdt);
- if (dt_expand_node(dt_root, fdt, 0) < 0)
+ if (pdt_expand_node(pdbg_dt_root, fdt, 0) < 0)
abort();
}
-u64 dt_get_number(const void *pdata, unsigned int cells)
+void pdbg_targets_init(void *fdt)
{
- const u32 *p = pdata;
- u64 ret = 0;
-
- while(cells--)
- ret = (ret << 32) | be32toh(*(p++));
- return ret;
+ pdbg_dt_root = pdt_new_node("", NULL, 0);
+ pdt_expand(fdt);
}
-u32 dt_n_address_cells(const struct pdbg_target *node)
+/* Work out the address to access based on the current target and
+ * final class name */
+static struct pdbg_target *get_class_addr(struct pdbg_target *target, const char *name, uint64_t *addr)
{
- if (!node->parent)
- return 0;
- return dt_prop_get_u32_def(node->parent, "#address-cells", 2);
-}
+ /* Check class */
+ while (strcmp(target->class, name)) {
-u32 dt_n_size_cells(const struct pdbg_target *node)
-{
- if (!node->parent)
- return 0;
- return dt_prop_get_u32_def(node->parent, "#size-cells", 1);
-}
+ if (target->translate)
+ *addr = target->translate(target, *addr);
+ else
+ *addr += pdbg_target_address(target, NULL);
-u64 dt_get_address(const struct pdbg_target *node, unsigned int index,
- u64 *out_size)
-{
- const struct dt_property *p;
- u32 na = dt_n_address_cells(node);
- u32 ns = dt_n_size_cells(node);
- u32 pos, n;
-
- p = dt_require_property(node, "reg", -1);
- n = (na + ns) * sizeof(u32);
- pos = n * index;
- assert((pos + n) <= p->len);
- if (out_size)
- *out_size = dt_get_number(p->prop + pos + na * sizeof(u32), ns);
- return dt_get_number(p->prop + pos, na);
+ /* Keep walking the tree translating addresses */
+ target = target->parent;
+
+ /* The root node doesn't have an address space so it's
+ * an error in the device tree if we hit this. */
+ assert(target != pdbg_dt_root);
+ }
+
+ return target;
}
-static u32 __dt_get_chip_id(const struct pdbg_target *node)
+struct pdbg_target *pdbg_target_class_addr(struct pdbg_target *target, const char *name, uint64_t *addr)
{
- const struct dt_property *prop;
+ uint64_t tmp;
- for (; node; node = node->parent) {
- prop = dt_find_property(node, "chip-id");
- if (prop)
- return dt_property_get_cell(prop, 0);
- }
- return 0xffffffff;
+ if (!addr)
+ addr = &tmp;
+
+ return get_class_addr(target, name, addr);
}
-u32 dt_get_chip_id(const struct pdbg_target *node)
+struct pdbg_target *pdbg_target_root(void)
{
- u32 id = __dt_get_chip_id(node);
- assert(id != 0xffffffff);
- return id;
+ return pdbg_dt_root;
}
-struct pdbg_target *dt_find_compatible_node_on_chip(struct pdbg_target *root,
- struct pdbg_target *prev,
- const char *compat,
- uint32_t chip_id)
+static struct pdt_property *pdt_find_property(const struct pdbg_target *node,
+ const char *name)
{
- struct pdbg_target *node;
+ struct pdt_property *i;
- node = prev ? dt_next(root, prev) : root;
- for (; node; node = dt_next(root, node)) {
- u32 cid = __dt_get_chip_id(node);
- if (cid == chip_id &&
- dt_node_is_compatible(node, compat))
- return node;
- }
+ list_for_each(&node->properties, i, list)
+ if (strcmp(i->name, name) == 0)
+ return i;
return NULL;
}
-unsigned int dt_count_addresses(const struct pdbg_target *node)
+static void pdt_resize_property(struct pdt_property **prop, size_t len)
{
- const struct dt_property *p;
- u32 na = dt_n_address_cells(node);
- u32 ns = dt_n_size_cells(node);
- u32 n;
-
- p = dt_require_property(node, "reg", -1);
- n = (na + ns) * sizeof(u32);
+ size_t new_len = sizeof(**prop) + len;
- if (n == 0)
- return 0;
+ *prop = realloc(*prop, new_len);
- return p->len / n;
+ /* Fix up linked lists in case we moved. (note: not an empty list). */
+ (*prop)->list.next->prev = &(*prop)->list;
+ (*prop)->list.prev->next = &(*prop)->list;
}
-u64 dt_translate_address(const struct pdbg_target *node, unsigned int index,
- u64 *out_size)
+void pdbg_set_target_property(struct pdbg_target *target, const char *name, const void *val, size_t size)
{
- /* XXX TODO */
- return dt_get_address(node, index, out_size);
+ struct pdt_property *p;
+
+ if ((p = pdt_find_property(target, name))) {
+ if (size > p->len) {
+ pdt_resize_property(&p, size);
+ p->len = size;
+ }
+
+ memcpy(p->prop, val, size);
+ } else {
+ pdt_add_property(target, name, val, size);
+ }
}
-bool dt_node_is_enabled(struct pdbg_target *node)
+void *pdbg_get_target_property(struct pdbg_target *target, const char *name, size_t *size)
{
- const struct dt_property *p = dt_find_property(node, "status");
+ struct pdt_property *p;
- if (!p)
- return true;
+ p = pdt_find_property(target, name);
+ if (p) {
+ if (size)
+ *size = p->len;
+ return p->prop;
+ } else if (size)
+ *size = 0;
- return p->len > 1 && p->prop[0] == 'o' && p->prop[1] == 'k';
+ return NULL;
}
deleted file mode 100644
@@ -1,228 +0,0 @@
-/* Copyright 2013-2014 IBM Corp.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __DEVICE_H
-#define __DEVICE_H
-#include <ccan/list/list.h>
-#include <ccan/short_types/short_types.h>
-#include "compiler.h"
-
-/* Any property or node with this prefix will not be passed to the kernel. */
-#define DT_PRIVATE "skiboot,"
-
-/*
- * An in-memory representation of a node in the device tree.
- *
- * This is trivially flattened into an fdt.
- *
- * Note that the add_* routines will make a copy of the name if it's not
- * a read-only string (ie. usually a string literal).
- */
-struct dt_property {
- struct list_node list;
- const char *name;
- size_t len;
- char prop[/* len */];
-};
-
-/* This is shared with device_tree.c .. make it static when
- * the latter is gone (hopefully soon)
- */
-extern u32 last_phandle;
-
-extern struct pdbg_target *dt_root;
-extern struct pdbg_target *dt_chosen;
-
-/* Create a new node. */
-struct pdbg_target *dt_new_node(const char *name, const void *fdt, int offset);
-
-/* Graft a root node into this tree. */
-bool dt_attach_root(struct pdbg_target *parent, struct pdbg_target *root);
-
-/* Add a property node, various forms. */
-struct dt_property *dt_add_property(struct pdbg_target *node,
- const char *name,
- const void *val, size_t size);
-struct dt_property *dt_add_property_string(struct pdbg_target *node,
- const char *name,
- const char *value);
-struct dt_property *dt_add_property_nstr(struct pdbg_target *node,
- const char *name,
- const char *value, unsigned int vlen);
-
-/* Given out enough GCC extensions, we will achieve enlightenment! */
-#define dt_add_property_strings(node, name, ...) \
- __dt_add_property_strings((node), ((name)), \
- sizeof((const char *[]) { __VA_ARGS__ })/sizeof(const char *), \
- __VA_ARGS__)
-
-struct dt_property *__dt_add_property_strings(struct pdbg_target *node,
- const char *name,
- int count, ...);
-
-/* Given out enough GCC extensions, we will achieve enlightenment! */
-#define dt_add_property_cells(node, name, ...) \
- __dt_add_property_cells((node), ((name)), \
- sizeof((u32[]) { __VA_ARGS__ })/sizeof(u32), \
- __VA_ARGS__)
-
-struct dt_property *__dt_add_property_cells(struct pdbg_target *node,
- const char *name,
- int count, ...);
-
-#define dt_add_property_u64s(node, name, ...) \
- __dt_add_property_u64s((node), ((name)), \
- sizeof((u64[]) { __VA_ARGS__ })/sizeof(u64), \
- __VA_ARGS__)
-
-struct dt_property *__dt_add_property_u64s(struct pdbg_target *node,
- const char *name,
- int count, ...);
-
-static inline struct dt_property *dt_add_property_u64(struct pdbg_target *node,
- const char *name, u64 val)
-{
- return dt_add_property_cells(node, name, (u32)(val >> 32), (u32)val);
-}
-
-void dt_del_property(struct pdbg_target *node, struct dt_property *prop);
-
-void dt_check_del_prop(struct pdbg_target *node, const char *name);
-
-/* Warning: moves *prop! */
-void dt_resize_property(struct dt_property **prop, size_t len);
-
-u32 dt_property_get_cell(const struct dt_property *prop, u32 index);
-
-/* First child of this node. */
-struct pdbg_target *dt_first(const struct pdbg_target *root);
-
-/* Return next node, or NULL. */
-struct pdbg_target *dt_next(const struct pdbg_target *root, const struct pdbg_target *prev);
-
-/* Iterate nodes */
-#define dt_for_each_node(root, node) \
- for (node = dt_first(root); node; node = dt_next(root, node))
-
-#define dt_for_each_child(parent, node) \
- list_for_each(&parent->children, node, list)
-
-/* Find a string in a string list */
-bool dt_prop_find_string(const struct dt_property *p, const char *s);
-
-/* Check a compatible property */
-bool dt_node_is_compatible(const struct pdbg_target *node, const char *compat);
-
-/* Find a node based on compatible property */
-struct pdbg_target *dt_find_compatible_node(struct pdbg_target *root,
- struct pdbg_target *prev,
- const char *compat);
-
-#define dt_for_each_compatible(root, node, compat) \
- for (node = NULL; \
- (node = dt_find_compatible_node(root, node, compat)) != NULL;)
-
-struct pdbg_target *dt_find_compatible_node_on_chip(struct pdbg_target *root,
- struct pdbg_target *prev,
- const char *compat,
- uint32_t chip_id);
-
-#define dt_for_each_compatible_on_chip(root, node, compat, chip_id) \
- for (node = NULL; \
- (node = dt_find_compatible_node_on_chip(root, node,\
- compat, chip_id)) != NULL;)
-/* Check status property */
-bool dt_node_is_enabled(struct pdbg_target *node);
-
-/* Build the full path for a node. Return a new block of memory, caller
- * shall free() it
- */
-char *dt_get_path(const struct pdbg_target *node);
-
-/* Find a node by path */
-struct pdbg_target *dt_find_by_path(struct pdbg_target *root, const char *path);
-
-/* Find a child node by name */
-struct pdbg_target *dt_find_by_name(struct pdbg_target *root, const char *name);
-
-/* Find a property by name. */
-struct dt_property *dt_find_property(const struct pdbg_target *node,\
- const char *name);
-const struct dt_property *dt_require_property(const struct pdbg_target *node,
- const char *name, int wanted_len);
-
-/* non-const variant */
-struct dt_property *__dt_find_property(struct pdbg_target *node, const char *name);
-
-/* Find a property by name, check if it's the same as val. */
-bool dt_has_node_property(const struct pdbg_target *node,
- const char *name, const char *val);
-
-/* Free a node (and any children). */
-void dt_free(struct pdbg_target *node);
-
-/* Parse an initial fdt */
-void dt_expand(const void *fdt);
-int dt_expand_node(struct pdbg_target *node, const void *fdt, int fdt_node) __warn_unused_result;
-
-/* Simplified accessors */
-u64 dt_prop_get_u64(const struct pdbg_target *node, const char *prop);
-u64 dt_prop_get_u64_def(const struct pdbg_target *node, const char *prop, u64 def);
-u32 dt_prop_get_u32(const struct pdbg_target *node, const char *prop);
-u32 dt_prop_get_u32_def(const struct pdbg_target *node, const char *prop, u32 def);
-u32 dt_prop_get_u32_index(const struct pdbg_target *node, const char *prop, u32 index);
-const void *dt_prop_get(const struct pdbg_target *node, const char *prop);
-const void *dt_prop_get_def(const struct pdbg_target *node, const char *prop,
- void *def);
-const void *dt_prop_get_def_size(const struct pdbg_target *node, const char *prop,
- void *def, size_t *len);
-u32 dt_prop_get_cell(const struct pdbg_target *node, const char *prop, u32 cell);
-u32 dt_prop_get_cell_def(const struct pdbg_target *node, const char *prop, u32 cell, u32 def);
-
-/* Parsing helpers */
-u32 dt_n_address_cells(const struct pdbg_target *node);
-u32 dt_n_size_cells(const struct pdbg_target *node);
-u64 dt_get_number(const void *pdata, unsigned int cells);
-
-/* Find an chip-id property in this node; if not found, walk up the parent
- * nodes. Returns -1 if no chip-id property exists. */
-u32 dt_get_chip_id(const struct pdbg_target *node);
-
-/* Address accessors ("reg" properties parsing). No translation,
- * only support "simple" address forms (1 or 2 cells). Asserts
- * if address doesn't exist
- */
-u64 dt_get_address(const struct pdbg_target *node, unsigned int index,
- u64 *out_size);
-
-/* Count "reg" property entries */
-unsigned int dt_count_addresses(const struct pdbg_target *node);
-
-/* Address translation
- *
- * WARNING: Current implementation is simplified and will not
- * handle complex address formats with address space indicators
- * nor will it handle "ranges" translations yet... (XX TODO)
- */
-u64 dt_translate_address(const struct pdbg_target *node, unsigned int index,
- u64 *out_size);
-
-/* compare function used to sort child nodes by name when added to the
- * tree. This is mainly here for testing.
- */
-int dt_cmp_subnodes(const struct pdbg_target *a, const struct pdbg_target *b);
-
-#endif /* __DEVICE_H */
@@ -91,8 +91,7 @@ static int host_pib_probe(struct pdbg_target *target)
if (!fd)
return -1;
- chip_id = dt_get_chip_id(target);
- if (chip_id == -1)
+ if (pdbg_get_target_u32_property(target, "chip-id", &chip_id))
goto out;
/* This check should probably be done earlier */
@@ -520,7 +520,7 @@ static int configure_nhtm(struct htm *htm, bool wrap)
NHTM_TTYPE_SIZE_MASK ))) /* no pattern matching */
return -1;
- if (dt_node_is_compatible(&htm->target, "ibm,power9-nhtm")) {
+ if (pdbg_target_compatible(&htm->target, "ibm,power9-nhtm")) {
if (HTM_ERR(pib_read(&htm->target, NHTM_FLEX_MUX, &val)))
return -1;
@@ -551,8 +551,7 @@ static char *get_debugfs_file(struct htm *htm, const char *file)
uint32_t chip_id;
char *filename;
- chip_id = dt_get_chip_id(&htm->target);
- if (chip_id == -1) {
+ if (pdbg_get_u32_property(&htm->target, "chip-id", &chip_id)) {
PR_ERROR("Couldn't find a chip id\n");
return NULL;
}
@@ -740,7 +739,7 @@ static int htm_toggle_debug_bit(struct htm *htm)
return 0; /* nhtm case */
/* FIXME: this is a hack for P8 */
- if (!dt_node_is_compatible(core, "ibm,power8-core")) {
+ if (!pdbg_target_compatible(core, "ibm,power8-core")) {
PR_ERROR("HTM is POWER8 only currently\n");
return -1;
}
@@ -867,7 +866,7 @@ static int do_htm_status(struct htm *htm)
uint64_t val, total;
int i, regs = 9;
- if (dt_node_is_compatible(&htm->target, "ibm,power9-nhtm"))
+ if (pdbg_target_compatible(&htm->target, "ibm,power9-nhtm"))
regs++;
PR_INFO("HTM register dump:\n");
@@ -990,8 +989,7 @@ static int do_htm_dump(struct htm *htm, char *filename)
return -1;
}
- chip_id = dt_get_chip_id(&htm->target);
- if (chip_id == -1)
+ if (pdbg_get_u32_property(&htm->target, "chip-id", &chip_id))
return -1;
trace_file = get_debugfs_file(htm, "trace");
@@ -1101,7 +1099,7 @@ static int nhtm_probe(struct pdbg_target *target)
if (!is_debugfs_memtrace_ok() || !is_debugfs_scom_ok())
return -1;
- if (dt_node_is_compatible(target, "ibm,power9-nhtm")) {
+ if (pdbg_target_compatible(target, "ibm,power9-nhtm")) {
pib_read(target, NHTM_FLEX_MUX, &val);
if (GETFIELD(NHTM_FLEX_MUX_MASK, val) != NHTM_FLEX_DEFAULT) {
PR_DEBUG("FLEX_MUX not default\n");
@@ -130,8 +130,11 @@ int i2c_target_probe(struct pdbg_target *target)
const char *bus;
int addr;
- bus = dt_prop_get_def(&pib->target, "bus", "/dev/i2c4");
- addr = dt_get_address(&pib->target, 0, NULL);
+ bus = pdbg_get_target_property(&pib->target, "bus", NULL);
+ if (!bus)
+ bus = "/dev/i2c4";
+
+ addr = pdbg_target_address(&pib->target, NULL);
assert(addr);
i2c_data = malloc(sizeof(*i2c_data));
@@ -1,7 +1,10 @@
+#include <stdlib.h>
#include <string.h>
+#include <libfdt/libfdt.h>
+
+#include "debug.h"
#include "target.h"
-#include "device.h"
#include "libpdbg.h"
static pdbg_progress_tick_t progress_tick;
@@ -137,51 +140,161 @@ const char *pdbg_target_dn_name(struct pdbg_target *target)
char *pdbg_target_path(const struct pdbg_target *target)
{
- return dt_get_path(target);
+ unsigned int len = 0;
+ const struct pdbg_target *n;
+ char *path, *p;
+
+ /* Dealing with NULL is for test/debug purposes */
+ if (!target)
+ return strdup("<NULL>");
+
+ for (n = target; n; n = n->parent) {
+ len += strlen(n->dn_name);
+ if (n->parent || n == target)
+ len++;
+ }
+ path = calloc(1, len + 1);
+ assert(path);
+ p = path + len;
+ for (n = target; n; n = n->parent) {
+ len = strlen(n->dn_name);
+ p -= len;
+ memcpy(p, n->dn_name, len);
+ if (n->parent || n == target)
+ *(--p) = '/';
+ }
+ assert(p == path);
+
+ return p;
}
-struct pdbg_target *pdbg_target_find_by_path(struct pdbg_target *target, const char *path)
+static const char *pdt_path_split(const char *p,
+ const char **namep, unsigned int *namel,
+ const char **addrp, unsigned int *addrl)
{
- if (!target)
- target = dt_root;
+ const char *at, *sl;
+
+ *namel = *addrl = 0;
+
+ /* Skip initial '/' */
+ while (*p == '/')
+ p++;
+
+ /* Check empty path */
+ if (*p == 0)
+ return p;
+
+ at = strchr(p, '@');
+ sl = strchr(p, '/');
+ if (sl == NULL)
+ sl = p + strlen(p);
+ if (sl < at)
+ at = NULL;
+ if (at) {
+ *addrp = at + 1;
+ *addrl = sl - at - 1;
+ }
+ *namep = p;
+ *namel = at ? (at - p) : (sl - p);
- return dt_find_by_path(target, path);
+ return sl;
}
-void pdbg_set_target_property(struct pdbg_target *target, const char *name, const void *val, size_t size)
+struct pdbg_target *pdbg_target_find_by_path(struct pdbg_target *target, const char *path)
{
- struct dt_property *p;
+ struct pdbg_target *n;
+ const char *pn, *pa = NULL, *p = path, *nn = NULL, *na = NULL;
+ unsigned int pnl, pal, nnl, nal;
+ bool match;
- if ((p = dt_find_property(target, name))) {
- if (size > p->len) {
- dt_resize_property(&p, size);
- p->len = size;
+ if (!target)
+ target = pdbg_target_root();
+
+ /* Walk path components */
+ while (*p) {
+ /* Extract next path component */
+ p = pdt_path_split(p, &pn, &pnl, &pa, &pal);
+ if (pnl == 0 && pal == 0)
+ break;
+
+ /* Compare with each child node */
+ match = false;
+ list_for_each(&target->children, n, list) {
+ match = true;
+ pdt_path_split(n->dn_name, &nn, &nnl, &na, &nal);
+ if (pnl && (pnl != nnl || strncmp(pn, nn, pnl)))
+ match = false;
+ if (pal && (pal != nal || strncmp(pa, na, pal)))
+ match = false;
+ if (match) {
+ target = n;
+ break;
+ }
}
- memcpy(p->prop, val, size);
- } else {
- dt_add_property(target, name, val, size);
+ /* No child match */
+ if (!match)
+ return NULL;
}
+
+ return target;
}
-void *pdbg_get_target_property(struct pdbg_target *target, const char *name, size_t *size)
+static uint32_t pdbg_target_get_u32_def(struct pdbg_target *target, const char *prop, u32 def)
{
- struct dt_property *p;
+ uint32_t val;
- p = dt_find_property(target, name);
- if (p) {
- if (size)
- *size = p->len;
- return p->prop;
- } else if (size)
- *size = 0;
+ if (pdbg_get_target_u32_property(target, prop, &val))
+ return def;
+ else
+ return val;
+}
- return NULL;
+static uint32_t pdt_n_address_cells(struct pdbg_target *target)
+{
+ if (!target->parent)
+ return 0;
+ return pdbg_target_get_u32_def(target->parent, "#address-cells", 2);
}
-uint64_t pdbg_get_address(struct pdbg_target *target, uint64_t *size)
+static uint32_t pdt_n_size_cells(struct pdbg_target *target)
{
- return dt_get_address(target, 0, size);
+ if (!target->parent)
+ return 0;
+ return pdbg_target_get_u32_def(target->parent, "#size-cells", 1);
+}
+
+static uint64_t pdt_get_number(const void *pdata, unsigned int cells)
+{
+ const u32 *p = pdata;
+ u64 ret = 0;
+
+ /* Our return type (u64) can only hold at most two cells */
+ assert(cells <= 2);
+
+ while(cells--)
+ ret = (ret << 32) | be32toh(*(p++));
+
+ return ret;
+}
+
+uint64_t pdbg_target_address(struct pdbg_target *target, uint64_t *out_size)
+{
+ size_t len;
+ u32 na = pdt_n_address_cells(target);
+ u32 ns = pdt_n_size_cells(target);
+ u32 pos, n, index = 0;
+ void *p;
+
+ p = pdbg_get_target_property(target, "reg", &len);
+ n = (na + ns) * sizeof(u32);
+ pos = n * index;
+ assert((pos + n) <= len);
+
+ if (out_size)
+ *out_size = pdt_get_number(p + pos + na * sizeof(u32), ns);
+
+ return pdt_get_number(p + pos, na);
}
/* Difference from below is that it doesn't search up the tree for the given
@@ -189,28 +302,61 @@ uint64_t pdbg_get_address(struct pdbg_target *target, uint64_t *size)
* future */
static int pdbg_get_target_u64_property(struct pdbg_target *target, const char *name, uint64_t *val)
{
- struct dt_property *p;
+ uint32_t *p;
+ size_t size;
- p = dt_find_property(target, name);
+ p = pdbg_get_target_property(target, name, &size);
if (!p)
return -1;
- *val = dt_get_number(p->prop, 2);
+ assert(size == 8);
+ *val = pdt_get_number(p, 2);
return 0;
}
int pdbg_get_target_u32_property(struct pdbg_target *target, const char *name, uint32_t *val)
{
- struct dt_property *p;
+ uint32_t *p;
+ size_t size;
+
+ p = pdbg_get_target_property(target, name, &size);
+ if (!p)
+ return -1;
+
+ assert(size == 4);
+ *val = be32toh(*p);
+
+ return 0;
+}
+
+int pdbg_get_target_u32_index(struct pdbg_target *target, const char *prop, int index, uint32_t *val)
+{
+ size_t len;
+ void *p;
- p = dt_find_property(target, name);
+ p = pdbg_get_target_property(target, prop, &len);
if (!p)
return -1;
- *val = dt_get_number(p->prop, 1);
+ assert(len >= (index+1)*sizeof(u32));
+
+ /* Always aligned, so this works. */
+ *val = be32toh(((const u32 *)p)[index]);
return 0;
}
+int pdbg_get_u32_property(struct pdbg_target *target, const char *name, uint32_t *val)
+{
+ struct pdbg_target *dn;
+
+ for (dn = target; dn; dn = dn->parent) {
+ if (!pdbg_get_target_u32_property(dn, name, val))
+ return 0;
+ }
+
+ return -1;
+}
+
int pdbg_get_u64_property(struct pdbg_target *target, const char *name, uint64_t *val)
{
struct pdbg_target *dn;
@@ -223,6 +369,26 @@ int pdbg_get_u64_property(struct pdbg_target *target, const char *name, uint64_t
return -1;
}
+bool pdbg_target_compatible(struct pdbg_target *target, const char *compatible)
+{
+ char *c, *end;
+ size_t len;
+
+ c = pdbg_get_target_property(target, "compatible", &len);
+ if (!c)
+ return false;
+
+ end = c + len;
+ while(c < end) {
+ if (!strcasecmp(compatible, c))
+ return true;
+
+ c += strlen(c) + 1;
+ }
+
+ return false;
+}
+
void pdbg_progress_tick(uint64_t cur, uint64_t end)
{
if (progress_tick)
@@ -12,6 +12,9 @@ struct pdbg_target;
struct pdbg_target_class;
/* loops/iterators */
+struct pdbg_target *__pdbg_find_compatible_node(struct pdbg_target *root,
+ struct pdbg_target *prev,
+ const char *compat);
struct pdbg_target *__pdbg_next_target(const char *klass, struct pdbg_target *parent, struct pdbg_target *last);
struct pdbg_target *__pdbg_next_child_target(struct pdbg_target *parent, struct pdbg_target *last);
@@ -45,6 +48,10 @@ enum pdbg_target_status {PDBG_TARGET_UNKNOWN = 0, PDBG_TARGET_ENABLED,
PDBG_TARGET_DISABLED, PDBG_TARGET_MUSTEXIST,
PDBG_TARGET_NONEXISTENT, PDBG_TARGET_RELEASED};
+#define pdbg_for_each_compatible(parent, target, compat) \
+ for (target = NULL; \
+ (target = __pdbg_find_compatible_node(parent, target, compat)) != NULL;)
+
#define pdbg_for_each_target(class, parent, target) \
for (target = __pdbg_next_target(class, parent, NULL); \
target; \
@@ -73,8 +80,12 @@ void pdbg_set_target_property(struct pdbg_target *target, const char *name, cons
/* Get the given property and return the size */
void *pdbg_get_target_property(struct pdbg_target *target, const char *name, size_t *size);
int pdbg_get_target_u32_property(struct pdbg_target *target, const char *name, uint32_t *val);
+int pdbg_get_target_u32_index(struct pdbg_target *target, const char *prop, int index, uint32_t *val);
+int pdbg_get_u32_property(struct pdbg_target *target, const char *name, uint32_t *val);
int pdbg_get_u64_property(struct pdbg_target *target, const char *name, uint64_t *val);
-uint64_t pdbg_get_address(struct pdbg_target *target, uint64_t *size);
+uint64_t pdbg_target_address(struct pdbg_target *target, uint64_t *size);
+struct pdbg_target *pdbg_target_class_addr(struct pdbg_target *target, const char *name, uint64_t *addr);
+bool pdbg_target_compatible(struct pdbg_target *target, const char *compatible);
/* Misc. */
void pdbg_targets_init(void *fdt);
@@ -155,7 +155,7 @@ static int assert_special_wakeup(struct core *chip)
if (i++ > SPECIAL_WKUP_TIMEOUT) {
PR_ERROR("Timeout waiting for special wakeup on %s@0x%08" PRIx64 "\n", chip->target.name,
- dt_get_address(&chip->target, 0, NULL));
+ pdbg_target_address(&chip->target, NULL));
return -1;
}
} while (!(gp0 & SPECIAL_WKUP_DONE));
@@ -355,7 +355,7 @@ static int p8_ram_setup(struct thread *thread)
/* We can only ram a thread if all the threads on the core/chip are
* quiesced */
- dt_for_each_compatible(&chip->target, target, "ibm,power8-thread") {
+ pdbg_for_each_compatible(&chip->target, target, "ibm,power8-thread") {
struct thread *tmp;
/* If this thread wasn't enabled it may not yet have been probed
@@ -479,7 +479,7 @@ static int p8_thread_probe(struct pdbg_target *target)
{
struct thread *thread = target_to_thread(target);
- thread->id = (dt_get_address(target, 0, NULL) >> 4) & 0xf;
+ thread->id = (pdbg_target_address(target, NULL) >> 4) & 0xf;
thread->status = get_thread_status(thread);
return 0;
@@ -118,8 +118,10 @@ static struct thread_state p9_get_thread_status(struct thread *thread)
static int p9_thread_probe(struct pdbg_target *target)
{
struct thread *thread = target_to_thread(target);
+ uint32_t tid;
- thread->id = dt_prop_get_u32(target, "tid");
+ assert(!pdbg_get_target_u32_property(target, "tid", &tid));
+ thread->id = tid;
thread->status = p9_get_thread_status(thread);
return 0;
@@ -527,7 +529,7 @@ static int p9_core_probe(struct pdbg_target *target)
if (i++ > SPECIAL_WKUP_TIMEOUT) {
PR_ERROR("Timeout waiting for special wakeup on %s@0x%08" PRIx64 "\n", target->name,
- dt_get_address(target, 0, NULL));
+ pdbg_target_address(target, NULL));
break;
}
} while (!(value & SPECIAL_WKUP_DONE));
@@ -1,52 +1,32 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
#include <stdint.h>
#include <inttypes.h>
#include <assert.h>
-#include <ccan/list/list.h>
-#include <libfdt/libfdt.h>
+#include "operations.h"
#include "bitutils.h"
+#include "libpdbg.h"
#include "target.h"
-#include "device.h"
-#include "operations.h"
#include "debug.h"
-struct list_head empty_list = LIST_HEAD_INIT(empty_list);
-struct list_head target_classes = LIST_HEAD_INIT(target_classes);
-
-/* Work out the address to access based on the current target and
- * final class name */
-static struct pdbg_target *get_class_target_addr(struct pdbg_target *target, const char *name, uint64_t *addr)
-{
- /* Check class */
- while (strcmp(target->class, name)) {
-
- if (target->translate)
- *addr = target->translate(target, *addr);
- else
- *addr += dt_get_address(target, 0, NULL);
-
- /* Keep walking the tree translating addresses */
- target = target->parent;
-
- /* The root node doesn't have an address space so it's
- * an error in the device tree if we hit this. */
- assert(target != dt_root);
- }
-
- return target;
-}
-
-struct pdbg_target *pdbg_class_target_addr(struct pdbg_target *target, const char *name, uint64_t *addr)
-{
- uint64_t tmp;
-
- if (!addr)
- addr = &tmp;
-
- return get_class_target_addr(target, name, addr);
-}
-
/* The indirect access code was largely stolen from hw/xscom.c in skiboot */
#define PIB_IND_MAX_RETRIES 10
#define PIB_IND_READ PPC_BIT(0)
@@ -130,7 +110,7 @@ int pib_read(struct pdbg_target *pib_dt, uint64_t addr, uint64_t *data)
uint64_t target_addr = addr;
int rc;
- pib_dt = get_class_target_addr(pib_dt, "pib", &target_addr);
+ pib_dt = pdbg_target_class_addr(pib_dt, "pib", &target_addr);
pib = target_to_pib(pib_dt);
if (target_addr & PPC_BIT(0))
rc = pib_indirect_read(pib, target_addr, data);
@@ -147,7 +127,7 @@ int pib_write(struct pdbg_target *pib_dt, uint64_t addr, uint64_t data)
uint64_t target_addr = addr;
int rc;
- pib_dt = get_class_target_addr(pib_dt, "pib", &target_addr);
+ pib_dt = pdbg_target_class_addr(pib_dt, "pib", &target_addr);
pib = target_to_pib(pib_dt);
PR_DEBUG("addr:0x%08" PRIx64 " data:0x%016" PRIx64 "\n",
target_addr, data);
@@ -165,7 +145,7 @@ int pib_wait(struct pdbg_target *pib_dt, uint64_t addr, uint64_t mask, uint64_t
uint64_t tmp;
int rc;
- pib_dt = get_class_target_addr(pib_dt, "pib", &addr);
+ pib_dt = pdbg_target_class_addr(pib_dt, "pib", &addr);
pib = target_to_pib(pib_dt);
do {
@@ -185,7 +165,7 @@ int opb_read(struct pdbg_target *opb_dt, uint32_t addr, uint32_t *data)
struct opb *opb;
uint64_t addr64 = addr;
- opb_dt = get_class_target_addr(opb_dt, "opb", &addr64);
+ opb_dt = pdbg_target_class_addr(opb_dt, "opb", &addr64);
opb = target_to_opb(opb_dt);
return opb->read(opb, addr64, data);
}
@@ -195,7 +175,7 @@ int opb_write(struct pdbg_target *opb_dt, uint32_t addr, uint32_t data)
struct opb *opb;
uint64_t addr64 = addr;
- opb_dt = get_class_target_addr(opb_dt, "opb", &addr64);
+ opb_dt = pdbg_target_class_addr(opb_dt, "opb", &addr64);
opb = target_to_opb(opb_dt);
return opb->write(opb, addr64, data);
@@ -206,7 +186,7 @@ int fsi_read(struct pdbg_target *fsi_dt, uint32_t addr, uint32_t *data)
struct fsi *fsi;
uint64_t addr64 = addr;
- fsi_dt = get_class_target_addr(fsi_dt, "fsi", &addr64);
+ fsi_dt = pdbg_target_class_addr(fsi_dt, "fsi", &addr64);
fsi = target_to_fsi(fsi_dt);
return fsi->read(fsi, addr64, data);
}
@@ -216,7 +196,7 @@ int fsi_write(struct pdbg_target *fsi_dt, uint32_t addr, uint32_t data)
struct fsi *fsi;
uint64_t addr64 = addr;
- fsi_dt = get_class_target_addr(fsi_dt, "fsi", &addr64);
+ fsi_dt = pdbg_target_class_addr(fsi_dt, "fsi", &addr64);
fsi = target_to_fsi(fsi_dt);
return fsi->write(fsi, addr64, data);
@@ -288,12 +268,6 @@ struct hw_unit_info *find_compatible_target(const char *compat)
return NULL;
}
-void pdbg_targets_init(void *fdt)
-{
- dt_root = dt_new_node("", NULL, 0);
- dt_expand(fdt);
-}
-
/* We walk the tree root down disabling targets which might/should
* exist but don't */
enum pdbg_target_status pdbg_target_probe(struct pdbg_target *target)
@@ -361,6 +335,9 @@ void pdbg_target_release(struct pdbg_target *target)
{
struct pdbg_target *child;
+ if (!target)
+ target = pdbg_target_root();
+
if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
return;
@@ -381,7 +358,7 @@ void pdbg_target_probe_all(struct pdbg_target *parent)
struct pdbg_target *child;
if (!parent)
- parent = dt_root;
+ parent = pdbg_target_root();
pdbg_for_each_child_target(parent, child) {
pdbg_target_probe_all(child);
@@ -405,8 +382,3 @@ void pdbg_target_priv_set(struct pdbg_target *target, void *priv)
{
target->priv = priv;
}
-
-struct pdbg_target *pdbg_target_root(void)
-{
- return dt_root;
-}
@@ -20,8 +20,8 @@
#include <ccan/list/list.h>
#include <ccan/str/str.h>
#include <ccan/container_of/container_of.h>
+#include <ccan/short_types/short_types.h>
#include "compiler.h"
-#include "device.h"
#include "libpdbg.h"
enum chip_type {CHIP_UNKNOWN, CHIP_P8, CHIP_P8NV, CHIP_P9};
@@ -178,4 +178,5 @@ struct xbus {
uint32_t chip_id;
};
#define target_to_xbus(x) container_of(x, struct xbus, target)
+
#endif
@@ -34,7 +34,6 @@
#include <ccan/array_size/array_size.h>
#include <libpdbg.h>
-#include <device.h>
#include <bitutils.h>
#include "main.h"
@@ -789,7 +789,7 @@ OPTCMD_DEFINE_CMD(probe, probe);
*/
static void atexit_release(void)
{
- pdbg_target_release(dt_root);
+ pdbg_target_release(NULL);
}
int main(int argc, char *argv[])
The device-tree parsing code in libpdbg/device.c was originally taken from Skiboot. Much of it is not useful for pdbg and is unused so can be removed. The remaining code could cause naming conflicts if it is ever used in a Skiboot like environment so has been restructured to allow most of the remaining definitions to be declared static. Signed-off-by: Alistair Popple <alistair@popple.id.au> --- Makefile.am | 1 - libpdbg/bmcfsi.c | 38 ++- libpdbg/cfam.c | 6 +- libpdbg/device.c | 751 ++++++++++++------------------------------------------ libpdbg/device.h | 228 ----------------- libpdbg/host.c | 3 +- libpdbg/htm.c | 14 +- libpdbg/i2c.c | 7 +- libpdbg/libpdbg.c | 232 ++++++++++++++--- libpdbg/libpdbg.h | 13 +- libpdbg/p8chip.c | 6 +- libpdbg/p9chip.c | 6 +- libpdbg/target.c | 90 +++---- libpdbg/target.h | 3 +- src/htm.c | 1 - src/main.c | 2 +- 16 files changed, 458 insertions(+), 943 deletions(-) delete mode 100644 libpdbg/device.h