@@ -28,6 +28,7 @@ obj-y += vgic.o
obj-y += vtimer.o
obj-y += vpl011.o
obj-y += hvm.o
+obj-y += device.o
#obj-bin-y += ....o
new file mode 100644
@@ -0,0 +1,74 @@
+/*
+ * xen/arch/arm/device.c
+ *
+ * Helpers to use a device retrieved via the device tree.
+ *
+ * Julien Grall <julien.grall@linaro.org>
+ * Copyright (C) 2013 Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 <asm/device.h>
+#include <xen/errno.h>
+#include <xen/lib.h>
+
+extern const struct device_desc _sdevice[], _edevice[];
+
+static bool_t __init device_is_compatible(const struct device_desc *desc,
+ const struct dt_device_node *dev)
+{
+ const char *const *compat;
+
+ if ( !desc->compatible )
+ return 0;
+
+ for ( compat = desc->compatible; *compat; compat++ )
+ {
+ if ( dt_device_is_compatible(dev, *compat) )
+ return 1;
+ }
+
+ return 0;
+}
+
+int __init device_init(struct dt_device_node *dev, enum device_type type,
+ const void *data)
+{
+ const struct device_desc *desc;
+
+ ASSERT(dev != NULL);
+
+ for ( desc = _sdevice; desc != _edevice; desc++ )
+ {
+ if ( desc->type != type )
+ continue;
+
+ if ( device_is_compatible(desc, dev) )
+ {
+ ASSERT(desc->init != NULL);
+
+ return desc->init(dev, data);
+ }
+
+ }
+
+ return -EBADF;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
@@ -76,6 +76,13 @@ SECTIONS
__lock_profile_end = .;
#endif
+ . = ALIGN(8);
+ .dev.info : {
+ _sdevice = .;
+ *(.dev.info)
+ _edevice = .;
+ } :text
+
. = ALIGN(PAGE_SIZE); /* Init code and data */
__init_begin = .;
.init.text : {
new file mode 100644
@@ -0,0 +1,52 @@
+#ifndef __ASM_ARM_DEVICE_H
+#define __ASM_ARM_DEVICE_H
+
+#include <xen/init.h>
+#include <xen/device_tree.h>
+
+enum device_type
+{
+ DEVICE_SERIAL
+};
+
+struct device_desc {
+ /* Device name */
+ const char *name;
+ /* Device type */
+ enum device_type type;
+ /* Array of device tree 'compatible' strings */
+ const char *const *compatible;
+ /* Device initialization */
+ int (*init)(struct dt_device_node *dev, const void *data);
+};
+
+/**
+ * device_init - Initialize a device
+ * @dev: device to initialize
+ * @type: type of the device (serial, network...)
+ * @data: specific data for initializing the device
+ *
+ * Return 0 on success.
+ */
+int __init device_init(struct dt_device_node *dev, enum device_type type,
+ const void *data);
+
+#define DT_DEVICE_START(_name, _namestr, _type) \
+static const struct device_desc __dev_desc_##_name __used \
+__attribute__((__section__(".dev.info"))) = { \
+ .name = _namestr, \
+ .type = _type, \
+
+#define DT_DEVICE_END \
+};
+
+#endif /* __ASM_ARM_DEVICE_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
Signed-off-by: Julien Grall <julien.grall@linaro.org> Changes in v2: - Add missing ALIGN in xen.lds.S --- xen/arch/arm/Makefile | 1 + xen/arch/arm/device.c | 74 ++++++++++++++++++++++++++++++++++++++++++ xen/arch/arm/xen.lds.S | 7 ++++ xen/include/asm-arm/device.h | 52 +++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 xen/arch/arm/device.c create mode 100644 xen/include/asm-arm/device.h