This introduces the concept of class devices in barebox. Class devices
group together devices of the same type. Several subsystems like
watchdog and network devices have a struct device embedded in their
subsystem specific struct anyway, so we can use this as a class device.
As these class devices are collected on a list we can use this list to
iterate over all network/watchdog devices and thus free the subsystems
from the burden of keeping a list themselves.

There is a 'class' command added in this patch which can be used to show
all registered classes along with the devices registered for each class.

Signed-off-by: Sascha Hauer <[email protected]>
---
 commands/Kconfig                  |  6 +++++
 commands/Makefile                 |  1 +
 commands/class.c                  | 30 ++++++++++++++++++++++
 drivers/base/Makefile             |  1 +
 drivers/base/class.c              | 41 +++++++++++++++++++++++++++++++
 include/asm-generic/barebox.lds.h |  7 ++++++
 include/device.h                  | 21 ++++++++++++++++
 7 files changed, 107 insertions(+)
 create mode 100644 commands/class.c
 create mode 100644 drivers/base/class.c

diff --git a/commands/Kconfig b/commands/Kconfig
index 899673bfee..7831e6276d 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -68,6 +68,12 @@ config CMD_BOOTROM
 
          bootrom [-la]
 
+config CMD_CLASS
+       tristate
+       prompt "class"
+       help
+         Show information about registered classes and devices
+
 config CMD_DEVINFO
        tristate
        default y
diff --git a/commands/Makefile b/commands/Makefile
index 30e1f8403e..f65187703f 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -115,6 +115,7 @@ obj-$(CONFIG_CMD_BAREBOX_UPDATE)+= barebox-update.o
 obj-$(CONFIG_CMD_MIITOOL)      += miitool.o
 obj-$(CONFIG_CMD_DETECT)       += detect.o
 obj-$(CONFIG_CMD_BOOT)         += boot.o
+obj-$(CONFIG_CMD_CLASS)                += class.o
 obj-$(CONFIG_CMD_DEVINFO)      += devinfo.o
 obj-$(CONFIG_CMD_DEVUNBIND)    += devunbind.o
 obj-$(CONFIG_CMD_DEVLOOKUP)    += devlookup.o
diff --git a/commands/class.c b/commands/class.c
new file mode 100644
index 0000000000..f5d67b012f
--- /dev/null
+++ b/commands/class.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <common.h>
+#include <command.h>
+#include <complete.h>
+
+static int do_class(int argc, char *argv[])
+{
+       struct class *class;
+       struct device *dev;
+
+       class_for_each(class) {
+               printf("%s:\n", class->name);
+               class_for_each_device(class, dev) {
+                       printf("    %s\n", dev_name(dev));
+               }
+       }
+
+       return 0;
+}
+
+BAREBOX_CMD_HELP_START(class)
+BAREBOX_CMD_HELP_TEXT("Show information about registered classes and their 
devices")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(class)
+       .cmd = do_class,
+       BAREBOX_CMD_DESC("show information about classes")
+       BAREBOX_CMD_GROUP(CMD_GRP_INFO)
+       BAREBOX_CMD_COMPLETE(empty_complete)
+BAREBOX_CMD_END
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index acc53763da..94b677eea0 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -3,6 +3,7 @@ obj-y   += bus.o
 obj-y  += driver.o
 obj-y  += platform.o
 obj-y  += resource.o
+obj-y  += class.o
 obj-y  += regmap/
 
 obj-$(CONFIG_PM_GENERIC_DOMAINS) += power.o
diff --git a/drivers/base/class.c b/drivers/base/class.c
new file mode 100644
index 0000000000..6757d34140
--- /dev/null
+++ b/drivers/base/class.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <device.h>
+#include <driver.h>
+#include <linux/list.h>
+
+LIST_HEAD(class_list);
+
+static int class_register(struct class *class)
+{
+       list_add_tail(&class->list, &class_list);
+
+       return 0;
+}
+
+int class_add_device(struct class *class, struct device *dev)
+{
+       list_add_tail(&dev->class_list, &class->devices);
+
+       return 0;
+}
+
+void class_remove_device(struct class *class, struct device *dev)
+{
+       list_del(&class->devices);
+}
+
+extern struct class __barebox_class_start;
+extern struct class __barebox_class_end;
+
+static int register_classes(void)
+{
+       struct class *c;
+
+       for (c = &__barebox_class_start;
+            c != &__barebox_class_end;
+            c++)
+               class_register(c);
+
+       return 0;
+}
+device_initcall(register_classes);
diff --git a/include/asm-generic/barebox.lds.h 
b/include/asm-generic/barebox.lds.h
index d3736ebaed..8bbf5907cd 100644
--- a/include/asm-generic/barebox.lds.h
+++ b/include/asm-generic/barebox.lds.h
@@ -70,6 +70,12 @@
        KEEP(*(SORT_BY_NAME(.barebox_magicvar*)))       \
        __barebox_magicvar_end = .;
 
+#define BAREBOX_CLASSES                                \
+       STRUCT_ALIGN();                         \
+       __barebox_class_start = .;              \
+       KEEP(*(SORT_BY_NAME(.barebox_class*)))  \
+       __barebox_class_end = .;
+
 #define BAREBOX_CLK_TABLE                      \
        STRUCT_ALIGN();                         \
        __clk_of_table_start = .;               \
@@ -138,6 +144,7 @@
        BAREBOX_SYMS                            \
        KERNEL_CTORS()                          \
        BAREBOX_MAGICVARS                       \
+       BAREBOX_CLASSES                         \
        BAREBOX_CLK_TABLE                       \
        BAREBOX_DTB                             \
        BAREBOX_RSA_KEYS                        \
diff --git a/include/device.h b/include/device.h
index ad1bc7ca1e..38eab6037e 100644
--- a/include/device.h
+++ b/include/device.h
@@ -76,6 +76,8 @@ struct device {
 
        struct list_head cdevs;
 
+       struct list_head class_list;
+
        const struct platform_device_id *id_entry;
        union {
                struct device_node *device_node;
@@ -102,6 +104,25 @@ struct device {
        char *deferred_probe_reason;
 };
 
+struct class {
+       const char *name;
+       struct list_head devices;
+       struct list_head list;
+};
+
+#define DECLARE_CLASS(_name, _classname)                                       
\
+       struct class _name __ll_elem(.barebox_class_##_name) = {                
\
+               .name = _classname,                                             
\
+               .devices = LIST_HEAD_INIT(_name.devices),                       
\
+       }
+
+int class_add_device(struct class *class, struct device *dev);
+void class_remove_device(struct class *class, struct device *dev);
+
+extern struct list_head class_list;
+#define class_for_each_device(class, dev) list_for_each_entry(dev, 
&class->devices, class_list)
+#define class_for_each(class) list_for_each_entry(class, &class_list, list)
+
 struct device_alias {
        struct device *dev;
        struct list_head list;
-- 
2.39.2


Reply via email to