diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2017-11-13 08:21:07 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2017-11-13 08:21:07 +0100 |
commit | 9d842e3bb0751a394e08f07495d9e918cb37f857 (patch) | |
tree | c7aa61049e874002cfbe52761db49dc06f2d3e8b /common | |
parent | e65434fca43a20a2f6dc207a02e7b03b749ba1b4 (diff) | |
parent | 2877e08f9e1afc0124c034c8466acedcc9696bac (diff) | |
download | barebox-9d842e3bb0751a394e08f07495d9e918cb37f857.tar.gz barebox-9d842e3bb0751a394e08f07495d9e918cb37f857.tar.xz |
Merge branch 'for-next/omap'
Diffstat (limited to 'common')
-rw-r--r-- | common/oftree.c | 89 | ||||
-rw-r--r-- | common/state/state.c | 23 | ||||
-rw-r--r-- | common/state/state.h | 17 | ||||
-rw-r--r-- | common/state/state_variables.c | 38 |
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; |