All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V4 00/32] Support multiple ARM platform in Xen
@ 2013-05-10 15:11 Julien Grall
  2013-05-10 15:11 ` [PATCH V4 01/32] xen/arm: Extend create_xen_entries prototype to take mapping attribute Julien Grall
                   ` (11 more replies)
  0 siblings, 12 replies; 25+ messages in thread
From: Julien Grall @ 2013-05-10 15:11 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Hi,

This is the fourth version of the patch series. It's rebased on the latest
staging.

Major changes in v4:
    - Introduce ioremap_nocache, ioremap_wc, ioremap_cache and use it
    - Merge patch "Remove early_ioremap" to "Introduce ioremap_attr"
    - Rework device tree printk

Major changes in v3:
    - Introduce ioremap_attr, ioreadl, iowritel
    - Typoes, hard tab, java doc...
    - Make generic UART based on DT architecture agnostic
    - Remove hardcoded IRQs in the virtual timer
    - Rework device tree printk

Major changes in v2:
    - Add platform_poweroff and platform_quirks
    - Rework early assembly printk to use
      macro instead of function
    - Use defines where it's possible in
      exynos UART code
    - Missing Signed-off-by from Anthony exynos UART code
    - Introduce request_dt_irq and setup_dt_irq. request_irq and setup_irq
    are deprecated for ARM. This part is divided in small patches (one to introduce
    new function and one to remove the old function) to avoid compilation breakage.

For all changes see in each patch. I have only reposted patch which are not
yet acked or changed in v4. All the others patch is in:
git clone -b arm-v4 git://xenbits.xen.org/people/julieng/xen-unstable.git

Xen can boot on both Arndale Board and Versatile Express without recompilation.
But there is still some hardcoded part, mainly in assembly.

Things to do:
   - Move secondary CPUs bring up code in platform specific
   - Move out of Xen the switch between secure mode and hypervisor mode
   - Rework dom0 device tree creation
   - Use everywhere the new device tree API
   - Add a support for SYS MMU

For the moment the ARM specific known bugs are:
    - Bash can sometimes crash with: segfault, memory corruption. It's
    seems it's due to a lack of VPF save/restore in Xen.
    - Assert in early code, ie before console is setup, let Xen spinned
    without an error message.

If you want to try this patch series you can clone:
git clone -b arm-v3 git://xenbits.xen.org/people/julieng/xen-unstable.git

The command line to compile Xen is the same as before. You just need to
specify on Xen command line, via the device tree, which UART will be used
for the console.

Feel free to test this branch. The wiki page is up-to-date for the arndale
board:
http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Arndale

Cheers,

Anthony PERARD (2):
  xen/arm: Add Exynos 4210 UART support
  xen/arm: Add Exynos 4210 UART support for early printk

Julien Grall (30):
  xen/arm: Extend create_xen_entries prototype to take mapping
    attribute
  xen/mm: Align virtual address on PAGE_SIZE in iounmap
  xen/arm: Introduce ioremap_attr, ioremap_cache, ioremap_nocache,
    ioremap_wc
  xen/arm: Add helpers ioreadl/iowritel
  xen/arm: Create a hierarchical device tree
  xen/arm: Add helpers to use the device tree
  xen/arm: Add helpers to retrieve an address from the device tree
  xen/arm: Add helpers to retrieve an interrupt description from the
    device tree
  xen/arm: Introduce gic_route_dt_irq
  xen/arm: Introduce gic_irq_xlate
  xen/arm: Introduce setup_dt_irq
  xen/arm: Introduce request_dt_irq
  xen/arm: Use hierarchical device tree to retrieve GIC information
  xen/arm: Retrieve timer interrupts from the device tree
  xen/arm: Don't hardcode VGIC informations
  xen/arm: Don't hardcode virtual timer IRQs
  xen/arm: Introduce a generic way to use a device from the device tree
  xen/arm: New callback in uart_driver to get device tree interrupt
    structure
  xen/arm: Add generic UART to get the device in the device tree
  xen/arm: Use device tree API in pl011 UART driver
  xen/arm: Use the device tree to map the address range and IRQ to dom0
  xen/arm: Allow Xen to run on multiple platform without recompilation
  xen/arm: WORKAROUND 1:1 memory mapping for dom0
  xen/arm: Add versatile express platform
  xen/arm: Remove request_irq
  xen/arm: Remove setup_irq
  xen/arm: Don't use pl011 UART by default for early printk
  xen/arm: Add platform specific code for the exynos5
  xen/arm: WORKAROUND Support kick cpus and switch to hypervisor for
    the exynos5
  xen/arm64: Remove hardcoded value for gic in assembly code

 config/arm32.mk                          |    1 +
 docs/misc/arm/early-printk.txt           |   15 +
 xen/arch/arm/Makefile                    |    4 +-
 xen/arch/arm/Rules.mk                    |   21 +
 xen/arch/arm/arm32/Makefile              |    4 +-
 xen/arch/arm/arm32/debug-exynos4210.inc  |   77 ++
 xen/arch/arm/arm32/debug-pl011.inc       |   58 ++
 xen/arch/arm/arm32/debug.S               |   33 +
 xen/arch/arm/arm32/head.S                |   84 +-
 xen/arch/arm/arm32/mode_switch.S         |   75 +-
 xen/arch/arm/arm64/Makefile              |    2 +
 xen/arch/arm/arm64/debug-pl011.inc       |   59 ++
 xen/arch/arm/arm64/debug.S               |   33 +
 xen/arch/arm/arm64/head.S                |   69 +-
 xen/arch/arm/arm64/mode_switch.S         |    7 +-
 xen/arch/arm/device.c                    |   74 ++
 xen/arch/arm/domain_build.c              |  191 ++++-
 xen/arch/arm/early_printk.c              |   16 +-
 xen/arch/arm/gic.c                       |  156 +++-
 xen/arch/arm/irq.c                       |    8 +-
 xen/arch/arm/mm.c                        |   57 +-
 xen/arch/arm/platform.c                  |  137 +++
 xen/arch/arm/platforms/Makefile          |    1 +
 xen/arch/arm/platforms/exynos5.c         |  110 +++
 xen/arch/arm/platforms/vexpress.c        |   40 +
 xen/arch/arm/setup.c                     |   14 +-
 xen/arch/arm/shutdown.c                  |   16 +-
 xen/arch/arm/time.c                      |   68 +-
 xen/arch/arm/vgic.c                      |   20 +-
 xen/arch/arm/vtimer.c                    |   13 +-
 xen/arch/arm/xen.lds.S                   |   14 +
 xen/common/device_tree.c                 | 1364 ++++++++++++++++++++++++++++--
 xen/drivers/char/Makefile                |    2 +
 xen/drivers/char/dt-uart.c               |   69 ++
 xen/drivers/char/exynos4210-uart.c       |  365 ++++++++
 xen/drivers/char/pl011.c                 |   88 +-
 xen/drivers/char/serial.c                |   16 +
 xen/drivers/video/arm_hdlcd.c            |    2 +-
 xen/include/asm-arm/config.h             |   15 +-
 xen/include/asm-arm/device.h             |   52 ++
 xen/include/asm-arm/domain.h             |    5 +-
 xen/include/asm-arm/early_printk.h       |    2 +-
 xen/include/asm-arm/exynos4210-uart.h    |  111 +++
 xen/include/asm-arm/gic.h                |   15 +-
 xen/include/asm-arm/irq.h                |    8 +
 xen/include/asm-arm/mm.h                 |   29 +-
 xen/include/asm-arm/page.h               |    2 +
 xen/include/asm-arm/platform.h           |   61 ++
 xen/include/asm-arm/platforms/exynos5.h  |   39 +
 xen/include/asm-arm/platforms/vexpress.h |   14 +
 xen/include/asm-arm/time.h               |   15 +
 xen/include/xen/device_tree.h            |  404 ++++++++-
 xen/include/xen/serial.h                 |   11 +-
 xen/include/xen/vmap.h                   |    4 +-
 54 files changed, 3800 insertions(+), 370 deletions(-)
 create mode 100644 docs/misc/arm/early-printk.txt
 create mode 100644 xen/arch/arm/arm32/debug-exynos4210.inc
 create mode 100644 xen/arch/arm/arm32/debug-pl011.inc
 create mode 100644 xen/arch/arm/arm32/debug.S
 create mode 100644 xen/arch/arm/arm64/debug-pl011.inc
 create mode 100644 xen/arch/arm/arm64/debug.S
 create mode 100644 xen/arch/arm/device.c
 create mode 100644 xen/arch/arm/platform.c
 create mode 100644 xen/arch/arm/platforms/exynos5.c
 create mode 100644 xen/drivers/char/dt-uart.c
 create mode 100644 xen/drivers/char/exynos4210-uart.c
 create mode 100644 xen/include/asm-arm/device.h
 create mode 100644 xen/include/asm-arm/exynos4210-uart.h
 create mode 100644 xen/include/asm-arm/platform.h
 create mode 100644 xen/include/asm-arm/platforms/exynos5.h

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH V4 01/32] xen/arm: Extend create_xen_entries prototype to take mapping attribute
  2013-05-10 15:11 [PATCH V4 00/32] Support multiple ARM platform in Xen Julien Grall
@ 2013-05-10 15:11 ` Julien Grall
  2013-05-13 11:01   ` Ian Campbell
  2013-05-10 15:11 ` [PATCH V4 02/32] xen/mm: Align virtual address on PAGE_SIZE in iounmap Julien Grall
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 25+ messages in thread
From: Julien Grall @ 2013-05-10 15:11 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

Changes in v4:
    - use "ai" instead of "flags" to reflect field which it goes in.
---
 xen/arch/arm/mm.c |    9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 2836cbb..bd7eb1a 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -631,7 +631,8 @@ enum xenmap_operation {
 static int create_xen_entries(enum xenmap_operation op,
                               unsigned long virt,
                               unsigned long mfn,
-                              unsigned long nr_mfns)
+                              unsigned long nr_mfns,
+                              unsigned int ai)
 {
     int rc;
     unsigned long addr = virt, addr_end = addr + nr_mfns * PAGE_SIZE;
@@ -664,6 +665,7 @@ static int create_xen_entries(enum xenmap_operation op,
                 }
                 pte = mfn_to_xen_entry(mfn);
                 pte.pt.table = 1;
+                pte.pt.ai = ai;
                 write_pte(&third[third_table_offset(addr)], pte);
                 break;
             case REMOVE:
@@ -693,12 +695,11 @@ int map_pages_to_xen(unsigned long virt,
                      unsigned long nr_mfns,
                      unsigned int flags)
 {
-    ASSERT(flags == PAGE_HYPERVISOR);
-    return create_xen_entries(INSERT, virt, mfn, nr_mfns);
+    return create_xen_entries(INSERT, virt, mfn, nr_mfns, flags);
 }
 void destroy_xen_mappings(unsigned long v, unsigned long e)
 {
-    create_xen_entries(REMOVE, v, 0, (e - v) >> PAGE_SHIFT);
+    create_xen_entries(REMOVE, v, 0, (e - v) >> PAGE_SHIFT, 0);
 }
 
 enum mg { mg_clear, mg_ro, mg_rw, mg_rx };
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH V4 02/32] xen/mm: Align virtual address on PAGE_SIZE in iounmap
  2013-05-10 15:11 [PATCH V4 00/32] Support multiple ARM platform in Xen Julien Grall
  2013-05-10 15:11 ` [PATCH V4 01/32] xen/arm: Extend create_xen_entries prototype to take mapping attribute Julien Grall
@ 2013-05-10 15:11 ` Julien Grall
  2013-05-10 16:16   ` Julien Grall
                     ` (2 more replies)
  2013-05-10 15:11 ` [PATCH V4 03/32] xen/arm: Introduce ioremap_attr, ioremap_cache, ioremap_nocache, ioremap_wc Julien Grall
                   ` (9 subsequent siblings)
  11 siblings, 3 replies; 25+ messages in thread
From: Julien Grall @ 2013-05-10 15:11 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, keir, ian.campbell, Julien Grall, Stefano.Stabellini

ioremap function can unlikely return an unaligned virtual address if
the physical address itself is unaligned on a page size.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Jan Beulich <jbeulich@suse.com>
CC: keir@xen.org

Changes in v4:
    - replace vaddr_t by unsigned int
---
 xen/include/xen/vmap.h |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/xen/include/xen/vmap.h b/xen/include/xen/vmap.h
index 88e5d99..45e9870 100644
--- a/xen/include/xen/vmap.h
+++ b/xen/include/xen/vmap.h
@@ -15,7 +15,9 @@ void __iomem *ioremap(paddr_t, size_t);
 
 static inline void iounmap(void __iomem *va)
 {
-    vunmap((void __force *)va);
+    unsigned int addr = (unsigned int)(void __force *)va;
+
+    vunmap((void *)(addr & PAGE_MASK));
 }
 
 void vm_init(void);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH V4 03/32] xen/arm: Introduce ioremap_attr, ioremap_cache, ioremap_nocache, ioremap_wc
  2013-05-10 15:11 [PATCH V4 00/32] Support multiple ARM platform in Xen Julien Grall
  2013-05-10 15:11 ` [PATCH V4 01/32] xen/arm: Extend create_xen_entries prototype to take mapping attribute Julien Grall
  2013-05-10 15:11 ` [PATCH V4 02/32] xen/mm: Align virtual address on PAGE_SIZE in iounmap Julien Grall
@ 2013-05-10 15:11 ` Julien Grall
  2013-05-10 15:24   ` Ian Campbell
  2013-05-10 15:11 ` [PATCH V4 04/32] xen/arm: Add helpers ioreadl/iowritel Julien Grall
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 25+ messages in thread
From: Julien Grall @ 2013-05-10 15:11 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Map physical range in virtual memory with a specific mapping attribute.
Also add new mapping attributes for ARM: PAGE_HYPERVISOR_NOCACHE
and PAGE_HYPERVISOR_WC.

This function replaces early_ioremap which is only able to deal with 2Mb
aligned mapping. Therefore, vmap initialization has been moved earlier.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v4:
    - Update comment
    - Merge "Remove early_ioremap" in this commit
    - Add ioremap_nocache, ioremap_cache, ioremap_wc for future use
    when, for instance, SYS MMU will be ported from Linux
---
 xen/arch/arm/mm.c             |   48 +++++++++++------------------------------
 xen/arch/arm/setup.c          |    4 ++--
 xen/drivers/video/arm_hdlcd.c |    2 +-
 xen/include/asm-arm/mm.h      |   19 ++++++++++++++--
 xen/include/asm-arm/page.h    |    2 ++
 5 files changed, 35 insertions(+), 40 deletions(-)

diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index bd7eb1a..d1290cd 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -38,6 +38,7 @@
 #include <xen/sched.h>
 #include <xen/vmap.h>
 #include <xsm/xsm.h>
+#include <xen/pfn.h>
 
 struct domain *dom_xen, *dom_io, *dom_cow;
 
@@ -567,45 +568,22 @@ void __init setup_frametable_mappings(paddr_t ps, paddr_t pe)
     frametable_virt_end = FRAMETABLE_VIRT_START + (nr_pages * sizeof(struct page_info));
 }
 
-/* Map the physical memory range start -  start + len into virtual
- * memory and return the virtual address of the mapping.
- * start has to be 2MB aligned.
- * len has to be < VMAP_VIRT_END - VMAP_VIRT_START.
- */
-static __initdata unsigned long early_vmap_start = VMAP_VIRT_END;
-void* __init early_ioremap(paddr_t start, size_t len, unsigned attributes)
+void *__init arch_vmap_virt_end(void)
 {
-    paddr_t end = start + len;
-    unsigned long map_start;
-
-    len = (len + SECOND_SIZE - 1) & ~SECOND_MASK;
-    early_vmap_start -= len;
-
-    ASSERT(!(start & (~SECOND_MASK)));
-    ASSERT(!(early_vmap_start & (~SECOND_MASK)));
-
-    /* The range we need to map is too big */
-    if ( early_vmap_start >= VMAP_VIRT_START )
-        return NULL;
-
-    map_start = early_vmap_start;
-    while ( start < end )
-    {
-        lpae_t e = mfn_to_xen_entry(start >> PAGE_SHIFT);
-        e.pt.ai = attributes;
-        write_pte(xen_second + second_table_offset(map_start), e);
-
-        start += SECOND_SIZE;
-        map_start += SECOND_SIZE;
-    }
-    flush_xen_data_tlb_range_va(early_vmap_start, len);
-
-    return (void*)early_vmap_start;
+    return (void *)VMAP_VIRT_END;
 }
 
-void *__init arch_vmap_virt_end(void)
+/*
+ * This function should only be used to remap device address ranges
+ * TODO: add a check to verify this assumption
+ */
+void *ioremap_attr(paddr_t pa, size_t len, unsigned int attributes)
 {
-    return (void *)early_vmap_start;
+    unsigned long pfn = PFN_DOWN(pa);
+    unsigned int offs = pa & (PAGE_SIZE - 1);
+    unsigned int nr = PFN_UP(offs + len);
+
+    return (__vmap(&pfn, nr, 1, 1, attributes) + offs);
 }
 
 static int create_xen_table(lpae_t *entry)
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 29447ef..a667db4 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -429,6 +429,8 @@ void __init start_xen(unsigned long boot_phys_offset,
     setup_pagetables(boot_phys_offset, get_xen_paddr());
     setup_mm(fdt_paddr, fdt_size);
 
+    vm_init();
+
 #ifdef EARLY_UART_ADDRESS
     /* TODO Need to get device tree or command line for UART address */
     pl011_init(0, FIXMAP_ADDR(FIXMAP_CONSOLE));
@@ -483,8 +485,6 @@ void __init start_xen(unsigned long boot_phys_offset,
 
     console_init_postirq();
 
-    vm_init();
-
     do_presmp_initcalls();
 
     for_each_present_cpu ( i )
diff --git a/xen/drivers/video/arm_hdlcd.c b/xen/drivers/video/arm_hdlcd.c
index d0ec13d..72979ea 100644
--- a/xen/drivers/video/arm_hdlcd.c
+++ b/xen/drivers/video/arm_hdlcd.c
@@ -211,7 +211,7 @@ void __init video_init(void)
 
     printk(KERN_INFO "Initializing HDLCD driver\n");
 
-    lfb = early_ioremap(framebuffer_start, framebuffer_size, DEV_WC);
+    lfb = ioremap_wc(framebuffer_start, framebuffer_size);
     if ( !lfb )
     {
         printk(KERN_ERR "Couldn't map the framebuffer\n");
diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
index 26c271e..63e1069 100644
--- a/xen/include/asm-arm/mm.h
+++ b/xen/include/asm-arm/mm.h
@@ -153,8 +153,23 @@ extern void setup_frametable_mappings(paddr_t ps, paddr_t pe);
 extern void set_fixmap(unsigned map, unsigned long mfn, unsigned attributes);
 /* Remove a mapping from a fixmap entry */
 extern void clear_fixmap(unsigned map);
-/* map a 2MB aligned physical range in virtual memory. */
-void* early_ioremap(paddr_t start, size_t len, unsigned attributes);
+/* map a physical range in virtual memory */
+void __iomem *ioremap_attr(paddr_t start, size_t len, unsigned attributes);
+
+static inline void __iomem *ioremap_nocache(paddr_t start, size_t len)
+{
+    return ioremap_attr(start, len, PAGE_HYPERVISOR_NOCACHE);
+}
+
+static inline void __iomem *ioremap_cache(paddr_t start, size_t len)
+{
+    return ioremap_attr(start, len, PAGE_HYPERVISOR);
+}
+
+static inline void __iomem *ioremap_wc(paddr_t start, size_t len)
+{
+    return ioremap_attr(start, len, PAGE_HYPERVISOR_WC);
+}
 
 #define mfn_valid(mfn)        ({                                              \
     unsigned long __m_f_n = (mfn);                                            \
diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h
index fd6946e..13fbd78 100644
--- a/xen/include/asm-arm/page.h
+++ b/xen/include/asm-arm/page.h
@@ -59,6 +59,8 @@
 #define DEV_CACHED    WRITEBACK
 
 #define PAGE_HYPERVISOR         (MATTR_MEM)
+#define PAGE_HYPERVISOR_NOCACHE (DEV_SHARED)
+#define PAGE_HYPERVISOR_WC      (DEV_WC)
 #define MAP_SMALL_PAGES         PAGE_HYPERVISOR
 
 /*
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH V4 04/32] xen/arm: Add helpers ioreadl/iowritel
  2013-05-10 15:11 [PATCH V4 00/32] Support multiple ARM platform in Xen Julien Grall
                   ` (2 preceding siblings ...)
  2013-05-10 15:11 ` [PATCH V4 03/32] xen/arm: Introduce ioremap_attr, ioremap_cache, ioremap_nocache, ioremap_wc Julien Grall
@ 2013-05-10 15:11 ` Julien Grall
  2013-05-10 15:38   ` Ian Campbell
  2013-05-10 16:24   ` Julien Grall
  2013-05-10 15:11 ` [PATCH V4 05/32] xen/arm: Create a hierarchical device tree Julien Grall
                   ` (7 subsequent siblings)
  11 siblings, 2 replies; 25+ messages in thread
From: Julien Grall @ 2013-05-10 15:11 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
 xen/include/asm-arm/mm.h |   10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
index 63e1069..3749f44 100644
--- a/xen/include/asm-arm/mm.h
+++ b/xen/include/asm-arm/mm.h
@@ -171,6 +171,16 @@ static inline void __iomem *ioremap_wc(paddr_t start, size_t len)
     return ioremap_attr(start, len, PAGE_HYPERVISOR_WC);
 }
 
+static inline uint32_t ioreadl(const volatile void __iomem *addr)
+{
+    return (*(volatile uint32_t *)addr);
+}
+
+static inline void iowritel(const volatile void __iomem *addr, uint32_t val)
+{
+    *(volatile uint32_t *)addr = val;
+}
+
 #define mfn_valid(mfn)        ({                                              \
     unsigned long __m_f_n = (mfn);                                            \
     likely(__m_f_n < max_page);                                               \
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH V4 05/32] xen/arm: Create a hierarchical device tree
  2013-05-10 15:11 [PATCH V4 00/32] Support multiple ARM platform in Xen Julien Grall
                   ` (3 preceding siblings ...)
  2013-05-10 15:11 ` [PATCH V4 04/32] xen/arm: Add helpers ioreadl/iowritel Julien Grall
@ 2013-05-10 15:11 ` Julien Grall
  2013-05-10 15:38   ` Ian Campbell
  2013-05-10 15:11 ` [PATCH V4 19/32] xen/arm: Add generic UART to get the device in the " Julien Grall
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 25+ messages in thread
From: Julien Grall @ 2013-05-10 15:11 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Add function to parse the device tree and create a hierarchical tree.

This code is based on drivers/of/base.c in linux source.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v4:
    - Replace dt_printk by a macro to avoid double buffering

Changes in v3:
    - Remove dt_switch_to_printk
    - Use system_state to choose between early_printk and printk
    - Remove DT_USE_BY_XEN, instead use DOMID_XEN

Changes in v2:
    - s/dom0$/device/ in comment "By default dom0 owns the dom0"
    - Use DOMID_XEN instead of DOMID_INVALID for DT_USED_BY_XEN
---
 xen/arch/arm/setup.c          |    1 +
 xen/common/device_tree.c      |  455 ++++++++++++++++++++++++++++++++++++++++-
 xen/include/xen/device_tree.h |   89 ++++++++
 3 files changed, 540 insertions(+), 5 deletions(-)

diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index a667db4..81bc956 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -430,6 +430,7 @@ void __init start_xen(unsigned long boot_phys_offset,
     setup_mm(fdt_paddr, fdt_size);
 
     vm_init();
+    dt_unflatten_host_device_tree();
 
 #ifdef EARLY_UART_ADDRESS
     /* TODO Need to get device tree or command line for UART address */
diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 7997f41..215feb1 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -2,6 +2,8 @@
  * Device Tree
  *
  * Copyright (C) 2012 Citrix Systems, Inc.
+ * Copyright 2009 Benjamin Herrenschmidt, IBM Corp
+ * benh@kernel.crashing.org
  *
  * 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
@@ -19,14 +21,56 @@
 #include <xen/stdarg.h>
 #include <xen/string.h>
 #include <xen/cpumask.h>
+#include <xen/ctype.h>
+#include <xen/lib.h>
 #include <asm/early_printk.h>
 
 struct dt_early_info __initdata early_info;
 void *device_tree_flattened;
+/* Host device tree */
+struct dt_device_node *dt_host;
+
+/**
+ * struct dt_alias_prop - Alias property in 'aliases' node
+ * @link: List node to link the structure in aliases_lookup list
+ * @alias: Alias property name
+ * @np: Pointer to device_node that the alias stands for
+ * @id: Index value from end of alias name
+ * @stem: Alias string without the index
+ *
+ * The structure represents one alias property of 'aliases' node as
+ * an entry in aliases_lookup list.
+ */
+struct dt_alias_prop {
+    struct list_head link;
+    const char *alias;
+    struct dt_device_node *np;
+    int id;
+    char stem[0];
+};
+
+static LIST_HEAD(aliases_lookup);
 
 /* Some device tree functions may be called both before and after the
    console is initialized. */
-static void (*dt_printk)(const char *fmt, ...) = early_printk;
+#define dt_printk(fmt, ...)                         \
+    do                                              \
+    {                                               \
+        if ( system_state == SYS_STATE_early_boot ) \
+            early_printk(fmt, ## __VA_ARGS__);      \
+        else                                        \
+            printk(fmt, ## __VA_ARGS__);            \
+    } while (0)
+
+#define ALIGN(x, a) ((x + (a) - 1) & ~((a) - 1));
+
+// #define DEBUG_DT
+
+#ifdef DEBUG_DT
+# define dt_dprintk(fmt, args...) dt_printk(XENLOG_DEBUG fmt, ##args)
+#else
+# define dt_dprintk(fmt, args...) do {} while ( 0 )
+#endif
 
 bool_t device_tree_node_matches(const void *fdt, int node, const char *match)
 {
@@ -263,7 +307,7 @@ static int dump_node(const void *fdt, int node, const char *name, int depth,
 
     if ( name[0] == '\0' )
         name = "/";
-    printk("%s%s:\n", prefix, name);
+    dt_printk("%s%s:\n", prefix, name);
 
     for ( prop = fdt_first_property_offset(fdt, node);
           prop >= 0;
@@ -273,7 +317,7 @@ static int dump_node(const void *fdt, int node, const char *name, int depth,
 
         p = fdt_get_property_by_offset(fdt, prop, NULL);
 
-        printk("%s  %s\n", prefix, fdt_string(fdt, fdt32_to_cpu(p->nameoff)));
+        dt_printk("%s  %s\n", prefix, fdt_string(fdt, fdt32_to_cpu(p->nameoff)));
     }
 
     return 0;
@@ -488,11 +532,412 @@ size_t __init device_tree_early_init(const void *fdt)
     device_tree_for_each_node((void *)fdt, early_scan_node, NULL);
     early_print_info();
 
-    dt_printk = printk;
-
     return fdt_totalsize(fdt);
 }
 
+static void __init *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
+                                       unsigned long align)
+{
+    void *res;
+
+    *mem = ALIGN(*mem, align);
+    res = (void *)*mem;
+    *mem += size;
+
+    return res;
+}
+
+/* Find a property with a given name for a given node and return it. */
+static const struct dt_property *
+dt_find_property(const struct dt_device_node *np,
+                 const char *name,
+                 u32 *lenp)
+{
+    const struct dt_property *pp;
+
+    if ( !np )
+        return NULL;
+
+    for ( pp = np->properties; pp; pp = pp->next )
+    {
+        if ( strcmp(pp->name, name) == 0 )
+        {
+            if ( lenp )
+                *lenp = pp->length;
+            break;
+        }
+    }
+
+    return pp;
+}
+
+const void *dt_get_property(const struct dt_device_node *np,
+                            const char *name, u32 *lenp)
+{
+    const struct dt_property *pp = dt_find_property(np, name, lenp);
+
+    return pp ? pp->value : NULL;
+}
+
+struct dt_device_node *dt_find_node_by_path(const char *path)
+{
+    struct dt_device_node *np;
+
+    for_each_device_node(dt_host, np)
+        if ( np->full_name && (dt_node_cmp(np->full_name, path) == 0) )
+            break;
+
+    return np;
+}
+
+/**
+ * unflatten_dt_node - Alloc and populate a device_node from the flat tree
+ * @fdt: The parent device tree blob
+ * @mem: Memory chunk to use for allocating device nodes and properties
+ * @p: pointer to node in flat tree
+ * @dad: Parent struct device_node
+ * @allnextpp: pointer to ->allnext from last allocated device_node
+ * @fpsize: Size of the node path up at the current depth.
+ */
+static unsigned long __init unflatten_dt_node(const void *fdt,
+                                              unsigned long mem,
+                                              unsigned long *p,
+                                              struct dt_device_node *dad,
+                                              struct dt_device_node ***allnextpp,
+                                              unsigned long fpsize)
+{
+    struct dt_device_node *np;
+    struct dt_property *pp, **prev_pp = NULL;
+    char *pathp;
+    u32 tag;
+    unsigned int l, allocl;
+    int has_name = 0;
+    int new_format = 0;
+
+    tag = be32_to_cpup((__be32 *)(*p));
+    if ( tag != FDT_BEGIN_NODE )
+    {
+        dt_printk(XENLOG_WARNING "Weird tag at start of node: %x\n", tag);
+        return mem;
+    }
+    *p += 4;
+    pathp = (char *)*p;
+    l = allocl = strlen(pathp) + 1;
+    *p = ALIGN(*p + l, 4);
+
+    /* version 0x10 has a more compact unit name here instead of the full
+     * path. we accumulate the full path size using "fpsize", we'll rebuild
+     * it later. We detect this because the first character of the name is
+     * not '/'.
+     */
+    if ( (*pathp) != '/' )
+    {
+        new_format = 1;
+        if ( fpsize == 0 )
+        {
+            /* root node: special case. fpsize accounts for path
+             * plus terminating zero. root node only has '/', so
+             * fpsize should be 2, but we want to avoid the first
+             * level nodes to have two '/' so we use fpsize 1 here
+             */
+            fpsize = 1;
+            allocl = 2;
+        }
+        else
+        {
+            /* account for '/' and path size minus terminal 0
+             * already in 'l'
+             */
+            fpsize += l;
+            allocl = fpsize;
+        }
+    }
+
+    np = unflatten_dt_alloc(&mem, sizeof(struct dt_device_node) + allocl,
+                            __alignof__(struct dt_device_node));
+    if ( allnextpp )
+    {
+        memset(np, 0, sizeof(*np));
+        np->full_name = ((char *)np) + sizeof(struct dt_device_node);
+        /* By default dom0 owns the device */
+        np->used_by = 0;
+        if ( new_format )
+        {
+            char *fn = np->full_name;
+            /* rebuild full path for new format */
+            if ( dad && dad->parent )
+            {
+                strlcpy(fn, dad->full_name, allocl);
+#ifdef DEBUG_DT
+                if ( (strlen(fn) + l + 1) != allocl )
+                {
+                    dt_dprintk("%s: p: %d, l: %d, a: %d\n",
+                               pathp, (int)strlen(fn),
+                               l, allocl);
+                }
+#endif
+                fn += strlen(fn);
+            }
+            *(fn++) = '/';
+            memcpy(fn, pathp, l);
+        }
+        else
+            memcpy(np->full_name, pathp, l);
+        prev_pp = &np->properties;
+        **allnextpp = np;
+        *allnextpp = &np->allnext;
+        if ( dad != NULL )
+        {
+            np->parent = dad;
+            /* we temporarily use the next field as `last_child'*/
+            if ( dad->next == NULL )
+                dad->child = np;
+            else
+                dad->next->sibling = np;
+            dad->next = np;
+        }
+    }
+    /* process properties */
+    while ( 1 )
+    {
+        u32 sz, noff;
+        const char *pname;
+
+        tag = be32_to_cpup((__be32 *)(*p));
+        if ( tag == FDT_NOP )
+        {
+            *p += 4;
+            continue;
+        }
+        if ( tag != FDT_PROP )
+            break;
+        *p += 4;
+        sz = be32_to_cpup((__be32 *)(*p));
+        noff = be32_to_cpup((__be32 *)((*p) + 4));
+        *p += 8;
+        if ( fdt_version(fdt) < 0x10 )
+            *p = ALIGN(*p, sz >= 8 ? 8 : 4);
+
+        pname = fdt_string(fdt, noff);
+        if ( pname == NULL )
+        {
+            dt_dprintk("Can't find property name in list!\n");
+            break;
+        }
+        if ( strcmp(pname, "name") == 0 )
+            has_name = 1;
+        l = strlen(pname) + 1;
+        pp = unflatten_dt_alloc(&mem, sizeof(struct dt_property),
+                                __alignof__(struct dt_property));
+        if ( allnextpp )
+        {
+            /* We accept flattened tree phandles either in
+             * ePAPR-style "phandle" properties, or the
+             * legacy "linux,phandle" properties.  If both
+             * appear and have different values, things
+             * will get weird.  Don't do that. */
+            if ( (strcmp(pname, "phandle") == 0) ||
+                 (strcmp(pname, "linux,phandle") == 0) )
+            {
+                if ( np->phandle == 0 )
+                    np->phandle = be32_to_cpup((__be32*)*p);
+            }
+            /* And we process the "ibm,phandle" property
+             * used in pSeries dynamic device tree
+             * stuff */
+            if ( strcmp(pname, "ibm,phandle") == 0 )
+                np->phandle = be32_to_cpup((__be32 *)*p);
+            pp->name = pname;
+            pp->length = sz;
+            pp->value = (void *)*p;
+            *prev_pp = pp;
+            prev_pp = &pp->next;
+        }
+        *p = ALIGN((*p) + sz, 4);
+    }
+    /* with version 0x10 we may not have the name property, recreate
+     * it here from the unit name if absent
+     */
+    if ( !has_name )
+    {
+        char *p1 = pathp, *ps = pathp, *pa = NULL;
+        int sz;
+
+        while ( *p1 )
+        {
+            if ( (*p1) == '@' )
+                pa = p1;
+            if ( (*p1) == '/' )
+                ps = p1 + 1;
+            p1++;
+        }
+        if ( pa < ps )
+            pa = p1;
+        sz = (pa - ps) + 1;
+        pp = unflatten_dt_alloc(&mem, sizeof(struct dt_property) + sz,
+                                __alignof__(struct dt_property));
+        if ( allnextpp )
+        {
+            pp->name = "name";
+            pp->length = sz;
+            pp->value = pp + 1;
+            *prev_pp = pp;
+            prev_pp = &pp->next;
+            memcpy(pp->value, ps, sz - 1);
+            ((char *)pp->value)[sz - 1] = 0;
+            dt_dprintk("fixed up name for %s -> %s\n", pathp,
+                       (char *)pp->value);
+        }
+    }
+    if ( allnextpp )
+    {
+        *prev_pp = NULL;
+        np->name = dt_get_property(np, "name", NULL);
+        np->type = dt_get_property(np, "device_type", NULL);
+
+        if ( !np->name )
+            np->name = "<NULL>";
+        if ( !np->type )
+            np->type = "<NULL>";
+    }
+    while ( tag == FDT_BEGIN_NODE || tag == FDT_NOP )
+    {
+        if ( tag == FDT_NOP )
+            *p += 4;
+        else
+            mem = unflatten_dt_node(fdt, mem, p, np, allnextpp, fpsize);
+        tag = be32_to_cpup((__be32 *)(*p));
+    }
+    if ( tag != FDT_END_NODE )
+    {
+        dt_printk(XENLOG_WARNING "Weird tag at end of node: %x\n", tag);
+        return mem;
+    }
+
+    *p += 4;
+    return mem;
+}
+
+/**
+ * __unflatten_device_tree - create tree of device_nodes from flat blob
+ *
+ * unflattens a device-tree, creating the
+ * tree of struct device_node. It also fills the "name" and "type"
+ * pointers of the nodes so the normal device-tree walking functions
+ * can be used.
+ * @fdt: The fdt to expand
+ * @mynodes: The device_node tree created by the call
+ */
+static void __init __unflatten_device_tree(const void *fdt,
+                                           struct dt_device_node **mynodes)
+{
+    unsigned long start, mem, size;
+    struct dt_device_node **allnextp = mynodes;
+
+    dt_dprintk(" -> unflatten_device_tree()\n");
+
+    dt_dprintk("Unflattening device tree:\n");
+    dt_dprintk("magic: %#08x\n", fdt_magic(fdt));
+    dt_dprintk("size: %#08x\n", fdt_totalsize(fdt));
+    dt_dprintk("version: %#08x\n", fdt_version(fdt));
+
+    /* First pass, scan for size */
+    start = ((unsigned long)fdt) + fdt_off_dt_struct(fdt);
+    size = unflatten_dt_node(fdt, 0, &start, NULL, NULL, 0);
+    size = (size | 3) + 1;
+
+    dt_dprintk("  size is %#lx allocating...\n", size);
+
+    /* Allocate memory for the expanded device tree */
+    mem = (unsigned long)_xmalloc (size + 4, __alignof__(struct dt_device_node));
+
+    ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef);
+
+    dt_dprintk("  unflattening %lx...\n", mem);
+
+    /* Second pass, do actual unflattening */
+    start = ((unsigned long)fdt) + fdt_off_dt_struct(fdt);
+    unflatten_dt_node(fdt, mem, &start, NULL, &allnextp, 0);
+    if ( be32_to_cpup((__be32 *)start) != FDT_END )
+        dt_printk(XENLOG_WARNING "Weird tag at end of tree: %08x\n",
+                  *((u32 *)start));
+    if ( be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef )
+        dt_printk(XENLOG_WARNING "End of tree marker overwritten: %08x\n",
+                  be32_to_cpu(((__be32 *)mem)[size / 4]));
+    *allnextp = NULL;
+
+    dt_dprintk(" <- unflatten_device_tree()\n");
+}
+
+static void dt_alias_add(struct dt_alias_prop *ap,
+                         struct dt_device_node *np,
+                         int id, const char *stem, int stem_len)
+{
+    ap->np = np;
+    ap->id = id;
+    strlcpy(ap->stem, stem, stem_len + 1);
+    list_add_tail(&ap->link, &aliases_lookup);
+    dt_dprintk("adding DT alias:%s: stem=%s id=%d node=%s\n",
+               ap->alias, ap->stem, ap->id, dt_node_full_name(np));
+}
+
+/**
+ * dt_alias_scan - Scan all properties of 'aliases' node
+ *
+ * The function scans all the properties of 'aliases' node and populate
+ * the the global lookup table with the properties.  It returns the
+ * number of alias_prop found, or error code in error case.
+ */
+static void __init dt_alias_scan(void)
+{
+    const struct dt_property *pp;
+    const struct dt_device_node *aliases;
+
+    aliases = dt_find_node_by_path("/aliases");
+    if ( !aliases )
+        return;
+
+    for_each_property_of_node( aliases, pp )
+    {
+        const char *start = pp->name;
+        const char *end = start + strlen(start);
+        struct dt_device_node *np;
+        struct dt_alias_prop *ap;
+        int id, len;
+
+        /* Skip those we do not want to proceed */
+        if ( !strcmp(pp->name, "name") ||
+             !strcmp(pp->name, "phandle") ||
+             !strcmp(pp->name, "linux,phandle") )
+            continue;
+
+        np = dt_find_node_by_path(pp->value);
+        if ( !np )
+            continue;
+
+        /* walk the alias backwards to extract the id and work out
+         * the 'stem' string */
+        while ( isdigit(*(end-1)) && end > start )
+            end--;
+        len = end - start;
+
+        id = simple_strtoll(end, NULL, 10);
+
+        /* Allocate an alias_prop with enough space for the stem */
+        ap = _xmalloc(sizeof(*ap) + len + 1, 4);
+        if ( !ap )
+            continue;
+        ap->alias = start;
+        dt_alias_add(ap, np, id, start, len);
+    }
+}
+
+void __init dt_unflatten_host_device_tree(void)
+{
+    __unflatten_device_tree(device_tree_flattened, &dt_host);
+    dt_alias_scan();
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index 19bda98..015b808 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -10,6 +10,10 @@
 #ifndef __XEN_DEVICE_TREE_H__
 #define __XEN_DEVICE_TREE_H__
 
+#include <asm/byteorder.h>
+#include <public/xen.h>
+#include <xen/init.h>
+#include <xen/string.h>
 #include <xen/types.h>
 
 #define DEVICE_TREE_MAX_DEPTH 16
@@ -52,6 +56,49 @@ struct dt_early_info {
     struct dt_module_info modules;
 };
 
+typedef u32 dt_phandle;
+
+/**
+ * dt_property - describe a property for a device
+ * @name: name of the property
+ * @length: size of the value
+ * @value: pointer to data contained in the property
+ * @next: pointer to the next property of a specific node
+ */
+struct dt_property {
+    const char *name;
+    u32 length;
+    void *value;
+    struct dt_property *next;
+};
+
+/**
+ * dt_device_node - describe a node in the device tree
+ * @name: name of the node
+ * @type: type of the node (ie: memory, cpu, ...)
+ * @full_name: full name, it's composed of all the ascendant name separate by /
+ * @used_by: who owns the node? (ie: xen, dom0...)
+ * @properties: list of properties for the node
+ * @child: pointer to the first child
+ * @sibling: pointer to the next sibling
+ * @allnext: pointer to the next in list of all nodes
+ */
+struct dt_device_node {
+    const char *name;
+    const char *type;
+    dt_phandle phandle;
+    char *full_name;
+    domid_t used_by; /* By default it's used by dom0 */
+
+    struct dt_property *properties;
+    struct dt_device_node *parent;
+    struct dt_device_node *child;
+    struct dt_device_node *sibling;
+    struct dt_device_node *next; /* TODO: Remove it. Only use to know the last children */
+    struct dt_device_node *allnext;
+
+};
+
 typedef int (*device_tree_node_func)(const void *fdt,
                                      int node, const char *name, int depth,
                                      u32 address_cells, u32 size_cells,
@@ -77,4 +124,46 @@ int device_tree_for_each_node(const void *fdt,
 const char *device_tree_bootargs(const void *fdt);
 void device_tree_dump(const void *fdt);
 
+/**
+ * dt_unflatten_host_device_tree - Unflatten the host device tree
+ *
+ * Create a hierarchical device tree for the host DTB to be able
+ * to retrieve parents.
+ */
+void __init dt_unflatten_host_device_tree(void);
+
+/**
+ * Host device tree
+ * DO NOT modify it!
+ */
+extern struct dt_device_node *dt_host;
+
+#define dt_node_cmp(s1, s2) strcmp((s1), (s2))
+#define dt_compat_cmp(s1, s2, l) strnicmp((s1), (s2), l)
+
+#define for_each_property_of_node(dn, pp)                   \
+    for ( pp = dn->properties; pp != NULL; pp = pp->next )
+
+#define for_each_device_node(dt, dn)                         \
+    for ( dn = dt; dn != NULL; dn = dn->allnext )
+
+static inline const char *dt_node_full_name(const struct dt_device_node *np)
+{
+    return (np && np->full_name) ? np->full_name : "<no-node>";
+}
+
+/**
+ * Find a property with a given name for a given node
+ * and return the value.
+ */
+const void *dt_get_property(const struct dt_device_node *np,
+                            const char *name, u32 *lenp);
+
+/**
+ * dt_find_node_by_path - Find a node matching a full DT path
+ * @path: The full path to match
+ *
+ * Returns a node pointer.
+ */
+struct dt_device_node *dt_find_node_by_path(const char *path);
 #endif
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH V4 19/32] xen/arm: Add generic UART to get the device in the device tree
  2013-05-10 15:11 [PATCH V4 00/32] Support multiple ARM platform in Xen Julien Grall
                   ` (4 preceding siblings ...)
  2013-05-10 15:11 ` [PATCH V4 05/32] xen/arm: Create a hierarchical device tree Julien Grall
@ 2013-05-10 15:11 ` Julien Grall
  2013-05-10 15:11 ` [PATCH V4 20/32] xen/arm: Use device tree API in pl011 UART driver Julien Grall
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 25+ messages in thread
From: Julien Grall @ 2013-05-10 15:11 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, keir, ian.campbell, Julien Grall, Stefano.Stabellini

This generic UART will find the right UART via xen command line
with dtuart=myserial.

"myserial" is the alias of the UART in the device tree. Xen will retrieve
the information via the device tree and call the initialization function for
this specific UART thanks to the device API.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
CC: keir@xen.org

Changes in v3:
    - Rename arm-uart.c (resp. arm_uart_init) to dt-uart.c (resp. dt_uart_init)
    - Remove serial_arm_defaults and replace by a string options
    - Let the specific UART driver to get its base address in the DT
    - Add SERHND_DTUART. The value is stolen to SERHND_COM1. Bump the
    value would needs some rework...

Changes in v2:
    - Use dtuart parameter instead of com1. The first one is more arm
    while the latter is more x86
---
 xen/arch/arm/setup.c         |    3 +-
 xen/drivers/char/Makefile    |    1 +
 xen/drivers/char/dt-uart.c   |   69 ++++++++++++++++++++++++++++++++++++++++++
 xen/drivers/char/serial.c    |    6 ++++
 xen/include/asm-arm/config.h |    2 +-
 xen/include/xen/serial.h     |    5 ++-
 6 files changed, 83 insertions(+), 3 deletions(-)
 create mode 100644 xen/drivers/char/dt-uart.c

diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index fc53117..2e331d3 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -436,8 +436,9 @@ void __init start_xen(unsigned long boot_phys_offset,
 #ifdef EARLY_UART_ADDRESS
     /* TODO Need to get device tree or command line for UART address */
     pl011_init(0, FIXMAP_ADDR(FIXMAP_CONSOLE));
-    console_init_preirq();
 #endif
+    dt_uart_init();
+    console_init_preirq();
 
     system_state = SYS_STATE_boot;
 
diff --git a/xen/drivers/char/Makefile b/xen/drivers/char/Makefile
index ab2246d..9c067f9 100644
--- a/xen/drivers/char/Makefile
+++ b/xen/drivers/char/Makefile
@@ -2,4 +2,5 @@ obj-y += console.o
 obj-$(HAS_NS16550) += ns16550.o
 obj-$(HAS_PL011) += pl011.o
 obj-$(HAS_EHCI) += ehci-dbgp.o
+obj-$(CONFIG_ARM) += dt-uart.o
 obj-y += serial.o
diff --git a/xen/drivers/char/dt-uart.c b/xen/drivers/char/dt-uart.c
new file mode 100644
index 0000000..93bb0f5
--- /dev/null
+++ b/xen/drivers/char/dt-uart.c
@@ -0,0 +1,69 @@
+/*
+ * xen/drivers/char/dt-uart.c
+ *
+ * Generic uart 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 <asm/early_printk.h>
+#include <asm/types.h>
+#include <xen/console.h>
+#include <xen/device_tree.h>
+#include <xen/serial.h>
+
+/*
+ * Configure UART port with a string:
+ * alias,options
+ *
+ * @alias: alias used in the device tree for the UART
+ * @options: UART speficic options (see in each UART driver)
+ */
+static char __initdata opt_dtuart[30] = "";
+string_param("dtuart", opt_dtuart);
+
+void __init dt_uart_init(void)
+{
+    struct dt_device_node *dev;
+    int ret;
+    const char *devalias = opt_dtuart;
+    char *options;
+
+    if ( !console_has("dtuart") || !strcmp(opt_dtuart, "") )
+    {
+        early_printk("No console\n");
+        return;
+    }
+
+    options = strchr(opt_dtuart, ',');
+    if ( options != NULL )
+        *(options++) = '\0';
+    else
+        options = "";
+
+    early_printk("Looking for UART console %s\n", devalias);
+    dev = dt_find_node_by_alias(devalias);
+
+    if ( !dev )
+    {
+        early_printk("Unable to find device \"%s\"\n", devalias);
+        return;
+    }
+
+    ret = device_init(dev, DEVICE_SERIAL, options);
+
+    if ( ret )
+        early_printk("Unable to initialize serial: %d\n", ret);
+}
diff --git a/xen/drivers/char/serial.c b/xen/drivers/char/serial.c
index 0ae7e4d..e1c3f47 100644
--- a/xen/drivers/char/serial.c
+++ b/xen/drivers/char/serial.c
@@ -271,6 +271,12 @@ int __init serial_parse_handle(char *conf)
         goto common;
     }
 
+    if ( !strncmp(conf, "dtuart", 5) )
+    {
+        handle = SERHND_DTUART;
+        goto common;
+    }
+
     if ( strncmp(conf, "com", 3) )
         goto fail;
 
diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
index 98a3a43..8ed72f5 100644
--- a/xen/include/asm-arm/config.h
+++ b/xen/include/asm-arm/config.h
@@ -39,7 +39,7 @@
 
 #define CONFIG_VIDEO 1
 
-#define OPT_CONSOLE_STR "com1"
+#define OPT_CONSOLE_STR "dtuart"
 
 #ifdef MAX_PHYS_CPUS
 #define NR_CPUS MAX_PHYS_CPUS
diff --git a/xen/include/xen/serial.h b/xen/include/xen/serial.h
index 5de5171..8af3bc4 100644
--- a/xen/include/xen/serial.h
+++ b/xen/include/xen/serial.h
@@ -9,6 +9,7 @@
 #ifndef __XEN_SERIAL_H__
 #define __XEN_SERIAL_H__
 
+#include <xen/init.h>
 #include <xen/spinlock.h>
 
 struct cpu_user_regs;
@@ -76,10 +77,11 @@ struct uart_driver {
 };
 
 /* 'Serial handles' are composed from the following fields. */
-#define SERHND_IDX      (3<<0) /* COM1, COM2, or DBGP?                    */
+#define SERHND_IDX      (3<<0) /* COM1, COM2, DBGP, DTUART?               */
 # define SERHND_COM1    (0<<0)
 # define SERHND_COM2    (1<<0)
 # define SERHND_DBGP    (2<<0)
+# define SERHND_DTUART  (0<<0) /* Steal SERHND_COM1 value */
 #define SERHND_HI       (1<<2) /* Mux/demux each transferred char by MSB. */
 #define SERHND_LO       (1<<3) /* Ditto, except that the MSB is cleared.  */
 #define SERHND_COOKED   (1<<4) /* Newline/carriage-return translation?    */
@@ -156,6 +158,7 @@ void ns16550_init(int index, struct ns16550_defaults *defaults);
 void ehci_dbgp_init(void);
 
 void pl011_init(int index, unsigned long register_base_address);
+void __init dt_uart_init(void);
 
 struct physdev_dbgp_op;
 int dbgp_op(const struct physdev_dbgp_op *);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH V4 20/32] xen/arm: Use device tree API in pl011 UART driver
  2013-05-10 15:11 [PATCH V4 00/32] Support multiple ARM platform in Xen Julien Grall
                   ` (5 preceding siblings ...)
  2013-05-10 15:11 ` [PATCH V4 19/32] xen/arm: Add generic UART to get the device in the " Julien Grall
@ 2013-05-10 15:11 ` Julien Grall
  2013-05-10 15:12 ` [PATCH V4 22/32] xen/arm: Allow Xen to run on multiple platform without recompilation Julien Grall
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 25+ messages in thread
From: Julien Grall @ 2013-05-10 15:11 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Allow UART driver to retrieve all its information in the device tree.
It's possible to choose the pl011 driver via the Xen command line.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

Changes in v4:
    - Use ioremap_nocache instead of ioremap_attr(..., PAGE_HYPERVISOR_NOCACHE)
    - Print a warning if config != ""

Changes in v3:
    - Remove the usage of serial_arm_defaults
    - Get the base address from the DT and map it with ioremap_attr
    - Allow only 1 PL011 assigned to SERHND_DTUART
    - Replace DT_USED_BY_XEN by DOMID_XEN

Changes in v2:
    - Rework TODO
    - Use the new function setup_dt_irq
---
 xen/arch/arm/gic.c       |    4 ---
 xen/arch/arm/setup.c     |    4 ---
 xen/drivers/char/pl011.c |   88 +++++++++++++++++++++++++++++++++++++---------
 xen/include/xen/serial.h |    1 -
 4 files changed, 72 insertions(+), 25 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 761f570..648b1a0 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -505,10 +505,6 @@ void gic_route_spis(void)
     int seridx;
     const struct dt_irq *irq;
 
-    /* XXX should get these from DT */
-    /* UART */
-    gic_route_irq(37, 0, 1u << smp_processor_id(), 0xa0);
-
     for ( seridx = 0; seridx <= SERHND_IDX; seridx++ )
     {
         if ( (irq = serial_dt_irq(seridx)) == NULL )
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 2e331d3..e5f4459 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -433,10 +433,6 @@ void __init start_xen(unsigned long boot_phys_offset,
     dt_unflatten_host_device_tree();
     dt_irq_xlate = gic_irq_xlate;
 
-#ifdef EARLY_UART_ADDRESS
-    /* TODO Need to get device tree or command line for UART address */
-    pl011_init(0, FIXMAP_ADDR(FIXMAP_CONSOLE));
-#endif
     dt_uart_init();
     console_init_preirq();
 
diff --git a/xen/drivers/char/pl011.c b/xen/drivers/char/pl011.c
index 8efd08e..05b5ef1 100644
--- a/xen/drivers/char/pl011.c
+++ b/xen/drivers/char/pl011.c
@@ -22,9 +22,16 @@
 #include <xen/serial.h>
 #include <xen/init.h>
 #include <xen/irq.h>
+#include <asm/early_printk.h>
+#include <xen/device_tree.h>
+#include <xen/errno.h>
+#include <asm/device.h>
+#include <xen/mm.h>
+#include <xen/vmap.h>
 
 static struct pl011 {
-    unsigned int baud, clock_hz, data_bits, parity, stop_bits, irq;
+    unsigned int baud, clock_hz, data_bits, parity, stop_bits;
+    struct dt_irq irq;
     volatile uint32_t *regs;
     /* UART with IRQ line: interrupt-driven I/O. */
     struct irqaction irqaction;
@@ -32,7 +39,7 @@ static struct pl011 {
     /* struct timer timer; */
     /* unsigned int timeout_ms; */
     /* bool_t probing, intr_works; */
-} pl011_com[2] = {{0}};
+} pl011_com = {0};
 
 /* PL011 register addresses */
 #define DR     (0x00/4)
@@ -163,13 +170,13 @@ static void __init pl011_init_postirq(struct serial_port *port)
     struct pl011 *uart = port->uart;
     int rc;
 
-    if ( uart->irq > 0 )
+    if ( uart->irq.irq > 0 )
     {
         uart->irqaction.handler = pl011_interrupt;
         uart->irqaction.name    = "pl011";
         uart->irqaction.dev_id  = port;
-        if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
-            printk("ERROR: Failed to allocate pl011 IRQ %d\n", uart->irq);
+        if ( (rc = setup_dt_irq(&uart->irq, &uart->irqaction)) != 0 )
+            printk("ERROR: Failed to allocate pl011 IRQ %d\n", uart->irq.irq);
     }
 
     /* Clear pending error interrupts */
@@ -215,7 +222,14 @@ static int pl011_getc(struct serial_port *port, char *pc)
 static int __init pl011_irq(struct serial_port *port)
 {
     struct pl011 *uart = port->uart;
-    return ((uart->irq > 0) ? uart->irq : -1);
+    return ((uart->irq.irq > 0) ? uart->irq.irq : -1);
+}
+
+static const struct dt_irq __init *pl011_dt_irq(struct serial_port *port)
+{
+    struct pl011 *uart = port->uart;
+
+    return &uart->irq;
 }
 
 static struct uart_driver __read_mostly pl011_driver = {
@@ -227,32 +241,74 @@ static struct uart_driver __read_mostly pl011_driver = {
     .tx_ready     = pl011_tx_ready,
     .putc         = pl011_putc,
     .getc         = pl011_getc,
-    .irq          = pl011_irq
+    .irq          = pl011_irq,
+    .dt_irq_get   = pl011_dt_irq,
 };
 
-/* TODO: Parse UART config from device-tree or command-line */
-
-void __init pl011_init(int index, unsigned long register_base_address)
+/* TODO: Parse UART config from the command line */
+static int __init pl011_uart_init(struct dt_device_node *dev,
+                                  const void *data)
 {
+    const char *config = data;
     struct pl011 *uart;
+    int res;
+    u64 addr, size;
 
-    if ( (index < 0) || (index > 1) )
-        return;
+    if ( strcmp(config, "") )
+    {
+        early_printk("WARNING: UART configuration is not supported\n");
+    }
 
-    uart = &pl011_com[index];
+    uart = &pl011_com;
 
     uart->clock_hz  = 0x16e3600;
     uart->baud      = 38400;
     uart->data_bits = 8;
     uart->parity    = PARITY_NONE;
     uart->stop_bits = 1;
-    uart->irq       = 37; /* TODO Need to find this from devicetree */
-    uart->regs      = (uint32_t *) register_base_address;
+
+    res = dt_device_get_address(dev, 0, &addr, &size);
+    if ( res )
+    {
+        early_printk("pl011: Unable to retrieve the base"
+                     " address of the UART\n");
+        return res;
+    }
+
+    uart->regs = ioremap_attr(addr, size, PAGE_HYPERVISOR_NOCACHE);
+    if ( !uart->regs )
+    {
+        early_printk("pl011: Unable to map the UART memory\n");
+
+        return -ENOMEM;
+    }
+
+    res = dt_device_get_irq(dev, 0, &uart->irq);
+    if ( res )
+    {
+        early_printk("pl011: Unable to retrieve the IRQ\n");
+        return res;
+    }
 
     /* Register with generic serial driver. */
-    serial_register_uart(uart - pl011_com, &pl011_driver, uart);
+    serial_register_uart(SERHND_DTUART, &pl011_driver, uart);
+
+    dt_device_set_used_by(dev, DOMID_XEN);
+
+    return 0;
 }
 
+static const char const *pl011_dt_compat[] __initdata =
+{
+    "arm,pl011",
+    NULL
+};
+
+DT_DEVICE_START(pl011, "PL011 UART", DEVICE_SERIAL)
+        .compatible = pl011_dt_compat,
+        .init = pl011_uart_init,
+DT_DEVICE_END
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/xen/serial.h b/xen/include/xen/serial.h
index 8af3bc4..9caf776 100644
--- a/xen/include/xen/serial.h
+++ b/xen/include/xen/serial.h
@@ -157,7 +157,6 @@ struct ns16550_defaults {
 void ns16550_init(int index, struct ns16550_defaults *defaults);
 void ehci_dbgp_init(void);
 
-void pl011_init(int index, unsigned long register_base_address);
 void __init dt_uart_init(void);
 
 struct physdev_dbgp_op;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH V4 22/32] xen/arm: Allow Xen to run on multiple platform without recompilation
  2013-05-10 15:11 [PATCH V4 00/32] Support multiple ARM platform in Xen Julien Grall
                   ` (6 preceding siblings ...)
  2013-05-10 15:11 ` [PATCH V4 20/32] xen/arm: Use device tree API in pl011 UART driver Julien Grall
@ 2013-05-10 15:12 ` Julien Grall
  2013-05-10 15:12 ` [PATCH V4 24/32] xen/arm: Add versatile express platform Julien Grall
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 25+ messages in thread
From: Julien Grall @ 2013-05-10 15:12 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Xen can include various platform support (ie: exynos5, versatile express...)
and choose during boot time a set of callbacks for the current board.
These callbacks will be called in places where each board can have specific
code. For the moment the callbacks are:
    - platform_init: additional initialization for the platform
    - platform_init_time: some platform (ie: Exynos 5) needs to initialize
    the timer with an uncommon way
    - platform_specific_mapping: add mapping to dom0 which are not specified
    in the device tree
    - platform_reset: reset the platform
    - platform_poweroff: poweroff the platform
    - platform_quirks: list of quirks for a specific board.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

Changes in v4:
    - More precision in the TODO

Changes in v3:
    - Remove platform_{read,write}
    - Move platform_init_time before reading the timer frequency

Changes in v2:
    - Add platform_poweroff
    - Add platform_quirks
---
 xen/arch/arm/Makefile          |    1 +
 xen/arch/arm/domain_build.c    |    4 ++
 xen/arch/arm/platform.c        |  137 ++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/setup.c           |    3 +
 xen/arch/arm/shutdown.c        |    2 +
 xen/arch/arm/time.c            |    6 ++
 xen/arch/arm/xen.lds.S         |    7 ++
 xen/include/asm-arm/platform.h |   55 ++++++++++++++++
 8 files changed, 215 insertions(+)
 create mode 100644 xen/arch/arm/platform.c
 create mode 100644 xen/include/asm-arm/platform.h

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 4955a21..2717f26 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -18,6 +18,7 @@ obj-y += p2m.o
 obj-y += percpu.o
 obj-y += guestcopy.o
 obj-y += physdev.o
+obj-y += platform.o
 obj-y += setup.o
 obj-y += time.o
 obj-y += smpboot.o
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 9a2ccad..75c3006 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -12,6 +12,7 @@
 #include <xen/libfdt/libfdt.h>
 #include <xen/guest_access.h>
 #include <asm/setup.h>
+#include <asm/platform.h>
 
 #include <asm/gic.h>
 #include <xen/irq.h>
@@ -513,6 +514,9 @@ int construct_dom0(struct domain *d)
         return rc;
 
     map_devices_from_device_tree(d);
+    rc = platform_specific_mapping(d);
+    if ( rc < 0 )
+        return rc;
 
     /* The following loads use the domain's p2m */
     p2m_load_VTTBR(d);
diff --git a/xen/arch/arm/platform.c b/xen/arch/arm/platform.c
new file mode 100644
index 0000000..afda302
--- /dev/null
+++ b/xen/arch/arm/platform.c
@@ -0,0 +1,137 @@
+/*
+ * xen/arch/arm/platform.c
+ *
+ * Helpers to execute platform specific code.
+ *
+ * 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/platform.h>
+#include <xen/device_tree.h>
+#include <xen/init.h>
+
+extern const struct platform_desc _splatform[], _eplatform[];
+
+/* Pointer to the current platform description */
+static const struct platform_desc *platform;
+
+
+static bool_t __init platform_is_compatible(const struct platform_desc *plat)
+{
+    const char *const *compat;
+
+    if ( !plat->compatible )
+        return 0;
+
+    for ( compat = plat->compatible; *compat; compat++ )
+    {
+        if ( dt_machine_is_compatible(*compat) )
+            return 1;
+    }
+
+    return 0;
+}
+
+/* List of possible platform */
+static void dump_platform_table(void)
+{
+    const struct platform_desc *p;
+
+    printk("Available platform support:\n");
+
+    for ( p = _splatform; p != _eplatform; p++ )
+        printk("    - %s\n", p->name);
+}
+
+int __init platform_init(void)
+{
+    int res = 0;
+
+    ASSERT(platform == NULL);
+
+    /* Looking for the platform description */
+    for ( platform = _splatform; platform != _eplatform; platform++ )
+    {
+        if ( platform_is_compatible(platform) )
+            break;
+    }
+
+    /* We don't have specific operations for this platform */
+    if ( platform == _eplatform )
+    {
+        /* TODO: dump DT machine compatible node */
+        printk(XENLOG_WARNING "WARNING: Unrecognized/unsupported device tree "
+              "compatible list\n");
+        dump_platform_table();
+        platform = NULL;
+    }
+    else
+        printk(XENLOG_INFO "Platform: %s\n", platform->name);
+
+    if ( platform && platform->init )
+        res = platform->init();
+
+    return res;
+}
+
+int __init platform_init_time(void)
+{
+    int res = 0;
+
+    if ( platform && platform->init_time )
+        res = platform->init_time();
+
+    return res;
+}
+
+int __init platform_specific_mapping(struct domain *d)
+{
+    int res = 0;
+
+    if ( platform && platform->specific_mapping )
+        res = platform->specific_mapping(d);
+
+    return res;
+}
+
+void platform_reset(void)
+{
+    if ( platform && platform->reset )
+        platform->reset();
+}
+
+void platform_poweroff(void)
+{
+    if ( platform && platform->poweroff )
+        platform->poweroff();
+}
+
+bool_t platform_has_quirk(uint32_t quirk)
+{
+    uint32_t quirks = 0;
+
+    if ( platform && platform->quirks )
+        quirks = platform->quirks();
+
+    return !!(quirks & quirk);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index e5f4459..da2a734 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -42,6 +42,7 @@
 #include <asm/early_printk.h>
 #include <asm/gic.h>
 #include <asm/cpufeature.h>
+#include <asm/platform.h>
 
 struct cpuinfo_arm __read_mostly boot_cpu_data;
 
@@ -440,6 +441,8 @@ void __init start_xen(unsigned long boot_phys_offset,
 
     processor_id();
 
+    platform_init();
+
     init_xen_time();
 
     gic_init();
diff --git a/xen/arch/arm/shutdown.c b/xen/arch/arm/shutdown.c
index 61b5280..0903842 100644
--- a/xen/arch/arm/shutdown.c
+++ b/xen/arch/arm/shutdown.c
@@ -5,6 +5,7 @@
 #include <xen/lib.h>
 #include <xen/mm.h>
 #include <xen/smp.h>
+#include <asm/platform.h>
 
 static void raw_machine_reset(void)
 {
@@ -21,6 +22,7 @@ static void raw_machine_reset(void)
     dsb(); isb();
     clear_fixmap(FIXMAP_MISC);
 #endif
+    platform_reset();
 }
 
 static void halt_this_cpu(void *arg)
diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
index 2e928bc..db849cf 100644
--- a/xen/arch/arm/time.c
+++ b/xen/arch/arm/time.c
@@ -33,6 +33,7 @@
 #include <asm/time.h>
 #include <asm/gic.h>
 #include <asm/cpufeature.h>
+#include <asm/platform.h>
 
 /*
  * Unfortunately the hypervisor timer interrupt appears to be buggy in
@@ -123,11 +124,16 @@ int __init init_xen_time(void)
            timer_irq[TIMER_HYP_PPI].irq,
            timer_irq[TIMER_VIRT_PPI].irq);
 
+    res = platform_init_time();
+    if ( res )
+        return res;
+
     /* Check that this CPU supports the Generic Timer interface */
     if ( !cpu_has_gentimer )
         panic("CPU does not support the Generic Timer v1 interface.\n");
 
     cpu_khz = READ_SYSREG32(CNTFRQ_EL0) / 1000;
+
     boot_count = READ_SYSREG64(CNTPCT_EL0);
     printk("Using generic timer at %lu KHz\n", cpu_khz);
 
diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
index deab040..3b60668 100644
--- a/xen/arch/arm/xen.lds.S
+++ b/xen/arch/arm/xen.lds.S
@@ -77,6 +77,13 @@ SECTIONS
 #endif
 
   . = ALIGN(8);
+  .arch.info : {
+      _splatform = .;
+      *(.arch.info)
+      _eplatform = .;
+  } :text
+
+  . = ALIGN(8);
   .dev.info : {
       _sdevice = .;
       *(.dev.info)
diff --git a/xen/include/asm-arm/platform.h b/xen/include/asm-arm/platform.h
new file mode 100644
index 0000000..e116265
--- /dev/null
+++ b/xen/include/asm-arm/platform.h
@@ -0,0 +1,55 @@
+#ifndef __ASM_ARM_PLATFORM_H
+#define __ASM_ARM_PLATFORM_H
+
+#include <xen/init.h>
+#include <xen/sched.h>
+#include <xen/mm.h>
+
+/* Describe specific operation for a board */
+struct platform_desc {
+    /* Platform name */
+    const char *name;
+    /* Array of device tree 'compatible' strings */
+    const char *const *compatible;
+    /* Platform initialization */
+    int (*init)(void);
+    int (*init_time)(void);
+    /* Specific mapping for dom0 */
+    int (*specific_mapping)(struct domain *d);
+    /* Platform reset */
+    void (*reset)(void);
+    /* Platform power-off */
+    void (*poweroff)(void);
+    /*
+     * Platform quirks
+     * Defined has a function because a platform can support multiple
+     * board with different quirk on each
+     */
+    uint32_t (*quirks)(void);
+};
+
+int __init platform_init(void);
+int __init platform_init_time(void);
+int __init platform_specific_mapping(struct domain *d);
+void platform_reset(void);
+void platform_poweroff(void);
+bool_t platform_has_quirk(uint32_t quirk);
+
+#define PLATFORM_START(_name, _namestr)                         \
+static const struct platform_desc  __plat_desc_##_name __used   \
+__attribute__((__section__(".arch.info"))) = {                  \
+    .name = _namestr,
+
+#define PLATFORM_END                                            \
+};
+
+#endif /* __ASM_ARM_PLATFORM_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH V4 24/32] xen/arm: Add versatile express platform
  2013-05-10 15:11 [PATCH V4 00/32] Support multiple ARM platform in Xen Julien Grall
                   ` (7 preceding siblings ...)
  2013-05-10 15:12 ` [PATCH V4 22/32] xen/arm: Allow Xen to run on multiple platform without recompilation Julien Grall
@ 2013-05-10 15:12 ` Julien Grall
  2013-05-10 15:39   ` Ian Campbell
  2013-05-10 15:12 ` [PATCH V4 28/32] xen/arm: Add Exynos 4210 UART support Julien Grall
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 25+ messages in thread
From: Julien Grall @ 2013-05-10 15:12 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

This platform contains nearly nothing specific except the reset function.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v4:
    - Use ioremap_nocache
    - Directly give SP810_ADDRESS without page alignment

Changes in v3:
    - Use ioremap_attr instead of fixmap

Changes in v2:
    - Add TODO to retrieve reset base address in the DT
---
 xen/arch/arm/platforms/vexpress.c        |   40 ++++++++++++++++++++++++++++++
 xen/arch/arm/shutdown.c                  |   14 -----------
 xen/include/asm-arm/config.h             |    3 ---
 xen/include/asm-arm/platforms/vexpress.h |    3 +++
 4 files changed, 43 insertions(+), 17 deletions(-)

diff --git a/xen/arch/arm/platforms/vexpress.c b/xen/arch/arm/platforms/vexpress.c
index fd4ce74..8fc30c4 100644
--- a/xen/arch/arm/platforms/vexpress.c
+++ b/xen/arch/arm/platforms/vexpress.c
@@ -18,7 +18,9 @@
  */
 
 #include <asm/platforms/vexpress.h>
+#include <asm/platform.h>
 #include <xen/mm.h>
+#include <xen/vmap.h>
 
 #define DCC_SHIFT      26
 #define FUNCTION_SHIFT 20
@@ -91,6 +93,44 @@ out:
 }
 
 /*
+ * TODO: Get base address from the device tree
+ * See arm,vexpress-reset node
+ */
+static void vexpress_reset(void)
+{
+    void __iomem *sp810;
+
+    /* Use the SP810 system controller to force a reset */
+    sp810 = ioremap_nocache(SP810_ADDRESS, PAGE_SIZE);
+
+    if ( !sp810 )
+    {
+        dprintk(XENLOG_ERR, "Unable to map SP810\n");
+        return;
+    }
+
+    /* switch to slow mode */
+    iowritel(sp810, 0x3);
+    dsb(); isb();
+    /* writing any value to SCSYSSTAT reg will reset the system */
+    iowritel(sp810 + 4, 0x1);
+    dsb(); isb();
+
+    iounmap(sp810);
+}
+
+static const char const *vexpress_dt_compat[] __initdata =
+{
+    "arm,vexpress",
+    NULL
+};
+
+PLATFORM_START(vexpress, "VERSATILE EXPRESS")
+    .compatible = vexpress_dt_compat,
+    .reset = vexpress_reset,
+PLATFORM_END
+
+/*
  * Local variables:
  * mode: C
  * c-file-style: "BSD"
diff --git a/xen/arch/arm/shutdown.c b/xen/arch/arm/shutdown.c
index 0903842..767cc12 100644
--- a/xen/arch/arm/shutdown.c
+++ b/xen/arch/arm/shutdown.c
@@ -3,25 +3,11 @@
 #include <xen/cpu.h>
 #include <xen/delay.h>
 #include <xen/lib.h>
-#include <xen/mm.h>
 #include <xen/smp.h>
 #include <asm/platform.h>
 
 static void raw_machine_reset(void)
 {
-    /* XXX get this from device tree */
-#ifdef SP810_ADDRESS
-    /* Use the SP810 system controller to force a reset */
-    volatile uint32_t *sp810;
-    set_fixmap(FIXMAP_MISC, SP810_ADDRESS >> PAGE_SHIFT, DEV_SHARED);
-    sp810 = ((uint32_t *)
-             (FIXMAP_ADDR(FIXMAP_MISC) + (SP810_ADDRESS & ~PAGE_MASK)));
-    sp810[0] = 0x3; /* switch to slow mode */
-    dsb(); isb();
-    sp810[1] = 0x1; /* writing any value to SCSYSSTAT reg will reset system */
-    dsb(); isb();
-    clear_fixmap(FIXMAP_MISC);
-#endif
     platform_reset();
 }
 
diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
index 8ed72f5..7599202 100644
--- a/xen/include/asm-arm/config.h
+++ b/xen/include/asm-arm/config.h
@@ -149,9 +149,6 @@ extern unsigned long frametable_virt_end;
 #define GIC_CR_OFFSET 0x2000
 #define GIC_HR_OFFSET 0x4000 /* Guess work http://lists.infradead.org/pipermail/linux-arm-kernel/2011-September/064219.html */
 #define GIC_VR_OFFSET 0x6000 /* Virtual Machine CPU interface) */
-/* Board-specific: base address of system controller */
-#define SP810_ADDRESS 0x1C020000
-
 
 #endif /* __ARM_CONFIG_H__ */
 /*
diff --git a/xen/include/asm-arm/platforms/vexpress.h b/xen/include/asm-arm/platforms/vexpress.h
index 67f8fef..5cf3aba 100644
--- a/xen/include/asm-arm/platforms/vexpress.h
+++ b/xen/include/asm-arm/platforms/vexpress.h
@@ -23,6 +23,9 @@
 #define V2M_SYS_CFG_OSC4      4
 #define V2M_SYS_CFG_OSC5      5
 
+/* Board-specific: base address of system controller */
+#define SP810_ADDRESS 0x1C020000
+
 #ifndef __ASSEMBLY__
 #include <xen/inttypes.h>
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH V4 28/32] xen/arm: Add Exynos 4210 UART support
  2013-05-10 15:11 [PATCH V4 00/32] Support multiple ARM platform in Xen Julien Grall
                   ` (8 preceding siblings ...)
  2013-05-10 15:12 ` [PATCH V4 24/32] xen/arm: Add versatile express platform Julien Grall
@ 2013-05-10 15:12 ` Julien Grall
  2013-05-10 15:12 ` [PATCH V4 30/32] xen/arm: Add platform specific code for the exynos5 Julien Grall
  2013-05-13 11:21 ` [PATCH V4 00/32] Support multiple ARM platform in Xen Ian Campbell
  11 siblings, 0 replies; 25+ messages in thread
From: Julien Grall @ 2013-05-10 15:12 UTC (permalink / raw)
  To: xen-devel
  Cc: Anthony PERARD, patches, ian.campbell, Julien Grall, Stefano.Stabellini

From: Anthony PERARD <anthony.perard@citrix.com>

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

Changes in v4:
    - Use ioremap_nocache instead of ioremap_attr(..., PAGE_HYPERVISOR_NOCACHE)
    - Add warning if config != ""

Changes in v3:
    - Directly get the base address from the DT and map it with ioremap_attr
    - Use ioreadl/iowritel
    - Typoes
    - Remove the remaining //

Changes in v2:
    - Use defines where it's possible
    - Move UART definition in a separate header. Will be used for early
    UART
    - Replace all  // by /* ... */
    - Add Anthony as first author
---
 config/arm32.mk                       |    1 +
 xen/drivers/char/Makefile             |    1 +
 xen/drivers/char/exynos4210-uart.c    |  365 +++++++++++++++++++++++++++++++++
 xen/include/asm-arm/exynos4210-uart.h |  111 ++++++++++
 4 files changed, 478 insertions(+)
 create mode 100644 xen/drivers/char/exynos4210-uart.c
 create mode 100644 xen/include/asm-arm/exynos4210-uart.h

diff --git a/config/arm32.mk b/config/arm32.mk
index f64f0c1..d8e958b 100644
--- a/config/arm32.mk
+++ b/config/arm32.mk
@@ -8,6 +8,7 @@ CONFIG_ARM_$(XEN_OS) := y
 CFLAGS += -marm
 
 HAS_PL011 := y
+HAS_EXYNOS4210 := y
 
 # Use only if calling $(LD) directly.
 #LDFLAGS_DIRECT_OpenBSD = _obsd
diff --git a/xen/drivers/char/Makefile b/xen/drivers/char/Makefile
index 9c067f9..37543f0 100644
--- a/xen/drivers/char/Makefile
+++ b/xen/drivers/char/Makefile
@@ -1,6 +1,7 @@
 obj-y += console.o
 obj-$(HAS_NS16550) += ns16550.o
 obj-$(HAS_PL011) += pl011.o
+obj-$(HAS_EXYNOS4210) += exynos4210-uart.o
 obj-$(HAS_EHCI) += ehci-dbgp.o
 obj-$(CONFIG_ARM) += dt-uart.o
 obj-y += serial.o
diff --git a/xen/drivers/char/exynos4210-uart.c b/xen/drivers/char/exynos4210-uart.c
new file mode 100644
index 0000000..f151390
--- /dev/null
+++ b/xen/drivers/char/exynos4210-uart.c
@@ -0,0 +1,365 @@
+/*
+ * xen/drivers/char/exynos4210-uart.c
+ *
+ * Driver for Exynos 4210 UART.
+ *
+ * Anthony PERARD <anthony.perard@citrix.com>
+ * Copyright (c) 2012 Citrix Systems.
+ *
+ * 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 <xen/config.h>
+#include <xen/console.h>
+#include <xen/errno.h>
+#include <xen/serial.h>
+#include <xen/init.h>
+#include <xen/irq.h>
+#include <xen/mm.h>
+#include <asm/early_printk.h>
+#include <asm/device.h>
+#include <asm/exynos4210-uart.h>
+
+static struct exynos4210_uart {
+    unsigned int baud, clock_hz, data_bits, parity, stop_bits;
+    struct dt_irq irq;
+    void *regs;
+    struct irqaction irqaction;
+} exynos4210_com = {0};
+
+/* These parity settings can be ORed directly into the ULCON. */
+#define PARITY_NONE  (0)
+#define PARITY_ODD   (0x4)
+#define PARITY_EVEN  (0x5)
+#define FORCED_CHECKED_AS_ONE (0x6)
+#define FORCED_CHECKED_AS_ZERO (0x7)
+
+#define exynos4210_read(uart, off)          ioreadl((uart)->regs + off)
+#define exynos4210_write(uart, off, val)    iowritel((uart->regs) + off, val)
+
+static void exynos4210_uart_interrupt(int irq, void *data, struct cpu_user_regs *regs)
+{
+    struct serial_port *port = data;
+    struct exynos4210_uart *uart = port->uart;
+    unsigned int status;
+
+    status = exynos4210_read(uart, UINTP);
+
+    while ( status != 0 )
+    {
+        /* Clear all pending interrupts
+         * but should take care of ERROR and MODEM
+         */
+
+        if ( status & UINTM_ERROR )
+        {
+            uint32_t error_bit;
+
+            error_bit = exynos4210_read(uart, UERSTAT);
+
+            if ( error_bit & UERSTAT_OVERRUN )
+                dprintk(XENLOG_ERR, "uart: overrun error\n");
+            if ( error_bit & UERSTAT_PARITY )
+                dprintk(XENLOG_ERR, "uart: parity error\n");
+            if ( error_bit & UERSTAT_FRAME )
+                dprintk(XENLOG_ERR, "uart: frame error\n");
+            if ( error_bit & UERSTAT_BREAK )
+                dprintk(XENLOG_ERR, "uart: break detected\n");
+            /* Clear error pending interrupt */
+            exynos4210_write(uart, UINTP, UINTM_ERROR);
+        }
+
+
+        if ( status & (UINTM_RXD | UINTM_ERROR) )
+        {
+            /* uart->regs[UINTM] |= RXD|ERROR; */
+            serial_rx_interrupt(port, regs);
+            /* uart->regs[UINTM] &= ~(RXD|ERROR); */
+            exynos4210_write(uart, UINTP, UINTM_RXD | UINTM_ERROR);
+        }
+
+        if ( status & (UINTM_TXD | UINTM_MODEM) )
+        {
+            /* uart->regs[UINTM] |= TXD|MODEM; */
+            serial_tx_interrupt(port, regs);
+            /* uart->regs[UINTM] &= ~(TXD|MODEM); */
+            exynos4210_write(uart, UINTP, UINTM_TXD | UINTM_MODEM);
+        }
+
+        status = exynos4210_read(uart, UINTP);
+    }
+}
+
+static void __init exynos4210_uart_init_preirq(struct serial_port *port)
+{
+    struct exynos4210_uart *uart = port->uart;
+    unsigned int divisor;
+    uint32_t ulcon;
+
+    /* reset, TX/RX disables */
+    exynos4210_write(uart, UCON, 0);
+
+    /* No Interrupt, auto flow control */
+    exynos4210_write(uart, UMCON, 0);
+
+    /* Line control and baud-rate generator. */
+    if ( uart->baud != BAUD_AUTO )
+    {
+        /* Baud rate specified: program it into the divisor latch. */
+        divisor = ((uart->clock_hz) / (uart->baud)) - 1;
+        /* FIXME: will use a hacked divisor, assuming the src clock and bauds */
+        exynos4210_write(uart, UFRACVAL, 53);
+        exynos4210_write(uart, UBRDIV, 4);
+    }
+    else
+    {
+        /*
+         * TODO: should be updated
+         * Baud rate already set: read it out from the divisor latch.
+         * divisor = (uart->regs[IBRD] << 6) | uart->regs[FBRD];
+         * uart->baud = (uart->clock_hz << 2) / divisor;
+         */
+    }
+
+    /*
+     * Number of bits per character
+     * 0 => 5 bits
+     * 1 => 6 bits
+     * 2 => 7 bits
+     * 3 => 8 bits
+     */
+    ASSERT(uart->data_bits >= 5 && uart->data_bits <= 8);
+    ulcon = (uart->data_bits - 5);
+
+    /*
+     * Stop bits
+     * 0 => 1 stop bit per frame
+     * 1 => 2 stop bit per frame
+     */
+    ASSERT(uart->stop_bits >= 1 && uart->stop_bits <= 2);
+    ulcon |= (uart->stop_bits - 1) << ULCON_STOPB_SHIFT;
+
+
+    /* Parity */
+    ulcon |= uart->parity << ULCON_PARITY_SHIFT;
+
+    exynos4210_write(uart, ULCON, ulcon);
+
+    /* Mask and clear the interrupts */
+    exynos4210_write(uart, UINTM, UINTM_ALLI);
+    exynos4210_write(uart, UINTP, UINTM_ALLI);
+
+    /* reset FIFO */
+    exynos4210_write(uart, UFCON, UFCON_FIFO_RESET);
+
+    /* TODO: Add timeout to avoid infinite loop */
+    while ( exynos4210_read(uart, UFCON) & UFCON_FIFO_RESET )
+        ;
+
+    /*
+     * Enable FIFO and set the trigger level of Tx FIFO
+     * The trigger level is always set to b101, an interrupt will be
+     * generated when data count of Tx FIFO is less than or equal to the
+     * following value:
+     * UART0 => 160 bytes
+     * UART1 => 40 bytes
+     * UART2 => 10 bytes
+     * UART3 => 10 bytes
+     */
+    exynos4210_write(uart, UFCON, UFCON_FIFO_TX_TRIGGER | UFCON_FIFO_EN);
+
+    /*
+     * Enable the UART for Rx and Tx
+     *   - Use only interrupt request
+     *   - Interrupts are level trigger
+     *   - Enable Rx timeout
+     */
+    exynos4210_write(uart, UCON,
+                     UCON_RX_IRQ_LEVEL | UCON_TX_IRQ_LEVEL | UCON_RX_IRQ |
+                     UCON_TX_IRQ | UCON_RX_TIMEOUT);
+}
+
+static void __init exynos4210_uart_init_postirq(struct serial_port *port)
+{
+    struct exynos4210_uart *uart = port->uart;
+    int rc;
+
+    uart->irqaction.handler = exynos4210_uart_interrupt;
+    uart->irqaction.name    = "exynos4210_uart";
+    uart->irqaction.dev_id  = port;
+
+    if ( (rc = setup_dt_irq(&uart->irq, &uart->irqaction)) != 0 )
+        dprintk(XENLOG_ERR, "Failed to allocated exynos4210_uart IRQ %d\n",
+                uart->irq.irq);
+
+    /* Unmask interrupts */
+    exynos4210_write(uart, UINTM, ~UINTM_ALLI);
+
+    /* Clear pending interrupts */
+    exynos4210_write(uart, UINTP, UINTM_ALLI);
+
+    /* Enable interrupts */
+    exynos4210_write(uart, UMCON, exynos4210_read(uart, UMCON) | UMCON_INT_EN);
+}
+
+static void exynos4210_uart_suspend(struct serial_port *port)
+{
+    BUG(); // XXX
+}
+
+static void exynos4210_uart_resume(struct serial_port *port)
+{
+    BUG(); // XXX
+}
+
+static unsigned int exynos4210_uart_tx_ready(struct serial_port *port)
+{
+    struct exynos4210_uart *uart = port->uart;
+
+    /* Tx fifo full ? */
+    if ( exynos4210_read(uart, UFSTAT) & UFSTAT_TX_FULL )
+        return 0;
+    else
+    {
+        uint32_t val = exynos4210_read(uart, UFSTAT);
+
+        val = (val & UFSTAT_TX_COUNT_MASK) >> UFSTAT_TX_COUNT_SHIFT;
+
+        /* XXX: Here we assume that we use UART 2/3, on the others
+         * UART the buffer is bigger
+         */
+        ASSERT(val >= 0 && val <= FIFO_MAX_SIZE);
+
+        return (FIFO_MAX_SIZE - val);
+    }
+}
+
+static void exynos4210_uart_putc(struct serial_port *port, char c)
+{
+    struct exynos4210_uart *uart = port->uart;
+
+    exynos4210_write(uart, UTXH, (uint32_t)(unsigned char)c);
+}
+
+static int exynos4210_uart_getc(struct serial_port *port, char *pc)
+{
+    struct exynos4210_uart *uart = port->uart;
+    uint32_t ufstat = exynos4210_read(uart, UFSTAT);
+    uint32_t count;
+
+    count = (ufstat & UFSTAT_RX_COUNT_MASK) >> UFSTAT_RX_COUNT_SHIFT;
+
+    /* Check if Rx fifo is full or if the is something in it */
+    if ( ufstat & UFSTAT_RX_FULL || count )
+    {
+        *pc = exynos4210_read(uart, URXH) & URXH_DATA_MASK;
+        return 1;
+    }
+    else
+        return 0;
+}
+
+static int __init exynos4210_uart_irq(struct serial_port *port)
+{
+    struct exynos4210_uart *uart = port->uart;
+
+    return uart->irq.irq;
+}
+
+static const struct dt_irq __init *exynos4210_uart_dt_irq(struct serial_port *port)
+{
+    struct exynos4210_uart *uart = port->uart;
+
+    return &uart->irq;
+}
+
+static struct uart_driver __read_mostly exynos4210_uart_driver = {
+    .init_preirq  = exynos4210_uart_init_preirq,
+    .init_postirq = exynos4210_uart_init_postirq,
+    .endboot      = NULL,
+    .suspend      = exynos4210_uart_suspend,
+    .resume       = exynos4210_uart_resume,
+    .tx_ready     = exynos4210_uart_tx_ready,
+    .putc         = exynos4210_uart_putc,
+    .getc         = exynos4210_uart_getc,
+    .irq          = exynos4210_uart_irq,
+    .dt_irq_get   = exynos4210_uart_dt_irq,
+};
+
+/* TODO: Parse UART config from the command line */
+static int __init exynos4210_uart_init(struct dt_device_node *dev,
+                                       const void *data)
+{
+    const char *config = data;
+    struct exynos4210_uart *uart;
+    int res;
+    u64 addr, size;
+
+    if ( strcmp(config, "") )
+    {
+        early_printk("WARNING: UART configuration is not supported\n");
+    }
+
+    uart = &exynos4210_com;
+
+    /* uart->clock_hz  = 0x16e3600; */
+    uart->baud      = BAUD_AUTO;
+    uart->data_bits = 8;
+    uart->parity    = PARITY_NONE;
+    uart->stop_bits = 1;
+
+    res = dt_device_get_address(dev, 0, &addr, &size);
+    if ( res )
+    {
+        early_printk("exynos4210: Unable to retrieve the base"
+                     " address of the UART\n");
+        return res;
+    }
+
+    uart->regs = ioremap_nocache(addr, size);
+    if ( !uart->regs )
+    {
+        early_printk("exynos4210: Unable to map the UART memory\n");
+    }
+    res = dt_device_get_irq(dev, 0, &uart->irq);
+    if ( res )
+    {
+        early_printk("exynos4210: Unable to retrieve the IRQ\n");
+        return res;
+    }
+
+    /* Register with generic serial driver. */
+    serial_register_uart(SERHND_DTUART, &exynos4210_uart_driver, uart);
+
+    dt_device_set_used_by(dev, DOMID_XEN);
+
+    return 0;
+}
+
+static const char const *exynos4210_dt_compat[] __initdata =
+{
+    "samsung,exynos4210-uart",
+    NULL
+};
+
+DT_DEVICE_START(exynos4210, "Exynos 4210 UART", DEVICE_SERIAL)
+        .compatible = exynos4210_dt_compat,
+        .init = exynos4210_uart_init,
+DT_DEVICE_END
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/exynos4210-uart.h b/xen/include/asm-arm/exynos4210-uart.h
new file mode 100644
index 0000000..330e1c0
--- /dev/null
+++ b/xen/include/asm-arm/exynos4210-uart.h
@@ -0,0 +1,111 @@
+/*
+ * xen/include/asm-arm/exynos4210-uart.h
+ *
+ * Common constant definition between early printk and the UART driver
+ * for the exynos 4210 UART
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARM_EXYNOS4210_H
+#define __ASM_ARM_EXYNOS4210_H
+
+
+/*
+ * this value is only valid for UART 2 and UART 3
+ * XXX: define per UART
+ */
+#define FIFO_MAX_SIZE 16
+
+/* register addresses */
+#define ULCON     (0x00)
+#define UCON      (0x04)
+#define UFCON     (0x08)
+#define UMCON     (0x0c)
+#define UTRSTAT   (0x10)
+#define UERSTAT   (0x14)
+#define UFSTAT    (0x18)
+#define UMSTAT    (0x1c)
+#define UTXH      (0x20)
+#define URXH      (0x24)
+#define UBRDIV    (0x28)
+#define UFRACVAL  (0x2c)
+#define UINTP     (0x30)
+#define UINTS     (0x34)
+#define UINTM     (0x38)
+
+/* UCON */
+#define UCON_RX_IRQ         (1 << 0)
+#define UCON_TX_IRQ         (1 << 2)
+#define UCON_RX_TIMEOUT     (1 << 7)
+
+/*
+ * FIXME: IRQ_LEVEL should be 1 << n but with this value, the IRQ
+ * handler will never end...
+ */
+#define UCON_RX_IRQ_LEVEL   (0 << 8)
+#define UCON_TX_IRQ_LEVEL   (0 << 9)
+
+/* ULCON */
+#define ULCON_STOPB_SHIFT 2
+#define ULCON_PARITY_SHIFT 3
+
+/* UFCON */
+#define UFCON_FIFO_TX_RESET     (1 << 2)
+#define UFCON_FIFO_RX_RESET     (1 << 1)
+#define UFCON_FIFO_RESET        (UFCON_FIFO_TX_RESET | UFCON_FIFO_RX_RESET)
+#define UFCON_FIFO_EN           (1 << 0)
+
+#define UFCON_FIFO_TX_TRIGGER   (0x6 << 8)
+
+/* UMCON */
+#define UMCON_INT_EN            (1 << 3)
+
+/* UERSTAT */
+#define UERSTAT_OVERRUN (1 << 0)
+#define UERSTAT_PARITY  (1 << 1)
+#define UERSTAT_FRAME   (1 << 2)
+#define UERSTAT_BREAK   (1 << 3)
+
+/* UFSTAT */
+#define UFSTAT_TX_FULL          (1 << 24)
+#define UFSTAT_TX_COUNT_SHIFT   (16)
+#define UFSTAT_TX_COUNT_MASK    (0xff << UFSTAT_TX_COUNT_SHIFT)
+#define UFSTAT_RX_FULL          (1 << 8)
+#define UFSTAT_RX_COUNT_SHIFT   (0)
+#define UFSTAT_RX_COUNT_MASK    (0xff << UFSTAT_RX_COUNT_SHIFT)
+
+/* UTRSTAT */
+#define UTRSTAT_TX_EMPTY        (1 << 1)
+
+/* URHX */
+#define URXH_DATA_MASK  (0xff)
+
+/* Interrupt bits (UINTP, UINTS, UINTM) */
+#define UINTM_MODEM     (1 << 3)
+#define UINTM_TXD       (1 << 2)
+#define UINTM_ERROR     (1 << 1)
+#define UINTM_RXD       (1 << 0)
+#define UINTM_ALLI      (UINTM_MODEM | UINTM_TXD | UINTM_ERROR | UINTM_RXD)
+
+#endif /* __ASM_ARM_EXYNOS4210_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH V4 30/32] xen/arm: Add platform specific code for the exynos5
  2013-05-10 15:11 [PATCH V4 00/32] Support multiple ARM platform in Xen Julien Grall
                   ` (9 preceding siblings ...)
  2013-05-10 15:12 ` [PATCH V4 28/32] xen/arm: Add Exynos 4210 UART support Julien Grall
@ 2013-05-10 15:12 ` Julien Grall
  2013-05-13 11:21 ` [PATCH V4 00/32] Support multiple ARM platform in Xen Ian Campbell
  11 siblings, 0 replies; 25+ messages in thread
From: Julien Grall @ 2013-05-10 15:12 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

Changes in v4:
    - Use ioremap_nocache instead of ioremap_attr(..., PAGE_HYPERVISOR_NOCACHE)

Changes in v3:
    - Remove hard tab
    - Typoes
    - Replace platform_{read,write} call to ioremap_attr, ioreadl, iowritel

Changes in v2:
    - Add dom0 1:1 mapping quirk for the arndale board
    - s/mapping/mappings/ in comment
    - Remove debug trap (unnecessary with linux 3.9)
---
 xen/arch/arm/platforms/Makefile         |    1 +
 xen/arch/arm/platforms/exynos5.c        |  110 +++++++++++++++++++++++++++++++
 xen/include/asm-arm/platforms/exynos5.h |   39 +++++++++++
 3 files changed, 150 insertions(+)
 create mode 100644 xen/arch/arm/platforms/exynos5.c
 create mode 100644 xen/include/asm-arm/platforms/exynos5.h

diff --git a/xen/arch/arm/platforms/Makefile b/xen/arch/arm/platforms/Makefile
index 4313e95..ff2b65b 100644
--- a/xen/arch/arm/platforms/Makefile
+++ b/xen/arch/arm/platforms/Makefile
@@ -1 +1,2 @@
 obj-y += vexpress.o
+obj-y += exynos5.o
diff --git a/xen/arch/arm/platforms/exynos5.c b/xen/arch/arm/platforms/exynos5.c
new file mode 100644
index 0000000..1368a04
--- /dev/null
+++ b/xen/arch/arm/platforms/exynos5.c
@@ -0,0 +1,110 @@
+/*
+ * xen/arch/arm/platforms/exynos5.c
+ *
+ * Exynos5 specific settings
+ *
+ * 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/p2m.h>
+#include <xen/config.h>
+#include <xen/device_tree.h>
+#include <xen/domain_page.h>
+#include <xen/mm.h>
+#include <xen/vmap.h>
+#include <asm/platforms/exynos5.h>
+#include <asm/platform.h>
+
+static int exynos5_init_time(void)
+{
+    uint32_t reg;
+    void __iomem *mct;
+
+    BUILD_BUG_ON(EXYNOS5_MCT_G_TCON >= PAGE_SIZE);
+
+    mct = ioremap_attr(EXYNOS5_MCT_BASE, PAGE_SIZE, PAGE_HYPERVISOR_NOCACHE);
+    if ( !mct )
+    {
+        dprintk(XENLOG_ERR, "Unable to map MCT\n");
+        return -ENOMEM;
+    }
+
+    /* Enable timer on Exynos 5250 should probably be done by u-boot */
+    reg = ioreadl(mct + EXYNOS5_MCT_G_TCON);
+    iowritel(mct + EXYNOS5_MCT_G_TCON, reg | EXYNOS5_MCT_G_TCON_START);
+
+    iounmap(mct);
+
+    return 0;
+}
+
+/* Additional mappings for dom0 (Not in the DTS) */
+static int exynos5_specific_mapping(struct domain *d)
+{
+    /* Map the chip ID */
+    map_mmio_regions(d, EXYNOS5_PA_CHIPID, EXYNOS5_PA_CHIPID + PAGE_SIZE - 1,
+                     EXYNOS5_PA_CHIPID);
+
+    /* Map the PWM region */
+    map_mmio_regions(d, EXYNOS5_PA_TIMER,
+                     EXYNOS5_PA_TIMER + (PAGE_SIZE * 2) - 1,
+                     EXYNOS5_PA_TIMER);
+
+    return 0;
+}
+
+static void exynos5_reset(void)
+{
+    void __iomem *pmu;
+
+    BUILD_BUG_ON(EXYNOS5_SWRESET >= PAGE_SIZE);
+
+    pmu = ioremap_nocache(EXYNOS5_PA_PMU, PAGE_SIZE);
+    if ( !pmu )
+    {
+        dprintk(XENLOG_ERR, "Unable to map PMU\n");
+        return;
+    }
+
+    iowritel(pmu + EXYNOS5_SWRESET, 1);
+    iounmap(pmu);
+}
+
+static uint32_t exynos5_quirks(void)
+{
+    return PLATFORM_QUIRK_DOM0_MAPPING_11;
+}
+
+static const char const *exynos5_dt_compat[] __initdata =
+{
+    "samsung,exynos5250",
+    NULL
+};
+
+PLATFORM_START(exynos5, "SAMSUNG EXYNOS5")
+    .compatible = exynos5_dt_compat,
+    .init_time = exynos5_init_time,
+    .specific_mapping = exynos5_specific_mapping,
+    .reset = exynos5_reset,
+    .quirks = exynos5_quirks,
+PLATFORM_END
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/platforms/exynos5.h b/xen/include/asm-arm/platforms/exynos5.h
new file mode 100644
index 0000000..ee5bdfa
--- /dev/null
+++ b/xen/include/asm-arm/platforms/exynos5.h
@@ -0,0 +1,39 @@
+#ifndef __ASM_ARM_PLATFORMS_EXYNOS5_H
+#define __ASM_ASM_PLATFORMS_EXYSNO5_H
+
+#define EXYNOS5_MCT_BASE            0x101c0000
+#define EXYNOS5_MCT_G_TCON          0x240       /* Relative to MCT_BASE */
+#define EXYNOS5_MCT_G_TCON_START    (1 << 8)
+
+#define EXYNOS5_PA_CHIPID           0x10000000
+#define EXYNOS5_PA_TIMER            0x12dd0000
+/* Base address of system controller */
+#define EXYNOS5_PA_PMU              0x10040000
+
+#define EXYNOS5_SWRESET             0x0400      /* Relative to PA_PMU */
+
+#define S5P_PA_SYSRAM   0x02020000
+
+/* Constants below is only used in assembly because the DTS is not yet parsed */
+#ifdef __ASSEMBLY__
+
+/* GIC Base Address */
+#define EXYNOS5_GIC_BASE_ADDRESS    0x10480000
+
+/* Timer's frequency */
+#define EXYNOS5_TIMER_FREQUENCY     (24 * 1000 * 1000) /* 24 MHz */
+
+/* Arndale machine ID */
+#define MACH_TYPE_SMDK5250          3774
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_ARM_PLATFORMS_EXYNOS5_H */
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH V4 03/32] xen/arm: Introduce ioremap_attr, ioremap_cache, ioremap_nocache, ioremap_wc
  2013-05-10 15:11 ` [PATCH V4 03/32] xen/arm: Introduce ioremap_attr, ioremap_cache, ioremap_nocache, ioremap_wc Julien Grall
@ 2013-05-10 15:24   ` Ian Campbell
  0 siblings, 0 replies; 25+ messages in thread
From: Ian Campbell @ 2013-05-10 15:24 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 16:11 +0100, Julien Grall wrote:
> Map physical range in virtual memory with a specific mapping attribute.
> Also add new mapping attributes for ARM: PAGE_HYPERVISOR_NOCACHE
> and PAGE_HYPERVISOR_WC.
> 
> This function replaces early_ioremap which is only able to deal with 2Mb
> aligned mapping. Therefore, vmap initialization has been moved earlier.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH V4 04/32] xen/arm: Add helpers ioreadl/iowritel
  2013-05-10 15:11 ` [PATCH V4 04/32] xen/arm: Add helpers ioreadl/iowritel Julien Grall
@ 2013-05-10 15:38   ` Ian Campbell
  2013-05-10 16:24   ` Julien Grall
  1 sibling, 0 replies; 25+ messages in thread
From: Ian Campbell @ 2013-05-10 15:38 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 16:11 +0100, Julien Grall wrote:
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> ---
>  xen/include/asm-arm/mm.h |   10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
> index 63e1069..3749f44 100644
> --- a/xen/include/asm-arm/mm.h
> +++ b/xen/include/asm-arm/mm.h
> @@ -171,6 +171,16 @@ static inline void __iomem *ioremap_wc(paddr_t start, size_t len)
>      return ioremap_attr(start, len, PAGE_HYPERVISOR_WC);
>  }
>  
> +static inline uint32_t ioreadl(const volatile void __iomem *addr)
> +{
> +    return (*(volatile uint32_t *)addr);
> +}

Is volatile here sufficient? I'd have thought some barriers ought to be
involved somewhere.

e.g. on Linux the equivalent functionality is:
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
        u32 val;
        asm volatile("ldr %1, %0"
                     : "+Qo" (*(volatile u32 __force *)addr),
                       "=r" (val));
        return val;
}
#define __iormb()               rmb()
#define ioread32(p)	({ unsigned int __v = le32_to_cpu((__force __le32)__raw_readl(p)); __iormb(); __v; })

Ian.

> +
> +static inline void iowritel(const volatile void __iomem *addr, uint32_t val)
> +{
> +    *(volatile uint32_t *)addr = val;
> +}
> +
>  #define mfn_valid(mfn)        ({                                              \
>      unsigned long __m_f_n = (mfn);                                            \
>      likely(__m_f_n < max_page);                                               \

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH V4 05/32] xen/arm: Create a hierarchical device tree
  2013-05-10 15:11 ` [PATCH V4 05/32] xen/arm: Create a hierarchical device tree Julien Grall
@ 2013-05-10 15:38   ` Ian Campbell
  0 siblings, 0 replies; 25+ messages in thread
From: Ian Campbell @ 2013-05-10 15:38 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 16:11 +0100, Julien Grall wrote:
> Add function to parse the device tree and create a hierarchical tree.
> 
> This code is based on drivers/of/base.c in linux source.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH V4 24/32] xen/arm: Add versatile express platform
  2013-05-10 15:12 ` [PATCH V4 24/32] xen/arm: Add versatile express platform Julien Grall
@ 2013-05-10 15:39   ` Ian Campbell
  0 siblings, 0 replies; 25+ messages in thread
From: Ian Campbell @ 2013-05-10 15:39 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 16:12 +0100, Julien Grall wrote:
> This platform contains nearly nothing specific except the reset function.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH V4 02/32] xen/mm: Align virtual address on PAGE_SIZE in iounmap
  2013-05-10 15:11 ` [PATCH V4 02/32] xen/mm: Align virtual address on PAGE_SIZE in iounmap Julien Grall
@ 2013-05-10 16:16   ` Julien Grall
  2013-05-10 16:22   ` Julien Grall
  2013-05-13 11:01   ` Ian Campbell
  2 siblings, 0 replies; 25+ messages in thread
From: Julien Grall @ 2013-05-10 16:16 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano.Stabellini, keir, ian.campbell, patches, xen-devel

On 05/10/2013 04:11 PM, Julien Grall wrote:

> ioremap function can unlikely return an unaligned virtual address if
> the physical address itself is unaligned on a page size.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Acked-by: Jan Beulich <jbeulich@suse.com>
> CC: keir@xen.org
> 
> Changes in v4:
>     - replace vaddr_t by unsigned int
> ---
>  xen/include/xen/vmap.h |    4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/xen/include/xen/vmap.h b/xen/include/xen/vmap.h
> index 88e5d99..45e9870 100644
> --- a/xen/include/xen/vmap.h
> +++ b/xen/include/xen/vmap.h
> @@ -15,7 +15,9 @@ void __iomem *ioremap(paddr_t, size_t);
>  
>  static inline void iounmap(void __iomem *va)
>  {
> -    vunmap((void __force *)va);
> +    unsigned int addr = (unsigned int)(void __force *)va;


Hum I used unsigned int instead of unsigned long. I will resend back
this patch.

> +
> +    vunmap((void *)(addr & PAGE_MASK));
>  }
>  
>  void vm_init(void);


-- 
Julien

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH V4 02/32] xen/mm: Align virtual address on PAGE_SIZE in iounmap
  2013-05-10 15:11 ` [PATCH V4 02/32] xen/mm: Align virtual address on PAGE_SIZE in iounmap Julien Grall
  2013-05-10 16:16   ` Julien Grall
@ 2013-05-10 16:22   ` Julien Grall
  2013-05-13 11:01   ` Ian Campbell
  2 siblings, 0 replies; 25+ messages in thread
From: Julien Grall @ 2013-05-10 16:22 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano.Stabellini, keir, ian.campbell, patches, xen-devel

ioremap function can unlikely return an unaligned virtual address if
the physical address itself is unaligned on a page size.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Jan Beulich <jbeulich@suse.com>
CC: keir@xen.org

Changes in v5:
    - replace unsigned int by unsigned long

Changes in v4:
    - replace vaddr_t by unsigned int
---
 xen/include/xen/vmap.h |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/xen/include/xen/vmap.h b/xen/include/xen/vmap.h
index 88e5d99..daee7f5 100644
--- a/xen/include/xen/vmap.h
+++ b/xen/include/xen/vmap.h
@@ -15,7 +15,9 @@ void __iomem *ioremap(paddr_t, size_t);
 
 static inline void iounmap(void __iomem *va)
 {
-    vunmap((void __force *)va);
+    unsigned long addr = (unsigned long)(void __force *)va;
+
+    vunmap((void *)(addr & PAGE_MASK));
 }
 
 void vm_init(void);
-- 
Julien

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH V4 04/32] xen/arm: Add helpers ioreadl/iowritel
  2013-05-10 15:11 ` [PATCH V4 04/32] xen/arm: Add helpers ioreadl/iowritel Julien Grall
  2013-05-10 15:38   ` Ian Campbell
@ 2013-05-10 16:24   ` Julien Grall
  1 sibling, 0 replies; 25+ messages in thread
From: Julien Grall @ 2013-05-10 16:24 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano.Stabellini, ian.campbell, patches, xen-devel

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v5:
    - Use functions from linux code
---
 xen/include/asm-arm/arm32/io.h |   46 ++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/arm64/io.h |   38 +++++++++++++++++++++++++++++++++
 xen/include/asm-arm/mm.h       |    8 +++++++
 3 files changed, 92 insertions(+)
 create mode 100644 xen/include/asm-arm/arm32/io.h
 create mode 100644 xen/include/asm-arm/arm64/io.h

diff --git a/xen/include/asm-arm/arm32/io.h b/xen/include/asm-arm/arm32/io.h
new file mode 100644
index 0000000..0d6da1f
--- /dev/null
+++ b/xen/include/asm-arm/arm32/io.h
@@ -0,0 +1,46 @@
+/*
+ *  Based on linux arch/arm/include/asm/io.h
+ *
+ *  Copyright (C) 1996-2000 Russell King
+ *
+ * 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.
+ *
+ * Modifications:
+ *  16-Sep-1996        RMK     Inlined the inx/outx functions & optimised for both
+ *                     constant addresses and variable addresses.
+ *  04-Dec-1997        RMK     Moved a lot of this stuff to the new architecture
+ *                     specific IO header files.
+ *  27-Mar-1999        PJB     Second parameter of memcpy_toio is const..
+ *  04-Apr-1999        PJB     Added check_signature.
+ *  12-Dec-1999        RMK     More cleanups
+ *  18-Jun-2000 RMK    Removed virt_to_* and friends definitions
+ *  05-Oct-2004 BJD     Moved memory string functions to use void __iomem
+ */
+#ifndef _ARM_ARM32_IO_H
+#define _ARM_ARM32_IO_H
+
+#include <asm/system.h>
+
+static inline uint32_t ioreadl(const volatile void __iomem *addr)
+{
+    uint32_t val;
+
+    asm volatile("ldr %1, %0"
+                 : "+Qo" (*(volatile uint32_t __force *)addr),
+                   "=r" (val));
+    dsb();
+
+    return val;
+}
+
+static inline void iowritel(const volatile void __iomem *addr, uint32_t val)
+{
+    dsb();
+    asm volatile("str %1, %0"
+                 : "+Qo" (*(volatile uint32_t __force *)addr)
+                 : "r" (val));
+}
+
+#endif /* _ARM_ARM32_IO_H */
diff --git a/xen/include/asm-arm/arm64/io.h b/xen/include/asm-arm/arm64/io.h
new file mode 100644
index 0000000..ec041cd
--- /dev/null
+++ b/xen/include/asm-arm/arm64/io.h
@@ -0,0 +1,38 @@
+/*
+ * Based on linux arch/arm64/include/asm/io.h
+ *
+ * Copyright (C) 1996-2000 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _ARM_ARM64_IO_H
+#define _ARM_ARM64_IO_H
+
+static inline uint32_t ioreadl(const volatile void __iomem *addr)
+{
+    uint32_t val;
+
+    asm volatile("ldr %w0, [%1]" : "=r" (val) : "r" (addr));
+    dsb();
+
+    return val;
+}
+
+static inline void iowritel(const volatile void __iomem *addr, uint32_t val)
+{
+    dsb();
+    asm volatile("str %w0, [%1]" : : "r" (val), "r" (addr));
+}
+
+#endif /* _ARM_ARM64_IO_H */
diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
index 63e1069..5e7c5a3 100644
--- a/xen/include/asm-arm/mm.h
+++ b/xen/include/asm-arm/mm.h
@@ -6,6 +6,14 @@
 #include <asm/page.h>
 #include <public/xen.h>
 
+#if defined(CONFIG_ARM_32)
+# include <asm/arm32/io.h>
+#elif defined(CONFIG_ARM_64)
+# include <asm/arm64/io.h>
+#else
+# error "unknown ARM variant"
+#endif
+
 /* Align Xen to a 2 MiB boundary. */
 #define XEN_PADDR_ALIGN (1 << 21)
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH V4 01/32] xen/arm: Extend create_xen_entries prototype to take mapping attribute
  2013-05-10 15:11 ` [PATCH V4 01/32] xen/arm: Extend create_xen_entries prototype to take mapping attribute Julien Grall
@ 2013-05-13 11:01   ` Ian Campbell
  0 siblings, 0 replies; 25+ messages in thread
From: Ian Campbell @ 2013-05-13 11:01 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 16:11 +0100, Julien Grall wrote:
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Acked-by: Ian Campbell <ian.campbell@citrix.com>

> Changes in v4:
>     - use "ai" instead of "flags" to reflect field which it goes in.

For this sort of meta-comment which isn't intended to go in the final
commit in the future please can you precede it with a "---" at the start
of a line, then "git am" will do the right thing and strip it for me.
e.g.:

-------8<---------------------

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

---
Changes in v4:
     - use "ai" instead of "flags" to reflect field which it goes in.
 
-------8<---------------------

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH V4 02/32] xen/mm: Align virtual address on PAGE_SIZE in iounmap
  2013-05-10 15:11 ` [PATCH V4 02/32] xen/mm: Align virtual address on PAGE_SIZE in iounmap Julien Grall
  2013-05-10 16:16   ` Julien Grall
  2013-05-10 16:22   ` Julien Grall
@ 2013-05-13 11:01   ` Ian Campbell
  2013-05-13 11:09     ` Jan Beulich
  2 siblings, 1 reply; 25+ messages in thread
From: Ian Campbell @ 2013-05-13 11:01 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, Keir (Xen.org), patches, xen-devel

On Fri, 2013-05-10 at 16:11 +0100, Julien Grall wrote:
> ioremap function can unlikely return an unaligned virtual address if
> the physical address itself is unaligned on a page size.

On x86 this causes:
In file included from /local/scratch/ianc/devel/committer.git/xen/include/asm/io.h:5,
                 from /local/scratch/ianc/devel/committer.git/xen/include/asm/mc146818rtc.h:8,
                 from rtc.c:26:
/local/scratch/ianc/devel/committer.git/xen/include/xen/vmap.h: In function ‘iounmap’:
/local/scratch/ianc/devel/committer.git/xen/include/xen/vmap.h:20: error: ‘PAGE_MASK’ undeclared (first use in this function)
/local/scratch/ianc/devel/committer.git/xen/include/xen/vmap.h:20: error: (Each undeclared identifier is reported only once
/local/scratch/ianc/devel/committer.git/xen/include/xen/vmap.h:20: error: for each function it appears in.)
make[5]: *** [rtc.o] Error 1
make[5]: *** Waiting for unfinished jobs....

Since I had already prepared the branch for commit/push and it was a bit
of a faff I will fold in the following patchlet:

diff --git a/xen/include/xen/vmap.h b/xen/include/xen/vmap.h
index daee7f5..b1923dd 100644
--- a/xen/include/xen/vmap.h
+++ b/xen/include/xen/vmap.h
@@ -2,6 +2,7 @@
 #define __XEN_VMAP_H__
 
 #include <xen/types.h>
+#include <asm/page.h>
 
 void *vm_alloc(unsigned int nr, unsigned int align);
 void vm_free(const void *);



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH V4 02/32] xen/mm: Align virtual address on PAGE_SIZE in iounmap
  2013-05-13 11:01   ` Ian Campbell
@ 2013-05-13 11:09     ` Jan Beulich
  2013-05-13 11:24       ` Ian Campbell
  0 siblings, 1 reply; 25+ messages in thread
From: Jan Beulich @ 2013-05-13 11:09 UTC (permalink / raw)
  To: Ian Campbell, Stefano Stabellini, Julien Grall
  Cc: xen-devel, Keir (Xen.org), patches

>>> On 13.05.13 at 13:01, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Fri, 2013-05-10 at 16:11 +0100, Julien Grall wrote:
>> ioremap function can unlikely return an unaligned virtual address if
>> the physical address itself is unaligned on a page size.
> 
> On x86 this causes:
> In file included from 
> /local/scratch/ianc/devel/committer.git/xen/include/asm/io.h:5,
>                  from 
> /local/scratch/ianc/devel/committer.git/xen/include/asm/mc146818rtc.h:8,
>                  from rtc.c:26:
> /local/scratch/ianc/devel/committer.git/xen/include/xen/vmap.h: In function 
> ‘iounmap’:
> /local/scratch/ianc/devel/committer.git/xen/include/xen/vmap.h:20: error: 
> ‘PAGE_MASK’ undeclared (first use in this function)
> /local/scratch/ianc/devel/committer.git/xen/include/xen/vmap.h:20: error: 
> (Each undeclared identifier is reported only once
> /local/scratch/ianc/devel/committer.git/xen/include/xen/vmap.h:20: error: 
> for each function it appears in.)
> make[5]: *** [rtc.o] Error 1
> make[5]: *** Waiting for unfinished jobs....

With this and the other two bugs that the recent "ARM-sharing-
more-code-with-x86" effort introduced, I wonder whether it's really
appropriate for doing this sort of stuff - without proper testing on
the x86 side - during the RC phase. 

Jan

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH V4 00/32] Support multiple ARM platform in Xen
  2013-05-10 15:11 [PATCH V4 00/32] Support multiple ARM platform in Xen Julien Grall
                   ` (10 preceding siblings ...)
  2013-05-10 15:12 ` [PATCH V4 30/32] xen/arm: Add platform specific code for the exynos5 Julien Grall
@ 2013-05-13 11:21 ` Ian Campbell
  2013-05-13 12:09   ` Julien Grall
  11 siblings, 1 reply; 25+ messages in thread
From: Ian Campbell @ 2013-05-13 11:21 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 16:11 +0100, Julien Grall wrote:
> For all changes see in each patch. I have only reposted patch which are not
> yet acked or changed in v4. All the others patch is in:
> git clone -b arm-v4 git://xenbits.xen.org/people/julieng/xen-unstable.git

I started from this and merged the resent ("v5") versions of "Align
virtual address on PAGE_SIZE in iounmap" and "xen/arm: Add helpers
ioreadl/iowritel" in the right places. Then I applied the various acks
and committed. I think I got everything but since this was a little more
involved than my usual shovelling routine please do confirm I didn't
miss (or mess up) anything.

Thanks!

Ian.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH V4 02/32] xen/mm: Align virtual address on PAGE_SIZE in iounmap
  2013-05-13 11:09     ` Jan Beulich
@ 2013-05-13 11:24       ` Ian Campbell
  0 siblings, 0 replies; 25+ messages in thread
From: Ian Campbell @ 2013-05-13 11:24 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Keir (Xen.org), Julien Grall, xen-devel, patches, Stefano Stabellini

On Mon, 2013-05-13 at 12:09 +0100, Jan Beulich wrote:
> >>> On 13.05.13 at 13:01, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> > On Fri, 2013-05-10 at 16:11 +0100, Julien Grall wrote:
> >> ioremap function can unlikely return an unaligned virtual address if
> >> the physical address itself is unaligned on a page size.
> > 
> > On x86 this causes:
> > In file included from 
> > /local/scratch/ianc/devel/committer.git/xen/include/asm/io.h:5,
> >                  from 
> > /local/scratch/ianc/devel/committer.git/xen/include/asm/mc146818rtc.h:8,
> >                  from rtc.c:26:
> > /local/scratch/ianc/devel/committer.git/xen/include/xen/vmap.h: In function 
> > ‘iounmap’:
> > /local/scratch/ianc/devel/committer.git/xen/include/xen/vmap.h:20: error: 
> > ‘PAGE_MASK’ undeclared (first use in this function)
> > /local/scratch/ianc/devel/committer.git/xen/include/xen/vmap.h:20: error: 
> > (Each undeclared identifier is reported only once
> > /local/scratch/ianc/devel/committer.git/xen/include/xen/vmap.h:20: error: 
> > for each function it appears in.)
> > make[5]: *** [rtc.o] Error 1
> > make[5]: *** Waiting for unfinished jobs....
> 
> With this and the other two bugs that the recent "ARM-sharing-
> more-code-with-x86" effort introduced, I wonder whether it's really
> appropriate for doing this sort of stuff - without proper testing on
> the x86 side - during the RC phase. 

That's a good question, which I'm afraid I didn't see until after I had
hit push. Sorry. We could revert but I'd rather not.

If it is any consolation I think this was the last major bit of ARM
functionality which was to be given such a broad freeze exception. (I
hope Stefano or Julien will correct me ASAP if this is wrong)

Ian.


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH V4 00/32] Support multiple ARM platform in Xen
  2013-05-13 11:21 ` [PATCH V4 00/32] Support multiple ARM platform in Xen Ian Campbell
@ 2013-05-13 12:09   ` Julien Grall
  0 siblings, 0 replies; 25+ messages in thread
From: Julien Grall @ 2013-05-13 12:09 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/13/2013 12:21 PM, Ian Campbell wrote:

> On Fri, 2013-05-10 at 16:11 +0100, Julien Grall wrote:
>> For all changes see in each patch. I have only reposted patch which are not
>> yet acked or changed in v4. All the others patch is in:
>> git clone -b arm-v4 git://xenbits.xen.org/people/julieng/xen-unstable.git
> 
> I started from this and merged the resent ("v5") versions of "Align
> virtual address on PAGE_SIZE in iounmap" and "xen/arm: Add helpers
> ioreadl/iowritel" in the right places. Then I applied the various acks
> and committed. I think I got everything but since this was a little more
> involved than my usual shovelling routine please do confirm I didn't
> miss (or mess up) anything.
> 


I have found all my patches in staging. Thanks for the merge!

Cheers,

-- 
Julien

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2013-05-13 12:09 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-10 15:11 [PATCH V4 00/32] Support multiple ARM platform in Xen Julien Grall
2013-05-10 15:11 ` [PATCH V4 01/32] xen/arm: Extend create_xen_entries prototype to take mapping attribute Julien Grall
2013-05-13 11:01   ` Ian Campbell
2013-05-10 15:11 ` [PATCH V4 02/32] xen/mm: Align virtual address on PAGE_SIZE in iounmap Julien Grall
2013-05-10 16:16   ` Julien Grall
2013-05-10 16:22   ` Julien Grall
2013-05-13 11:01   ` Ian Campbell
2013-05-13 11:09     ` Jan Beulich
2013-05-13 11:24       ` Ian Campbell
2013-05-10 15:11 ` [PATCH V4 03/32] xen/arm: Introduce ioremap_attr, ioremap_cache, ioremap_nocache, ioremap_wc Julien Grall
2013-05-10 15:24   ` Ian Campbell
2013-05-10 15:11 ` [PATCH V4 04/32] xen/arm: Add helpers ioreadl/iowritel Julien Grall
2013-05-10 15:38   ` Ian Campbell
2013-05-10 16:24   ` Julien Grall
2013-05-10 15:11 ` [PATCH V4 05/32] xen/arm: Create a hierarchical device tree Julien Grall
2013-05-10 15:38   ` Ian Campbell
2013-05-10 15:11 ` [PATCH V4 19/32] xen/arm: Add generic UART to get the device in the " Julien Grall
2013-05-10 15:11 ` [PATCH V4 20/32] xen/arm: Use device tree API in pl011 UART driver Julien Grall
2013-05-10 15:12 ` [PATCH V4 22/32] xen/arm: Allow Xen to run on multiple platform without recompilation Julien Grall
2013-05-10 15:12 ` [PATCH V4 24/32] xen/arm: Add versatile express platform Julien Grall
2013-05-10 15:39   ` Ian Campbell
2013-05-10 15:12 ` [PATCH V4 28/32] xen/arm: Add Exynos 4210 UART support Julien Grall
2013-05-10 15:12 ` [PATCH V4 30/32] xen/arm: Add platform specific code for the exynos5 Julien Grall
2013-05-13 11:21 ` [PATCH V4 00/32] Support multiple ARM platform in Xen Ian Campbell
2013-05-13 12:09   ` Julien Grall

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.