summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2017-11-13 08:21:07 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2017-11-13 08:21:07 +0100
commit9d842e3bb0751a394e08f07495d9e918cb37f857 (patch)
treec7aa61049e874002cfbe52761db49dc06f2d3e8b /common
parente65434fca43a20a2f6dc207a02e7b03b749ba1b4 (diff)
parent2877e08f9e1afc0124c034c8466acedcc9696bac (diff)
downloadbarebox-9d842e3bb0751a394e08f07495d9e918cb37f857.tar.gz
barebox-9d842e3bb0751a394e08f07495d9e918cb37f857.tar.xz
Merge branch 'for-next/omap'
Diffstat (limited to 'common')
-rw-r--r--common/oftree.c89
-rw-r--r--common/state/state.c23
-rw-r--r--common/state/state.h17
-rw-r--r--common/state/state_variables.c38
4 files changed, 158 insertions, 9 deletions
diff --git a/common/oftree.c b/common/oftree.c
index 09a4455a9e..40eb35f188 100644
--- a/common/oftree.c
+++ b/common/oftree.c
@@ -11,6 +11,7 @@
#include <getopt.h>
#include <init.h>
#include <boot.h>
+#include <i2c/i2c.h>
#define MAX_LEVEL 32 /* how deeply nested we will go */
@@ -260,3 +261,91 @@ struct fdt_header *of_get_fixed_tree(struct device_node *node)
return fdt;
}
+
+/**
+ * of_autoenable_device_by_path() - Autoenable a device by a device tree path
+ * @param path Device tree path up from the root to the device
+ * @return 0 on success, -enodev on failure. If no device found in the device
+ * tree.
+ *
+ * This function will search for a device and will enable it in the kernel
+ * device tree, if it exists and is loaded.
+ */
+int of_autoenable_device_by_path(char *path)
+{
+ struct device_node *node;
+ int ret;
+
+ node = of_find_node_by_name(NULL, path);
+ if (!node)
+ node = of_find_node_by_path(path);
+
+ if (!node)
+ return -ENODEV;
+
+ if (!of_device_is_available(node))
+ return -ENODEV;
+
+ ret = of_register_set_status_fixup(path, 1);
+ if (!ret)
+ printf("autoenabled %s\n", node->name);
+ return ret;
+}
+
+/**
+ * of_autoenable_i2c_by_component - Autoenable a i2c client by a device tree path
+ * @param path Device tree path up from the root to the i2c client
+ * @return 0 on success, -enodev on failure. If no i2c client found in the i2c
+ * device tree.
+ *
+ * This function will search for a i2c client, tries to write to the client and
+ * will enable it in the kernel device tree, if it exists and is accessible.
+ */
+int of_autoenable_i2c_by_component(char *path)
+{
+ struct device_node *node;
+ struct i2c_adapter *i2c_adapter;
+ struct i2c_msg msg;
+ char data[1] = {0x0};
+ int ret;
+ uint32_t addr;
+
+ if (!IS_ENABLED(CONFIG_I2C))
+ return -ENODEV;
+
+ node = of_find_node_by_name(NULL, path);
+ if (!node)
+ node = of_find_node_by_path(path);
+ if (!node)
+ return -ENODEV;
+ if (!node->parent)
+ return -ENODEV;
+
+ ret = of_property_read_u32(node, "reg", &addr);
+ if (ret)
+ return -ENODEV;
+
+ i2c_adapter = of_find_i2c_adapter_by_node(node->parent);
+ if (!i2c_adapter)
+ return -ENODEV;
+
+ msg.buf = data;
+ msg.addr = addr;
+ msg.len = 1;
+
+ /* Try to communicate with the i2c client */
+ ret = i2c_transfer(i2c_adapter, &msg, 1);
+ if (ret == -EREMOTEIO)
+ return -ENODEV;
+ if (ret < 1) {
+ printf("failed to autoenable i2c device on address 0x%x with %i\n",
+ addr, ret);
+ return ret;
+ }
+
+ ret = of_register_set_status_fixup(path, 1);
+ if (!ret)
+ printf("autoenabled i2c device %s\n", node->name);
+
+ return ret;
+}
diff --git a/common/state/state.c b/common/state/state.c
index 266d211bd7..6399bd3736 100644
--- a/common/state/state.c
+++ b/common/state/state.c
@@ -246,7 +246,7 @@ static int state_convert_node_variable(struct state *state,
}
if (conv == STATE_CONVERT_FROM_NODE_CREATE) {
- sv = vtype->create(state, name, node);
+ sv = vtype->create(state, name, node, vtype);
if (IS_ERR(sv)) {
ret = PTR_ERR(sv);
dev_err(&state->dev, "failed to create %s: %s\n", name,
@@ -693,6 +693,27 @@ int state_get_name(const struct state *state, char const **name)
return 0;
}
+int state_read_mac(struct state *state, const char *name, u8 *buf)
+{
+ struct state_variable *svar;
+ struct state_mac *mac;
+
+ if (!state || !name || !buf)
+ return -EINVAL;
+
+ svar = state_find_var(state, name);
+ if (IS_ERR(svar))
+ return PTR_ERR(svar);
+
+ if (svar->type->type != STATE_VARIABLE_TYPE_MAC)
+ return -EINVAL;
+
+ mac = to_state_mac(svar);
+ memcpy(buf, mac->value, 6);
+
+ return 0;
+}
+
void state_info(void)
{
struct state *state;
diff --git a/common/state/state.h b/common/state/state.h
index 81aaec23b6..fcc6b9f5cd 100644
--- a/common/state/state.h
+++ b/common/state/state.h
@@ -9,6 +9,14 @@ enum state_flags {
STATE_FLAG_NO_AUTHENTIFICATION = (1 << 0),
};
+enum state_variable_type {
+ STATE_VARIABLE_TYPE_UINT8,
+ STATE_VARIABLE_TYPE_UINT32,
+ STATE_VARIABLE_TYPE_ENUM32,
+ STATE_VARIABLE_TYPE_MAC,
+ STATE_VARIABLE_TYPE_STRING
+};
+
/**
* state_backend_storage_bucket - This class describes a single backend storage
* object copy
@@ -119,19 +127,22 @@ struct state_variable;
/* A variable type (uint32, enum32) */
struct variable_type {
const char *type_name;
+ enum state_variable_type type;
struct list_head list;
int (*export) (struct state_variable *, struct device_node *,
enum state_convert);
int (*import) (struct state_variable *, struct device_node *);
- struct state_variable *(*create) (struct state * state,
- const char *name,
- struct device_node *);
+ struct state_variable *(*create) (struct state *,
+ const char *,
+ struct device_node *,
+ const struct variable_type *);
};
/* instance of a single variable */
struct state_variable {
struct state *state;
struct list_head list;
+ const struct variable_type *type;
const char *name;
unsigned int start;
unsigned int size;
diff --git a/common/state/state_variables.c b/common/state/state_variables.c
index 56bcd9590a..de9ba4ab61 100644
--- a/common/state/state_variables.c
+++ b/common/state/state_variables.c
@@ -101,7 +101,8 @@ static int state_uint8_set(struct param_d *p, void *priv)
static struct state_variable *state_uint8_create(struct state *state,
const char *name,
- struct device_node *node)
+ struct device_node *node,
+ const struct variable_type *vtype)
{
struct state_uint32 *su32;
struct param_d *param;
@@ -116,6 +117,7 @@ static struct state_variable *state_uint8_create(struct state *state,
}
su32->param = param;
+ su32->var.type = vtype;
su32->var.size = sizeof(uint8_t);
#ifdef __LITTLE_ENDIAN
su32->var.raw = &su32->value;
@@ -129,7 +131,8 @@ static struct state_variable *state_uint8_create(struct state *state,
static struct state_variable *state_uint32_create(struct state *state,
const char *name,
- struct device_node *node)
+ struct device_node *node,
+ const struct variable_type *vtype)
{
struct state_uint32 *su32;
struct param_d *param;
@@ -144,6 +147,7 @@ static struct state_variable *state_uint32_create(struct state *state,
}
su32->param = param;
+ su32->var.type = vtype;
su32->var.size = sizeof(uint32_t);
su32->var.raw = &su32->value;
su32->var.state = state;
@@ -218,7 +222,8 @@ static int state_enum32_import(struct state_variable *sv,
static struct state_variable *state_enum32_create(struct state *state,
const char *name,
- struct device_node *node)
+ struct device_node *node,
+ const struct variable_type *vtype)
{
struct state_enum32 *enum32;
int ret, i, num_names;
@@ -234,6 +239,7 @@ static struct state_variable *state_enum32_create(struct state *state,
enum32->names = xzalloc(sizeof(char *) * num_names);
enum32->num_names = num_names;
+ enum32->var.type = vtype;
enum32->var.size = sizeof(uint32_t);
enum32->var.raw = &enum32->value;
enum32->var.state = state;
@@ -300,13 +306,15 @@ static int state_mac_import(struct state_variable *sv, struct device_node *node)
static struct state_variable *state_mac_create(struct state *state,
const char *name,
- struct device_node *node)
+ struct device_node *node,
+ const struct variable_type *vtype)
{
struct state_mac *mac;
int ret;
mac = xzalloc(sizeof(*mac));
+ mac->var.type = vtype;
mac->var.size = ARRAY_SIZE(mac->value);
mac->var.raw = mac->value;
mac->var.state = state;
@@ -402,7 +410,8 @@ static int state_string_get(struct param_d *p, void *priv)
static struct state_variable *state_string_create(struct state *state,
const char *name,
- struct device_node *node)
+ struct device_node *node,
+ const struct variable_type *vtype)
{
struct state_string *string;
uint32_t start_size[2];
@@ -420,6 +429,7 @@ static struct state_variable *state_string_create(struct state *state,
return ERR_PTR(-EILSEQ);
string = xzalloc(sizeof(*string) + start_size[1]);
+ string->var.type = vtype;
string->var.size = start_size[1];
string->var.raw = &string->raw;
string->var.state = state;
@@ -440,26 +450,31 @@ static struct state_variable *state_string_create(struct state *state,
static struct variable_type types[] = {
{
.type_name = "uint8",
+ .type = STATE_VARIABLE_TYPE_UINT8,
.export = state_uint32_export,
.import = state_uint32_import,
.create = state_uint8_create,
}, {
.type_name = "uint32",
+ .type = STATE_VARIABLE_TYPE_UINT32,
.export = state_uint32_export,
.import = state_uint32_import,
.create = state_uint32_create,
}, {
.type_name = "enum32",
+ .type = STATE_VARIABLE_TYPE_ENUM32,
.export = state_enum32_export,
.import = state_enum32_import,
.create = state_enum32_create,
}, {
.type_name = "mac",
+ .type = STATE_VARIABLE_TYPE_MAC,
.export = state_mac_export,
.import = state_mac_import,
.create = state_mac_create,
}, {
.type_name = "string",
+ .type = STATE_VARIABLE_TYPE_STRING,
.export = state_string_export,
.import = state_string_import,
.create = state_string_create,
@@ -479,6 +494,19 @@ struct variable_type *state_find_type_by_name(const char *name)
return NULL;
}
+struct variable_type *state_find_type(const enum state_variable_type type)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(types); i++) {
+ if (type == types[i].type) {
+ return &types[i];
+ }
+ }
+
+ return NULL;
+}
+
struct state_variable *state_find_var(struct state *state, const char *name)
{
struct state_variable *sv;