diff mbox

[RFC,16/29] xen/arm: Introduce a generic way to use a device from the device tree

Message ID 55ff8478c616656fda2e460907131f6caa942473.1367188423.git.julien.grall@linaro.org
State Changes Requested, archived
Headers show

Commit Message

Julien Grall April 28, 2013, 11:01 p.m. UTC
Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
 xen/arch/arm/Makefile        |    1 +
 xen/arch/arm/device.c        |   74 ++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/xen.lds.S       |    6 ++++
 xen/include/asm-arm/device.h |   52 +++++++++++++++++++++++++++++
 4 files changed, 133 insertions(+)
 create mode 100644 xen/arch/arm/device.c
 create mode 100644 xen/include/asm-arm/device.h

Comments

Ian Campbell April 29, 2013, 3:44 p.m. UTC | #1
On Mon, 2013-04-29 at 00:01 +0100, Julien Grall wrote:
> diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
> index fd755d7..7434e83 100644
> --- a/xen/arch/arm/xen.lds.S
> +++ b/xen/arch/arm/xen.lds.S
> @@ -76,6 +76,12 @@ SECTIONS
>    __lock_profile_end = .;
>  #endif
>  
> +  .dev.info : {

No ALIGNment requirement?

> +      _sdevice = .;
> +      *(.dev.info)
> +      _edevice = .;
> +  } :text
> +
>    . = ALIGN(PAGE_SIZE);             /* Init code and data */
>    __init_begin = .;
>    .init.text : {
Julien Grall April 29, 2013, 4:58 p.m. UTC | #2
On 04/29/2013 04:44 PM, Ian Campbell wrote:

> On Mon, 2013-04-29 at 00:01 +0100, Julien Grall wrote:
>> diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
>> index fd755d7..7434e83 100644
>> --- a/xen/arch/arm/xen.lds.S
>> +++ b/xen/arch/arm/xen.lds.S
>> @@ -76,6 +76,12 @@ SECTIONS
>>    __lock_profile_end = .;
>>  #endif
>>  
>> +  .dev.info : {
> 
> No ALIGNment requirement?


I don't think so. I can add ALIGN(8) to be sure.
diff mbox

Patch

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 2106a4f..7a73b79 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -27,6 +27,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..7434e83 100644
--- a/xen/arch/arm/xen.lds.S
+++ b/xen/arch/arm/xen.lds.S
@@ -76,6 +76,12 @@  SECTIONS
   __lock_profile_end = .;
 #endif
 
+  .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:
+ */