diff mbox

[V3,26/41] xen/arm: Introduce a generic way to use a device from the device tree

Message ID 1368152307-598-27-git-send-email-julien.grall@linaro.org
State Superseded, archived
Headers show

Commit Message

Julien Grall May 10, 2013, 2:18 a.m. UTC
Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

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
diff mbox

Patch

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 8f75044..4955a21 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -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
 
diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
new file mode 100644
index 0000000..dc751a9
--- /dev/null
+++ b/xen/arch/arm/device.c
@@ -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:
+ */
diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
index fd755d7..deab040 100644
--- a/xen/arch/arm/xen.lds.S
+++ b/xen/arch/arm/xen.lds.S
@@ -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 : {
diff --git a/xen/include/asm-arm/device.h b/xen/include/asm-arm/device.h
new file mode 100644
index 0000000..9e47ca6
--- /dev/null
+++ b/xen/include/asm-arm/device.h
@@ -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:
+ */