This patch adds an API to automatically enable either hardware components with existing device drivers or i2c clients. All functions take a device tree path to find the hardware and will fix up the node status in the kernel device tree, if it's accessible. Signed-off-by: Daniel Schultz <d.schultz@xxxxxxxxx> --- common/Kconfig | 9 +++++ common/Makefile | 1 + common/autoenable.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/autoenable.h | 21 ++++++++++ 4 files changed, 140 insertions(+) create mode 100644 common/autoenable.c create mode 100644 include/autoenable.h diff --git a/common/Kconfig b/common/Kconfig index 57418ca..8d2a3e6 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -712,6 +712,15 @@ config CONSOLE_NONE endchoice +config KERNEL_AUTOENABLE + bool + prompt "Autoenable of components" + help + Say Y to unlock an API for automatically enable either hardware + components with existing device drivers or i2c clients. All functions + take a device tree path to find the hardware and will fix up the node + status in the kernel device tree, if it's accessible. + choice prompt "Console activation strategy" depends on CONSOLE_FULL diff --git a/common/Makefile b/common/Makefile index 8cd0ab3..4d7b0f9 100644 --- a/common/Makefile +++ b/common/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_FLEXIBLE_BOOTARGS) += bootargs.o obj-$(CONFIG_GLOBALVAR) += globalvar.o obj-$(CONFIG_GREGORIAN_CALENDER) += date.o obj-$(CONFIG_KALLSYMS) += kallsyms.o +obj-$(CONFIG_KERNEL_AUTOENABLE) += autoenable.o obj-$(CONFIG_MALLOC_DLMALLOC) += dlmalloc.o obj-$(CONFIG_MALLOC_TLSF) += tlsf_malloc.o tlsf.o obj-$(CONFIG_MALLOC_DUMMY) += dummy_malloc.o diff --git a/common/autoenable.c b/common/autoenable.c new file mode 100644 index 0000000..be76942 --- /dev/null +++ b/common/autoenable.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2017 PHYTEC Messtechnik GmbH, + * Author: Daniel Schultz <d.schultz@xxxxxxxxx> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/err.h> +#include <of.h> +#include <stdio.h> +#include <stdlib.h> +#include <i2c/i2c.h> + +/** + * 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 autoenable_device_by_path(char *path) +{ + struct device_d *device; + 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; + + device = of_find_device_by_node(node); + if (!device) + return -ENODEV; + + ret = of_register_set_status_fixup(path, 1); + if (!ret) + printf("autoenabled %s\n", device->name); + return ret; +} + +/** + * autoenable_i2c_by_path - 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 autoenable_i2c_by_path(char *path) +{ + struct device_node *node; + struct i2c_adapter *i2c_adapter; + struct i2c_msg msg; + char data[1] = {0x0}; + int addr; + const __be32 *ip; + int ret; + + 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; + + ip = of_get_property(node, "reg", NULL); + if (!ip) + return -ENODEV; + addr = be32_to_cpup(ip); + + 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/include/autoenable.h b/include/autoenable.h new file mode 100644 index 0000000..26811b0 --- /dev/null +++ b/include/autoenable.h @@ -0,0 +1,21 @@ +#ifndef __AUTOENABLE_H +#define __AUTOENABLE_H + +#include <linux/err.h> + +#ifdef CONFIG_KERNEL_AUTOENABLE +int autoenable_device_by_path(char *path); +int autoenable_i2c_by_path(char *path); +#else +inline int autoenable_device_by_path(char *path) +{ + return -EINVAL; +} + +inline int autoenable_i2c_by_path(char *path) +{ + return -EINVAL; +} +#endif /* CONFIG_KERNEL_AUTOENABLE */ + +#endif /* __AUTOENABLE_H */ -- 2.7.4 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox