9
0
Fork 0

state: add fixup to copy state from barebox to kernel device tree

This patch registeres a DT fixup, that copies the statate nodes from the active
to the kernel DT. The backend reference will be a phandles.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
[ukl: add call to of_unregister_fixup]
This commit is contained in:
Marc Kleine-Budde 2015-05-04 01:09:13 +02:00 committed by Jan Luebbe
parent 4e26c8c6d9
commit 177c5b7739
1 changed files with 100 additions and 7 deletions

View File

@ -435,13 +435,6 @@ static struct state *state_new(const char *name)
return state;
}
void state_release(struct state *state)
{
list_del(&state->list);
unregister_device(&state->dev);
free(state);
}
static struct state_variable *state_find_var(struct state *state,
const char *name)
{
@ -673,6 +666,101 @@ static int state_from_node(struct state *state, struct device_node *node,
return ret;
}
static int of_state_fixup(struct device_node *root, void *ctx)
{
struct state *state = ctx;
const char *compatible = "barebox,state";
struct device_node *new_node, *node, *parent, *backend_node;
struct property *p;
int ret;
phandle phandle;
node = of_find_node_by_path_from(root, state->root->full_name);
if (node) {
/* replace existing node - it will be deleted later */
parent = node->parent;
} else {
char *of_path, *c;
/* look for parent, remove last '/' from path */
of_path = xstrdup(state->root->full_name);
c = strrchr(of_path, '/');
if (!c)
return -ENODEV;
*c = '0';
parent = of_find_node_by_path(of_path);
if (!parent)
parent = root;
free(of_path);
}
/* serialize variable definitions */
new_node = state_to_node(state, parent, STATE_CONVERT_FIXUP);
if (IS_ERR(new_node))
return PTR_ERR(new_node);
/* compatible */
p = of_new_property(new_node, "compatible", compatible,
strlen(compatible) + 1);
if (!p) {
ret = -ENOMEM;
goto out;
}
/* backend-type */
if (!state->backend) {
ret = -ENODEV;
goto out;
}
p = of_new_property(new_node, "backend-type", state->backend->name,
strlen(state->backend->name) + 1);
if (!p) {
ret = -ENOMEM;
goto out;
}
/* backend phandle */
backend_node = of_find_node_by_path_from(root, state->backend->of_path);
if (!backend_node) {
ret = -ENODEV;
goto out;
}
phandle = of_node_create_phandle(backend_node);
ret = of_property_write_u32(new_node, "backend", phandle);
if (ret)
goto out;
/* address-cells + size-cells */
ret = of_property_write_u32(new_node, "#address-cells", 1);
if (ret)
goto out;
ret = of_property_write_u32(new_node, "#size-cells", 1);
if (ret)
goto out;
/* delete existing node */
if (node)
of_delete_node(node);
return 0;
out:
of_delete_node(new_node);
return ret;
}
void state_release(struct state *state)
{
of_unregister_fixup(of_state_fixup, state);
list_del(&state->list);
unregister_device(&state->dev);
free(state);
}
/*
* state_new_from_node - create a new state instance from a device_node
*
@ -694,6 +782,11 @@ struct state *state_new_from_node(const char *name, struct device_node *node)
return ERR_PTR(ret);
}
ret = of_register_fixup(of_state_fixup, state);
if (ret) {
state_release(state);
return ERR_PTR(ret);
}
return state;
}